Translations / i18n / localizations for programs
한국어 · Deutsch · English · Español · Français · Polski · Português · Русский · 中文(中国) · 日本語
This is about how a program can use different strings for various languages like English, Chinese, German, Finnish, Italian and any other language.
- i18n is short for internationalization (18 being the number of characters between i and n of the word internationalization)
- l10n is short for localization (10 being the number of characters between l and n of the word localization)
Quick i18n
This is intended as be a quick guide to introduce yourself in the world of translations and get things done quickly. Check also Language Codes and BidiMode.
For your information the most used languages in the world are:
- 1 - Chinese: With more than 1.2 billion native speakers in the world.
- 2 - Spanish: Spanish occupies the 2nd place and is spoken in approximately 30 countries.
- 3 - English: 335 million worldwide, about 5% of the world’s population. (This does not take into account second language spoken).
- 4 - Hindi: Spoken by over 260 million people.
- 5 - Arabic: Spoken in almost 60 countries around the world.
- 6 - Portuguese: Population of Brazil is over 200 million. The population of Portugal is just over 10 million.
- 7 - Bengali: The main language of Bangladesh (population 155 million) and one of India’s many official languages.
- 8 - Russian and Japanese.
poedit
The best known tool is a program called poedit. poedit is a tool for translators. It produces both PO and MO as output.
Translating Forms
When you save a form with the i18n options enabled, it generates a file .lrj, that file is used to create the final .po file. So is very important that you include that file with your source code in the version system you're using, don't add that file to ignored (say .gitignore), else your translations will be broken.
Translating Resourcestrings
This is the way to store a resourcestring in a unit:
resourcestring
Caption1 = 'Some text';
HelloWorld1 = 'Hello World';Resourcestrings are like normal string constants, that means you can assign them to any string:
Label1.Caption := HelloWorld1;Compiling into .po files
Resourcestrings are compiled into .po files if you enable i18n in the Lazarus IDE. Go to Project > Project Options > i18n > Enable i18n. When you recompile your application the .po files will be updated. You may also select a directory where .po files will be stored, recommended po_files.
The default translation is recommended to be in English or the default language of your application, since it will be loaded if no other translation file is found.
When you have your project1.po copy and paste it and rename it to project1.es.po or one of the Language Codes of your choice. Then you will have 2 languages: English and Spanish. Then you must send to the translator the files for translation.
Your folder structure will look something like this:
project1\po_files\
project1\po_files\project1.po
project1\po_files\project1.es.poConverting .po files to .mo files
When you have the translation finished in the .po file, you want to compile it to .mo to load it faster since is a binary format. To convert to .mo you can use poedit and go to File > Compile as .mo.
Note that Everything else about translations has a section about where a Lazarus app looks for its language files.
Automatic translation
When you have the .mo files ready, put them in the locale or languages folder right to your application executable, then include the unit DefaultTranslator and that's all. The translation will be done automatically.
uses
DefaultTranslator;You want to distribute only the .mo files in the locale or languages directory, since .po files are usefull only for making the translation and compiling them into a .mo file.
Your folder structure will look something like this:
project1\project1.exe
project1\locale\
project1\locale\project1.mo
project1\locale\project1.es.moTesting translations
When you have everything ready. you want to test if the translations looks fine in your application for each language you have. Automatic translation has a feature that you can use in order to test each language quickly.
You must run your executable with the command line parameter --lang followed by the language code of your choice.
You will run your executable like this in order to test Spanish translation:
project1.exe --lang esAnd you will see the translated application.
You can do this with the IDE. Go to Run > Run Parameters .... In that window in the input Command line parameters (without application name) write this:
--lang itThen Run (F9) and you will see the translated application.
Final steps
These steps are to get a better result for your entire translation.
Translate LCL
To get everything translated you must include the LCL translations into your application locale folder.
Copy everything inside the folder C:\lazarus\lcl\languages to your locale folder. Then you will have the LCL translated for your application.
Format Settings
For Windows you must read Step-by-step instructions for creating multi-language applications#Format settings to get format settings in the right place.
Under Linux, BSD and macOS there are several locales defining things like time and date format or the thousands separator. In order to initialize the RTL you need to include the clocale unit in the uses section of your program (.lpr file).
BiDiMode
BidiMode is for languages like Arabic that read and write right to left. See also Script direction and languages for a list of LTR (Left To Right) and RTL (Right To Left) languages and most used languages in general.
With this unit you can determine what BiDiMode is right for you. This code is tested in Lazarus Trunk and may or not work in current release (see the changes on this page to get the old source).
First save this unit as ubidimodetools.pas:
unit ubidimodetools;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils;
function GetLang: string;
function GetBiDiMode: TBiDiMode;
implementation
uses
FileUtil, LCLProc, LazUTF8;
function GetLang: string;
var
T: string; // unused FallBackLang
i: integer;
begin
Result := '';
{ We use the same method that is used in LCLTranslator unit }
for i := 1 to Paramcount - 1 do
if (ParamStrUTF8(i) = '--LANG') or (ParamStrUTF8(i) = '-l') or
(ParamStrUTF8(i) = '--lang') then
Result := ParamStrUTF8(i + 1);
//Win32 user may decide to override locale with LANG variable.
if Result = '' then
Result := GetEnvironmentVariableUTF8('LANG');
if Result = '' then
LazGetLanguageIDs(Result, {%H-}T);
end;
function GetBiDiMode: TBiDiMode;
begin
case GetLang of
// Arabic
'ar': Result := bdRightToLeft;
else
Result := bdLeftToRight;
end;
end;
end.When you create a form do this:
BiDiMode := GetBiDiMode;Note: You must be sure that you have the proper translations in order to get it working.
Note 2: Maybe this is not neccesary at all since Windows can change the BiDiMode automatically.
Technical Details
gettext
The main technology involved in the process of translations is GNU gettext. FPC comes with the gettext unit.
uses
gettext;PO
PO – Portable Object. This is the file that you receive back from the translators. It’s a text file that includes the original text and the translations.
MO
MO – Machine Object. The MO file includes the exact same contents as the PO file. The two files differ in their format. While a PO file is a text file and is easy for humans to read, MO files are compiled and are easy for computers to read. The unit gettext implements TMOFile and has several procedures to do the translation from .mo files, if you want to use it.
unit gettext;
...
TMOFile = class
...
procedure GetLanguageIDs(var Lang, FallbackLang: string);
procedure TranslateResourceStrings(AFile: TMOFile);
procedure TranslateUnitResourceStrings(const AUnitName:string; AFile: TMOFile);
procedure TranslateResourceStrings(const AFilename: String);
procedure TranslateUnitResourceStrings(const AUnitName:string; const AFilename: String);Everything else about translations
Here is all the translation material that was here in the past. There are a lot of articles about translations that can cause trouble to novices. To keep it simple this other material has been moved to: Everything else about translations. Please keep this article as clean as possible.
See also
- IDE Development: Translations, i18n, lrt, po files
- Getting translation strings right
- Translating/Internationalization/Localization
- Step-by-step instructions for creating multi-language applications
- Embedding po files into the executable
From the Free Pascal wiki, page "Translations / i18n / localizations for programs", as the Internet Archive kept it on 2025-03-23, last changed on 2024-08-09. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.
Edited on wiki.freepascal.org by 23 people, 2007–2021
From the official wiki's backup of 26 May 2024: who edited this page there, and when. Edits made there after that date were not recorded, and the earlier versions are not shown here; the main page says why.
| When | Who | What changed |
|---|---|---|
| Mattias2 | New page: ==Overview== This is about how a program can use different strings for various languages like english, chinese, german, finnish, italian, ... . Basically it works like this: Add a ''resou... | |
| Mattias2 | Overview | |
| Mattias2 | .po Files | |
| Mattias2 | IDE options for automatic updates of .po files | |
| Mattias2 | IDE options for automatic updates of .po files | |
| Junior | ||
| Junior | Overview: added template | |
| Junior | Translating | |
| Mattias2 | IDE options for automatic updates of .po files | |
| Mattias2 | Translating at start of program | |
| Mattias2 | Future work / ToDos | |
| Mattias2 | Future work / ToDos | |
| Mattias2 | Future work / ToDos | |
| GMorris | Future work / ToDos | |
| Mattias2 | Translating at start of program | |
| Luca | How to actually translate form elements | |
| Mattias2 | Future work / ToDos | |
| Mattias2 | Translating the IDE | |
| Jesusrmx | IDE options for automatic updates of .po files: duplicates, fuzzy items | |
| Vincent | Remove of Obsolete entries: typo | |
| Vincent | Duplicate entries | |
| Vincent | Fuzzy entries | |
| Mattias2 | Overview | |
| Mattias2 | Related topics | |
| Maxim | Translating Forms, Datamodules and Frames: - DefaultTranslator supports .po file since 0.9.29 | |
| Chronos | ||
| Chronos | ||
| Maxim | Translating | |
| BigChimp | .po Files (minor) | |
| BigChimp | .po Files: Added virtaal info | |
| BigChimp | Remove of Obsolete entries (minor) | |
| BigChimp | Fuzzy entries: typos, grammar (minor) | |
| Mattias2 | Translating at start of program | |
| Ggeldenhuys | Translating at start of program: corrected the syntax highlighter (minor) | |
| Vincent | Text replace - "delphi>" to "syntaxhighlight>" (minor) | |
| Vincent | Text replace - "Delphi>" to "syntaxhighlight>" (minor) | |
| Vincent | Text replace - "pascal>" to "syntaxhighlight>" (minor) | |
| Jhusak | Fuzzy entries (minor) | |
| BigChimp | Link (minor) | |
| BigChimp | (minor) | |
| BigChimp | Translating: wording, layout of note | |
| Leledumbo | Translating Forms, Datamodules and Frames: update LANG to make it look as variable (as how it should be) due to misinterpretation by readers, update DefaultTranslator capability to look for .po also | |
| Jwdietrich | Compiling po files into the executable | |
| Jwdietrich | Cross-platform method to determine system language | |
| SagePtr | Changed TranslateUnitResourceStrings to Translations.TranslateUnitResourceStrings (exists in Gettext unit too, but takes other parameters). (minor) | |
| Arent | .po Files | |
| Windsurferme | .po Files | |
| Yuichiro Takahashi | ||
| Yuichiro Takahashi | (minor) | |
| Bart | Compiling po files into the executable: Alternative example to avoid crash in Lazarus 1.2 and earlier | |
| Bart | Compiling po files into the executable | |
| Bart | Compiling po files into the executable: Language (minor) | |
| Bart | Compiling po files into the executable | |
| Windsurferme | See also | |
| BigChimp | Translators (minor) | |
| Mattias2 | Translators | |
| Mattias2 | fixed typo | |
| Gillou58 | Translators | |
| 007 | Compiling po files into the executable: using fpc resources | |
| 007 | FPC Resources (Recommended) (minor) | |
| 007 | ||
| 007 | Overview | |
| 007 | Compiling into .po files (minor) | |
| 007 | Automatic translation (minor) | |
| 007 | Automatic translation (minor) | |
| 007 | Quick i18n: testing translations | |
| 007 | Testing translations: command line parameters form IDE | |
| 007 | Testing translations | |
| 007 | Quick i18n (minor) | |
| 007 | Quick i18n (minor) | |
| 007 | Quick i18n (minor) | |
| 007 | Automatic translation: missing text | |
| 007 | Automatic translation: final steps | |
| 007 | Final steps | |
| 007 | Final steps (minor) | |
| 007 | Final steps | |
| 007 | BiDiMode | |
| 007 | Everything else about translations | |
| 007 | Additional info | |
| 007 | Format Settings | |
| 007 | BiDiMode | |
| Arent | ||
| 007 | BiDiMode: Updated code to work in trunk | |
| Trev | Fixed syntax highlighting; typos (minor) | |
| Roland57 | (minor) | |
| Dbannon | looking for language files | |
| 007 | Quick i18n | |
| Trev | See also: Add explicit link to "everything else" for this subject |
Talk about this page
Nobody has opened a bench for this page yet. Sign in to open one.
