Skip to content

Update Locale

Keeping the GNU gettext .po files of an application in sync with the strings you mark for translation — scattered across YAML metadata and Delphi code — is tedious by hand. KIDEx automates it: with one command it scans the project's metadata and sources, extracts every translatable string, and merges the result into a language's default.popreserving the translations already done.

This is the recommended way to build and maintain the .po files of a Kittox application: you mark strings with _(...) (and use the standard label nodes), then re-run this command whenever metadata or code changes. Translators working in parallel never lose their work.

Why this matters

A typical Kittox application has hundreds of strings scattered across:

  • YAML metadataDisplayLabel, PluralDisplayLabel, Hint, AllowedValues labels, button/ToolView captions, dialog titles, filter labels
  • Delphi source — strings inside _('...') calls in Controllers.pas, Rules.pas, UseKitto.pas and your own units

Manually keeping the .po files aligned with all of this is impractical. KIDEx does it in seconds with two extraction passes merged into a single .po:

Update Locale workflow

What it extracts

1. YAML metadata

KIDEx walks the loaded metadata catalog — Models, Views, Layouts and the top-level Config *.yaml files — and collects a node's value when either:

  • the node name is one of the configured localizable keys — by default AppTitle, ConfirmationMessage, DisplayLabel, Folder, FreeSearch, Hint, PluralDisplayLabel (list read from Localization/Yaml/DefaultKeyNames in KIDEx's Config.yaml); or
  • the node value is already wrapped as _(...).

The _(...) wrapper is stripped, so the msgid is the plain text (e.g. DisplayLabel: _(Bar Chart) → msgid Bar Chart).

Wrap everything you want translated

The name list above is intentionally small. Any other translatable YAML value must be wrapped in _(...) to be picked up — view Title, ToolViews labels, filter captions, AllowedValues descriptions (never the DB codes), etc. For model fields the recommended form is an explicit DisplayLabel: _(English), which is both extracted and self-documenting.

Never wrap a value that is not shown to the user

The _(...) wrapper makes a value change with the session language. That is right for a label and wrong for anything the application matches, stores or emits. Leave these alone:

NodeWhat it really is
PluralModelNamethe XML element name wrapping a record set in GetAsXML (TKViewTableRecords.GetXMLTagName), used by the XML export and FOP report tools — not a label, despite the name
AllowedValues keys, filter Items keysthe codes stored in the database — translate the value after the colon, never the key
SQL comparison literals inside ExpressionWHEN {Q}STATUS = 'ATT' and the like; only the displayed text in the same expression may be wrapped
PhysicalName, ClientFileName, TemplateFileName, FileName, Model, View, Layout, Field, ImageName, DefaultValue, rule parameterstable/column, file and object names

The plural caption is a different node, PluralDisplayLabel, and that one you do wrap. See what must not be wrapped for the reasoning.

2. Delphi sources

KIDEx then runs the bundled dxgettext (dxgettext.exe --delphi) over the project's sibling Source\ folder, extracting every _('...') / gettext string from your Delphi units into a temporary catalog.

3. Merge

The two passes are merged into the target language's default.po with msgcat: existing msgstr values are kept, and strings found for the first time are added with an empty translation, ready to be filled in.

The operation is non-destructive — it only adds missing msgids; it never overwrites an existing translation.

Scope

  • It maintains the application catalog only — default.po per language. The framework strings (Kitto.po) are shipped translated by Ethea and are not regenerated here.
  • It works on one language at a time: you run it on a specific default.po.

Prerequisites

  • A project open in KIDEx.
  • The bundled dxgettext tools (dxgettext.exe and msgcat.exe), shipped under Kide\Bin\dxgettexttools. The folder is read from Localization/dxgettext/Path in KIDEx's Config.yaml (default %APP_PATH%dxgettexttools) and shown read-only in the dialog.
  • Project layout: Home\Metadata\ (the YAML), a sibling Source\ folder (the Delphi units), and the target Home\Locale\<lang>\LC_MESSAGES\default.po. The New Project Wizard creates the locale skeleton.

Running it

  1. In the KIDEx file tree, expand the project's Locales node — each language appears with its default.po.
  2. Right-click the language you want and choose Update…. The Update Locale dialog opens, showing the target .po and the dxgettext tools path.
  3. Click Update. The status line reports progress and ends with Done.

Repeat for each language you ship.

After the update: translate and compile

KIDEx updates the .po but does not compile the .mo. Newly-found strings appear with an empty msgstr:

  1. Open Home\Locale\<lang>\LC_MESSAGES\default.po in Poedit (or any gettext editor).
  2. Translate the empty entries.
  3. Save — Poedit writes default.mo automatically (or run msgfmt default.po -o default.mo). The runtime reads the .mo.

See Localization for the runtime side (file structure, .mo, language selection).

Adding a new language

  1. Create Home\Locale\<lang>\LC_MESSAGES\ (e.g. de, es, pt, pt_BR) and copy an existing default.po into it — or start from an empty file.
  2. Run Update… on it to fill it with all current msgids.
  3. Translate and compile as above.

The login/menu language switcher is built from the locale subfolders, so the new language appears automatically once its folder exists.

Notes & limitations

  • Non-destructive: existing translations are preserved; the update only adds new (empty) msgids.
  • It does not mark changed strings as fuzzy, nor move removed strings to an obsolete section — cleaning up stale entries is a manual/translator task (e.g. Poedit's Catalog → Purge deleted translations).
  • The top-level Resources → Update Locale Files… main-menu entry is currently a placeholder; use the per-language Update… tree action described above.

See also

Released under Apache License, Version 2.0.