focustense / StardewUI

UI/widget library for Stardew modding
MIT License
5 stars 1 forks source link

Internationalized attributes #28

Closed focustense closed 2 weeks ago

focustense commented 1 month ago

Technically, all i18n can be achieved by simply using the models, but in writing the docs/examples, I see a lot of scenarios in which it would be more convenient to write i18n strings in the templates themselves.

A hypothetical syntax would be similar to attribute bindings, e.g.

<label text={#ModDescription} />

Or perhaps a more explicit:

<label text={i18n:ModDescription} />

Note that although this is technically possible because every ViewEngine does have direct access to the IModHelper and therefore its TranslationHelper, we have to be very careful about how it behaves in any but the most typical scenarios, for example the <include> element, which is potentially using a template provided by a different mod, but not rendering it with that mod's ViewEngine instance.

It might be possible to work around this by storing the translation helper with the registration, since it is the IViewEngine that registers asset paths as well. But this will also only work for views registered in exactly that way, and not e.g. view assets registered through a Content Patcher mod, which should be supported even if it's not quite as nice (i.e. no hot reload).

Other solutions, like using mod-qualified i18n names ("i18n:author.ModName:key") have their own set of footguns, for example implying that any i18n key from anywhere could be used when in fact it's only the specific mods that are using the StardewUI framework and have registered with the API.

This might require some research and experimentation to get exactly right; I don't have a perfect design in mind at this time, and will update the issue later if/when I think of one.

focustense commented 2 weeks ago

My still somewhat tentative conclusion is that there is only one way to provide an experience that will be consistent and not horribly confusing or full of landmines:

  1. Unqualified string IDs are always assumed to belong to whichever mod is providing the view. If a mod-mod replaces an entire view, and wants to reference strings from the original mod, then it has to qualify those IDs. This means keeping track of which mod ID was used to load a view.

  2. Qualified IDs have to be able to read translations from any mod that's installed, regardless of whether or not the target mod uses StardewUI. Otherwise, it's just going to be too unpredictable, and we'll eventually land in situations where (for example) a mod decides to stop using StardewUI and suddenly a whole bunch of interpolations break, even though the mod is still installed.

I don't like i18n: as a prefix. Yes, it's used in Content Patcher. It's also overlong, inconsistent with StarML's style everywhere else, easy to mistake with the string interpolations used in content patcher which aren't supported, and not even really the correct term (entire products are "internationalized"; individual strings are "translated" or "localized").

While # does seem suggestive of "number", so do $ and %, both of which feel less natural, and & or ! just seem weird. So I think I'll go with the hash. It's no more or less arbitrary than @ for an asset, users will have to look it up one time and then they'll know.