Difference between revisions of "Internationalization/translation function"

m (Introduction)
(Changed escape character)
 
(7 intermediate revisions by 3 users not shown)
Line 1: Line 1:
[[Category:Projects]]
 
 
[[Category:Internationalization]]
 
[[Category:Internationalization]]
  
Line 9: Line 8:
 
  <code>[eiffel,N] "A normal string"</code>
 
  <code>[eiffel,N] "A normal string"</code>
 
* composed string  
 
* composed string  
  <code>[eiffel,N] "A string composed by "+count.out+" strings, like this or "+a_string+"%N"</code>
+
  <code>[eiffel,N] "A string composed by " + count.out + " strings, like this or " + a_string + "%N"</code>
 
* strings with plural form
 
* strings with plural form
 
<code>[eiffel,N]
 
<code>[eiffel,N]
  if n=1 then
+
  if n = 1 then
 
     Result := "a string"
 
     Result := "a string"
 
  else
 
  else
    Result := "strings"
+
    Result := "strings"
 
  end
 
  end
 
</code>
 
</code>
Line 26: Line 25:
  
 
<code>[eiffel,N]
 
<code>[eiffel,N]
i18n (a_string : STRING) : STRING
+
i18n(a_string: STRING_GENERAL): STRING_32
     --Function for the translation of normal strings
+
     -- Function for the translation of normal strings
  
i18n_pl (strings : TUPLE[STRING]; form : INTEGER) : STRING
+
i18n_pl(strings: TUPLE[STRING_GENERAL]; form: INTEGER): STRING_32
     --Function for the translation of normal strings
+
     -- Function for the translation of normal strings
 
     -- with plural form
 
     -- with plural form
  
i18n_comp (a_string : STRING; args : TUPLE) : STRING
+
i18n_comp(a_string: STRING_GENERAL; args: TUPLE): STRING_32
     --Function for the translation of composit strings
+
     -- Function for the translation of composit strings
  
i18n_comp_pl (strings : TUPLE[STRING]; args : TUPLE; form : INTEGER) : STRING
+
i18n_comp_pl(strings: TUPLE[STRING_GENERAL]; args: TUPLE; form: INTEGER): STRING_32
     --Function for the translation of composit
+
     -- Function for the translation of composit
 
     -- strings with plural forms
 
     -- strings with plural forms
 
</code>
 
</code>
  
With this solution, the programmer should write composit strings as (or in a similar way) he would do it for the C ''printf'' function. The composit string above would be somthing like this:
+
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:
  
<code>[eiffel,N] i18n_comp("A string composed by %a1 strings, like this or %a2%N", [count, a_string])
+
<code>[eiffel,N] i18n_comp("A string composed by $1 strings, like this or $2%N", [count, a_string])
 
</code>
 
</code>
  
where ''%a1'' is the place where the first string in the argument tuple (here ''count'') has to go. I've [[Talk:Internationalization/translation_function|'''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.
+
where ''$1'' is the place where the first string in the argument tuple (here ''count'') has to go. I've [[Talk:Internationalization/translation_function|'''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===
 
===An example===
Line 59: Line 58:
 
[...]
 
[...]
 
if n = 1
 
if n = 1
io.put_string("Remove file "+file_name.out+"?%N")
+
io.put_string("Remove file " + file_name.out + "?%N")
 
else
 
else
io.put_string ("Delete following files?"+list.out+" there are "
+
io.put_string ("Delete following files?" + list.out + " there are "
                 +list.count.out+"files%N")
+
                 + list.count.out + "files%N")
 
end
 
end
 
[...]
 
[...]
Line 76: Line 75:
  
 
[...]
 
[...]
io.put_string(["Remove file %a1?%N",
+
io.put_string(i18n_comp_pl(["Remove file $1?%N",
                 "Delete following files? %a2 there are %a3 files%N"],
+
                 "Delete following files? $2 there are $3 files%N"],
                 [file_name, list, list_count], n)
+
                 [file_name, list, list_count], n))
 
[...]
 
[...]
 
</code>
 
</code>
Line 85: Line 84:
  
 
  #: A comment
 
  #: A comment
  msgid "Remove file %a1?%N"
+
  msgid "Remove file $1?%N"
  msgid_plural "Delete following files? %a2 there are %a3 files%N"
+
  msgid_plural "Delete following files? $2 there are $3 files%N"
  msgstr[0] "Rimuovere il file %a1?"
+
  msgstr[0] "Rimuovere il file $1?"
  msgstr[1] "Cancellare i seguenti file? %a2 ce ne sono %a3%N"
+
  msgstr[1] "Cancellare i seguenti file? $2 ce ne sono $3%N"
  
 
You might ask yourself, ''why a function for all the pluralforms''?
 
You might ask yourself, ''why a function for all the pluralforms''?
Line 107: Line 106:
 
==Additional things==
 
==Additional things==
  
A nice thing whe could do, when parsing the source code of a program to internationalize, is to recognize comments about the string.
+
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:
 
For example:
  
Line 113: Line 112:
  
 
[...]
 
[...]
io.put_string(["Remove file %a1?%N",
+
io.put_string(i18n_comp_pl(["Remove file $1?%N",
                 "Delete following files? %a2 there are %a3 files%N"],
+
                 "Delete following files? $2 there are $3 files%N"],
                 [file_name, list, list_count], n)
+
                 [file_name, list, list_count], list_count))
--A comment of the author
+
-- A comment of the author
 
[...]
 
[...]
 
</code>
 
</code>
  
woud then look like this in the PO file:
+
would then look like this in the PO file:
  
 
  #. A comment of the author
 
  #. A comment of the author
 
  #. Function name, class name, file path
 
  #. Function name, class name, file path
  #. %a1 = file_name
+
  #. $1 = file_name
  #. %a2 = list
+
  #. $2 = list
  #. %a3 = list_count
+
  #. $3 = list_count
  msgid "Remove file %a1?%N"
+
  msgid "Remove file $1?%N"
  msgid_plural "Delete following files? %a2 there are %a3 files%N"
+
  msgid_plural "Delete following files? $2 there are $3 files%N"
  msgstr[0] "Rimuovere il file %a1?"
+
  msgstr[0] "Rimuovere il file $1?"
  msgstr[1] "Cancellare i seguenti file? %a2 ce ne sono %a3%N"
+
  msgstr[1] "Cancellare i seguenti file? $2 ce ne sono $3%N"

Latest revision as of 07:20, 8 June 2006


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"