ludic.i18n: tr / trf / trn take the compiler's Key (k"...", kn"..." for trn), built from string(k); keys_test with key literals

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-29 23:56:05 +03:00
parent cdaeb33e12
commit 11447b8650
3 changed files with 24 additions and 25 deletions

View file

@ -75,7 +75,7 @@ port I18nWorld {
| --- | --- | | --- | --- |
| `L(s) -> string` | what the game draws, in the language in use (cached) | | `L(s) -> string` | what the game draws, in the language in use (cached) |
| `Ln(one, many, n) -> string` | a count's form, with `{1}` the count; English is one for 1, many otherwise (the old form) | | `Ln(one, many, n) -> string` | a count's form, with `{1}` the count; English is one for 1, many otherwise (the old form) |
| `tr(k)`, `trf(k, a, b, c, d)`, `trn(k, n, a, b, c) -> string` | a key, a key with its holes' arguments, a plural key by `n`: made into text by `L` | | `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_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_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_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 |

View file

@ -1,6 +1,6 @@
# keys.ludic - a key as the game carries it: its text behind a marker byte (the compiler's k"..." is # keys.ludic - a key as the game carries it: the compiler's Key (k"..." is its text behind byte 1, kn"..."
# exactly that), holes as byte 31 then each argument, a plural's count first. Nothing here needs the # behind byte 2), made into a string with holes as byte 31 then each argument, a plural's count first.
# language: the text is made where it is drawn (L), so code that makes text never takes I18nState. # Nothing here needs the language: the text is made where it is drawn (L), never taking I18nState.
export const I18N_KEY: int = 1 # k"pause.resume" is "\\x01pause.resume" export const I18N_KEY: int = 1 # k"pause.resume" is "\\x01pause.resume"
export const I18N_PLURAL: int = 2 # kn"catch.count": a count chooses the form export const I18N_PLURAL: int = 2 # kn"catch.count": a count chooses the form
export const I18N_SEP: int = 31 # between the key and each argument export const I18N_SEP: int = 31 # between the key and each argument
@ -22,16 +22,15 @@ export function key_text(k: string) -> string {
return k[1..e] return k[1..e]
} }
# the text of a key: drawn translated where it is drawn (a free cast once the key is typed) # the text of a key: drawn translated where it is drawn (its marked text, a free cast)
export function tr(k: string) -> string { return k } export function tr(k: Key) -> string { return string(k) }
# a key's text with its holes, {1} .. {4}, filled by strings already made (a number, a name, another key) # a key's text with its holes, {1} .. {4}, filled by strings already made (a number, a name, another key)
export function trf(k: string, a: string, b: string, c: string, d: string) -> string { export function trf(k: Key, a: string, b: string, c: string, d: string) -> string {
var mark = I18N_KEY let s = string(k)
if i18n_is_key(k) { mark = k[0] } return kx_join(I18N_KEY, key_text(s), a, b, c, d, kx_count(a, b, c, d))
return kx_join(mark, key_text(k), a, b, c, d, kx_count(a, b, c, d))
} }
# a plural key's text by n: the count is {1}, a .. c are {2} .. {4} # a plural key's text by n: the count is {1}, a .. c are {2} .. {4}
export function trn(k: string, n: int, a: string, b: string, c: string) -> string { return kx_join(I18N_PLURAL, key_text(k), `{n}`, a, b, c, 1 + kx_count(a, b, c, "")) } export function trn(k: Key, n: int, a: string, b: string, c: string) -> string { return kx_join(I18N_PLURAL, key_text(string(k)), `{n}`, a, b, c, 1 + kx_count(a, b, c, "")) }
function kx_count(a: string, b: string, c: string, d: string) -> int { function kx_count(a: string, b: string, c: string, d: string) -> int {
if len(d) > 0 { return 4 } if len(d) > 0 { return 4 }

View file

@ -32,38 +32,38 @@ program I18nKeysTest {
test "a key is its English under en.po, its own language's text when there is one, else English, else itself" (i18n_st: mut I18nState) { test "a key is its English under en.po, its own language's text when there is one, else English, else itself" (i18n_st: mut I18nState) {
start (i18n_st) start (i18n_st)
expect(L(i18n_st, i18n_key("pause.resume")) == "Resume") expect(L(i18n_st, tr(k"pause.resume")) == "Resume")
expect(L(i18n_st, tr(i18n_key("pause.quit"))) == "Quit") expect(L(i18n_st, tr(k"pause.quit")) == "Quit")
i18n_load_text(i18n_st, tt()) i18n_load_text(i18n_st, tt())
expect(L(i18n_st, i18n_key("pause.resume")) == "Devam") expect(L(i18n_st, tr(k"pause.resume")) == "Devam")
expect(L(i18n_st, i18n_key("pause.quit")) == "Quit") # the language lacks it: English expect(L(i18n_st, i18n_key("pause.quit")) == "Quit") # the language lacks it: English
expect(L(i18n_st, i18n_key("nowhere.at_all")) == "nowhere.at_all") # en.po lacks it: the key expect(L(i18n_st, i18n_key("nowhere.at_all")) == "nowhere.at_all") # en.po lacks it: the key
i18n_loud(i18n_st, true) i18n_loud(i18n_st, true)
expect(L(i18n_st, i18n_key("nowhere.else")) == "[[nowhere.else]]") # a developer's build says so expect(L(i18n_st, i18n_key("nowhere.else")) == "[[nowhere.else]]") # a developer's build says so
i18n_off(i18n_st) i18n_off(i18n_st)
expect(L(i18n_st, i18n_key("pause.resume")) == "Resume") # back to English: nothing stale kept expect(L(i18n_st, tr(k"pause.resume")) == "Resume") # back to English: nothing stale kept
} }
test "holes take their arguments in the language's order, and an argument that is a key is made first" (i18n_st: mut I18nState) { test "holes take their arguments in the language's order, and an argument that is a key is made first" (i18n_st: mut I18nState) {
start (i18n_st) start (i18n_st)
expect(L(i18n_st, trf(i18n_key("hud.day"), "12", "", "", "")) == "Day 12") expect(L(i18n_st, trf(k"hud.day", "12", "", "", "")) == "Day 12")
let saw = trf(i18n_key("catch.saw"), i18n_key("species.elk.a_name"), "5:30", "", "") let saw = trf(k"catch.saw", tr(k"species.elk.a_name"), "5:30", "", "")
expect(L(i18n_st, saw) == "You saw an elk at 5:30.") expect(L(i18n_st, saw) == "You saw an elk at 5:30.")
i18n_load_text(i18n_st, tt()) i18n_load_text(i18n_st, tt())
expect(L(i18n_st, trf(i18n_key("hud.day"), "12", "", "", "")) == "12. Gun") expect(L(i18n_st, trf(k"hud.day", "12", "", "", "")) == "12. Gun")
expect(L(i18n_st, saw) == "5:30 saatinde bir geyik gordun.") expect(L(i18n_st, saw) == "5:30 saatinde bir geyik gordun.")
expect(L(i18n_st, trf(i18n_key("hud.day"), "", "", "", "")) == ". Gun") # a missing argument is empty expect(L(i18n_st, trf(k"hud.day", "", "", "", "")) == ". Gun") # a missing argument is empty
expect(key_text(saw) == "catch.saw" and key_text("Settings") == "Settings") expect(key_text(saw) == "catch.saw" and key_text("Settings") == "Settings")
} }
test "a plural key takes its form by the count, by each language's own rule, falling back to English's" (i18n_st: mut I18nState) { test "a plural key takes its form by the count, by each language's own rule, falling back to English's" (i18n_st: mut I18nState) {
start (i18n_st) start (i18n_st)
expect(L(i18n_st, trn(i18n_key("pack.items"), 1, "", "", "")) == "1 item") expect(L(i18n_st, trn(kn"pack.items", 1, "", "", "")) == "1 item")
expect(L(i18n_st, trn(i18n_key("pack.items"), 3, "", "", "")) == "3 items") expect(L(i18n_st, trn(kn"pack.items", 3, "", "", "")) == "3 items")
i18n_load_text(i18n_st, tt()) i18n_load_text(i18n_st, tt())
expect(L(i18n_st, trn(i18n_key("pack.items"), 21, "", "", "")) == "21 esya") # n%10 == 1 expect(L(i18n_st, trn(kn"pack.items", 21, "", "", "")) == "21 esya") # n%10 == 1
expect(L(i18n_st, trn(i18n_key("pack.items"), 5, "", "", "")) == "5 esyalar") expect(L(i18n_st, trn(kn"pack.items", 5, "", "", "")) == "5 esyalar")
expect(L(i18n_st, trn(i18n_key("catch.count"), 2, "", "", "")) == "2 trout") # the language lacks it expect(L(i18n_st, trn(kn"catch.count", 2, "", "", "")) == "2 trout") # the language lacks it
} }
test "the old English form still works beside keys, so a game can move over a file at a time" (i18n_st: mut I18nState) { test "the old English form still works beside keys, so a game can move over a file at a time" (i18n_st: mut I18nState) {
@ -71,7 +71,7 @@ program I18nKeysTest {
expect(L(i18n_st, "Settings") == "Settings") expect(L(i18n_st, "Settings") == "Settings")
i18n_load_text(i18n_st, tt()) i18n_load_text(i18n_st, tt())
expect(L(i18n_st, "Settings") == "Ayarlar") expect(L(i18n_st, "Settings") == "Ayarlar")
expect(L(i18n_st, i18n_key("pause.resume")) == "Devam") expect(L(i18n_st, tr(k"pause.resume")) == "Devam")
expect(not i18n_is_key("Settings") and i18n_is_key(i18n_key("x")) and i18n_is_key(i18n_key_plural("x"))) expect(not i18n_is_key("Settings") and i18n_is_key(i18n_key("x")) and i18n_is_key(i18n_key_plural("x")))
} }
} }