ludic/packages/ludic.i18n/po.ludic

96 lines
2.7 KiB
Text

# 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])
}