Translate new or untranslated i18n strings from English messages.json to all other locale files, maintaining consistency with each language's existing translations.
Automatically translate new or untranslated strings from the English messages.json to all other locale files, maintaining consistency with each language's existing translations.
all: process all languagesde, ja, bg): process only that languagereport: only show what's missing/untranslated, don't translate_locales/en/messages.json_locales/ except en/messages.json using Chrome extension i18n format:
{
"keyName": {
"message": "Translated text",
"description": "Context for translators"
}
}
_locales/en/messages.json (the English source)._locales/ to discover target languages.messages.json and compare against English:
message value in the target is identical to the English message value AND the key is NOT in the skip-list (see below).Language | Missing | Untranslated | Orphan
----------|---------|--------------|-------
de | 3 | 1 | 0
ja | 3 | 5 | 0
...
report, stop here. Otherwise, ask the user for confirmation before proceeding (unless --yes was passed).These keys are expected to have the same value as English in many/all languages. Do NOT flag them as untranslated:
appName — brand name, kept as "TagSpaces Web Clipper" in all languagesoptionsTutorialLink — "Tutorial" is used as-is in many Romance and Latin-based languages (ca, es, es_CL, id_ID, it, pt_BR, pt_PT, and others)message is a single symbol, number, or punctuation (e.g., "-", "/")message is a proper noun or brand name only (e.g., "TagSpaces")message is a widely-used English loanword that many languages keep as-is (e.g., "Ok", "Email", "Markdown", "Tutorial")For each language that needs translations:
messages.json for that language.For each language, translate all missing and untranslated keys:
message value as the source text.description field from the English source as-is (descriptions stay in English for developer reference)._locales/en/messages.json — it is read-only for this skill.$PLACEHOLDER$ and {{variables}} exactly — template placeholders must appear in the translation unchanged. Do not translate, reorder, or remove them.<br>, <b>, </b>, <a> etc. must remain intact.messages.json with:
_locales/en/messages.json (this keeps diffs clean and structure consistent)._locales/en/messages.json).node -e "JSON.parse(require('fs').readFileSync('path'))" or equivalent).Language | Added | Updated | Removed | Status
----------|-------|---------|---------|-------
de | 3 | 1 | 0 | OK
ja | 3 | 5 | 0 | OK
...
messages.json| Case | Handling |
|---|---|
| Value same as English but intentional | Use the skip-list; also check if 5+ other languages have the same value |
New language directory with empty/missing messages.json | Generate a complete translation from scratch |
Key has only whitespace or empty string as message | Treat as untranslated |
English value contains line breaks (\n) | Preserve line breaks in translation |
| English value is very long (100+ chars) | Translate fully, do not truncate |
de and de_DE both exist | Special case: de and de_DE must always be kept in sync — they should have identical content. When translating German, write the same output to both _locales/de/messages.json and _locales/de_DE/messages.json. This is for historical reasons. |
saveFullScreenshotLabel at the end instead of after saveScreenshotTitle). When writing, always reorder to match English — this is expected and keeps diffs clean.es (Spain) uses "Añadir" vs es_CL (Chile) uses "Agregar"pt_PT uses "ficheiro/ecrã/etiquetas" vs pt_BR uses "arquivo/tela/tags"fr uses "enregistrés" vs fr_CA uses "sauvegardés"zh_CN (Simplified), zh_HK (Traditional HK), zh_TW (Traditional TW) each have distinct terminology