Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commit3bb1da2647

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:

  1. the player's choice (i18n.choose), kept on the device for their ZeroMind account, or for the signed-out player;
  2. the language ZeroMind shows the player (the zeromindLocale boot argument ZeroMind's page passes, or the desktop --zeromind-locale);
  3. the platform's preferred languages, most preferred first;
  4. 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 of available when 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 }; choiceKept is device, or run in 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

platformsourcechanges reach the engine
LinuxLANGUAGE, LC_ALL, LC_MESSAGES, LANGat boot
Windows, macOSthe user's language listat boot and when the window regains focus
browsernavigator.languageson languagechange
Androidthe activity's configuration locales (the per-app language when set)on the configuration change, without restarting the app