| name | sync-translations |
| description | Keeps all translation files in messages/ in sync. Use this skill whenever new UI text is added to the codebase, a translation key is missing in one language, or the wording of an existing translation changes. Detects missing keys, stale translations, and structural drift between language files. |
Synchronize all translation files in messages/ so every language contains the same keys with correct, natural translations.
Project i18n Setup
- Library:
next-intl
- Source of truth for structure:
messages/de.json (German, default locale)
- All locales: defined in
src/i18n/config.ts → currently ['de', 'en']
- Message files:
messages/<locale>.json — one per locale, flat namespace objects
- Usage in code:
useTranslations('<namespace>') / getTranslations('<namespace>'), then t('key')
Your Task
When invoked, work through the following steps in order.
Step 1 — Read everything relevant
- Read
src/i18n/config.ts to get the current list of locales.
- Read every file in
messages/ (one per locale).
- Scan the entire
src/ directory for translation key usage:
- Find all
useTranslations('namespace') and getTranslations('namespace') calls
- Find all
t('key'), t('namespace.key'), and t('key', {...}) call patterns
- Focus on
.tsx, .ts files under src/
Step 2 — Identify what needs to change
Check for four types of issues:
A) Missing keys
A key exists in one language file but not in another.
- Reference language:
de.json (German is the source of truth for structure)
- List every key path (e.g.
dashboard.noTransactions) that is present in de.json but absent from another locale.
- Also check the reverse: keys in non-German files that don't exist in
de.json are orphaned and should be noted but NOT automatically deleted — report them for manual review.
B) Keys used in code but missing from ALL message files
A t('key') call references a key that doesn't exist in any messages/ file.
- These are newly added UI strings that haven't been translated yet.
- They need to be added to every locale.
C) Structural drift
The JSON structure (nesting, namespace names) differs between files.
- Example:
de.json has { "expenses": { "title": "..." } } but en.json has "expensesTitle": "..." at the top level.
- Flag these — do not silently restructure without reporting.
D) Explicitly changed wording (only when invoked after a specific change)
If the user describes a text change (e.g. "I updated the label for X"), identify the affected key and update all other locales to match the new meaning.
Step 3 — Plan before editing
Write out a concise change plan before touching any file. Group by locale and type:
de.json — no changes needed (reference)
en.json — ADD 3 keys:
expenses.filterByCategory (missing)
analytics.forecastTitle (missing)
settings.resetConfirm (missing)
— NOTE: orphaned key 'dashboard.chartPlaceholder' exists only in en.json
If no changes are needed, state that clearly and stop.
Step 4 — Edit the message files
Apply every planned addition or correction.
Translation quality rules:
- Translations must be natural, idiomatic, and context-aware — not word-for-word.
- German (de): formal enough for a finance app, but approachable. Use "du" forms unless the existing file uses "Sie". Check the existing tone before adding new strings.
- English (en): concise, professional. Match the register of existing English strings.
- For financial/accounting terms use the standard terminology of the target language (e.g. "Girokonto" not "Gehaltskonto", "Savings Account" not "Saving Account").
- Preserve all interpolation placeholders exactly:
{count}, {name}, {amount} must appear unchanged in every locale.
- Preserve ICU message syntax for plurals and selects if used.
- Keep key order inside each namespace consistent with
de.json — new keys go at the bottom of their namespace.
File format rules:
- Valid JSON only — no trailing commas, no comments.
- Same indentation as the existing file (2 spaces).
- Do not reformat or reorder existing keys — only add or correct.
Step 5 — Check for new locales
After syncing, re-read src/i18n/config.ts. If a new locale was added that has no file in messages/ yet, create the full messages/<locale>.json by translating every key from de.json. Apply the same translation quality rules.
Step 6 — Verify
After all edits, confirm:
Report the checklist result. List any orphaned keys (present in non-German files but not in de.json) separately as items for manual review — do not delete them automatically.