Latest Posts

Topic: Untranslatable strings

SirVer
Joined: 2009-02-19, 15:18
Posts: 1440
Ranking
One Elder of Players
Location: Germany - Munich
Posted at: 2013-10-20, 22:52

Just fyi, I just added a wrapper for ngettext into our lua implementation - the only thing missing therefore should be the string extraction (if i understand correctly). No promises when I get around to that, but you should be all let to fix the Lua stuff. Let me know when something is not working as intended.


Top Quote
GunChleoc
Avatar
Joined: 2013-10-07, 15:56
Posts: 3276
Ranking
One Elder of Players
Location: RenderedRect
Posted at: 2013-10-21, 08:32

Busy indexing nil values

Top Quote
GunChleoc
Avatar
Joined: 2013-10-07, 15:56
Posts: 3276
Ranking
One Elder of Players
Location: RenderedRect
Posted at: 2013-10-21, 08:57

SirVer wrote:

Öhh... I have no idea how we can implement that frankly. I think gettext assumes that the same sentence in english is also always the same sentence in other languages. But I have not enough experience to say if this is always true and the case.

Don't scratch your head, you can't, unless you want to implement language-specific rules for every language on the planet that has Sandhi effects or other grammatical interaction between the placeholder and the rest of the string. A lot of it could be taken care of by a gender and case marking system like the people at OpenTTD implemented, but I think such a thing would be too much work here - I haven't come across heaps of problematic strings so far.

The only way around this we have at the moment is not to use a placeholder, but to have some string duplication instead. I went ahead and did this for my example string. There is only a finite number of militarysites units can occupy. So, if translators use a tool with a translation memory like Virtaal, it won't be that much extra translation work: just grab the string suggestion, add the name of the militarysite and do any grammatical adjustments that might be needed.

Another way might be to split the string in a different place, but is doesn't work in this case, because the idiomatic way to translate "occupied your" for my language is something like "took up residence in your", so we have a complete grammar mismatch - furthermore, I don't think we would get any string reuse out of this one anyway.

To make a long story short, we might do some redesign of individual strings though, but only if translators flag up problems.

BTW German has problems with this particular placeholder as well because of gender; the current translation is:

Deine Soldaten haben dein(e) %s belegt.`

And what we need is:

Deine Soldaten haben dein Wachhaus / dein__e__ Barracke / dein__en__ Spähturm belegt.

So, German will benefit from this change as well face-smile.png

Edited: 2013-10-21, 08:59

Busy indexing nil values

Top Quote
GunChleoc
Avatar
Joined: 2013-10-07, 15:56
Posts: 3276
Ranking
One Elder of Players
Location: RenderedRect
Posted at: 2013-10-21, 09:45

SirVer wrote:

  • Added string.bformat which wraps boost::format - as discussed.

Could you please give me a usage example? I tried this:

    descr[#descr+1] = (_"  %1$s (%2$i P) x %3$i = %4$i P<br>"):bformat(
        ware, value, count, lpoints
    )

in scripting/win_conditions/02_collectors.lua with and without the $, and the result is a crash:

Writing Scripting Data ... PANIC: unprotected error in call to Lua API
(Attempt to persist a C function)

ETA: I get this crash with any game type. Do we have a bug here?

Edited: 2013-10-21, 09:56

Busy indexing nil values

Top Quote
SirVer
Joined: 2009-02-19, 15:18
Posts: 1440
Ranking
One Elder of Players
Location: Germany - Munich
Posted at: 2013-10-21, 10:38

Yes, we do have a bug. Sorry for not properly testing this - it was a quick implementation yesterday before going to bed. It is fixed in the current version, please try again.

Note that you will not be able to load safe games from trunk or any other version of Widelands with the current version.


Top Quote
GunChleoc
Avatar
Joined: 2013-10-07, 15:56
Posts: 3276
Ranking
One Elder of Players
Location: RenderedRect
Posted at: 2013-10-21, 15:23

Thanks, it is running now. I am unable to get the system to grab a translation though. I have verified that win_conditions.mo gets updated from the .po file by fiddling with another string.

This is my code in 02_collectors.lua:

    descr[#descr+1] = (_"  %1$s (%2$i P) x %3$i = %4$i P<br>"):bformat(
        ware, value, count, lpoints
    )

And my entry in the message catalog:

msgid "  %1$s (%2$i P) x %3$i = %4$i P<br>"
msgstr "  reversed string? %4$i = %3$i x (%2$i P) %1$sP<br>"

Busy indexing nil values

Top Quote
SirVer
Joined: 2009-02-19, 15:18
Posts: 1440
Ranking
One Elder of Players
Location: Germany - Munich
Posted at: 2013-10-22, 07:22

probably just the wrong text domain. try adding

   set_textdomain("win_conditions")

at the beginning of the lua function that calculates the points. Was needed for me, but works now.


Top Quote
GunChleoc
Avatar
Joined: 2013-10-07, 15:56
Posts: 3276
Ranking
One Elder of Players
Location: RenderedRect
Posted at: 2013-10-22, 08:46

Yes, that was it. So, the text domain will need to be set for each Lua function instead of just once for each script file.


Busy indexing nil values

Top Quote
SirVer
Joined: 2009-02-19, 15:18
Posts: 1440
Ranking
One Elder of Players
Location: Germany - Munich
Posted at: 2013-10-22, 09:53

It is not quite that easy. All of Lua shares one textdomain - you can set it with set_textdomain() and it will be set till the next time any Lua code changes it again. You can not rely that the text_domain stays set. That is why I introduced the pattern of *_texts.lua files - the strings are translated when this file is run and the text stays in memory (translated) for the rest of the game. This has its warts too though - it means that if you save a game and ship it to a friend who has another language, the texts stay in your language.

Nevertheless, I think this pattern is best - gettext is a quite expensive operation as one can see when profiling Widelands (some parts, like the statistics do not remember the translated text and retranslate them every frame and this shows in the profile). Therefore, the right course of Action would be to pull the strings into a table at the top of the file that is translated as the game starts and then never again.


Top Quote
GunChleoc
Avatar
Joined: 2013-10-07, 15:56
Posts: 3276
Ranking
One Elder of Players
Location: RenderedRect
Posted at: 2013-10-22, 10:47

Nevertheless, I think this pattern is best - gettext is a quite expensive operation as one can see when profiling Widelands (some parts, like the statistics do not remember the translated text and retranslate them every frame and this shows in the profile). Therefore, the right course of Action would be to pull the strings into a table at the top of the file that is translated as the game starts and then never again.

That will be fine for the bformat stuff, but not for ngettext, because ngettext needs the value of a variable at runtime to pull the correct version of the string from the catalog. I could try pushing the textdomain call farther down though when it's only used in one branch of a conditional statement.


Busy indexing nil values

Top Quote