ludic/packages/ludic.i18n/patterns.ludic
2026-09-25 14:02:21 +03:00

83 lines
2.1 KiB
Text

# patterns.ludic - a msgid with holes ("Day {1}"): its literal pieces, how much English they pin
# down, and a chain by its first (else last) four bytes so a lookup tries only its own kind
function holes(s: string) -> int {
let n = len(s)
var h = 0
var i = 0
while i < n {
if hole_at(s, i) >= 0 {
h += 1
i = hole_end(s, i)
continue
}
i += 1
}
return h
}
function add_pattern(i18n_st: mut I18nState, id: string, tr: string) -> void {
let p = i18n_st.pat_n
i18n_st.pat_n += 1
let l0 = len(i18n_st.lits)
let n = len(id)
var seg = 0
var i = 0
var nl = 0
var score = 0
while i < n {
let num = hole_at(id, i)
if num >= 0 {
push(i18n_st.lits, id[seg..i])
score += i - seg
i18n_st.pat_ph[l0 + nl] = num
nl += 1
i = hole_end(id, i)
seg = i
continue
}
i += 1
}
push(i18n_st.lits, id[seg..n])
score += n - seg
nl += 1
i18n_st.pat_l0[p] = l0
i18n_st.pat_nl[p] = nl
i18n_st.pat_sc[p] = score
push(i18n_st.pat_out, tr)
chain(i18n_st, p, i18n_st.lits[l0], i18n_st.lits[l0 + nl - 1])
}
function chain(i18n_st: mut I18nState, p: int, first: string, last: string) -> void {
if len(first) >= 4 {
let key: string = first[0..4]
i18n_st.nx_p[p] = Dict.get_or(i18n_st.pfx, key, 0)
Dict.set(i18n_st.pfx, key, p + 1)
} else if len(last) >= 4 {
let key: string = last[len(last) - 4..len(last)]
i18n_st.nx_s[p] = Dict.get_or(i18n_st.sfx, key, 0)
Dict.set(i18n_st.sfx, key, p + 1)
} else {
i18n_st.nx_g[p] = i18n_st.gen_head
i18n_st.gen_head = p + 1
}
}
# a translation with its holes filled from caps, by number: a translation may reorder or drop them
function fill_holes(i18n_st: I18nState, t: string, l0: int, nl: int, cs: []string) -> string {
let n = len(t)
var r = ""
var seg = 0
var i = 0
while i < n {
let num = hole_at(t, i)
if num >= 0 {
r = r + t[seg..i]
for g in 0 .. nl - 1 { if i18n_st.pat_ph[l0 + g] == num { r = r + cs[g] } }
i = hole_end(t, i)
seg = i
continue
}
i += 1
}
return r + t[seg..n]
}