ludic/packages/ludic.i18n
2026-09-30 02:58:13 +03:00
..
tests ludic.i18n: the English path is out of L (26.9) - a plain string is drawn as it is in every language (a player named Settings stays Settings), a key, a key glued into text and a bracketed line are made as before. The pattern tables, the sentence and padding lookups, Ln, i18n_pattern_count and kr_words' English-argument lookup are gone; a language's .po is read for keys and plurals. Tests move to keys; README and a changeset say so. 2026-09-30 02:58:13 +03:00
bytes.ludic feat(packages): ludic.i18n - gettext languages from a shipped list and a player's folder, exact lines, patterns whose holes are translated in turn, paragraphs a sentence at a time, plurals by Plural-Forms, X-Font atlases through a port 2026-09-25 08:20:46 +03:00
index.ludic ludic.i18n: the English path is out of L (26.9) - a plain string is drawn as it is in every language (a player named Settings stays Settings), a key, a key glued into text and a bracketed line are made as before. The pattern tables, the sentence and padding lookups, Ln, i18n_pattern_count and kr_words' English-argument lookup are gone; a language's .po is read for keys and plurals. Tests move to keys; README and a changeset say so. 2026-09-30 02:58:13 +03:00
keyed.ludic ludic.i18n: keys (phase 26.1) - en.po as the base, tr/trf/trn marked strings made into text by L, keyed plurals, the fallback to English then the key ([[key]] loud in a dev build), the English form beside it 2026-09-29 23:16:12 +03:00
keyed_args.ludic ludic.i18n: the English path is out of L (26.9) - a plain string is drawn as it is in every language (a player named Settings stays Settings), a key, a key glued into text and a bracketed line are made as before. The pattern tables, the sentence and padding lookups, Ln, i18n_pattern_count and kr_words' English-argument lookup are gone; a language's .po is read for keys and plurals. Tests move to keys; README and a changeset say so. 2026-09-30 02:58:13 +03:00
keyed_render.ludic ludic.i18n: the English path is out of L (26.9) - a plain string is drawn as it is in every language (a player named Settings stays Settings), a key, a key glued into text and a bracketed line are made as before. The pattern tables, the sentence and padding lookups, Ln, i18n_pattern_count and kr_words' English-argument lookup are gone; a language's .po is read for keys and plurals. Tests move to keys; README and a changeset say so. 2026-09-30 02:58:13 +03:00
keys.ludic ludic.i18n: inside a bracket an argument's bytes ride raw - trf escapes a 27 or 31 only outside brackets, and the decoder unescapes only there, so a bracketed line carrying a key with holes (Ada's brief: its legend line's escaped arguments) keeps its own escapes whichever way it was put in (a game's txt_key raw, or trf). 81e1f7d8 unescaped inside the bracket and split the legend's arguments out of the brief. nest_test holds a key whose hole holds a key with two holes: bare, bracketed raw, bracketed through trf, and escaped. 2026-09-30 02:00:20 +03:00
langs.ludic ludic.i18n: a language's lookups kept once read; switching back restores them 2026-09-29 12:21:53 +03:00
mixed.ludic ludic.i18n: the English path is out of L (26.9) - a plain string is drawn as it is in every language (a player named Settings stays Settings), a key, a key glued into text and a bracketed line are made as before. The pattern tables, the sentence and padding lookups, Ln, i18n_pattern_count and kr_words' English-argument lookup are gone; a language's .po is read for keys and plurals. Tests move to keys; README and a changeset say so. 2026-09-30 02:58:13 +03:00
nest.ludic ludic.i18n: a line bracketed inside another (bytes 29 .. 30) is made by L itself - each bracket outermost in, a key whole through keyed() so its escaped arguments stay whole, and a split on 31 never inside a bracket (a game's txt_key puts its nested line raw); a stray bracket draws nothing. The game's tx_L did this alone, so L in a test or anywhere else drew the brackets (26.9's move, made now). nest_test holds it. 2026-09-30 01:39:44 +03:00
package.ludic feat(packages): ludic.i18n - gettext languages from a shipped list and a player's folder, exact lines, patterns whose holes are translated in turn, paragraphs a sentence at a time, plurals by Plural-Forms, X-Font atlases through a port 2026-09-25 08:20:46 +03:00
plural.ludic ludic.i18n: the English path is out of L (26.9) - a plain string is drawn as it is in every language (a player named Settings stays Settings), a key, a key glued into text and a bracketed line are made as before. The pattern tables, the sentence and padding lookups, Ln, i18n_pattern_count and kr_words' English-argument lookup are gone; a language's .po is read for keys and plurals. Tests move to keys; README and a changeset say so. 2026-09-30 02:58:13 +03:00
po.ludic ludic.ui, ludic.i18n: frame_allocs to 0 - a wrap, an ellipsis, a tooltip's lines, a text-shadow's colour and a range's value kept by what made them; pointer events from a ring; inline text joined through the memo; the pool's and the state's lists through ui_kept; parse, memo miss, pool miss, lazy start and template errors declared; the translation cache clears in place 2026-09-28 16:41:47 +03:00
ports.ludic ludic.i18n: the English path is out of L (26.9) - a plain string is drawn as it is in every language (a player named Settings stays Settings), a key, a key glued into text and a bracketed line are made as before. The pattern tables, the sentence and padding lookups, Ln, i18n_pattern_count and kr_words' English-argument lookup are gone; a language's .po is read for keys and plurals. Tests move to keys; README and a changeset say so. 2026-09-30 02:58:13 +03:00
README.md ludic.i18n: the English path is out of L (26.9) - a plain string is drawn as it is in every language (a player named Settings stays Settings), a key, a key glued into text and a bracketed line are made as before. The pattern tables, the sentence and padding lookups, Ln, i18n_pattern_count and kr_words' English-argument lookup are gone; a language's .po is read for keys and plurals. Tests move to keys; README and a changeset say so. 2026-09-30 02:58:13 +03:00
state.ludic ludic.i18n: the English path is out of L (26.9) - a plain string is drawn as it is in every language (a player named Settings stays Settings), a key, a key glued into text and a bracketed line are made as before. The pattern tables, the sentence and padding lookups, Ln, i18n_pattern_count and kr_words' English-argument lookup are gone; a language's .po is read for keys and plurals. Tests move to keys; README and a changeset say so. 2026-09-30 02:58:13 +03:00
tables.ludic ludic.i18n: the English path is out of L (26.9) - a plain string is drawn as it is in every language (a player named Settings stays Settings), a key, a key glued into text and a bracketed line are made as before. The pattern tables, the sentence and padding lookups, Ln, i18n_pattern_count and kr_words' English-argument lookup are gone; a language's .po is read for keys and plurals. Tests move to keys; README and a changeset say so. 2026-09-30 02:58:13 +03:00
translate.ludic ludic.i18n: the English path is out of L (26.9) - a plain string is drawn as it is in every language (a player named Settings stays Settings), a key, a key glued into text and a bracketed line are made as before. The pattern tables, the sentence and padding lookups, Ln, i18n_pattern_count and kr_words' English-argument lookup are gone; a language's .po is read for keys and plurals. Tests move to keys; README and a changeset say so. 2026-09-30 02:58:13 +03:00
use.ludic ludic.i18n: the English path is out of L (26.9) - a plain string is drawn as it is in every language (a player named Settings stays Settings), a key, a key glued into text and a bracketed line are made as before. The pattern tables, the sentence and padding lookups, Ln, i18n_pattern_count and kr_words' English-argument lookup are gone; a language's .po is read for keys and plurals. Tests move to keys; README and a changeset say so. 2026-09-30 02:58:13 +03:00

ludic.i18n

A game in any language, from gettext files anyone can add. The code names text by KEYS, never by its English: a key says what a text is FOR (pause.resume), en.po says what it says in English, and every other language is a .po keyed the same way. Text is made at the moment it is drawn, so a line that reaches the screen is covered wherever it was built. Uses nothing - not even ludic.base; the font atlas and the mod folder are the game's, through a port.

import "ludic.i18n"
i18n_use("tr")                                     # from settings; the atlas follows
ov_text(x, y, 16, L(tr(k"pause.resume")), ...)     # "Resume"; "Devam" in Turkish
ov_text(x, y, 16, L(trf(k"hud.day", `{day}`, "", "", "")), ...)
ov_text(x, y, 16, L(trn(kn"pack.items", n, "", "", "")), ...)

Keys

A key travels as a string with a marker byte in front (the compiler's k"pause.resume" is exactly that; kn"..." a plural key), so code that makes text never takes the language's state: the text is made where it is drawn, by L.

  • A key's text is the language in use's, else en.po's (read from the languages' directory the first time a key is asked for), else the key itself - [[key]] in a developer's build (i18n_loud), said once.
  • Holes {1} .. {4} take trf's arguments in the language's own order, and a translation may reorder or drop them; an argument that is a key is made into its text first. A plural's count is {1}, and its form is the language's Plural-Forms rule's.
  • A key's line inside another's hole survives: an argument's own separators are escaped outside brackets, and a line bracketed with bytes 29 .. 30 (a game's nested line) rides raw and is made first, outermost in.
  • Anything without a marker is drawn as it is, in every language: a player's name, a chat line, a number, a path. There is no lookup by English words, so a player named "Settings" stays "Settings". A key glued into such text ("Photo: " + tr(k"...")) is still made where it sits, an interim help for code on its way to a key of its own.

Where languages come from

Later ones replace earlier ones with the same code:

  • <dir>/languages.txt - the ones that ship, one code per line (# a comment), each <dir>/<code>.po.
  • every *.po in the mod folder the port names - a player drops a file in and picks it. No build.

X-Language-Name in the header is what a menu shows; X-Font names a font atlas directory beside the .po, for a script the default atlas does not carry; Plural-Forms picks the plural rule. A language that lacks a key draws its English, so a partial file is always playable.

Config and port

i18n_config(dir, default_font)                      # "assets/lang", "assets/kit/font" unless said
port I18nWorld {
  mod_dir: fn() -> string          # a player's own .po files; "" none (the default)
  forced: fn() -> string           # a code that wins over the one asked for (a test); "" none
  font_ready: fn() -> bool         # is there an overlay to load an atlas into (default no)
  set_font: fn(string) -> bool     # load that atlas directory
}

API

L(s) -> string what the game draws, in the language in use (made once per distinct line, kept)
tr(k: Key), trf(k: Key, a, b, c, d), trn(k: Key, n, a, b, c) -> string a key (k"..."), a key with its holes' arguments, a plural key (kn"...") by n: made into text by L
i18n_key(name), i18n_key_plural(name), key_text(k), i18n_is_key(s) a key named at run time, its name without the marker, whether a string is one
i18n_base_text(text), i18n_loud(on) the base (en.po) from text, for a test; a developer's build's loud missing key
i18n_init(), i18n_count(), i18n_index(code), i18n_code_at(i), i18n_name_at(i), i18n_font_at(i), i18n_mod_dir() the languages found, "en" first
i18n_use(code), i18n_off(), i18n_on(), i18n_current() choosing one; whether anything is translating
i18n_font_base(dir), i18n_font_now() the atlas the overlay was opened with, and the one it has now
i18n_load_text(text), i18n_parse(text) -> []PoEntry, i18n_header(text, field) a .po from text, outright
i18n_exact_count(), i18n_plural_rule(), i18n_plural_form(rule, n), PL_* what the file gave
i18n_find, i18n_starts, i18n_ends the byte helpers, for a game that wants them

Tests

ludic test packages/ludic.i18n

keys_test: keys, holes, plurals, a key glued into text, plain text as it is. nest_test: lines inside lines, bare, bracketed and escaped. i18n_test: a shipped list and a mod folder in the temp directory, a language's keys, plurals (a Russian-shaped rule), the font and its fallback, a mod replacing a shipped code, a forced code.