Creating translatable strings

Discussion of Lua and LuaWML support, development, and ideas.

Moderator: Forum Moderators

Post Reply
CIB
Code Contributor
Posts: 625
Joined: November 24th, 2006, 11:26 pm

Creating translatable strings

Post by CIB »

I'm not sure how to do this.

Obviously: "foo" .. bar .. "baz" is not going to work

Given that V is a WML variable metatable, I tried:

Code: Select all

V.bar = bar
V.message = _ "foo $bar baz"
But oddly, this doesn't seem to do variable substitution immediately, which will cause strings generated in loops to be messy. For example:

Code: Select all

for _, value in ipairs(values) do
 V.value = value
 V.message = V.message .. "List item: $value\n"
end
Would just print the last list item over and over again.

Finally, there's string.format, like

Code: Select all

V.value = string.format(_ "foo %s baz", bar)
But the obvious problem is that if the translated string shuffles variables around, it'll break.
User avatar
8680
Moderator Emeritus
Posts: 742
Joined: March 20th, 2011, 11:45 pm
Location: The past

Re: Creating translatable strings

Post by 8680 »

What about this?

Code: Select all

bar = "..."
s = tostring(_ "foo {bar} baz"): gsub("{([^{}]+)}", _ENV)
It won’t work for WML variables though. It may work for WML variables (and only WML variables) if you replace _ENV with the WML variable metatable, but why use WML variables in Lua?
User avatar
Elvish_Hunter
Posts: 1575
Joined: September 4th, 2009, 2:39 pm
Location: Lintanir Forest...

Re: Creating translatable strings

Post by Elvish_Hunter »

Translatable string are not normal strings, but a special data type. You must cast them with tostring() to use them (with the exception of the .. operator). See http://wiki.wesnoth.org/LuaWML:Display# ... textdomain :

Code: Select all

wesnoth.message(string.format(tostring(_ "You gain %d gold."), amount))
Alternatively, to perform variable substitution with the $ symbol, you can take a look at wesnoth.tovconfig(). See http://wiki.wesnoth.org/LuaWML:Events#wesnoth.tovconfig.
CIB wrote:

Code: Select all

for _, value in ipairs(values) do
 V.value = value
 V.message = V.message .. "List item: $value\n"
end
Also, variable names that start with _ are reserved for constants as a convention. Don't try to use obscure variable names to save typing, or you'll end up typing more to fix bugs (it always happens to me :P ). Replace _ with "index" or "i", even if you don't plan to use it in the for cycle.
Current maintainer of these add-ons, all on 1.16:
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
CIB
Code Contributor
Posts: 625
Joined: November 24th, 2006, 11:26 pm

Re: Creating translatable strings

Post by CIB »

8680 wrote:What about this?

Code: Select all

bar = "..."
s = tostring(_ "foo {bar} baz"): gsub("{([^{}]+)}", _ENV)
It won’t work for WML variables though. It may work for WML variables (and only WML variables) if you replace _ENV with the WML variable metatable, but why use WML variables in Lua?
If this does what I think it does(that's some very compressed code right there), that's an excellent idea and it'll remain compatible with variable re-ordering. And yes, using WML variables was only a workaround and maybe a tribute to translators who are used to that way. :) (The $ syntax, not the origin of the variables)

@Elvish_Hunter: Ahh, I didn't realize that, though I guess that's because for my test cases it didn't matter.
CIB
Code Contributor
Posts: 625
Joined: November 24th, 2006, 11:26 pm

Re: Creating translatable strings

Post by CIB »

Okay, I tried to make life simple on me, but it backfired:

Code: Select all

-- custom textdomain function that'll return a translator that
-- does variable substitution as well as translation
helper.textdomain = function(domain)
	local translator = wesnoth.textdomain(domain)
	return function(str)
		return tostring(translator(str)): gsub("{([^{}]+)}", getfenv(2))
	end
end
_ENV won't work because obviously I need the environment of the caller, and getfenv doesn't exist anymore in lua 5.2. What now?
User avatar
Elvish_Hunter
Posts: 1575
Joined: September 4th, 2009, 2:39 pm
Location: Lintanir Forest...

Re: Creating translatable strings

Post by Elvish_Hunter »

CIB wrote:Okay, I tried to make life simple on me, but it backfired:

Code: Select all

-- custom textdomain function that'll return a translator that
-- does variable substitution as well as translation
helper.textdomain = function(domain)
	local translator = wesnoth.textdomain(domain)
	return function(str)
		return tostring(translator(str)): gsub("{([^{}]+)}", getfenv(2))
	end
end
_ENV won't work because obviously I need the environment of the caller, and getfenv doesn't exist anymore in lua 5.2. What now?
I forgot to say that the only exception to the "no underscore variables" is the translation marker, that must always be the underscore _ .
Try in this way:

Code: Select all

-- #textdomain "my-campaign"
_ = wesnoth.textdomain( "my-campaign" )

local test = wesnoth.get_variable( "my_variable_name" )
wesnoth.message( string.format( tostring( _"Item: %s" ), test ) )
To retrieve a WML variable, instead of complicating it with metatables, just use wesnoth.get_variable, passing the WML variable name as argument. :wink: A different procedure is required for WML arrays, but let's do things one step per time. :)
Then, pass the string with the formatting codes and the translation marker to tostring. This will, in turn, pass the translated string, as well as all the other values for substitution, to string.format. And it won't break if the %s is moved around the translated string, but only in case the translator decided, for some unknown reason, to remove the %s from the .po file.
Current maintainer of these add-ons, all on 1.16:
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
User avatar
8680
Moderator Emeritus
Posts: 742
Joined: March 20th, 2011, 11:45 pm
Location: The past

Re: Creating translatable strings

Post by 8680 »

CIB wrote:_ENV won't work because obviously I need the environment of the caller, and getfenv doesn't exist anymore in lua 5.2. What now?
Here are some more possibilities.
Elvish_Hunter wrote:And it won't break if the %s is moved around the translated string, but only in case the translator decided, for some unknown reason, to remove the %s from the .po file.
What if there are multiple variables to be interpolated, and translation necessitates changing their order?
User avatar
Elvish_Hunter
Posts: 1575
Joined: September 4th, 2009, 2:39 pm
Location: Lintanir Forest...

Re: Creating translatable strings

Post by Elvish_Hunter »

8680 wrote:What if there are multiple variables to be interpolated, and translation necessitates changing their order?
That may be an issue, considering that Lua applies the formatting flags in sequence. In that case, or the translators try to avoid altering the order of the formatting fields (not always possible), or using a series of string.gsub() may become a viable option.
There may be other possible solutions, of course.
Current maintainer of these add-ons, all on 1.16:
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
Post Reply