Sign in Join
Wiki copytemporary

Using resourcestrings: what changed

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

Title: Using resourcestrings

OldNewLine
1+Resource strings provide a mechanism to internationalize (and to some degree localize) your application.
2+
3+## rationale
4+
5+Resource strings are constants with an extra level of indirection. The default value (as written in your [[Source code|source code]]) is stored in the executable program. That means it is always available, even if loading the translation fails.
6+
7+## common steps
8+
9+The first step is to *use* resource strings for every string that potentially needs translation. In this tutorial we want to internationalize our Hello World program:
10+
11+```delphi
12+program helloWorld(input, output, stdErr);
13+resourceString
14+ hello = 'Hello world';
15+begin
16+ writeLn(hello);
17+end.
18+```
19+
20+The [[FPC]] creates a file ending in `.rsj` (resource string [[JSON]]) for every compiled module containing a `resourceString` section. For the above program it looks like this (pretty-format added):
21+
22+``` json
23+{
24+ "version": 1,
25+ "strings": [
26+ {
27+ "hash": 20229140,
28+ "name": "helloworld.hello",
29+ "sourcebytes": [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100],
30+ "value": "Hello world"
31+ }
32+ ]
33+}
34+```
35+
36+This intermediate file format was created, so the compiler does not need any knowledge of the utilized translation tool. It just needs to create `.rsj` files.
37+
38+The following steps differ on the used internationalization mechanism. As of 2021 the FPC only supports [[GNU]] gettext entirely. The reason gettext was chosen is that it is more or less standard on Unix-like systems, like [[Linux]] or [[FreeBSD]].
39+
40+## GNU get text
41+
42+### limitations
43+
44+As mentioned, GNU gettext is widely available on Unix-like systems. However, gettext is horribly inefficient. Also, gettext is context insensitive, that means it operates on the string itself: Sometimes the same word/sentence must be translated differently according to the context, but this is not possible.
45+
46+### procedure
47+
48+1. Convert the `.rsj` file into GNU gettext’s portable object format:
49+ ``` bash
50+ rstconv -f po -i helloWorld.rsj -o helloWorld.po
51+ ```
52+2. Create a working copy of the generated file, e. g.
53+ ``` bash
54+ cp helloWorld.po helloWorld-de.po
55+ ```
56+
57+ and translate it with your favorite translation tool or simply with a text editor.
58+
59+msgid "Hello world" msgstr "Hallo Welt"
60+
61+1. Convert the PO file to an MO (machine object) file using gettext’s utility `msgfmt`:
62+ ``` bash
63+ msgfmt -o helloWorld-de.mo helloWorld-de.po
64+ ```
65+2. Integrate gettext in your program:
66+
67+uses
68+
69+`   gettext;`
70+
71+resourceString
72+
73+`   hello = 'Hello world';`
74+
75+begin
76+
77+`   translateResourceStrings('helloWorld-%s.mo');`\
78+`   writeLn(hello);`
79+
80+end.
81+
82+The `%s` is substituted with the locale’s name. Examining an `strace` you will see, that for example first `helloWorld‑de.mo` is attempted to open. If it does not exist, it tries `helloWorld‑de_DE.mo`. If neither file exists, the resource string’s default values as specified in your source code are used.
83+
84+1. Run the program and celebrate your achievement:
85+ ``` bash
86+ LANG='de_DE.UTF-8' ./helloWorld
87+ ```
88+
89+For more details see the [gettext unit documentation](https://www.freepascal.org/docs-html/fcl/gettext/index.html).
90+
91+## resource DLLs
92+
93+The FPC’s standard RTL does not yet contain portable functions for loading texts from resource [[DLL|DLLs]] containing translations (as [[Delphi]] does), but the first step would be:
94+
95+1. Convert the `.rsj` file into a resource compiler script:
96+ ``` bash
97+ rstconv -f rc -i helloWorld.rsj -o helloWorld.rc
98+ ```
99+
100+## message files
101+
102+The FPC currently does not support this, but the first step would be:
103+
104+1. Convert the `.rsj` file in an IBM OS/2 message file:
105+ ``` bash
106+ rstconv -f msg -c HWX -i helloWorld.rsj -o helloWorld.msg
107+ ```
108+
109+ The component identifier indicated by `‑c` may be any three upper-case [[ASCII]] letters, but it should be unique within your project.
110+
111+## alternatives
112+
113+To implement another mechanism, 3 things are needed:
114+
115+1. Update rstconv so it can output another format.
116+2. Tools to manipulate the other format.
117+3. Implement a unit that loads the other format at [[runtime|run-time]].
118+
119+[[Routine|Routines]] to directly manipulate a program’s resource string tables, i. e. the extra level of indirection for resource strings, were available in the objpas unit [until revision 31687](https://gitlab.com/freepascal.org/fpc/source//commit/4494565a154b1c6b313c9ddc3a09f7102719c5b3).
120+
121+## history
122+
123+Formerly, the FPC created text files ending in `.rst`. While changing to the JSON format, the name of the [`rstconv` utility](https://www.freepascal.org/docs-html/user/userse45.html) was preserved. `rstconv` can still convert `.rst` files.
124+
125+```text
126+# hash value = 20229140
127+helloworld.hello='Hello world'
128+```
129+
130+## see also
131+
132+- [[Step-by-step instructions for creating multi-language applications]]
133+
134+---
135+*From the Free Pascal wiki, page "Using resourcestrings", as it stood on 2022-01-25 after a change by Kai Burghardt, 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).*
136+Category: Tutorials

Back to history