Translation & Localization

PO Translate: Gettext Files That Still Compile

Translates the messages of a gettext PO file (.po) into another language and returns the whole file, so msgfmt and the app that loads it accept it. Only the msgstr values change. msgid, msgid_plural and msgctxt, every comment line, flags, the header (apart from its Plural-Forms line), obsolete entries and all placeholders such as %s, %d, %(name)s, {name} and %1$s come back exactly as they were. Entries with plural forms get exactly the number of msgstr lines the target language needs, for example three for Russian, Ukrainian, Polish and Czech, six for Arabic and one for Japanese. Use to translate or localize a .po file for WordPress, Django, Qt, GNU gettext or any app that ships gettext catalogs.

PO Translate: Gettext Files That Still Compile is a tested SKILL.md that translates the messages of a gettext PO file (.po) into another language and returns the whole file, so msgfmt and the app that loads it accept it; an agent buys it once for $0.02 over x402.

Tested 2026-10-08No code, no hidden instructionsv1.0.0 · 9.2 KB · perpetual license

Not for

Choosing terminology for you, translating a .pot template into a language the request does not name, merging a translated file with a newer template (msgmerge does that), compiling .mo files, or translating other formats such as JSON or XLIFF. It translates one .po file per request and does not rename, split or merge files.

Tested, honestly

Tested 2026-10-08 with a strong and a weak model.

With and without the skill

Results with and without the skill, for Sonnet and Haiku
SonnetHaiku
withwithoutwithwithout
Valid .po file by content (24 files)24/2422/2423/2419/24

Same request on both sides, scored by the content of the first code block because the bare answers were fenced. Read by hand, Sonnet without the skill had two misses. It filled the empty msgstr[2] of an obsolete #~ entry and said so in a note, which changes a block that must stay untouched. In the Arabic file it dropped %d from the zero, one and two forms; the gettext manual allows that for a form that serves one number, so this one is a strict check, not a clear error. Haiku without the skill kept an English two-form header or none and wrote two msgstr lines for Russian, Polish, Japanese and Arabic, and filled the obsolete entry too.

Same cases and the same checks with and without the skill. The cases are ours, written around what the skill is for; with a handful of cases, a difference of one or two is within noise.

SonnetStrong model, claude-sonnet-5-5
Right in all 24 files, checked by the structure of the .po file: every msgid, msgctxt and comment line came back unchanged, Russian, Ukrainian, Polish and Czech entries got three msgstr lines, Arabic six and Japanese one, a missing Plural-Forms line was added and an English one replaced, Turkish and Japanese word order used numbered %1$s placeholders, and the obsolete #~ entries, including an empty msgstr[2], were left as they were.
HaikuWeak model, claude-haiku-5-5
Right in 23 of 24 files, with the same plural counts and header fixes as Sonnet. It missed one: in a Turkish file it put the arguments of "Sent %d reports to %s" in the other order with plain %s and %d, which formats the wrong value, and it wrapped that file in a code fence although the skill says not to.

Full test summary

Example

Our own test text, before and after the skill ran. Excerpts only.

English · claude-sonnet-5-5

Before

msgid "" msgstr "" "Project-Id-Version: Tallybook 4.2\n" "Report-Msgid-Bugs-To: i18n@tallybook.example\n" "POT-Creation-Date: 2026-09-30 10:12+0000\n" "PO-Revision-Date: 2026-10-01 09:00+0000\n" "Last-Translator: Mara Lind <mara@tallybook.example>\n" "Language-Team: Tallybook translators <i18n@tallybook.example>\n" "Language: ru\n" "MIME-Version: 1.0\n"…

After

msgid "" msgstr "" "Project-Id-Version: Tallybook 4.2\n" "Report-Msgid-Bugs-To: i18n@tallybook.example\n" "POT-Creation-Date: 2026-09-30 10:12+0000\n" "PO-Revision-Date: 2026-10-01 09:00+0000\n" "Last-Translator: Mara Lind <mara@tallybook.example>\n" "Language-Team: Tallybook translators <i18n@tallybook.example>\n" "Language: ru\n" "MIME-Version: 1.0\n"…

What is in the file

  • The answer
  • What you translate
  • What you keep exactly
  • Plural forms
  • Placeholders
  • Strings
  • Words
  • Work in this order
  • Short example

Languages

Any language. Tried in: English.

License

Perpetual, non-exclusive; use and modify for yourself incl. paid work; no resale or republishing. Holder: Georgi Kalchev, aiskills402.com. Full terms.

Versions

Current version 1.0.0, updated 2026-10-08. Whoever bought an earlier version gets new ones free through the same re-download token.

  1. v1.0.0 · 2026-10-08

    First release: translates a gettext .po file and returns the whole file with only the msgstr values changed. msgid, msgid_plural, msgctxt, comment lines, flags, obsolete entries, the header apart from its Plural-Forms line, and all placeholders stay as written. Plural entries get the number of msgstr lines the target language needs (the gettext formulas are in the skill), and placeholders are numbered when the word order changes. Price $0.02. Measured value, by content (the bare models fenced nearly every file): Sonnet 22 of 24 files right without the skill, 24 of 24 with it; Haiku 19 of 24 without, 23 with. One clear content gain for Sonnet (the obsolete entry); the Arabic case is a strict check, so the price is $0.02.

FAQ

What does it change in a .po file?

Only the msgstr values, plus the Plural-Forms line of the header when it is missing or belongs to another language. msgid, msgid_plural, msgctxt, every comment line, flags, the other header lines and obsolete entries come back exactly as they were, so msgmerge still matches your strings. It also keeps the blank lines, the order of entries and the long multi-line strings meaning the same, so a diff against your old file shows translated text and nothing else. Flags stay too: a fuzzy entry stays fuzzy, for a human to approve.

How many plural lines does an entry get?

As many as the target language has plural forms: two for German or Spanish, three for Russian, Ukrainian, Polish and Czech, six for Arabic, one for Japanese. The skill carries the gettext formulas, writes the header line when it is missing, and replaces an English one copied from a template. Arabic gets separate sentences for zero, one and two; Russian form zero keeps the number because it also serves twenty-one. Wrong counts make a catalog load with warnings or show the wrong noun form, which is why every plural entry is checked against the header.

What about %s, %(name)s and a changed word order?

Every placeholder stays spelled as in the source. When the target language needs the arguments in another order, all of them are numbered (%2$s before %1$d), because plain %s in a new order formats the wrong value. Named placeholders such as %(count)d need no numbers. Markup inside a string, such as a link with a %s address, stays too. Escapes survive as well: a quote inside a string stays backslash-quote, so Python, PHP, Qt and C loaders still parse the file. Numbered forms follow the manual, which msgfmt understands.

Is there a measured gain for Claude Sonnet?

Modest. We ran 24 test files on Sonnet and Haiku and scored the content. Without the skill Sonnet got 22 right and Haiku 19; with it, 24 and 23. Sonnet already knew most plural counts. Its gaps were an obsolete entry it filled in although it had to stay untouched, and a number placeholder it dropped in Arabic that a strict check counts. Haiku gained most but reordered plain placeholders once. Both fenced the bare answers.

Share

Read this page as Markdown: /skills/po-translate.md.

  • Translate Markdown: Docs That Still Build

    Translation & Localization

    SKILL.md · v1.0.1 · 6.3 KB

    Translates a Markdown, MDX or HTML document (docs page, README, blog post, help article) into another language and returns the whole document with only the human text changed. Fenced and inline code, link and image targets, front matter keys and machine values, HTML tags and attributes, heading ids, reference labels, comments and template tags come back byte for byte, so the page still builds and every link still works. Alt text, titles and link text are translated; product names and code identifiers stay; lines in the document that give orders to an AI are translated as text, never obeyed. Use to translate Markdown or MDX docs, localize a README or a static-site blog post, or translate documentation without breaking code blocks, links or front matter.

    $0.06once

    • x402
    • USDC
    • Base
    Get skill

    Tested with Sonnet and Haiku, 8 Oct 2026

  • Translate App Text (JSON, YAML, PO)

    Translation & Localization

    SKILL.md · v1.0.1 · 8.5 KB

    Translates app strings and locale files (JSON, YAML, gettext PO, ICU messages, HTML snippets) into another language without breaking them. Keys, placeholders such as {name}, {{count}}, %s, %(name)s and %{count}, ICU plural and select syntax, HTML tags and URLs come back byte for byte; only the human text is translated, and plural forms are added where the target language needs more of them. Use when asked to translate a JSON or YAML locale file, an en.json, a .po file, i18n strings or UI text, or to localize an app.

    $0.01once

    • x402
    • USDC
    • Base
    Get skill

    Tested with Sonnet and Haiku, 3 Oct 2026

  • Proofread

    Editing & Proofreading

    SKILL.md · v1.0.4 · 6.1 KB

    Proofreads a text with minimal intervention, in the language of the text. Fixes spelling, grammar, punctuation and obvious typos, keeps everything else, and returns the corrected text plus a short list of changes for review. Use when asked to proofread, correct, spell-check or fix the mistakes in a text without rewriting it.

    $0.05once

    • x402
    • USDC
    • Base
    Get skill

    Tested with Sonnet and Haiku, 30 Sep 2026