diff --git a/packages/ludic.i18n/keyed_args.ludic b/packages/ludic.i18n/keyed_args.ludic index 6de5a29c..e3668e1d 100644 --- a/packages/ludic.i18n/keyed_args.ludic +++ b/packages/ludic.i18n/keyed_args.ludic @@ -1,6 +1,7 @@ # keyed_args.ludic - a key's arguments as the decoder reads them: unescaped, looked up while still English, a count -# an argument as it was handed in: each 27 before a 27 or a 31 taken off +# an argument as it was handed in: each 27 before a 27 or a 31 taken off, outside a bracket only (a +# bracketed line inside it was carried raw, and its own escapes are its own) @alloc_ok("a key made into text (a cache miss): an argument that held a key with holes") function kr_unescape(s: string) -> string { var esc = false @@ -8,9 +9,11 @@ function kr_unescape(s: string) -> string { if not esc { return s } let buf = buffer(len(s)) var n = 0 + var d = 0 var i = 0 while i < len(s) { - if s[i] == I18N_ESC and i + 1 < len(s) { i += 1 } + d = kx_depth(d, s[i]) + if d == 0 and s[i] == I18N_ESC and i + 1 < len(s) { i += 1 } buf[n] = s[i] n += 1 i += 1 diff --git a/packages/ludic.i18n/keys.ludic b/packages/ludic.i18n/keys.ludic index 5d9a9b38..8266d6bd 100644 --- a/packages/ludic.i18n/keys.ludic +++ b/packages/ludic.i18n/keys.ludic @@ -63,16 +63,23 @@ function kx_sep(buf: []byte, at: int) -> int { buf[at] = I18N_SEP return at + 1 } -# an argument's bytes, a 27 before each 27 or 31 of its own, so a key with holes can be one +# an argument's bytes, a 27 before each 27 or 31 of its own outside any bracket (a bracketed line's +# bytes are its own and ride raw, 29 .. 30 delimit it), so a key with holes can be one function kx_len(s: string) -> int { var n = len(s) - for i in 0 .. len(s) { if s[i] == I18N_SEP or s[i] == I18N_ESC { n += 1 } } + var d = 0 + for i in 0 .. len(s) { + d = kx_depth(d, s[i]) + if d == 0 and (s[i] == I18N_SEP or s[i] == I18N_ESC) { n += 1 } + } return n } function kx_arg(buf: []byte, at: int, s: string) -> int { var j = at + var d = 0 for i in 0 .. len(s) { - if s[i] == I18N_SEP or s[i] == I18N_ESC { + d = kx_depth(d, s[i]) + if d == 0 and (s[i] == I18N_SEP or s[i] == I18N_ESC) { buf[j] = I18N_ESC j += 1 } @@ -81,6 +88,12 @@ function kx_arg(buf: []byte, at: int, s: string) -> int { } return j } +# how deep in brackets a byte leaves the reader +function kx_depth(d: int, c: int) -> int { + if c == I18N_OPEN { return d + 1 } + if c == I18N_CLOSE and d > 0 { return d - 1 } + return d +} function kx_put(buf: []byte, at: int, s: string) -> int { for i in 0 .. len(s) { buf[at + i] = s[i] } return at + len(s) diff --git a/packages/ludic.i18n/tests/nest_test.ludic b/packages/ludic.i18n/tests/nest_test.ludic index 1be2f917..1bf5eaab 100644 --- a/packages/ludic.i18n/tests/nest_test.ludic +++ b/packages/ludic.i18n/tests/nest_test.ludic @@ -5,7 +5,7 @@ program I18nNestTest { numbers float 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 en() -> string { return po_line("hud.day", "Day {1}") + po_line("pause.quit", "Quit") + po_line("shop.ada", "Ada: {1}") } + function en() -> string { return po_line("hud.day", "Day {1}") + po_line("pause.quit", "Quit") + po_line("shop.ada", "Ada: {1}") + po_line("lore.talk", "{1} is back, {2}.") + po_line("lore.brief", "{1} {2} {3}") } function tt() -> string { return po_line("hud.day", "{1}. Gun") + po_line("pause.quit", "Cik") + po_line("Settings", "Ayarlar") } function b(s: string) -> string { let o = buffer(1) @@ -39,4 +39,17 @@ program I18nNestTest { expect(L(i18n_st, "Quit" + text_of(c, 1)) == "Quit") expect(kx_nested("Quit") == false) } + + test "a key whose hole holds a key with two holes, bare, bracketed as a game's txt_key puts it, or in trf" (i18n_st: mut I18nState) { + start(i18n_st) + let talk = trf(k"lore.talk", "Old Maroon", "under the far shore", "", "") + let brief = trf(k"lore.brief", "Lightning.", talk, tr(k"pause.quit"), "") + let whole = "Lightning. Old Maroon is back, under the far shore. Quit" + expect(L(i18n_st, brief) == whole) + let sep = buffer(1) + sep[0] = I18N_SEP + expect(L(i18n_st, b(tr(k"shop.ada") + text_of(sep, 1) + b(brief))) == "Ada: " + whole) # txt_key's shape: raw inside + expect(L(i18n_st, trf(k"shop.ada", b(brief), "", "", "")) == "Ada: " + whole) + expect(L(i18n_st, trf(k"shop.ada", brief, "", "", "")) == "Ada: " + whole) + } }