LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Rseding91
Factorio Staff
Factorio Staff
Posts: 13218
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by Rseding91 »

Zeblote wrote:Anyways, this topic was about accessing the localized text in mods.

Where exactly is the problem with determinism, assuming we have the following:

- player variable that has the locale he is using
- method to get localized text given a specific string and locale
- event that runs when a player changes locale
Locale doesn't have to be identical on all peers.

You can make a mod that changes/adds locale and use it in MP without any other peers having to have that mod.
If you want to get ahold of me I'm almost always on Discord.

User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by aubergine18 »

Sync .cfg files amongst peers?
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.

User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by aubergine18 »

Another example of a mod stymied by not being able to get actual translations for text - the search feature in "What does it do?" mod can only search on locale keys, not the translated names of items etc. viewtopic.php?p=210544#p210544
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.

Coppermine
Long Handed Inserter
Long Handed Inserter
Posts: 79
Joined: Sat May 06, 2017 11:25 am
Contact:

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by Coppermine »

aubergine18 wrote:Another example of a mod stymied by not being able to get actual translations for text - the search feature in "What does it do?" mod can only search on locale keys, not the translated names of items etc. viewtopic.php?p=210544#p210544
I've been working on some improvements to What Is It Used For and hit both the problems listed in this thread. I wanted to be able to sort by localised name and filter by localised name, and both are impossible.

So I just wanted to add my voice to this request.

If we can't request a particular string in a particular locale because not all players need to have the same locales installed then perhaps we can have a function to get the English localised name? That would still be better than what we have now. There are quite a lot of items where the internal name is quite different from the English localised name (e.g. mods often add prefixes for namespacing, which ruins sort order).

User avatar
mickael9
Fast Inserter
Fast Inserter
Posts: 112
Joined: Mon Mar 14, 2016 4:04 am
Contact:

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by mickael9 »

Coppermine wrote:If we can't request a particular string in a particular locale because not all players need to have the same locales installed then perhaps we can have a function to get the English localised name? That would still be better than what we have now. There are quite a lot of items where the internal name is quite different from the English localised name (e.g. mods often add prefixes for namespacing, which ruins sort order).
English locale is like any other: it can be modified by the client and be different than the server's version which would cause desyncs.

Here is my proposal for a sortable & filterable table which would solve the problem: viewtopic.php?f=28&t=48164

sparr
Smart Inserter
Smart Inserter
Posts: 1329
Joined: Fri Feb 14, 2014 5:52 pm
Contact:

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by sparr »

Proposed solution over in viewtopic.php?f=28&t=59296

Coppermine
Long Handed Inserter
Long Handed Inserter
Posts: 79
Joined: Sat May 06, 2017 11:25 am
Contact:

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by Coppermine »

Just to keep track of all the threads in one place, here's another: viewtopic.php?f=28&t=57945

Coppermine
Long Handed Inserter
Long Handed Inserter
Posts: 79
Joined: Sat May 06, 2017 11:25 am
Contact:

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by Coppermine »

In case anyone missed it, this is now possible (and has been for a while now) thanks to this addition to the API.

I just finished implementing localized string filtering for What is it Really Used For?, and it seems to work great. Thanks, devs!

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

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by eradicator »

Coppermine wrote:
Mon Jan 27, 2020 10:25 am
In case anyone missed it, this is now possible (and has been for a while now) thanks to this addition to the API.

I just finished implementing localized string filtering for What is it Really Used For?, and it seems to work great. Thanks, devs!
Care to share a few details about the implementation? In particular how many requests do you dispatch at once? Or how long does it take to finish translation of a heavily modded game on a not-so-great connection etc?
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.

Coppermine
Long Handed Inserter
Long Handed Inserter
Posts: 79
Joined: Sat May 06, 2017 11:25 am
Contact:

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by Coppermine »

eradicator wrote:
Mon Jan 27, 2020 10:55 am
Care to share a few details about the implementation? In particular how many requests do you dispatch at once? Or how long does it take to finish translation of a heavily modded game on a not-so-great connection etc?
You can of course look at the code. I just set up a memoised function that requests a translation if it's not already locally cached. It requests all the translations the first time you try to filter the list, so I suspect there might be a noticeable hiccup the first time each player uses the filter, but hopefully it should be fast after that.

I haven't tested on a multiplayer game.

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

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by eradicator »

Coppermine wrote:
Mon Jan 27, 2020 11:36 am
eradicator wrote:
Mon Jan 27, 2020 10:55 am
Care to share a few details about the implementation? In particular how many requests do you dispatch at once? Or how long does it take to finish translation of a heavily modded game on a not-so-great connection etc?
You can of course look at the code. I just set up a memoised function that requests a translation if it's not already locally cached. It requests all the translations the first time you try to filter the list, so I suspect there might be a noticeable hiccup the first time each player uses the filter, but hopefully it should be fast after that.

I haven't tested on a multiplayer game.
In that case i can tell you that it won't work in multiplayer. I tested the "request everything at once" approach myself before and it basically becomes impossible for anyone to join multiplayer servers even though it works fine in singleplayer.
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.

Coppermine
Long Handed Inserter
Long Handed Inserter
Posts: 79
Joined: Sat May 06, 2017 11:25 am
Contact:

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by Coppermine »

eradicator wrote:
Mon Jan 27, 2020 12:43 pm
In that case i can tell you that it won't work in multiplayer. I tested the "request everything at once" approach myself before and it basically becomes impossible for anyone to join multiplayer servers even though it works fine in singleplayer.
Thanks for the warning. Can you point me to any established best practices that have been found effective?

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

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by eradicator »

Coppermine wrote:
Mon Jan 27, 2020 11:37 pm
eradicator wrote:
Mon Jan 27, 2020 12:43 pm
In that case i can tell you that it won't work in multiplayer. I tested the "request everything at once" approach myself before and it basically becomes impossible for anyone to join multiplayer servers even though it works fine in singleplayer.
Thanks for the warning. Can you point me to any established best practices that have been found effective?
If i knew those i wouldn't have asked you how your implementation works ;). My guess is that nobody has done enough testing yet.
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.

Helfima
Fast Inserter
Fast Inserter
Posts: 199
Joined: Tue Jun 28, 2016 11:40 am
Contact:

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by Helfima »

my mod has been using the function for several months and no one reported a problem on this feature

for each player
1) I build a set of all localised string
2) I request translate for all localised string in a loop (https://github.com/Helfima/helmod/blob/ ... r.lua#L422)
3) I listen the event on_string_translated (https://github.com/Helfima/helmod/blob/ ... r.lua#L292 , https://github.com/Helfima/helmod/blob/ ... r.lua#L642)

https://mods.factorio.com/mods/Helfima/helmod

Coppermine
Long Handed Inserter
Long Handed Inserter
Posts: 79
Joined: Sat May 06, 2017 11:25 am
Contact:

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by Coppermine »

I did indeed have some reports of multiplayer issues with requesting all the translations at once. So in WIIRUF version 1.5.6 I throttled the requests to 100 at a time (that is, 100 per keypress in the search box) and that seems to have resolved the issue. It does mean that the very first time any player searches they may not get all the results they expect, but it was a reasonable quick fix.

It would probably be better to do the rate-limiting based on time rather than keypresses, but this was much simpler. Ideally someone should probably roll all this into some standard library code (if they haven't already).

Helfima
Fast Inserter
Fast Inserter
Posts: 199
Joined: Tue Jun 28, 2016 11:40 am
Contact:

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by Helfima »

Me i push all values by step of 100 on few tick before display the result

https://github.com/Helfima/helmod/blob/ ... r.lua#L399

if you see the next function you can see the waiting

User avatar
raiguard
Factorio Staff
Factorio Staff
Posts: 452
Joined: Wed Dec 13, 2017 8:29 pm
Contact:

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by raiguard »

Coppermine wrote:
Mon Mar 09, 2020 12:11 pm
Ideally someone should probably roll all this into some standard library code (if they haven't already).
I spent a lot of time writing and rewriting a translation module that I use in my mods. It rate-limits to 50 translations per tick, and that's total - if two players are doing translations at once, it'll do 25 per player. It also supports multiple dictionaries being translated simultaneously, and even creates and manages a /retranslate-all-dictionaries command that will cause any mods using it to retranslate their dictionaries (assuming they're set up to do so).

It does depend on my lualib's event module, but could fairly easily be made to work standalone.

Usage is very simple:

Code: Select all

local function do_translations(player)
  local translation_data = {
    {internal="iron-ore", localised={"item-name.iron-ore"}},
    {internal="copper-ore", localised={"item-name.copper-ore"}},
    -- etc...
  }

  translation.start(player, 'ores', translation_data)
end

-- later on, somewhere
script.on_event(translation.finish_event, function(e)
  global.players[e.player_index].dictionary = {
    lookup = e.lookup,
    sorted_translations = e.sorted_translations,
    translations = e.translations
  }
end
EXAMPLE OUTPUT:

Code: Select all

lookup = {
  ["Iron ore"] = {"iron-ore"},
  ["Copper ore"] = {"copper-ore"}
}
sorted_translations = {
  "Copper ore",
  "Iron ore",
}
translations = {
  ["iron-ore"] = "Iron ore",
  ["copper-ore"] = "Copper ore"
}
(lookup values are arrays in the case that multiple different internal names have the same translation)

The way that this module is meant to be used is to run when a player first joins a game. You prevent usage of your GUI until the translations are finished, store the translations in global, then enable use of your GUI. In your search loop, you can simply use the data stored in global.

Right now it's designed to retranslate whenever a player re-joins a game. However, I'm considering changing this behavior since most people probably don't change languages all that often. In the case that they do, they can retranslate all dictionaries using the /retranslate-all-dictionaries command.

TL;DR: I made a library to do this, you can use it if you like.
Don't forget, you're here forever.

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

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by eradicator »

After just looking at your examples... can your library handle these cases?

a) *different* translations for {'item-name.copper-ore'} and {'entity-name.copper-ore'} (recipe-name, etcpp).

b) Compound localised strings like {'__1__ blabla', {'item-name.copper-ore'}} (i.e. fluid barrels)

Also would you mind sharing how did you arrived at the solution of limiting per tick instead of per batch? (i.e. independant of network latency)

(Also thanks for sharing really! 50~100 batch size is at least a good starting point.)
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.

User avatar
raiguard
Factorio Staff
Factorio Staff
Posts: 452
Joined: Wed Dec 13, 2017 8:29 pm
Contact:

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by raiguard »

eradicator wrote:
Sun Apr 12, 2020 1:20 am
After just looking at your examples... can your library handle these cases?

a) *different* translations for {'item-name.copper-ore'} and {'entity-name.copper-ore'} (recipe-name, etcpp).

b) Compound localised strings like {'__1__ blabla', {'item-name.copper-ore'}} (i.e. fluid barrels)

Also would you mind sharing how did you arrived at the solution of limiting per tick instead of per batch? (i.e. independant of network latency)

(Also thanks for sharing really! 50~100 batch size is at least a good starting point.)
a) Yes. When you're giving it stuff to translate, the "internal" name can be whatever you want. So you can differentiate between recipes and items easily. You could also put them into entirely separate dictionaries if you want (that's what I do).

b) Also yes. It supports any localised strings you throw at it.

c) I'm not sure what you mean? The library has an array of localised strings that it needs to translate for every player. On every tick, it runs through the next n amount of translations, then saves the position where it ended. Then on the next tick it picks back up and does the next batch. Network latency has never been an issue, it just works.

I made a script to test it with while I was developing it, you can view it here to see how I used it.
Don't forget, you're here forever.

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

Re: LuaPlayer.translate( LocalisedString ), LuaPlayer.locale

Post by eradicator »

Raiguard wrote:
Sun Apr 12, 2020 3:55 am
c) I'm not sure what you mean? The library has an array of localised strings that it needs to translate for every player. On every tick, it runs through the next n amount of translations, then saves the position where it ended. Then on the next tick it picks back up and does the next batch. Network latency has never been an issue, it just works.
That's just "theorycrafting" on my part. There's two possible implementation: a) the one you use that sends stuff in fixed intervals and b) one that waits until the result of the previous request arrives before sending off the next one. Not having done any extensive testing i was merely curious if you had evidence that makes one of them universally better than the other. On further thought a continous data stream (a) is probably better even if latency is high.
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.

Post Reply

Return to “Implemented mod requests”