
frontend-i18n
by allenlin90
SKILL.md
name: frontend-i18n description: Provides guidelines for implementing internationalization (i18n) in frontend applications using Paraglide JS and the shared @eridu/i18n package.
Frontend i18n Pattern
This skill outlines the standard pattern for implementing internationalization in Eridu frontend applications. We use Paraglide JS for type-safe, lightweight i18n.
Architecture
- Tooling:
@inlang/paraglide-js(v2+) - Configuration: Defined in
project.inlangat the app root. - Message Storage: JSON files in
src/i18n/messages/{lang}.json. - Output: Generated code in
src/paraglide(typically gitignored). - Shared Library:
@eridu/i18n(workspace package) for common translations and locale definitions.
Workflow: Adding Translations
- Locate the Message File: Open
src/i18n/messages/en.json(English is the source language). - Add Your Key: Add a new key-value pair. You can nest keys for better organization.
{ "dashboard": { "title": "My Dashboard", "welcomeUser": "Welcome back, {name}!" } } - Automatic Compilation: If the dev server (
pnpm dev) is running, Paraglide will automatically detect changes and regeneratesrc/paraglide. - Use in Component: Import the messages and use them.
Usage in Components
1. App-Specific Messages
Import from the generated local alias (usually configured as @/paraglide/messages).
import * as m from '@/paraglide/messages';
export function Dashboard({ userName }) {
// Simple message
const title = m['dashboard.title']();
// Message with parameters
const welcome = m['dashboard.welcomeUser']({ name: userName });
return (
<div>
<h1>{title}</h1>
<p>{welcome}</p>
</div>
);
}
Note: Because we use nested keys in JSON (e.g.
dashboard.title), Paraglide exports them with the exact path as the name. Since these contain dots, you must use bracket notation:m['dashboard.title']().
2. Shared Messages
For common terms (Save, Cancel, Table headers, etc.), use the shared @eridu/i18n package to ensure consistency.
import * as sharedM from '@eridu/i18n';
// Usage
<Button>{sharedM['common.save']()}</Button>
<Button>{sharedM['common.cancel']()}</Button>
3. Locale Management
Use the LocaleEnum and helper functions from @eridu/i18n when dealing with locale logic (e.g., language switchers).
import { LocaleEnum, LOCALE_LABELS } from '@eridu/i18n';
// Access available locales and their labels
{Object.entries(LOCALE_LABELS).map(([code, label]) => (
<option key={code} value={code}>{label}</option>
))}
Best Practices
- Grouping: Group messages by feature or page (e.g.,
admin,auth,settings). - Naming: Use
camelCasefor keys (e.g.,welcomeUsernotwelcome-user). - Parameters: Use named parameters
{param}instead of positional arguments. - No Hardcoding: Never hardcode user-facing strings in components. Always extract them to
en.json. - Review Shared: Before adding a generic term like "Submit" or "Error", check
packages/i18n/messages/en.jsonto see if it already exists in the shared library.
Troubleshooting
- "Property '...' does not exist on type...": Run
pnpm devorpnpm buildto force regeneration of the Paraglide files. - Missing Translations: Ensure you've added the key to
en.json. Other languages (e.g.,zh-TW) can be filled in later or via translation tools.
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon