# i18n_test.ludic - languages from a shipped list and a mod folder, a language's keys and their holes, # plurals, the font a language names, and plain text drawn as it is; every file written to the # temp directory import "ludic.i18n" program I18nTest { numbers float state I18nTestState { forced_code: string = "" fonts_set: []string = null font_ok: bool = true } function dir() -> string { return Os.temp_dir() + "/ludic-i18n-test" } function mods() -> string { return dir() + "/mods" } function t_mods() -> string { return mods() } function t_forced(i18n_test_st: I18nTestState) -> string { return i18n_test_st.forced_code } function t_ready() -> bool { return true } function t_font(i18n_test_st: mut I18nTestState, d: string) -> bool { push(i18n_test_st.fonts_set, d) return i18n_test_st.font_ok } bind I18nWorld { mod_dir: fn t_mods, forced: fn t_forced, font_ready: fn t_ready, set_font: fn t_font } function q(s: string) -> string { return "\"" + s + "\"" } function po_line(id: string, tr: string) -> string { return "msgid " + q(id) + "\nmsgstr " + q(tr) + "\n\n" } function header(name: string, extra: string) -> string { return "msgid \"\"\nmsgstr \"\"\n\"X-Language-Name: " + name + "\\n\"\n" + extra + "\n" } # a shipped "tt" with a font of its own, and a Russian-shaped plural function tt() -> string { var s = header("Test Tongue", "\"X-Font: font_tt\\n\"\n\"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : 2);\\n\"") s = s + po_line("menu.settings", "Zettings") + po_line("items.fiber.name", "Lif") + po_line("hud.day", "{1}. Gun") s = s + po_line("pack.gain", "{2} +{1}") + po_line("empty.one", "") s = s + "msgid \"catch.count\"\nmsgid_plural \"catch.count\"\nmsgstr[0] \"{1} alabalik\"\nmsgstr[1] \"{1} alabaliga\"\nmsgstr[2] \"{1} alabaliklar\"\n\n" s = s + "msgid \"multi.line\"\nmsgstr \"Cok\"\n\"satir\\n\"\n" return s } function fresh(i18n_st: mut I18nState, i18n_test_st: mut I18nTestState) -> void { i18n_test_st.forced_code = "" i18n_test_st.fonts_set = new []string i18n_test_st.font_ok = true Fs.mkdir(dir()) Fs.mkdir(mods()) Fs.write_text(dir() + "/languages.txt", "# shipped\ntt\nnope\n") Fs.write_text(dir() + "/tt.po", tt()) Fs.remove(mods() + "/zz.po") i18n_config(i18n_st, dir(), "font_default") i18n_init(i18n_st) } test "the shipped list and English are found, a missing file is not" (i18n_st: mut I18nState, i18n_test_st: mut I18nTestState) { fresh(i18n_st, i18n_test_st) expect_eq(i18n_count(i18n_st), 2) expect(i18n_code_at(i18n_st, 0) == "en") expect_eq(i18n_index(i18n_st, "tt"), 1) expect_eq(i18n_index(i18n_st, "nope"), 0) expect(i18n_name_at(i18n_st, 1) == "Test Tongue") expect(i18n_font_at(i18n_st, 1) == dir() + "/font_tt") expect(L(i18n_st, "Settings") == "Settings") } test "a language's keys, their holes, and plain text drawn as it is" (i18n_st: mut I18nState, i18n_test_st: mut I18nTestState) { fresh(i18n_st, i18n_test_st) i18n_use(i18n_st, "tt") expect(i18n_on(i18n_st)) expect(i18n_current(i18n_st) == "tt") expect(L(i18n_st, tr(k"menu.settings")) == "Zettings") expect(L(i18n_st, trf(k"hud.day", "12", "", "", "")) == "12. Gun") expect(L(i18n_st, trf(k"pack.gain", "2", tr(k"items.fiber.name"), "", "")) == "Lif +2") expect(L(i18n_st, tr(k"multi.line")) == "Coksatir\n") expect(L(i18n_st, "Settings") == "Settings") expect_eq(i18n_exact_count(i18n_st), 5) } test "plurals by the file's rule" (i18n_st: mut I18nState, i18n_test_st: mut I18nTestState) { fresh(i18n_st, i18n_test_st) i18n_use(i18n_st, "tt") expect_eq(i18n_plural_rule(i18n_st), PL_SLAVIC) expect(L(i18n_st, trn(kn"catch.count", 21, "", "", "")) == "21 alabalik") expect(L(i18n_st, trn(kn"catch.count", 5, "", "", "")) == "5 alabaliklar") expect_eq(i18n_plural_form(PL_NOT_ONE, 0), 1) expect_eq(i18n_plural_form(PL_ABOVE_ONE, 0), 0) expect_eq(i18n_plural_form(PL_SLAVIC, 3), 1) expect_eq(i18n_plural_form(PL_ONE_FORM, 7), 0) } test "the font follows the language, and falls back when it will not load" (i18n_st: mut I18nState, i18n_test_st: mut I18nTestState) { fresh(i18n_st, i18n_test_st) i18n_font_base(i18n_st, "font_default") i18n_use(i18n_st, "tt") expect_eq(len(i18n_test_st.fonts_set), 1) expect(i18n_font_now(i18n_st) == dir() + "/font_tt") i18n_use(i18n_st, "en") expect(i18n_font_now(i18n_st) == "font_default") i18n_test_st.font_ok = false i18n_use(i18n_st, "tt") expect(i18n_font_now(i18n_st) == "font_default") } test "a language switched back to is its kept tables, not its file read again; a new probe reads it" (i18n_st: mut I18nState, i18n_test_st: mut I18nTestState) { fresh(i18n_st, i18n_test_st) i18n_use(i18n_st, "tt") let first = L(i18n_st, tr(k"menu.settings")) Fs.write_text(dir() + "/tt.po", header("Tongue", "") + po_line("menu.settings", "Changed")) i18n_use(i18n_st, "en") i18n_use(i18n_st, "tt") expect(L(i18n_st, tr(k"menu.settings")) == first) i18n_init(i18n_st) i18n_use(i18n_st, "tt") expect(L(i18n_st, tr(k"menu.settings")) == "Changed") } test "a mod in the player's folder is found, replaces a shipped code, and goes when removed" (i18n_st: mut I18nState, i18n_test_st: mut I18nTestState) { fresh(i18n_st, i18n_test_st) Fs.write_text(mods() + "/zz.po", header("Mod Tongue", "") + po_line("menu.settings", "Mettings")) Fs.write_text(mods() + "/tt.po", header("Tongue Two", "") + po_line("menu.settings", "Z2")) i18n_init(i18n_st) expect_eq(i18n_count(i18n_st), 3) expect(i18n_name_at(i18n_st, i18n_index(i18n_st, "zz")) == "Mod Tongue") i18n_use(i18n_st, "zz") expect(L(i18n_st, tr(k"menu.settings")) == "Mettings") expect(L(i18n_st, "Day 3") == "Day 3") i18n_use(i18n_st, "tt") expect(L(i18n_st, tr(k"menu.settings")) == "Z2") Fs.remove(mods() + "/zz.po") Fs.remove(mods() + "/tt.po") i18n_init(i18n_st) expect_eq(i18n_index(i18n_st, "zz"), 0) i18n_use(i18n_st, "en") expect(not i18n_on(i18n_st)) expect(L(i18n_st, "Settings") == "Settings") } test "a forced code wins over the one asked for" (i18n_st: mut I18nState, i18n_test_st: mut I18nTestState) { fresh(i18n_st, i18n_test_st) i18n_test_st.forced_code = "tt" i18n_use(i18n_st, "en") expect(i18n_current(i18n_st) == "tt") } test "a header field, and a .po loaded from text" (i18n_st: mut I18nState) { expect(i18n_header(tt(), "X-Language-Name") == "Test Tongue") expect(i18n_header(tt(), "X-Nothing") == "") i18n_load_text(i18n_st, po_line("pause.quit", "Cik")) expect(L(i18n_st, tr(k"pause.quit")) == "Cik") i18n_off(i18n_st) expect(not (L(i18n_st, tr(k"pause.quit")) == "Cik")) # back to English, whatever en.po is found } }