| name | translate-po | |||||
|---|---|---|---|---|---|---|
| description | Translate untranslated gettext .po entries for changedetection.io. Use when: "translate", "翻訳", "fill in translations", "translate po files", "translate missing strings", "/translate-po". | |||||
| argument-hint | [locale] (e.g. ja, fr, de, it, ko — omit for all languages) | |||||
| allowed-tools |
|
Translate untranslated entries in changedetection.io's .po files.
locale(optional): Target locale code (e.g.ja,fr,de). If omitted, process all languages.
| Code | Language | Word order notes |
|---|---|---|
| cs | Czech (Čeština) | SVO, but flexible |
| de | German (Deutsch) | V2 word order, verb-final in subclauses |
| es | Spanish (Español) | SVO, adjective-after-noun |
| fr | French (Français) | SVO, adjective-after-noun |
| it | Italian (Italiano) | SVO, adjective-after-noun |
| ja | Japanese (日本語) | SOV, particles, modifier-before-head |
| ko | Korean (한국어) | SOV, particles, modifier-before-head |
| pt_BR | Portuguese Brazil (Português) | SVO, adjective-after-noun |
| tr | Turkish (Türkçe) | SOV, agglutinative |
| uk | Ukrainian (Українська) | SVO, flexible |
| zh | Chinese Simplified (中文简体) | SVO, modifier-before-head |
| zh_Hant_TW | Chinese Traditional (繁體中文) | SVO, modifier-before-head |
Skip: en_GB and en_US — these fall through to English source strings by design.
Read @changedetectionio/translations/{locale}/LC_MESSAGES/messages.po.
The file is large (80-130KB). Read it in chunks to find untranslated entries.
Find entries with empty msgstr "" (but NOT the file header which also has msgstr "").
An untranslated entry looks like:
#: changedetectionio/blueprint/backups/restore.py
msgid "Backup zip file"
msgstr ""A translated entry looks like:
#: changedetectionio/blueprint/backups/restore.py
msgid "Include groups"
msgstr "グループを含める"For each untranslated entry, produce a translation following these rules:
- Use "monitor" or "watcher" terminology — NEVER "clock"
- Use the most brief wording suitable
- Match the tone and style of existing translated entries in the same file
%(name)s,%(count)d,%(mb)setc. must appear in msgstr unchanged- Entries marked
#, python-formathave Python format strings — be extra careful
Some msgid/msgstr span multiple lines:
msgid ""
"First line "
"second line"
msgstr ""
"訳文1行目 "
"訳文2行目"Preserve the multiline structure when the original uses it.
Templates sometimes split UI strings into multiple adjacent msgid fragments.
For example, the template might render: "Set to" + input_field + "to disable".
In English this reads naturally, but in languages with different word order (especially SOV languages like Japanese, Korean, Turkish), a 1:1 translation of each fragment produces broken or unnatural text.
When to redistribute:
- The msgid is a short phrase fragment (not a complete sentence)
- Adjacent fragments in the same source file form a complete phrase when combined
- Direct translation of the fragment would be unnatural in the target language
How to redistribute:
- Identify the complete phrase by looking at adjacent entries from the same source file
- Check the template source to understand the exact HTML structure between fragments
- Translate the complete phrase naturally in the target language
- Classify which redistribution pattern applies (see below), then distribute accordingly
- Every fragment MUST have a non-empty msgstr — gettext treats
msgstr ""as untranslated and falls back to the English source string, which breaks the sentence (e.g. "Set to" appearing in the middle of Japanese text). If a fragment has no natural equivalent in the target language (e.g. English "Use" before a noun phrase is redundant in Japanese), usemsgstr " "(a single space) — HTML collapses whitespace so it renders as nothing, while gettext treats it as translated. - Always add a translator comment explaining which pattern was applied and why
Pattern A — Move predicate to later fragment (most common)
English SVO puts the verb early; SOV languages need it at the end. Move the verb/predicate into the later fragment.
| English | Target (ja) |
|---|---|
"These settings are" added "to any existing..." |
「これらの設定は」既存の〜に追加「されます。」 |
"Accepts the" [token] "placeholders..." |
" " [token] 「以下のプレースホルダーを受け付けます」 |
Pattern B — Swap fragment meanings
When the English and target word order are fully reversed, swap what goes into the front vs. back fragment.
| English | Target (ja) |
|---|---|
"Base URL used for the" [token] "token in notification links." |
「通知リンクの」[token]「トークンに使用するベースURL。」 |
"This will wait" [n] "seconds before extracting the text." |
「テキスト抽出前に」[n]「秒間待機します。」 |
"So it's always better to select" [X] "when you're interested in new content." |
「新しいコンテンツに興味がある場合は」[X]「を選択することをおすすめします。」 |
Pattern C — Single-space suppression (often combined with Pattern A)
When a fragment is semantically unnecessary in the target language, set msgstr " " to suppress it. Frequently used together with Pattern A: suppress the front fragment, move predicate to the back.
| msgid | Pattern | Reason |
|---|---|---|
"Set to" |
A+C | Predicate moved to "to disable", front suppressed |
"There are" |
A+C | Absorbed into "system-wide notification URLs enabled" |
"Use" |
C alone | Following noun phrase is self-sufficient |
Comment format:
Typical explanation line patterns:
- One-way move:
# 述語の訳を後半にまとめた(predicate moved to later fragment) - Swap:
# 〇〇と〇〇の訳を入れ替えた(e.g.# 条件節と述語の訳を入れ替えた)
# 訳注: "Original complete phrase in English"
# → 「Complete natural translation」
# 述語の訳を後半にまとめた
#: changedetectionio/path/to/source.py
msgid "fragment part"
msgstr "redistributed translation"Use the comment language that matches the locale:
- Japanese:
# 訳注: - Korean:
# 역주: - Other languages:
# TN:(Translator's Note)
After redistribution, evaluate the msgid's reuse risk:
- High risk (add risk warning): msgid is a short/generic English word or phrase (≤3 words, common parts of speech like prepositions, bare verbs, common nouns) AND the msgstr drastically differs from a 1:1 translation (e.g.
"file"→ complete predicate sentence,"in"→"-","Set to"→" "). - Low risk (skip warning): msgid is long/specific (≥4 words or contains a full clause, proper nouns, distinctive punctuation) and unlikely to be copy-pasted into a new template.
For high-risk entries, append a warning line to the # 訳注: block:
- Japanese:
# リスク: 将来このフラグメントが別テンプレートで再利用されると、本来の英語の意味とは異なる訳が流用されて壊れる。新規追加時は見直すこと。 - Other languages:
# RISK: If this fragment is reused in another template later, the redistributed translation will diverge from the original English meaning and break. Review before adding new usages.
This alerts future maintainers (human or agent) that the redistribute is context-specific and cannot be safely shared across templates.
.po files sort entries by source file order. When a redistributed fragment's paired fragments live in the same source file, they appear adjacent in the .po file and a single # 訳注: block covers them all.
But if a fragment is referenced across multiple templates (e.g. "Use" in both _common_fields.html and text-options.html), its paired fragments may scatter to non-adjacent positions in the .po file. In that case, a maintainer editing one of the paired fragments won't see the main # 訳注: and may break the redistribution.
When to add a cross-reference comment:
For each non-adjacent paired fragment of a redistributed msgid — especially fragments that carry the moved predicate or other non-1:1 translation — add a short reference back to the main 訳注:
- Japanese:
# 訳注: msgid "<primary>" (別箇所) と共に再配分された訳。msgid "<primary>" の訳注を参照のこと。 - Other languages:
# TN: Redistributed together with msgid "<primary>" (elsewhere). See the 訳注 / TN on msgid "<primary>".
Replace <primary> with the anchor msgid that carries the full 訳注 block.
Adjacency check: After writing all translations, scan the paired-fragment msgids of each redistribute block. If any paired msgid is not directly adjacent (separated by unrelated entries) to the main 訳注 block, add a cross-reference there.
Languages most likely to need redistribution:
- SOV languages (ja, ko, tr): Almost always need redistribution for fragment pairs
- Romance languages (fr, es, it, pt_BR): Sometimes, especially with adjective placement
- German (de): Sometimes, due to verb-final in subclauses
- Others (cs, uk, zh, zh_Hant_TW): Occasionally
Reference: Check @changedetectionio/translations/ja/LC_MESSAGES/messages.po
for existing examples of redistribution with # 訳注: comments.
Use the Edit tool to write translations into the .po file.
Edit each untranslated entry by replacing its empty msgstr "" with the translation.
For entries needing redistribution, also add the translator comment lines before the entry. When the redistribution targets a short/generic fragment (see "Risk warning for generic short fragments" above), also append the risk warning line.
Run:
python setup.py compile_catalogThis compiles all .po files to .mo binary format.
Before finishing, verify:
- All
%(...)s/%(...)dformat placeholders preserved exactly - No English left in msgstr (except for proper nouns, technical terms, URLs)
- Fragment redistributions have translator comments
- Short/generic redistribute fragments have a reuse-risk warning in their 訳注 block
- Non-adjacent paired fragments of a redistribute block have a cross-reference 訳注 pointing to the primary msgid
-
python setup.py compile_catalogsucceeds without errors - Tone matches existing translations in the file