Recent

Author Topic: I18N  (Read 1594 times)

pleumann

  • Full Member
  • ***
  • Posts: 106
I18N
« on: July 16, 2023, 10:31:45 am »
Hi,

I managed to make my application multi-language. It was a bit tricky. There are several Wiki pages describing the process, but it seems to me they were made for different stages/versions of Lazarus. For instance, the name of the unit to include varies. Also, I've never seen Lazarus generate a .po file. Instead, I got a .pot file. Weirdly, it contained only a fraction of my strings until I noticed the "move each form once, then save" hint.

Anyway, it works, and I'm wondering about two things:

1) Is there an elegant way of dealing with UI strings that are used repeatedly? Or can the inspector refer to (resource) strings defined elsewhere? I don't want to fill in all my captions programmatically because I like the "full preview" the form designer gives me.

2) How resilient to identifier renames is the whole I18N mechanism? I noticed full "identifier paths" are included in the language files, but not in all cases. I also saw language files containing some hashes, presumably to be able to assign strings properly after a rename has been made?

Cheers!
Joerg

PeterX

  • Sr. Member
  • ****
  • Posts: 445
Re: I18N
« Reply #1 on: February 22, 2026, 11:40:16 pm »
Also, I've never seen Lazarus generate a .po file. Instead, I got a .pot file.
.pot file, yes. I have the same experience actually ..

WIKI seems to be old ..

https://wiki.freepascal.org/Translations_/_i18n_/_localizations_for_programs
usually using latest Lazarus release version with Windows 10 or 11

luca

  • Jr. Member
  • **
  • Posts: 90
Re: I18N
« Reply #2 on: February 23, 2026, 07:42:45 am »
I use poedit tool. This tool helps to translate in an intelligent way by recognizing same word.

wp

  • Hero Member
  • *****
  • Posts: 13512
Re: I18N
« Reply #3 on: February 23, 2026, 10:31:54 am »
I've never seen Lazarus generate a .po file. Instead, I got a .pot file.
Yes, this has been changed several years ago. .pot is the template for the .po files from which all po files are derived. Copy it and rename its extension to .po and insert the country code for the language into which you want it to be translated: myproject.pot --> myproject.de.po (German translation), myproject.fr.po (French translation), etc. Then open each po file in a translation tool, such as POEdit, and translate each entry. Note that if you want to switch languages without having to restart the application you should also provide a myproject.en.po (assuming that your default language is English) where you simply copy the original strings into the translated column (CTRL+B in POEdit).

1) Is there an elegant way of dealing with UI strings that are used repeatedly? Or can the inspector refer to (resource) strings defined elsewhere? I don't want to fill in all my captions programmatically because I like the "full preview" the form designer gives me.
In practice, there are two options.
  • Put DefaultTranslator or LCLTranslator into the uses clause, make sure that "Extract translateable strings from a form when saving its LFM file" is checked on the i18n page of the project settings. This will automatically extract the strings from your forms and put them into the pot template. But note that some strings are ignored, usually strings in controls which usually provide "dynamic", varying information (TComboBox, TMemo). If your project is under version control (git, svn) make sure that the lrj files are included - they provide the information about the strings in the units. The disadvantage of this approach, however, is that the same strings may appear several times in the pot file and thus unnecessary translation work is required. You can exclude controls from automatic translation by adding the full path to the text/caption of this control (e.g. "tmainform.ecit1.text") to the "Exclude" box in project options,  i18n page in the project settings.
  • Don't use Default/LCLTranslator, but declare all strings as "resourcestrings", uncheck the box "Extract translatable strings from a form when saving its LFM file" in the i18n prage of the project settings (to prevent creation of the .lrj files) and run the translation manually by calling "TranslateUnitResourceStrings" in the translations unit. This way you have full control over the strings entering the pot file. As a disadvantage, you must provide code for each form to assign the resourcestrings to the captions/hints/texts of the controls. See attached project as an example.
Your choice...

2) How resilient to identifier renames is the whole I18N mechanism?
Basically, if you rename an identifier the pot/po files will be updated. However, sometimes the po system cannot clearly identify which eintries are to be deleted - they are marked as "fuzzy" in the pot/po files. Not 100% sure but I think when you check "Force update PO files upon next build" and rebuild the project (important: "Run" > "Build"!) they should be removed. Doing this does NOT erase existing translations.
« Last Edit: February 23, 2026, 10:35:24 am by wp »

jcmontherock

  • Sr. Member
  • ****
  • Posts: 354
Re: I18N
« Reply #4 on: February 23, 2026, 11:51:33 am »
The pot file is the source for each language you want to add. Put it in a separate directory (languages for ex.). Then copy the pot file for each the new language language you want to have.
Code: Pascal  [Select][+][-]
  1. Myapplication.pot -> Myapplication.en.po
  2. Myapplication.pot -> Myapplication.fr.po
  3.  

Then do the translation with an application which can create the .mo file (ex Editpo which translate the file into: Myapplication.fr.mo).
That's all you have to do. All these files are updated when you rebuild the application.
Windows 11 UTF8-64 - Lazarus 4.6-64 - FPC 3.2.2

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12851
  • FPC developer.
Re: I18N
« Reply #5 on: February 23, 2026, 04:11:43 pm »
Specially for windows, an alternative way would to be to use the dxgettext source scanner. That also comes with some delphi specific tools and doesn't need multi line comments to be encoded with \n

Unfortunately dxgettext itself doesn't work yet with Lazarus due to not using the same mechanism for resource strings.

I have a simple sequence of runcommands that do the following

- If I use multiple scans (e.g. directory of application A, B, C and some common directories), combine them to Acombined,Bcombined,Ccombined etc.
- take the last translated .po.for each language
- combine with result of scan (.pot so to say) to create a new file .lang.po
- Also I create a .POT that is 1:1, but with the value prefixed by an asterisk(*). This can be used to visually quickly check if texts in the application are translatable. I called these <name>star.lang.po
- Similarly I also create a version of .lang.po the translated file with a hash (#) before untranslated results to make them pop out if you run them.


 

TinyPortal © 2005-2018