Skip to content

How to translate UI text to other languages

For onboarding, please refer to the section of "Localizing" in project README.

i18n Go API

Public API usage is covered in i18n/doc.go.

Documentation as to how to use the Go code should be written inside doc comments in Go code. It should not be written here.

Primer for translators

If you only want to translate strings without touching code, use Codeberg’s Weblate:

Placeholders and formatting

  • Translations may contain placeholders like {{.Name}}.
  • Keep these placeholders exactly as written, including the curly braces and the dot.
  • You can freely reorder placeholders within the translated text.
  • Example: {{.Count}} items selected can become 選択されたアイテム: {{.Count}} in Japanese.
  • Do not include HTML, write plain text.

Formatting uses Go's text/template package. Digits and number separators are not localised automatically.

Style tips

  • Be clear and concise, match the tone of the UI.
  • Prefer consistent terminology across the app. TODO: Create a catalogue for this purpose.
  • If a single English word is ambiguous, ask for more context or expect a contextual variant to be added using TrC or TrNC, for example context menu versus status.

Extraction workflow

We use a Go AST-based extractor. Make sure to regenerate templ code before extracting.

Developer commands via build.sh:

Text Only
1
2
3
./build.sh i18n_extract    # generate POT template
./build.sh i18n_merge      # merge POT into all locale PO files
./build.sh i18n_validate   # validate PO files with msgfmt

Typical flow:

  1. Regenerate templ code and the POT: ./build.sh i18n_extract
  2. Merge into all locales: ./build.sh i18n_merge
  3. Validate: ./build.sh i18n_validate
  4. Commit changes to the POT and any updated PO files.

Gitlab CI TODO

  • Add a job that:
  • Runs ./build.sh i18n_extract and fails if it produces a git diff to the POT.
  • Runs ./build.sh i18n_merge and ./build.sh i18n_validate.
  • Commits updated PO files in a separate MR?
  • NOTE: Ensure gettext tools msgmerge and msgfmt are available in the runner image.

Notes

  • We intentionally do not compile or load .mo files. Parsing .po is sufficient and keeps the build simpler. If we later measure performance issues attributable to .po parsing, we can revisit.
  • Tag translations for user-generated content live in i18n/data/tag_translations.yaml and are surfaced via i18n.TrTagName. They are intentionally separate from UI message catalogues and may move to another package later.

References

gettext format:

  • https://docs.weblate.org/en/latest/formats/gettext.html#example-files
  • https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html
  • http://ftp.twaren.net/Unix/GNU/old-gnu/Manuals/gettext-0.11.2/html_node/gettext_9.html

templ guides:

  • Implicit ctx context.Context variable: https://templ.guide/syntax-and-usage/context/
  • Implicit children templ.Component variable: https://templ.guide/syntax-and-usage/template-composition/#children
  • templ.NopComponent: https://pkg.go.dev/github.com/a-h/templ#pkg-variables