How to Localize an Application
Kittox supports full localization of both the framework interface and your application's metadata. You can also build multi-language applications where each user selects their language at login.
Step 1: Localize the framework interface
The framework ships translated in English, Italian, German, Spanish and Portuguese — its locale folder is KittoX/Home/Locale/:
KittoX/Home/Locale/
it/
LC_MESSAGES/
Kitto.po # Source strings (editable with Poedit)
Kitto.mo # Compiled binary (used at runtime)To add a new language:
- Copy the
it/folder and rename it with the language code (e.g.de/,fr/,es/) - Open
Kitto.powith Poedit - Translate all
msgstrentries - Save — Poedit generates the
.mofile automatically
The .po file covers all framework strings: form buttons (Save, Confirm, Cancel, Edit, Close, Delete, Save All, etc.), error messages, login labels, confirmation dialogs, and client-side JavaScript strings.
Step 2: Localize your application metadata
Your application's locale folder ({App}/Home/Locale/) follows the same structure. Use the _() marker in YAML files:
Field labels and hints:
Fields:
Doll_Name: String(40) not null
DisplayLabel: _(Name)
Date_Bought: Date
DisplayLabel: _(Birth Date)
Picture: Blob
DisplayLabel: _(Photo)
Hint: _(Select a picture)Allowed values:
Fields:
Dress_Size: String(4)
AllowedValues:
XS: _(Extra Small)
S: _(Small)
M: _(Medium)See the HelloKitto and TasKitto examples for complete working samples.
Mark only what the user reads
In the snippet above only the descriptions are wrapped: XS, S, M are the codes stored in the database. The same care applies to PluralModelName (an XML tag name, not a caption — the caption is PluralDisplayLabel), to physical and file names, and to comparison literals inside SQL Expression nodes. See what must not be wrapped.
Step 3: Mark strings in Delphi code
In custom controllers and rules, use _() from EF.Localization:
uses
EF.Localization;
procedure TCheckDuplicateInvitations.BeforeAdd(const ARecord: TKRecord);
begin
if ARecord.Store.Count('INVITEE_ID', ARecord.FieldByName('INVITEE_ID').Value) > 1 then
RaiseError(_('Cannot invite the same girl twice.'));
end;Step 4: Generate the .po files with KIDEX
Marking strings is only half the job — they must land in the .po catalogs. Don't do this by hand: KIDEx extracts them for you and keeps each language's default.po in sync with your metadata and code.
- In KIDEx, expand the project's Locales node, right-click the language and choose Update….
- KIDEx scans the metadata (Models / Views / Layouts / Config) and runs dxgettext over your
Source\folder, then merges everything into that language'sdefault.po— existing translations are preserved, brand-new strings appear empty. - Translate the empty entries in Poedit and save to compile the
.mo.
Re-run Update… whenever you change metadata or code — it is non-destructive. See Update Locale for the full workflow and the list of auto-recognized YAML keys.
Step 5: Enable multi-language at runtime
Language selection is configured in Config.yaml:
LanguageId: # empty → follow the browser (Accept-Language); set a code (en, it, …) to force it
LanguagePerSession: True- With an empty
LanguageId, the language is auto-detected from the browser (Accept-Language) on the first visit. - With
LanguagePerSession: True, a LanguageSwitcher flag dropdown lets the user switch language at any time; it lists every language for which the application ships a compiled catalog (Home/Locale/<code>/LC_MESSAGES/*.mo) plus English — a folder without a.mois ignored, and the framework's own catalogs do not make a language selectable. In the examples it appears on the login form and at the bottom of the home menu — add it to any layout region withController: LanguageSwitcher.
See also
- Localization Reference — full reference, file structure, client-side strings
- Update Locale (KIDEx) — extract/refresh the
.pofiles from YAML + Delphi sources - LanguageSwitcher — the flag drop-down controller for switching language
- Login — language selector on the login page
