Internationalization/translation function

Revision as of 07:20, 8 June 2006 by Trosim (Talk | contribs) (Changed escape character)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)


Introduction

The problem for the translation is that we need a way to translate three different types of string:

  • normal strings
"A normal string"
  • composed string
"A string composed by " + count.out + " strings, like this or " + a_string + "%N"
  • strings with plural form
if n = 1 then
     Result := "a string"
 else
     Result := "strings"
 end

Another problem is that not all languages have the same rules for plural forms, see below and here for more details.

Possible solution

I propose a solution, with four functions (I've got little fantasy for the function names):

i18n(a_string: STRING_GENERAL): STRING_32
    -- Function for the translation of normal strings
 
i18n_pl(strings: TUPLE[STRING_GENERAL]; form: INTEGER): STRING_32
    -- Function for the translation of normal strings
    -- with plural form
 
i18n_comp(a_string: STRING_GENERAL; args: TUPLE): STRING_32
    -- Function for the translation of composit strings
 
i18n_comp_pl(strings: TUPLE[STRING_GENERAL]; args: TUPLE; form: INTEGER): STRING_32
    -- Function for the translation of composit
    -- strings with plural forms

With this solution, the programmer should write composit strings as (or in a similar way) he would do for the C printf function. The composit string above would be something like this:

i18n_comp("A string composed by $1 strings, like this or $2%N", [count, a_string])

where $1 is the place where the first string in the argument tuple (here count) has to go. I've choosen that the items in the argument tuple are of type ANY, to insert them in the string we have to apply the functon out to all items.

An example

A complete example of how it could work.


Piece of code without internationalization:

[...]
if n = 1
io.put_string("Remove file " + file_name.out + "?%N")
else
io.put_string ("Delete following files?" + list.out + " there are "
                + list.count.out + "files%N")
end
[...]



Piece of code with internationalization:

[...]
io.put_string(i18n_comp_pl(["Remove file $1?%N",
                "Delete following files? $2 there are $3 files%N"],
                [file_name, list, list_count], n))
[...]

the content of the PO file would be:

#: A comment
msgid "Remove file $1?%N"
msgid_plural "Delete following files? $2 there are $3 files%N"
msgstr[0] "Rimuovere il file $1?"
msgstr[1] "Cancellare i seguenti file? $2 ce ne sono $3%N"

You might ask yourself, why a function for all the pluralforms?

The number of plural forms differ between languages. This is somewhat surprising for those who only have experiences with Romanic and Germanic languages since here the number is the same (there are two). But other language families have only one form or many forms. For example,

In Polish the translation of file is plik, and the plural forms are:

2,3,4 pliki
5-21 pliko'w
22-24 pliki
25-31 pliko'w
and so on...

for more information about this topic go here

Additional things

A nice thing we could do, when parsing the source code of a program to internationalize, is to recognize comments about the string. For example:

[...]
io.put_string(i18n_comp_pl(["Remove file $1?%N",
                "Delete following files? $2 there are $3 files%N"],
                [file_name, list, list_count], list_count))
-- A comment of the author
[...]

would then look like this in the PO file:

#. A comment of the author
#. Function name, class name, file path
#. $1 = file_name
#. $2 = list
#. $3 = list_count
msgid "Remove file $1?%N"
msgid_plural "Delete following files? $2 there are $3 files%N"
msgstr[0] "Rimuovere il file $1?"
msgstr[1] "Cancellare i seguenti file? $2 ce ne sono $3%N"