
Vertaalbestanden synchroniseren: houd i18n-sleutels gelijk in alle locales
Telkens wanneer een ontwikkelaar een sleutel aan de bronlocale toevoegt, raken 15 andere localebestanden achterop. Door ontbrekende sleutels krijgen gebruikers onbewerkte paden te zien. Verouderde sleutels verspillen vertaaltijd en vergroten de bundel. Geautomatiseerde synchronisatie houdt alles gelijk.
Het synchronisatieprobleem
Vertaalbestanden lopen voortdurend uiteen. Een ontwikkelaar voegt 'settings.notifications.title' toe aan en.json, maar vergeet de sleutel aan de 15 andere localebestanden toe te voegen. Een andere ontwikkelaar verwijdert 'onboarding.welcome' uit de code, maar laat de sleutel in alle localebestanden staan. Een derde ontwikkelaar hernoemt 'user.name' in het Engels naar 'user.displayName', maar doet dat niet in de andere locales. Na enkele maanden lopen je localebestanden uiteen: sleutels ontbreken, zijn verouderd of komen niet overeen tussen locales.
// The problem: translation files drift out of sync
// Developer adds a new feature with new keys:
// en.json (source of truth)
{
"nav.home": "Home",
"nav.about": "About",
"nav.pricing": "Pricing", // NEW
"nav.changelog": "Changelog" // NEW
}
// de.json (out of sync - missing new keys)
{
"nav.home": "Startseite",
"nav.about": "Über uns"
// nav.pricing - MISSING
// nav.changelog - MISSING
}
// de.json also has stale keys from deleted features:
{
"nav.home": "Startseite",
"nav.about": "Über uns",
"nav.legacy_page": "Alte Seite" // STALE - removed from en.json
}Ontbrekende sleutels detecteren
Een ontbrekende sleutel staat wel in de bronlocale, maar niet in een doellocale. Dit is het meest voorkomende en schadelijkste synchronisatieprobleem: gebruikers zien onbewerkte sleutelpaden zoals 'settings.notifications.title' in plaats van vertaalde tekst. i18n-validate detecteert ontbrekende sleutels door de sleutelstructuur van elke locale met de bron te vergelijken.
# Detect missing and stale keys
npx i18n-validate sync \
--source locales/en.json \
--targets 'locales/*.json'
# Output:
# locales/de.json:
# Missing keys (2):
# - nav.pricing
# - nav.changelog
# Stale keys (1):
# - nav.legacy_page
# Coverage: 66.7% (2/3 keys)
#
# locales/ja.json:
# Missing keys (5):
# - nav.pricing
# - nav.changelog
# - settings.theme
# - settings.language
# - settings.notifications
# Coverage: 50.0% (5/10 keys)Verouderde sleutels detecteren
Een verouderde sleutel staat in vertaalbestanden, maar wordt niet meer in de code aangeroepen. Verouderde sleutels verspillen vertaaltijd (vertalers vertalen tekenreeksen die niemand ziet), vergroten de bundel en maken het onderhoud onduidelijk. Om verouderde sleutels te detecteren, moeten localebestanden worden vergeleken met verwijzingen in de code.
# Step 1: Check which files are out of sync
npx i18n-validate sync --source locales/en.json --targets 'locales/*.json'
# Step 2: Auto-fill missing keys with source values (as placeholders)
npx i18n-validate sync \
--source locales/en.json \
--targets 'locales/*.json' \
--fill-missing \
--fill-value "[NEEDS TRANSLATION] {{source}}"
# Step 3: Remove stale keys no longer in source
npx i18n-validate sync \
--source locales/en.json \
--targets 'locales/*.json' \
--remove-stale
# Step 4: Sort keys to match source order (cleaner diffs)
npx i18n-validate sync \
--source locales/en.json \
--targets 'locales/*.json' \
--sort-keys
# All at once:
npx i18n-validate sync \
--source locales/en.json \
--targets 'locales/*.json' \
--fill-missing \
--remove-stale \
--sort-keysSynchronisatie automatiseren
De effectiefste synchronisatiestrategie combineert drie lagen: 1) pre-commit-hooks die de synchronisatie bij elke commit valideren; 2) controles in de CI-pipeline die merges met synchronisatieproblemen blokkeren; 3) periodieke volledige audits die afwijkingen door hotfixes en handmatige bewerkingen opsporen.
# .husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# Check if source locale file changed
SOURCE_CHANGED=$(git diff --cached --name-only | grep -c 'locales/en.json')
if [ "$SOURCE_CHANGED" -gt 0 ]; then
echo "Source locale changed - checking sync..."
npx i18n-validate sync \
--source locales/en.json \
--targets 'locales/*.json' \
--fail-on-missing \
--min-coverage 90
if [ $? -ne 0 ]; then
echo ""
echo "Translation files are out of sync!"
echo "Run: npx i18n-validate sync --fill-missing"
exit 1
fi
fi# .github/workflows/i18n-sync.yml
name: Translation Sync Check
on:
pull_request:
paths:
- 'locales/**'
jobs:
sync-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check translation sync
run: npx i18n-validate sync \
--source locales/en.json \
--targets 'locales/*.json' \
--fail-on-missing \
--min-coverage 95
- name: Comment on PR if out of sync
if: failure()
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Translation files are out of sync. Please run npx i18n-validate sync --fill-missing and commit.'
})Rapportage over vertaaldekking
De vertaaldekking is het percentage bronsleutels waarvoor elke doellocale een vertaling bevat. i18n-validate genereert een dekkingsrapport met percentages per locale en markeert locales die achterop raken. Gebruik dekkingsdrempels in CI om merges te blokkeren wanneer de dekking onder een aanvaardbaar niveau komt.
// Split large translation files by feature/namespace
// locales/
// ├── en/
// │ ├── common.json (nav, footer, errors)
// │ ├── auth.json (login, register, reset)
// │ ├── dashboard.json (dashboard-specific)
// │ └── settings.json (settings page)
// ├── de/
// │ ├── common.json
// │ ├── auth.json
// │ ├── dashboard.json
// │ └── settings.json
// Sync with namespace support:
npx i18n-validate sync \
--source 'locales/en/*.json' \
--targets 'locales/*/%.json' \
--namespace-pattern '{locale}/{namespace}.json'
// Benefits:
// - Smaller files, easier to review
// - Feature teams own their translations
// - Lazy-load only needed namespaces
// - Parallel translation workflowsProbeer i18n Agent nu
Zet je vertaalbestand hier neer
JSON, YAML, PO, XML, CSV, Markdown, Properties
of klik om een bestand te selecteren
Doeltalen