Sign in Join
Wiki copytemporary

Translations / i18n / localizations for programs: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
1-This is about how a program can use different strings for various languages like English, Chinese, German, Finnish, Italian and any other language.
1+This is about how a program can use different strings for various languages like English, Chinese, German, Finnish, Italian and any other language.
22
3-- **i18n** is short for **internationalization** (18 being the number of characters between i and n of the word internationalization)
4-- **l10n** is short for **localization** (10 being the number of characters between l and n of the word localization)
3+ * **i18n** is short for **internationalization** (18 being the number of characters between i and n of the word internationalization)
4+ * **l10n** is short for **localization** (10 being the number of characters between l and n of the word localization)
55
6+
7+
68## Quick i18n
79
8-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]].
10+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]].
911
10-For your information the most used languages in the world ([source](http://www.redlinels.com/2014/01/10/most-widely-spoken-languages/)) are:
12+For your information the most used languages in the world are:
1113
12-- 1 - Chinese: With more than 1.2 billion native speakers in the world
13-- 2 - Spanish: Spanish occupies the No. 2 spot and is spoken in approximately 30 countries.
14-- 3 - English: 335 million worldwide—about 5% of the world’s population. (This does not takes into account second language spoken).
15-- 4 - Hindi: Spoken by over 260 million people.
16-- 5 - Arabic: Spoken in almost 60 countries around the world.
17-- 6 - Portuguese: Population of Brazil is over 200 million. The population of Portugal is just over 10 million.
18-- 7 - Bengali: The main language of Bangladesh (population, 155 million) and one of India’s many official languages.
19-- 8 - Russian and Japanese.
14+ * 1 - Chinese: With more than 1.2 billion native speakers in the world.
15+ * 2 - Spanish: Spanish occupies the 2nd place and is spoken in approximately 30 countries.
16+ * 3 - English: 335 million worldwide, about 5% of the world’s population. (This does not take into account second language spoken).
17+ * 4 - Hindi: Spoken by over 260 million people.
18+ * 5 - Arabic: Spoken in almost 60 countries around the world.
19+ * 6 - Portuguese: Population of Brazil is over 200 million. The population of Portugal is just over 10 million.
20+ * 7 - Bengali: The main language of Bangladesh (population 155 million) and one of India’s many official languages.
21+ * 8 - Russian and Japanese.
2022
2123### poedit
2224
23-The best known tool is a program called [poedit](https://poedit.net/). poedit is a tool for translators. It produces both PO and MO as output.
25+The best known tool is a program called [poedit](<https://poedit.net/>). poedit is a tool for translators. It produces both PO and MO as output.
2426
2527### Translating Forms
2628
27-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.
29+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.
2830
2931### Translating Resourcestrings
3032
31-This is the way to store a resourcestring in a unit:
32-
33-``` pascal
33+This is the way to store a resourcestring in a unit:
34+```
3435resourcestring
35- Caption1 = 'Some text';
36- HelloWorld1 = 'Hello World';
36+ Caption1 = 'Some text';
37+ HelloWorld1 = 'Hello World';
3738```
3839
39-Resourcestrings are like normal string constants, that means you can assign them to any string:
40-
41-``` pascal
40+Resourcestrings are like normal string constants, that means you can assign them to any string:
41+```
4242Label1.Caption := HelloWorld1;
4343```
4444
4545### Compiling into .po files
4646
47-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**.
48-
49-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.
47+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**.
5048
51-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.
49+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.
5250
53-Your folder structure will look something like this:
51+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.
5452
55-```text
53+Your folder structure will look something like this:
54+```
5655project1\po_files\
57-project1\po_files\project1.po
58-project1\po_files\project1.es.po
56+ project1\po_files\project1.po
57+ project1\po_files\project1.es.po
5958```
6059
6160### Converting .po files to .mo files
6261
63-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.
62+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.
6463
65-Note that [[Everything else about translations]] has a section about where a Lazarus app looks for its language files.
64+Note that [[Everything else about translations]] has a section about where a Lazarus app looks for its language files.
6665
6766### Automatic translation
6867
69-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.
70-
71-``` pascal
68+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.
69+```
7270uses
73- DefaultTranslator;
71+ DefaultTranslator;
7472```
7573
76-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.
77-
78-Your folder structure will look something like this:
74+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.
7975
80-```text
76+Your folder structure will look something like this:
77+```
8178project1\project1.exe
82-project1\locale\
83-project1\locale\project1.mo
84-project1\locale\project1.es.mo
79+ project1\locale\
80+ project1\locale\project1.mo
81+ project1\locale\project1.es.mo
8582```
8683
8784### Testing translations
8885
89-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.
90-
91-You must run your executable with the command line parameter **--lang** followed by the language code of your choice.
86+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.
9287
93-You will run your executable like this in order to test Spanish translation:
88+You must run your executable with the command line parameter **\--lang** followed by the language code of your choice.
9489
95-```text
90+You will run your executable like this in order to test Spanish translation:
91+```
9692project1.exe --lang es
9793```
9894
99-And you will see the translated application.
100-
101-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:
95+And you will see the translated application.
10296
103-```text
97+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:
98+```
10499--lang it
105100```
106101
107-Then **Run (F9)** and you will see the translated application.
102+Then **Run (F9)** and you will see the translated application.
108103
109104### Final steps
110105
111-These steps are to get a better result for your entire translation.
106+These steps are to get a better result for your entire translation.
112107
113108#### Translate LCL
114109
115-To get everything translated you must include the LCL translations into your application **locale** folder.
110+To get everything translated you must include the LCL translations into your application **locale** folder.
116111
117-Copy everything inside the folder **C:\lazarus\lcl\languages** to your **locale** folder. Then you will have the LCL translated for your application.
112+Copy everything inside the folder **C:\lazarus\lcl\languages** to your **locale** folder. Then you will have the LCL translated for your application.
118113
119114#### Format Settings
120115
121-For Windows you must read [[Step-by-step instructions for creating multi-language applications|Step-by-step instructions for creating multi-language applications#Format settings]] to get format settings in the right place.
116+For Windows you must read [[Step-by-step instructions for creating multi-language applications|Step-by-step instructions for creating multi-language applications#Format settings]] to get format settings in the right place.
122117
123-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).
118+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).
124119
125120#### BiDiMode
126121
127-[[BidiMode]] is for languages like Arabic that read and write right to left. See also [Script direction and languages](http://www.w3.org/International/questions/qa-scripts.en) for a list of LTR (Left To Right) and RTL (Right To Left) languages and most used languages in general.
128-
129-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).
122+[[BidiMode]] is for languages like Arabic that read and write right to left. See also [Script direction and languages](<http://www.w3.org/International/questions/qa-scripts.en>) for a list of LTR (Left To Right) and RTL (Right To Left) languages and most used languages in general.
130123
131-First save this unit as ubidimodetools.pas:
124+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).
132125
133-``` pascal
126+First save this unit as ubidimodetools.pas:
127+```
134128unit ubidimodetools;
135-
136-{$mode objfpc}{$H+}
137-
138-interface
139-
140-uses
141- Classes, SysUtils;
142-
143-function GetLang: string;
144-function GetBiDiMode: TBiDiMode;
145-
146-implementation
147-
148-uses
149- FileUtil, LCLProc, LazUTF8;
150-
151-function GetLang: string;
152-var
153- T: string; // unused FallBackLang
154- i: integer;
155-begin
156- Result := '';
157- { We use the same method that is used in LCLTranslator unit }
158-
159- for i := 1 to Paramcount - 1 do
160- if (ParamStrUTF8(i) = '--LANG') or (ParamStrUTF8(i) = '-l') or
161- (ParamStrUTF8(i) = '--lang') then
162- Result := ParamStrUTF8(i + 1);
163-
164- //Win32 user may decide to override locale with LANG variable.
165- if Result = '' then
166- Result := GetEnvironmentVariableUTF8('LANG');
167-
168- if Result = '' then
169- LazGetLanguageIDs(Result, {%H-}T);
170-end;
171-
172-function GetBiDiMode: TBiDiMode;
173-begin
174- case GetLang of
175- // Arabic
176- 'ar': Result := bdRightToLeft;
177- else
178- Result := bdLeftToRight;
179- end;
180-end;
181-
182-end.
129+
130+ {$mode objfpc}{$H+}
131+
132+ interface
133+
134+ uses
135+ Classes, SysUtils;
136+
137+ function GetLang: string;
138+ function GetBiDiMode: TBiDiMode;
139+
140+ implementation
141+
142+ uses
143+ FileUtil, LCLProc, LazUTF8;
144+
145+ function GetLang: string;
146+ var
147+ T: string; // unused FallBackLang
148+ i: integer;
149+ begin
150+ Result := '';
151+ { We use the same method that is used in LCLTranslator unit }
152+
153+ for i := 1 to Paramcount - 1 do
154+ if (ParamStrUTF8(i) = '--LANG') or (ParamStrUTF8(i) = '-l') or
155+ (ParamStrUTF8(i) = '--lang') then
156+ Result := ParamStrUTF8(i + 1);
157+
158+ //Win32 user may decide to override locale with LANG variable.
159+ if Result = '' then
160+ Result := GetEnvironmentVariableUTF8('LANG');
161+
162+ if Result = '' then
163+ LazGetLanguageIDs(Result, {%H-}T);
164+ end;
165+
166+ function GetBiDiMode: TBiDiMode;
167+ begin
168+ case GetLang of
169+ // Arabic
170+ 'ar': Result := bdRightToLeft;
171+ else
172+ Result := bdLeftToRight;
173+ end;
174+ end;
175+
176+ end.
183177```
184178
185-When you create a form do this:
186-
187-``` pascal
179+When you create a form do this:
180+```
188181BiDiMode := GetBiDiMode;
189182```
190183
191-**Note:** You must be sure that you have the proper translations in order to get it working.
184+**Note:** You must be sure that you have the proper translations in order to get it working.
192185
193-**Note 2:** Maybe this is not neccesary at all since Windows can change the BiDiMode automatically.
186+**Note 2:** Maybe this is not neccesary at all since Windows can change the BiDiMode automatically.
194187
195188### Technical Details
196189
197190#### gettext
198191
199-The main technology involved in the process of translations is [GNU gettext](https://www.gnu.org/software/gettext/manual/gettext.html). FPC comes with the gettext unit.
200-
201-``` pascal
192+The main technology involved in the process of translations is [GNU gettext](<https://www.gnu.org/software/gettext/manual/gettext.html>). FPC comes with the gettext unit.
193+```
202194uses
203- gettext;
195+ gettext;
204196```
205197
206198#### PO
207199
208-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.
200+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.
209201
210202#### MO
211203
212-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.
213-
214-``` pascal
204+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.
205+```
215206unit gettext;
216-
217-...
218-
219-TMOFile = class
220-
221-...
222-
223- procedure GetLanguageIDs(var Lang, FallbackLang: string);
224- procedure TranslateResourceStrings(AFile: TMOFile);
225- procedure TranslateUnitResourceStrings(const AUnitName:string; AFile: TMOFile);
226- procedure TranslateResourceStrings(const AFilename: String);
227- procedure TranslateUnitResourceStrings(const AUnitName:string; const AFilename: String);
207+
208+ ...
209+
210+ TMOFile = class
211+
212+ ...
213+
214+ procedure GetLanguageIDs(var Lang, FallbackLang: string);
215+ procedure TranslateResourceStrings(AFile: TMOFile);
216+ procedure TranslateUnitResourceStrings(const AUnitName:string; AFile: TMOFile);
217+ procedure TranslateResourceStrings(const AFilename: String);
218+ procedure TranslateUnitResourceStrings(const AUnitName:string; const AFilename: String);
228219```
229220
230221## Everything else about translations
231222
232-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.
223+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.
233224
234225## See also
235226
236-- [[IDE Development|IDE Development: Translations, i18n, lrt, po files]]
237-- [[Getting translation strings right]]
238-- [[Lazarus Documentation|Translating/Internationalization/Localization]]
239-- [[Step-by-step instructions for creating multi-language applications]]
240-- [[Everything else about translations|Embedding po files into the executable]]
227+ * [[IDE Development|IDE Development: Translations, i18n, lrt, po files]]
228+ * [[Getting translation strings right]]
229+ * [[Lazarus Documentation|Translating/Internationalization/Localization]]
230+ * [[Step-by-step instructions for creating multi-language applications]]
231+ * [[Everything else about translations|Embedding po files into the executable]]
241232
242233---
243-*From the Free Pascal wiki, page "Translations / i18n / localizations for programs", as it stood on 2021-01-24 after a change by Trev, out of the wiki's dump of 2024-05-26. 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](/wiki-contact).*
244-Category: Localization
245-Category: Tutorials
234+*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](/wiki-contact).*

Back to history