translate-keys
Translate keys that exist in messages/en.json but are missing from one or more of the other locale files, writing the translations inline.
Locales
English is the source of truth: messages/en.json.
Target locales to update:
messages/de.json(German)messages/es.json(Spanish)messages/fr.json(French)messages/pt.json(Portuguese)messages/ru.json(Russian)messages/zh-CN.json(Simplified Chinese)messages/it.json(Italian)messages/pl.json(Polish)messages/sv.json(Swedish)messages/nl.json(Dutch)messages/ja.json(Japanese)messages/no.json(Norwegian Bokmål)messages/da.json(Danish)
Procedure
- Read
messages/en.jsonand get the list of keys in order. - Remove duplicate translations — run
pnpm deduplicate-translations.- This finds keys with identical English values, picks the most-used key as canonical (by
git grepcount insrc/), rewrites allsrc/references, and removes the duplicate keys from every locale file. - Run with
--dry-runfirst if you want to preview changes before applying. - Skip this step if you only added new keys and didn't touch existing ones.
- This finds keys with identical English values, picks the most-used key as canonical (by
- For each target locale file:
- Read the file.
- Identify missing keys — any key that is in en.json but absent,
null, or empty string in the target. - If zero missing keys, skip this locale and report "up to date".
- Otherwise translate each missing value from English into the target language, following the preservation rules below.
- Build the final object by iterating en.json's key order: for each en.json key, use the target file's existing value if present, otherwise use the translated value. This preserves key order.
- Write the file as JSON with tab indentation, UTF-8, with a single trailing newline. Equivalent to
JSON.stringify(obj, null, '\t') + '\n'.
- Report a one-line summary per locale.
Preservation rules (do NOT translate these)
- Placeholders: curly-brace tokens like
{emailAddress},{number},{amount},{link}— keep verbatim, same position within the sentence. - Markdown syntax: preserve
**bold**,[link-text](/url),`inline`. Translate the visible text inside brackets; keep URLs, bold markers, and backticks exact. - HTML: preserve tags like
<span class="gradient-text">…</span>. Translate the text between the tags only; never alter attributes or tag names. - Escape sequences:
\n,\t,\"— keep exact, same positions. - Brand names and technical terms: keep as-is —
scrt.link,scrt,Secret Request/Secret Requests(product name),AES-256,AES-256-GCM,RSA-2048,RSA-OAEP,PBKDF2,Stripe,Google,Resend,Paraglide,Vercel,GDPR,CCPA. - Currency codes / ISO codes:
USD,EUR,CHF, etc.
Translation style
- Match the tone of existing translations already in the same locale file. Before translating, scan a few existing entries to calibrate formality (French
tuvs.vous, Spanishtúvs.usted). Default to the register already used in that file. - German: always use informal address —
du/dich/dein(neverSie/Ihnen/Ihr). - Prefer concise, UI-natural phrasings over literal translations. UI strings should read like the product speaks the user's language natively.
- Keep punctuation consistent with the target language (French thin-space before
:/!/?, Spanish inverted¿¡, Germanßwhere appropriate, CJK full-width punctuation).
Never touch
- The
$schemakey at the top of each file — preserve as-is. - Any non-empty value that already exists in a target locale — leave it alone.
messages/en.jsonitself — it is read-only input.
After running
Run pnpm lint to confirm JSON formatting still passes Prettier. Fix any drift before committing.
Run pnpm cleanup-translation-keys to remove any keys from locale files that are no longer referenced in src/. Do this periodically or after deleting features.
Source: stophecom/scrt-link-v2 — distributed by TomeVault.