Builtin Library
README.md
i18n
The player's language: which of a world's languages to show them, the
languages their platform says they read, the locale the engine chose for its
own text, the locales the engine offers, their own choice, and a signal when
any of it changes. The same i18n global in every VM.
local lang = i18n.pick({ "en", "pt", "es" }) -- "pt" for a Brazilian player
i18n.emulate({ "es-MX" }) -- try the world as a Mexican visitor; nil puts this machine's back
print(i18n.locale()) -- "en"
print(i18n.preferred()[1]) -- "pt-BR" on a device set to Portuguese (Brazil)
for _, l in i18n.offered() do print(l.tag, l.nativeName) end
local r = i18n.choose("pt-BR") -- refused unless pt-BR is offered
if not r.ok then log.warn(r.reason) end
local id = i18n.onChange(function(locale, preferred)
log.info(("now %s; platform %s"):format(locale, table.concat(preferred, ",")))
end)
i18n.offChange(id)
How the locale is chosen
One chain, the first link that matches an offered locale deciding:
- the player's choice (
i18n.choose), kept on the device for their ZeroMind account, or for the signed-out player; - the language ZeroMind shows the player (the
zeromindLocaleboot argument ZeroMind's page passes, or the desktop--zeromind-locale); - the platform's preferred languages, most preferred first;
en, the engine's source language.
A link matches an offered locale with the same tag, then one its tag
truncates to (pt-BR-x-abc to pt-BR), then one with the same language
(pt to pt-BR). The engine offers a locale once its manifest is launched,
and it offers en and pt-BR; a player none of whose links matches either
gets en. i18n.sources() names every link and the one that decided.
The chosen locale is also the one the engine names to ZeroMind on its requests
(x-zeromind-locale) and the one the text system picks fallback fonts for.
API
i18n.pick(available) -> string: which of the content's languages the player reads (the first ofavailablewhen none matches).i18n.emulate(tags?) -> { ok, locale?, platform?, reason? }: stand a visitor's language list in; nil reads the platform's own again.i18n.locale() -> string: the chosen locale.i18n.fallback() -> {string}: the chosen locale's fallback chain.i18n.preferred() -> {string}: the platform's preferred languages.i18n.offered() -> {Locale}:{ tag, name, nativeName, fallback }per offered locale.i18n.choice() -> string?: the player's own choice.i18n.choose(tag?) -> { ok, locale?, decidedBy?, reason?, offered? }: choose, or clear with nil.i18n.sources() -> Sources:{ locale, decidedBy, matched, choice, zeromind, platform, signedIn, choiceKept };choiceKeptisdevice, orrunin an offline engine, which keeps a choice for that run alone.i18n.onChange(fn(locale, preferred)) -> id/i18n.offChange(id).
Where the platform list comes from
| platform | source | changes reach the engine |
|---|---|---|
| Linux | LANGUAGE, LC_ALL, LC_MESSAGES, LANG | at boot |
| Windows, macOS | the user's language list | at boot and when the window regains focus |
| browser | navigator.languages | on languagechange |
| Android | the activity's configuration locales (the per-app language when set) | on the configuration change, without restarting the app |