# po.ludic - a gettext file: msgid / msgid_plural / msgstr / msgstr[k] and their continuation lines; # comments, flags and msgctxt are read past property PoEntry { id: string = "", plural: string = "", str: string = "", forms: []string } function entry_new() -> PoEntry { let e = new PoEntry e.forms = new []string return e } function entry_put(e: PoEntry, mode: int, s: string) -> void { if mode == 1 { e.id = e.id + s } if mode == 2 { e.str = e.str + s } if mode == 3 { e.plural = e.plural + s } if mode == 4 { e.forms[len(e.forms) - 1] = e.forms[len(e.forms) - 1] + s } } @alloc_ok("on a language change: a .po read") export function i18n_parse(text: string) -> []PoEntry { let r = new []PoEntry let lines = lines_of(text) var mode = 0 # 1 msgid, 2 msgstr, 3 msgid_plural, 4 msgstr[k] var e: PoEntry = null for li in 0 .. len(lines) { let line = trim(lines[li]) if i18n_starts(line, "msgid ") { if e != null { push(r, e) } e = entry_new() e.id = unquote(line, 6) mode = 1 } else if e != null and i18n_starts(line, "msgid_plural ") { e.plural = unquote(line, 13) mode = 3 } else if e != null and i18n_starts(line, "msgstr[") { push(e.forms, unquote(line, 7)) mode = 4 } else if e != null and i18n_starts(line, "msgstr ") { e.str = unquote(line, 7) mode = 2 } else if len(line) > 0 and line[0] == 34 { if e != null { entry_put(e, mode, unquote(line, 0)) } } else { if e != null and (mode == 2 or mode == 4) { push(r, e) e = null } mode = 0 } } if e != null { push(r, e) } return r } # the string whose opening quote is at or after `from`, with \" \\ \n \t undone function unquote(line: string, from: int) -> string { let n = len(line) var i = from while i < n and line[i] != 34 { i += 1 } i += 1 var seg = i var s = "" while i < n { let c = line[i] if c == 92 and i + 1 < n { if i > seg { s = s + line[seg..i] } let e = line[i + 1] if e == 110 { s = s + "\n" } else if e == 116 { s = s + "\t" } else { s = s + line[i + 1..i + 2] } i += 2 seg = i continue } if c == 34 { break } i += 1 } if i > seg { s = s + line[seg..i] } return s } # a header field out of the msgstr "" block: "X-Language-Name: Türkçe\n" @alloc_ok("on a language change: a .po's header read") export function i18n_header(text: string, field: string) -> string { var n = len(text) if n > 4000 { n = 4000 } let key = field + ": " let at = i18n_find(text, n, 0, key, len(key)) if at < 0 { return "" } let s0 = at + len(key) var e = s0 while e < n and text[e] != 92 and text[e] != 34 and text[e] != 10 { e += 1 } return trim(text[s0..e]) }