Constructing localized strings in game

Place to get help with not working mods / modding interface.
Post Reply
Pi-C
Smart Inserter
Smart Inserter
Posts: 1653
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Constructing localized strings in game

Post by Pi-C »

I've another localization problem. :-)

Suppose you have these strings defined:

Code: Select all

[strings]
list=You get __1__ as result.
AND=and
That's easy to use if you only want to show one value:

Code: Select all

local a = "an iron gear"
game.print({"", "strings.list", a})
But how about a list composed of variables that may or may not be set?

Code: Select all

local a = entity.get_driver()
if a then a = a. player end
local b = entity.get_passenger()
if b then b = b.player end

local output = ""
if a then output = a end
if a and b then output = output .. ' ' .. {"strings.AND"} .. ' ' end
if b then output = output .. b

game.print({"", "strings.list", output})
I can't get this to work! The best I could achieve was getting wrong output (output would contain literal "strings.AND" instead of localized "and") without crashing the game, the worst was a crash due to trying to concatenate a table when a string was expected. Where is my mistake?
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

User avatar
DaveMcW
Smart Inserter
Smart Inserter
Posts: 3700
Joined: Tue May 13, 2014 11:06 am
Contact:

Re: Constructing localized strings in game

Post by DaveMcW »

Code: Select all

[strings]
list=You get __1__ as result.
AND=__1__ and __2__

Code: Select all

game.print({"strings.list", {"strings.AND", {"item-name.copper-plate"}, {"item-name.iron-plate"}}})

Pi-C
Smart Inserter
Smart Inserter
Posts: 1653
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Constructing localized strings in game

Post by Pi-C »

DaveMcW wrote:
Wed Sep 18, 2019 7:33 am

Code: Select all

[strings]
list=You get __1__ as result.
AND=__1__ and __2__

Code: Select all

game.print({"strings.list", {"strings.AND", {"item-name.copper-plate"}, {"item-name.iron-plate"}}})
That's so easy again … So, I don't have to add the individual pieces to compose one string, but define three different strings (one for "only a", one for "only b", one for "a and b" -- I can't use variables that have no value).

Guess it was getting too late last night, and switching between different Factorio instances (with occasional restarts of both because otherwise the mods' checksums would cause desync) so many times took its toll. Thank you for your help! :-)
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: Constructing localized strings in game

Post by eradicator »

Pi-C wrote:
Wed Sep 18, 2019 6:45 am

Code: Select all

game.print({"", "strings.list", output})
Only the first string in each localised string (==table) is a template, so this would literally print "strings.list".

But so many possibilities to get to your result:

Dynamic composition:

Code: Select all

[strings]
youhave=You have __1__.
and=and

if driver and passenger then
  game.print{"strings.youhave",{"",driver,{"strings.and"},passenger}}
else
  game.print{"strings.youhave",driver or passenger}
  end

By-case templates:

Code: Select all

[strings]
twothing=You have __1__ and __2__
onething=You have __1__  
  
if driver and passenger then
  game.print{"strings.twothing",driver,passenger}
else
  game.print{"strings.onething",driver or passenger}
  end
Pi-C wrote:
Wed Sep 18, 2019 8:38 am
I can"t use variables that have no value).
A localized string is a table, so you can abuse the fact that in lua every undefined element is nil, so adding nil to the end of a table does nothing:

Code: Select all

local lstring = {"","hi "}
local last_name = "foo"
local first_name = nil
table.insert(lstring,"my name is ")
table.insert(lstring,first_name)
table.insert(lstring,last_name)
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.

Pi-C
Smart Inserter
Smart Inserter
Posts: 1653
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Constructing localized strings in game

Post by Pi-C »

eradicator wrote:
Wed Sep 18, 2019 10:15 am
But so many possibilities to get to your result:

Dynamic composition:

Code: Select all

if driver and passenger then
  game.print{"strings.youhave",{"",driver,{"strings.and"},passenger}}
else
  game.print{"strings.youhave",driver or passenger}
  end

I like this one! The "or" saves one ifelse-block, that's more elegant than my current solution.
By-case templates:

Code: Select all

[strings]
twothing=You have __1__ and __2__
onething=You have __1__  
Will definitely work, but means more strings to translate. :-)
Pi-C wrote:
Wed Sep 18, 2019 8:38 am
I can"t use variables that have no value).
A localized string is a table, so you can abuse the fact that in lua every undefined element is nil, so adding nil to the end of a table does nothing:

Code: Select all

local lstring = {"","hi "}
local last_name = "foo"
local first_name = nil
table.insert(lstring,"my name is ")
table.insert(lstring,first_name)
table.insert(lstring,last_name)
That's a neat trick! Basically, it's the same thing I tried to achieve (build the message from individual blocks if these blocks exist), but without any checks required, so it looks much cleaner. Thanks for showing!
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

Post Reply

Return to “Modding help”