Common Issues‎ > ‎

I18N

This page is about using the native internationalization features for FreePascal and Lazarus to localize forms and strings in the code.  For information about localization for databases, please see "DB I18N".

There is a wiki page about using Internationalization/Localization features in Lazarus and FreePascal, but it isn't really sufficient to get beginners up and running.

Probably the best description I have seen so far is from user diablow on the lazarus IDE forums:

How to add i18n to your application

inally, I managed to find a simple and effective way to make my application localizeable. It uses just one unit and no code.
1. Add unit "defaulttranslator" to your uses list.
2. Enable "i18n" in "Project Options" and set "PO output directory" to "locale" or "languages". You can put translation files right into application folder, but that would just make a mess. Don't forget to create an appropriate folder.
3. Add components to the form. If you already have all components on your form, you'll have to move it a little bit, so it's modified.
4. Save your project.
5. Now there should be .po files in your "locale" or "languages" folder. For different languages files should be copied and renamed like so "project1.XX.po", where XX is language code (e.g. "en", "de", etc.).
6. Translate .po files with translation software, and generate .mo files. I suggest to use POEdit.
7. Run your application, and the translation to be used will be chosen by your regional locale settings. If you need to test other language - just start your application with following command line parameters - "-l XX" or "-lang XX", where XX is a language code.
This method is not very versatile, but it translates resource strings and LCL component properties.

This is actually pretty close to the truth.
In addition to those instructions, though, there are some details to be aware of:

Directory Name Matters
The directory name mentioned above actually has to be "locale" or "languages", or the program won't find them when it runs.  Unfortunately, the Lazarus GUI doesn't mention this or help you out.  (Note:  On OS X, it won't find the folder anyway, but more about that below).
Lazarus Internationalization Opt


What are .po files?
Once you enable the i18n options in Lazarus, it will generate .po files for your application based on the components in your forms, using the text in the form as the base language.  Several other files are created in the process, so it's a bit clunky, but it does work.

ResourceStrings
In the case that your program doesn't have any hard-coded text in the code and everything is in the GUI, the .po files generated by default will be sufficient - however that's probably not realistic in most cases.  Error messages and informational messages are often included in code as constants.  These should all be moved to a new section in each unit called "ResourceString".  These work mostly like normal Strings or constants from the programmer's point of view - but they are automatically translated if the translator unit is set up properly.  (i.e. if your forms are being translated automatically, these strings will be as well).

POEdit
Unless you want to edit the .po files by hand, you need to download a translation program that supports .po/.mo files.  These are standard files, so the required applications don't have to be Pascal specific in any way.  Probably the simplest option is simply to download the POEdit installer from SourceForge.net, and try it out.  There are ready-made versions for Windows, OS X, and Linux.  There are also other alternative .po file editors you can try out.

POEdit Usage is relatively self-explanatory.  After opening the application .po file, the source text will be displayed on the left side, while the translated versions (which will initially be blank) are showe on the right side.  You simply enter the translation for each entry and then save the file.
POEdit on OS X

Make sure to save your AppName.po file as AppName.XX.po, where XX is the 2 character ISO language code (Not country code).  Since the .po file format can only handle a single language at a time, you will need a new .po file for each language you want to support.

Alternatives:
If you don't love the internationalization system used by FreePascal, you can roll your own:  On form.show or such, you can run some code like "for component in myPanel do
(component as TControl).caption := ..." and load in text from an INI file or database.  (You can use LazUTF8 utilities to find out the user'S current language.  Alternatively, for Unix text mode programs, you can read the "LANG" environmental variable).   Note that you will have to do slightly more work than shown in this sample, because some components have a "text" field, whereas others have "caption", or none at all.

You can use Precision Language Suite.  They support FreePascal/Lazarus, and allow use of their code for free.  (The editor is commercial, though).  The only realistic problem is that they don't support their editor on OS X or Linux, which means you will need to have a Windows machine around to use that tool.  

OS X Issues:
The above instructions work fine in Windows and Linux, but a bit more work is needed to get things to go smoothly for GUI programs on OS X.

L10n Files Not Located
The the defaulttranslator unit won't find your .po/.mo files.  This is because all of the helper routines in the LCLProc and LazUTF8 units use ParamStr(0) to find the location of the program executable, and then search for the .po files relative to that.  The problem is that OS X GUI programs live inside "Application Bundles", which are special folders.  It makes sense that the translatable strings should be put inside the application bundle, since you would want them to be moved when the program is.  The only problem is that if you configure Lazarus to generate the .PO files into a folder inside the application bundle, then you will break things for other platforms.  Thus, the easiest way is to simply copy the .po files into the application bundle using a script file like so:

.po file copy script

# Copies po files into application bundle to make OS X happy
mkdir ./AppName.app/Contents/MacOS/locale
cp ./i18n/*.po ./AppName.app/Contents/MacOS/locale/
You can set this to run as part of the build process if you find running manually to be too troublesome.

Detecting the user language in OS X
For non-GUI apps, you can simply examine the LANG variable, which is what the helper routines used by the defaulttranslator unit do by default on other platforms.  This doesn't work with GUI apps, though, so instead, a .plist file (preference file) in the application bundle is searched to determine what languages are supported.  Sadly, although Lazarus generates a skeleton file, it doesn't set up the required entries, so if you don't put them in yourself, your program will not detect the language you're running in.  You can detect if you are having this problem as follows:  You run the program from the IDE or Finder and it shows the program in the development language, not the current system language specified in the system preferences, but if you run the program with the --LANG argument, everything displays in the requested language.  (If not, check the issue above!)  

The easiest way to add the require items is to simply copy them from another application bundle.  I use the Lazarus bundle's plist file.  You need to copy the CFBundleLocalizations (May just display as "Localizations") and paste it into your Plist file.  You can open the application's plist file as follows:  Right-click on the bundle and select "Show package contents".  Then find the info.plist file and open it.  Note that on many systems, double-clicking the file will open it with XCode.  This is fine and will work, but XCode is a heavier tool than required to do the job.  You can also right-click, select "Open With...", followed by "PList Editor".

This is what you will see inside your application bundle:
Inside the Application Bundle

This is what you will see if you open the plist file in the PList editor. (This screen shot was taken after inserting the localizations).




Comments