Latest Posts

Topic: Preparing for translation

kaputtnik
Avatar
Topic Opener
Joined: 2013-02-18, 20:48
Posts: 2537
OS: Archlinux
Version: current master
Ranking
One Elder of Players
Location: Germany
Posted at: 2023-12-29, 13:10

Some questions about preparing for translation:

npgettext, example:

settings_window:get_child("spinbox_label").text = _("Investigate around the ") .. npgettext("around player position:", "player position:", "player positions:", count)

Do the arguments to npgettext also need the translation function _("text")? E.g.: npgettext("around player position:", _("player position:"), _("player positions:"), count)


What about such a construct (total_gr, granite and marble are numbers):

-- TRANSLATORS: Word or sign which means approximately. Keep it short.
local ca = _("ca. ")

text_tmp = text_tmp .. p(_("As Resources: "))
                       .. li_arrow(total_gr .. _(" granite ") .. _(" or "))
                       .. li_arrow(ca .. granite .. _(" granite ")
                       .. _(" and ") .. ca .. marble .. _(" marble")
                       )

Will it be sufficient to add a translators comment with an example of the resulting text? Or should each row be a separate translation string?


I have also a function that turns a fields table to a string:

-- TRANSLATORS: Sign between coordinates like 54/56
local field_sep = _("/")

function get_field_string(f)
   return f.x .. field_sep .. f.y
end

Does this need special treating because of the numbers? E.g. using bformat?


Top Quote
Nordfriese
Avatar
Joined: 2017-01-17, 18:07
Posts: 2046
OS: Debian Testing
Version: Latest master
Ranking
One Elder of Players
Location: 0x55555d3a34c0
Posted at: 2023-12-29, 15:35

kaputtnik wrote:

Some questions about preparing for translation:

npgettext, example:

~~~~ settings_window:get_child("spinbox_label").text = _("Investigate around the ") .. npgettext("around player position:", "player position:", "player positions:", count) ~~~~

Do the arguments to npgettext also need the translation function _("text")? E.g.: npgettext("around player position:", _("player position:"), _("player positions:"), count)

No, ngettext already is the translation function. Translating the arguments again will not work.

Note that string concatenation for translatable texts will lead to grammar errors in languages with a different syntax. Just use one very long ngettext call with the complete text, e.g.

settings_window:get_child("spinbox_label").text = npgettext("around_player_position", "Investigate around the player position:", "Investigate around the player positions:", count)

Also note that we don't usually use ngettext at all just to distinguish singular and plural (and just add a TRANSLATORS comment to let us know if someone needs plural forms), and only use ngettext if the actual number is part of the text.


What about such a construct (total_gr, granite and marble are numbers):

~~~~ -- TRANSLATORS: Word or sign which means approximately. Keep it short. local ca = _("ca. ")

text_tmp = text_tmp .. p(("As Resources: ")) .. li_arrow(total_gr .. (" granite ") .. (" or ")) .. li_arrow(ca .. granite .. (" granite ") .. (" and ") .. ca .. marble .. (" marble") ) ~~~~

Will it be sufficient to add a translators comment with an example of the resulting text? Or should each row be a separate translation string?

Again, please no string concatenations, instead use something like

_("ca. %1$s granite and ca. %2$s marble"):bformat(granite, marble)

If a translatable string contains leading or trailing whitespace, you're always doing something wrong.


I have also a function that turns a fields table to a string:

~~~~ -- TRANSLATORS: Sign between coordinates like 54/56 local field_sep = _("/")

function get_field_string(f) return f.x .. field_sep .. f.y end ~~~~

Does this need special treating because of the numbers? E.g. using bformat?

Again, yes, use return _("%1$d/%2$d"):bformat(f.x, f.y)

When in doubt, always prefer bformat over concatenation.


Top Quote
kaputtnik
Avatar
Topic Opener
Joined: 2013-02-18, 20:48
Posts: 2537
OS: Archlinux
Version: current master
Ranking
One Elder of Players
Location: Germany
Posted at: 2023-12-29, 15:52

Many thanks!

Is this snipped correct?

p(join_sentences(_("For a description of the table columns look at"), a(_("this post in the widelands forum"), "url", "https://www.widelands.org/forum/post/41426/")))

Top Quote
Nordfriese
Avatar
Joined: 2017-01-17, 18:07
Posts: 2046
OS: Debian Testing
Version: Latest master
Ranking
One Elder of Players
Location: 0x55555d3a34c0
Posted at: 2023-12-29, 19:39

No, join_sentences can be used only for two separate sentences; splitting a sentence into two halves will cause grammar errors. For example in German this concatenation would become "Für eine Beschreibung der Tabellenspalten sieh bitte an / diesen Beitrag im Widelands-Forum" – sounds awkward, the "an" should be moved to the end of the sentence.

join_sentences is just a simple wrapper around _("%1$s %2$s"):bformat(arg1, arg2). In your example just use bformat directly too:

p(
    -- TRANSLATORS: Placeholder is "this post in the Widelands forum"
    _("For a description of the table columns look at %s"):bformat(a(
    -- TRANSLATORS: Will be inserted into "For a description of the table columns look at %s"
    _("this post in the Widelands forum"),
    "url", "https://www.widelands.org/forum/post/41426/")))

Top Quote
kaputtnik
Avatar
Topic Opener
Joined: 2013-02-18, 20:48
Posts: 2537
OS: Archlinux
Version: current master
Ranking
One Elder of Players
Location: Germany
Posted at: 2023-12-30, 10:06

Thanks again!

Hopefully i applied most of those preparations now. There are two places where some more text is shown. According to the documentation (Handling long strings) they should be split into shorter parts. For one i did this:

local note1 = _("Calculating all the data for a whole map can take some time and needs round about 1.5 GB free memory for really big maps, like Europe v1.2.")
local note2 = _("The Editor does not react for this time!")
local note3 = _("If you are sure click the button below and be patient …")
settings_window:get_child("whole_map_hint").text=rt(
                                          p(note1)..
                                          p_font("color=ff9999", note2)..
                                          p(note3)
                                          )

I think for the second place of long text splitting is not needed?

p(_("Note that especially the amount for fish is misleading, because each field of water has a default amount of fish and fishers can fish only at the shore. This might be fixed in an other version of this add-on."))

Last question: Do translators need to know if a string is shown as a header? For the header of table columns i added a translators comment, but for other strings i am not sure.


Top Quote
Nordfriese
Avatar
Joined: 2017-01-17, 18:07
Posts: 2046
OS: Debian Testing
Version: Latest master
Ranking
One Elder of Players
Location: 0x55555d3a34c0
Posted at: 2023-12-30, 12:57

Yes those examples look right.

Splitting for long strings is only necessary for reeeaaaally long texts, as in hundreds of words, and then the real point is that such a text should be better split into several paragraphs; Transifex offers fuzzy string matching so a small change in a long text does not force the translator to type the entire text again.

Whether a text is used as a header is usually not relevant, but adding TRANSLATORS comments to explain how and where a string is used can never hurt face-wink.png


Top Quote
kaputtnik
Avatar
Topic Opener
Joined: 2013-02-18, 20:48
Posts: 2537
OS: Archlinux
Version: current master
Ranking
One Elder of Players
Location: Germany
Posted at: 2024-01-20, 12:20

I have a string (tool tip) which is defined for three editboxes: "Enter coordinates in form of x, y"

I do not know if all three strings appear on transifex, although they are equal and one translation would fit. Do a translator has to translate the same string three times? Is it better to define this string only one time? E.g. make one variable out of it and use this variable for the three editboxes?


Top Quote
Nordfriese
Avatar
Joined: 2017-01-17, 18:07
Posts: 2046
OS: Debian Testing
Version: Latest master
Ranking
One Elder of Players
Location: 0x55555d3a34c0
Posted at: 2024-01-20, 14:53

Identical strings only appear once on Transifex, unless you explicitly disambiguate them with pgettext.

For long strings that are used many times, a variable can still be useful to keep consistency if you ever want to change the phrasing or spelling, but for such a short string used in only 3 places this is not a concern and would IMHO only make the code less readable.


Top Quote
kaputtnik
Avatar
Topic Opener
Joined: 2013-02-18, 20:48
Posts: 2537
OS: Archlinux
Version: current master
Ranking
One Elder of Players
Location: Germany
Posted at: 2024-10-14, 15:55

Another question:

I have a function that turns milliseconds to hh:mm:ss and returns the fomatted string:

         -- Format milliseconds to a string like 02:22:30 
         local function _format_time(ms)

            if ms == nil then return "-" end

            local hh = (ms // (60 * 60 * 1000)) % 24
            local mm = (ms // (60 * 1000)) % 60
            local ss = (ms // 1000) % 60

            --TRANSLATORS: This is a time string in form of hh:mm:ss
            return _("%1$02d:%2$02d:%3$02d"):bformat(hh, mm, ss)
         end

When using this returned string, i guess this needs no translation anymore, but i am not sure. E.g.:

 p(_("%1$s"):bformat(_format_time(wl.Game().time)))    -- is this superfluous?

 p(_format_time(wl.Game().time))                       -- this should be sufficient, shouldn't it?

Top Quote
Nordfriese
Avatar
Joined: 2017-01-17, 18:07
Posts: 2046
OS: Debian Testing
Version: Latest master
Ranking
One Elder of Players
Location: 0x55555d3a34c0
Posted at: 2024-10-14, 18:18

It is quite superfluous, although it does no harm.

"%s":bformat(arg) simply returns arg. And any translator will translate the string "%1$s" simply as "%1$s". So this is a no-op.

P.S. "-" should have pgettext translation markup though.

Edited: 2024-10-14, 18:19

Top Quote