Skip to content

i18n: Translations for addons (separate domain) #728

Open

Description

@echoix

Addon messages and interface strings are not translatable today. This issue records what was found while working on #727 and proposes how to add addon translations later, as a separate gettext domain so that the core translators (with limited capacity) are not flooded.

Current state

Nothing is extracted. OSGeo/grass-addons has no POT/PO/MO files, no make pot-like target, and no translation workflow. The old scriptstrings Make rules ran during addon builds, but g.extension passed STRINGDIR=<addon source dir>, so the <tool>_to_translate.c files were written into the temporary build directory and deleted (scripts/g.extension/g.extension.py had # TODO: handle locales also for addons). #727 removes these rules and the dead STRINGDIR.

Runtime lookup only uses core catalogs, so an addon string is translated only if the identical string exists in core:

  • Interface headers: g.parser translates with GRASS_TRANSLATION_DOMAIN or grassmods (general/g.parser/translate.c). Nothing sets GRASS_TRANSLATION_DOMAIN, and G_init_locale() (lib/gis/locale.c) binds only grasslibs and grassmods to $GISBASE/locale, so another domain would be looked up in the system locale directory.
  • Python _(): the builtin from python/grass/__init__.py tries grasslibs, then grassmods, then grasswxpy from $GISBASE/locale. A few addons call gettext.install("grassmods" or "grasswxpy", ...) themselves (e.g. r.basin, v.krige); some use plain gettext.gettext.
  • C: _() uses PACKAGE, which is grassmods for all addons (include/Make/Module.make).

Size: the headers of the 366 script tools in grass-addons (364 Script.make with $(PGM).py, and 2 ShScript.make shell scripts, r.stream.variables and r.stream.watersheds) give 5359 strings, 4829 of them not in any core POT. This doesn't count _() messages in addon Python and C code.

Proposal

  1. Extraction (in grass-addons):
    • Headers: utils/grass_tool_header_pot.py from i18n: Extract tool header strings without a build, with context for translators #727 reads any script (Python, shell, extension-less) and accepts file arguments. Add an option to search another tree layout (src/<category>/...), or pass the files found from the Makefiles.
    • Messages: xgettext for _() / n_() in addon .py, .c, .cpp, as locale/Makefile does in core.
    • Write one grassaddons.pot in grass-addons; add a Weblate component for it, possibly with low priority or headers only at first.
  2. Runtime (in core):
    • Bind the addon domain in G_init_locale() to the directory where addon translations are installed.
    • g.parser: look up grassaddons after grassmods (or have g.extension set GRASS_TRANSLATION_DOMAIN when running addons).
    • Python: add the domain to the _translate fallback chain in python/grass/__init__.py.
    • C addons: PACKAGE could be set to grassaddons by the addon build, with a fallback to grassmods for strings shared with core.
  3. Installation: decide where .mo files go ($GRASS_ADDON_BASE/locale?) and whether g.extension downloads compiled catalogs or compiles them with msgfmt (not always available, e.g. on Windows).

Open questions

  • Is a single grassaddons domain right, or one per addon (simpler to ship with the addon, but many small Weblate components)?
  • Should strings already translated in core be excluded from grassaddons.pot to save translator time (the runtime fallback to grassmods would still find them)?
  • Start with interface headers only, since they are what users see in the GUI and in --help?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions