API to extract localised strings for prototypes

Place to ask discuss and request the modding support of Factorio. Don't request mods here.
User avatar
Therax
Filter Inserter
Filter Inserter
Posts: 471
Joined: Sun May 21, 2017 6:28 pm
Contact:

API to extract localised strings for prototypes

Post by Therax »

There are complex rules used by the C++ to determine the correct localised string for a given blueprint.

An entity's name in the world is entity_prototype.localised_name, or if that doesn't exist, then it is {"entity-name.<entity_prototype.name>"}.

If an item has a place result, its localised_name is the localised_name of the placed entity, as determined from the entity prototype using the method above. If it doesn't have a place_result, the localised_name is {"item-name.<item_prototype.name>"}.

If a recipe has a main_product, or it has single result, its localised_name is the localised_name of the result item, as determined using the method above. If the recipe has multiple products defined and no main_product, the localised_name is {"recipe-name".<recipe_prototype.name>}.

The rules are unambiguous but tedious to implement, and it would be nice to have a Lua API somewhere that does the recursive resolution, and returns a LocalizedString suitable for display (i.e. by interpolation in another Localized String).
Miniloader — UPS-friendly 1x1 loaders
Bulk Rail Loaders — Rapid train loading and unloading
Beltlayer & Pipelayer — Route items and fluids freely underground
Rseding91
Factorio Staff
Factorio Staff
Posts: 14339
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: API to extract localised strings for prototypes

Post by Rseding91 »

I'm not sure what specifically you're asking for. The game uses a specific localized name for a specific prototype. If you want a recipe name you call recipe.localized_name.

Unless you mean something else?
If you want to get ahold of me I'm almost always on Discord.
User avatar
Therax
Filter Inserter
Filter Inserter
Posts: 471
Joined: Sun May 21, 2017 6:28 pm
Contact:

Re: API to extract localised strings for prototypes

Post by Therax »

Sorry, this request was particularly badly written. Yes, at control phase prototype.localised_name works great. The original use case was for something that could be used during data phase to generate localised strings based on recipe names.

For example, in base/data-updates.lua, we find this line:

Code: Select all

    localised_name = {"recipe-name.fill-barrel", {"fluid-name." .. fluid.name}},
for automatically generating barrel filling recipes.

This works for fluids because the LocalisedString for fluids is predictable and simple to derive. If a mod wants to create recipes derived from other recipes, such as a "recycling" mod that generates inverse recipes, determining the proper localised_name during the data phase is tricky, and each mod ends up re-implementing the same logic, often incorrectly.

The request is for a Lua function accessible during data phase and maintained by Wube, say in core/lualib or similar, that mirrors the C++ behavior that generates the localised_name for a prototype during prototype compilation which is then available as prototype.localised_name during control phase. This wouldn't be perfect since another mod could modify data between the time this function was called to compute a LocalisedString and the actual compilation of prototypes.

An alternative would be a way to add a form of LocalisedString that would be evaluated by the C++ during prototype compilation. For example, the above might be expressed as:

Code: Select all

localised_name = {"recipe-name.fill-barrel", {type="fluid", name=fluid.name}}
During prototype compilation, this would be replaced by the value of "game.fluid_prototypes[fluid.name].localised_name". In other words, a LocalisedString that could reference a prototype, instead of only being able to directly reference the localization tables. This could break due to circular references which would have to be detected during prototype compilation, however, so I understand if that's not something you're willing to implement.
Miniloader — UPS-friendly 1x1 loaders
Bulk Rail Loaders — Rapid train loading and unloading
Beltlayer & Pipelayer — Route items and fluids freely underground
User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5207
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: API to extract localised strings for prototypes

Post by eradicator »

I once wrote a function to extract the current localized name of an item in data stage. (original post):
eradicator wrote: Here's the hopefully 100% correct version:

Code: Select all

local derived --courtesy of eradicator
  if item.localised_name then
      derived = item.localised_name
  elseif item.place_result then
      derived = 'entity-name.'..item.place_result
  elseif item.placed_as_equipment_result then
      derived = 'equipment-name.'..item.placed_as_equipment_result
  else
      derived = 'item-name.'..item.name
  end
So i can wholeheartedly agree that it would be awesome to not have to guess this myself. (i.e. an official utility function get_localized_name(prototype) -> LocalisedString). Also looking at this and at the fluid-barrel naming function i'd suspect that the fluid barrel recipe doesn't get a correct name if a fluid happens to have a localized_name instead of using fluid-name.fluid-name. I.e. because the fluid itself is procedurally derived from another prototype.
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
Therax
Filter Inserter
Filter Inserter
Posts: 471
Joined: Sun May 21, 2017 6:28 pm
Contact:

Re: API to extract localised strings for prototypes

Post by Therax »

eradicator wrote: Here's the hopefully 100% correct version:

Code: Select all

local derived --courtesy of eradicator
  if item.localised_name then
      derived = item.localised_name
  elseif item.place_result then
      derived = 'entity-name.'..item.place_result
  elseif item.placed_as_equipment_result then
      derived = 'equipment-name.'..item.placed_as_equipment_result
  else
      derived = 'item-name.'..item.name
  end
And even this is incorrect if the entity or equipment declares its own localised_name. This stuff is tricky. :D
Miniloader — UPS-friendly 1x1 loaders
Bulk Rail Loaders — Rapid train loading and unloading
Beltlayer & Pipelayer — Route items and fluids freely underground
User avatar
mrudat
Fast Inserter
Fast Inserter
Posts: 248
Joined: Fri Feb 16, 2018 5:21 am
Contact:

Re: API to extract localised strings for prototypes

Post by mrudat »

Ideally we shouldn't need to do any lookup at all. Instead it should be sufficient to go:

Code: Select all

new_recipe.localised_name = { "", { "description.My prefix" }, { "recipe-name." .. recipe.name } }
and have the runtime lookup what recipe's localised name happens to be, regardless of if the translation for recipe-name.that-item is defined, or if it is in fact a explicit localised_string defined on the entity that's placed by the item that recipe creates.
CaveGrinder
Inserter
Inserter
Posts: 35
Joined: Fri Aug 24, 2018 7:42 pm
Contact:

Re: API to extract localised strings for prototypes

Post by CaveGrinder »

fully agree with this request, it is a major headache to get this correct. An API/Approach in the data stage would be appreciated.

It gets even worse when reusing an entities description: the base game displays nothing if no description is present. yet if you use it in a localized_description (use case is an entity description: "__1__ (Quality level: __2__)", where 1 is supposed to be the entities actual description and 2 is a string from my mod), we get the missing locale error string unless a description exists. only 20% (42 out of 209 in "en") of entities have a description, so the only 100% correct way for me is to hard-code the list of entities for which the base game defines a description(wrongly relying only on the "en" locale file) and only use it when inside this list.
robot256
Filter Inserter
Filter Inserter
Posts: 934
Joined: Sun Mar 17, 2019 1:52 am
Contact:

Re: API to extract localised strings for prototypes

Post by robot256 »

the base game displays nothing if no description is present. yet if you use it in a localized_description ..., we get the missing locale error string unless a description exists
Hey, this is starting to narrow down to something that could be considered a bug! The game treats a missing description entry as blank, but the locale parser treats it as an error. If the parser treated missing entries as blank too, it still wouldn't be perfect (your example would end up with a leading space) but it would be much better.
User avatar
mrudat
Fast Inserter
Fast Inserter
Posts: 248
Joined: Fri Feb 16, 2018 5:21 am
Contact:

Re: API to extract localised strings for prototypes

Post by mrudat »

Worse; for many entity types, a blank description results in an auto-generated description, and there's no way I know of to add to it, you can only replace it.

Edit: fix tyop
bNarFProfCrazy
Fast Inserter
Fast Inserter
Posts: 194
Joined: Sat Apr 23, 2016 7:11 am
Contact:

Re: API to extract localised strings for prototypes

Post by bNarFProfCrazy »

https://gist.github.com/theRustyKnife/4 ... e61affe5ab (WIP) recipe ( + a few others ) -> localised_name

Tested with GDIW + Bobs
Post Reply

Return to “Modding interface requests”