Wiki copymirror

This is a mirror of the wiki at pascal.chat. Editing, history and sign-in are there.

Using resourcestrings

Bahasa Indonesia · English · Español · Русский

Resource strings provide a mechanism to internationalize (and to some degree localize) your application.

rationale

Resource strings are constants with an extra level of indirection. The default value (as written in your source code) is stored in the executable program. That means it is always available, even if loading the translation fails.

common steps

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:

delphi
program helloWorld(input, output, stdErr);
resourceString
    hello = 'Hello world';
begin
    writeLn(hello);
end.

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):

json
{
  "version": 1,
  "strings": [
    {
      "hash": 20229140,
      "name": "helloworld.hello",
      "sourcebytes": [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100],
      "value": "Hello world"
    }
  ]
}

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.

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.

GNU get text

limitations

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.

procedure

  1. Convert the .rsj file into GNU gettext’s portable object format:

    bash
    rstconv -f po -i helloWorld.rsj -o helloWorld.po
  2. Create a working copy of the generated file, e. g.

    bash
    cp helloWorld.po helloWorld-de.po

    and translate it with your favorite translation tool or simply with a text editor.

msgid "Hello world" msgstr "Hallo Welt"

  1. Convert the PO file to an MO (machine object) file using gettext’s utility msgfmt:
    bash
    msgfmt -o helloWorld-de.mo helloWorld-de.po
  2. Integrate gettext in your program:

uses

   gettext;

resourceString

   hello = 'Hello world';

begin

   translateResourceStrings('helloWorld-%s.mo');
   writeLn(hello);

end.

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.

  1. Run the program and celebrate your achievement:
    bash
    LANG='de_DE.UTF-8' ./helloWorld

For more details see the gettext unit documentation.

resource DLLs

The FPC’s standard RTL does not yet contain portable functions for loading texts from resource DLLs containing translations (as Delphi does), but the first step would be:

  1. Convert the .rsj file into a resource compiler script:
    bash
    rstconv -f rc -i helloWorld.rsj -o helloWorld.rc

message files

The FPC currently does not support this, but the first step would be:

  1. Convert the .rsj file in an IBM OS/2 message file:

    bash
    rstconv -f msg -c HWX -i helloWorld.rsj -o helloWorld.msg

    The component identifier indicated by ‑c may be any three upper-case [[ASCII]] letters, but it should be unique within your project.

alternatives

To implement another mechanism, 3 things are needed:

  1. Update rstconv so it can output another format.
  2. Tools to manipulate the other format.
  3. Implement a unit that loads the other format at run-time.

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.

history

Formerly, the FPC created text files ending in .rst. While changing to the JSON format, the name of the rstconv utility was preserved. rstconv can still convert .rst files.

text
# hash value = 20229140
helloworld.hello='Hello world'

see also


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.

Revision 1, last changed by WikiArchive .