Update intllib, add `core.get_translator_auto()` wrapper

master
Maksim 2021-12-26 20:51:26 +01:00 committed by MoNTE48
parent 318a67d168
commit b2dc09ad3a
3 changed files with 50 additions and 48 deletions

View File

@ -1,16 +1,9 @@
local strsub, strrep = string.sub, string.rep
local strmatch, strgsub = string.match, string.gsub
local function trim(str)
return strmatch(str, "^%s*(.-)%s*$")
end
local escapes = { n="\n", r="\r", t="\t" } local escapes = { n="\n", r="\r", t="\t" }
local function unescape(str) local function unescape(str)
return (strgsub(str, "(\\+)([nrt]?)", function(bs, c) return (str:gsub("(\\+)([nrt]?)", function(bs, c)
local bsl = #bs local bsl = #bs
local realbs = strrep("\\", bsl/2) local realbs = ("\\"):rep(bsl/2)
if bsl%2 == 1 then if bsl%2 == 1 then
c = escapes[c] or c c = escapes[c] or c
end end
@ -27,14 +20,14 @@ local function parse_po(str)
end end
for _, line in ipairs(str:split("\n")) do repeat for _, line in ipairs(str:split("\n")) do repeat
lineno = lineno + 1 lineno = lineno + 1
line = trim(line) line = line:trim()
if line == "" or strmatch(line, "^#") then if line == "" or line:match("^#") then
state, msgid, msgid_plural = nil, nil, nil state, msgid, msgid_plural = nil, nil, nil
break -- continue break -- continue
end end
local mid = strmatch(line, "^%s*msgid%s*\"(.*)\"%s*$") local mid = line:match("^%s*msgid%s*\"(.*)\"%s*$")
if mid then if mid then
if state == "id" then if state == "id" then
return perror("unexpected msgid") return perror("unexpected msgid")
@ -43,7 +36,7 @@ local function parse_po(str)
break -- continue break -- continue
end end
mid = strmatch(line, "^%s*msgid_plural%s*\"(.*)\"%s*$") mid = line:match("^%s*msgid_plural%s*\"(.*)\"%s*$")
if mid then if mid then
if state ~= "id" then if state ~= "id" then
return perror("unexpected msgid_plural") return perror("unexpected msgid_plural")
@ -52,15 +45,14 @@ local function parse_po(str)
break -- continue break -- continue
end end
local ind, mstr = strmatch(line, local ind, mstr = line:match("^%s*msgstr([0-9%[%]]*)%s*\"(.*)\"%s*$")
"^%s*msgstr([0-9%[%]]*)%s*\"(.*)\"%s*$")
if ind then if ind then
if not msgid then if not msgid then
return perror("missing msgid") return perror("missing msgid")
elseif ind == "" then elseif ind == "" then
msgstrind = 0 msgstrind = 0
elseif strmatch(ind, "%[[0-9]+%]") then elseif ind:match("%[[0-9]+%]") then
msgstrind = tonumber(strsub(ind, 2, -2)) msgstrind = tonumber(ind:sub(2, -2))
else else
return perror("malformed msgstr") return perror("malformed msgstr")
end end
@ -73,7 +65,7 @@ local function parse_po(str)
break -- continue break -- continue
end end
mstr = strmatch(line, "^%s*\"(.*)\"%s*$") mstr = line:match("^%s*\"(.*)\"%s*$")
if mstr then if mstr then
if state == "id" then if state == "id" then
msgid = msgid..unescape(mstr) msgid = msgid..unescape(mstr)
@ -107,9 +99,9 @@ end
-- It handles enough stuff to parse the `Plural-Forms` header correctly. -- It handles enough stuff to parse the `Plural-Forms` header correctly.
-- Note that it assumes the C expression is valid to begin with. -- Note that it assumes the C expression is valid to begin with.
local function compile_plural_forms(str) local function compile_plural_forms(str)
local plural = strmatch(str, "plural=([^;]+);?$") local plural = str:match("plural=([^;]+);?$")
local function replace_ternary(s) local function replace_ternary(s)
local c, t, f = strmatch(s, "^(.-)%?(.-):(.*)") local c, t, f = s:match(s"^(.-)%?(.-):(.*)")
if c then if c then
return ("__if(" return ("__if("
..replace_ternary(c) ..replace_ternary(c)
@ -120,10 +112,10 @@ local function compile_plural_forms(str)
return s return s
end end
plural = replace_ternary(plural) plural = replace_ternary(plural)
plural = strgsub(plural, "&&", " and ") plural = plural:gsub("&&", " and ")
plural = strgsub(plural, "||", " or ") plural = plural:gsub("||", " or ")
plural = strgsub(plural, "!=", "~=") plural = plural:gsub("!=", "~=")
plural = strgsub(plural, "!", " not ") plural = plural:gsub("!", " not ")
local f, err = loadstring([[ local f, err = loadstring([[
local function __if(c, t, f) local function __if(c, t, f)
if c and c~=0 then return t else return f end if c and c~=0 then return t else return f end
@ -150,7 +142,7 @@ end
local function parse_headers(str) local function parse_headers(str)
local headers = { } local headers = { }
for _, line in ipairs(str:split("\n")) do for _, line in ipairs(str:split("\n")) do
local k, v = strmatch(line, "^([^:]+):%s*(.*)") local k, v = line:match("^([^:]+):%s*(.*)")
if k then if k then
headers[k] = v headers[k] = v
end end

View File

@ -3,7 +3,7 @@ intllib = {
strings = {}, strings = {},
} }
local path = core.get_builtin_path() .. DIR_DELIM .. "intllib" .. DIR_DELIM local path = core.get_builtin_path() .. "intllib" .. DIR_DELIM
dofile(path .. "lib.lua") dofile(path .. "lib.lua")
local LANG = core.settings:get("language") local LANG = core.settings:get("language")
@ -67,15 +67,14 @@ function intllib.Getter(modname)
end end
local strfind, strsub = string.find, string.sub
local langs local langs
local function split(str, sep) local function split(str, sep)
local pos, endp = 1, #str+1 local pos, endp = 1, #str+1
return function() return function()
if (not pos) or pos > endp then return end if (not pos) or pos > endp then return end
local s, e = strfind(str, sep, pos, true) local s, e = str:find(sep, pos, true)
local part = strsub(str, pos, s and s-1) local part = str:sub(pos, s and s-1)
pos = e and e + 1 pos = e and e + 1
return part return part
end end
@ -89,14 +88,14 @@ function intllib.get_detected_languages()
local function addlang(l) local function addlang(l)
local sep local sep
langs[#langs+1] = l langs[#langs+1] = l
sep = strfind(l, ".", 1, true) sep = l:find(".", 1, true)
if sep then if sep then
l = strsub(l, 1, sep-1) l = l:sub(1, sep-1)
langs[#langs+1] = l langs[#langs+1] = l
end end
sep = strfind(l, "_", 1, true) sep = l:find("_", 1, true)
if sep then if sep then
langs[#langs+1] = strsub(l, 1, sep-1) langs[#langs+1] = l:sub(1, sep-1)
end end
end end
@ -138,8 +137,9 @@ local function catgettext(catalogs, msgid)
end end
end end
local floor = math.floor
local function catngettext(catalogs, msgid, msgid_plural, n) local function catngettext(catalogs, msgid, msgid_plural, n)
n = math.floor(n) n = floor(n)
for _, cat in ipairs(catalogs) do for _, cat in ipairs(catalogs) do
local msgstr = cat and cat[msgid] local msgstr = cat and cat[msgid]
if msgstr then if msgstr then
@ -158,7 +158,7 @@ function intllib.make_gettext_pair(modname)
if gettext_getters[modname] then if gettext_getters[modname] then
return unpack(gettext_getters[modname]) return unpack(gettext_getters[modname])
end end
local modpath = core.get_modpath(modname) and core.get_modpath(modname) local modpath = core.get_modpath(modname)
local localedir = modpath and modpath.."/locale" local localedir = modpath and modpath.."/locale"
local catalogs = localedir and gettext.load_catalogs(localedir) or {} local catalogs = localedir and gettext.load_catalogs(localedir) or {}
local getter = Getter(modname) local getter = Getter(modname)
@ -192,18 +192,24 @@ function intllib.get_strings(modname, langcode)
modname = modname or core.get_current_modname() modname = modname or core.get_current_modname()
local msgstr = intllib.strings[modname] local msgstr = intllib.strings[modname]
if not msgstr then if not msgstr then
local modpath = core.get_modpath(modname) and core.get_modpath(modname) local modpath = core.get_modpath(modname)
msgstr = { } msgstr = { }
if modpath then if modpath then
for _, l in ipairs(get_locales(langcode)) do for _, l in ipairs(get_locales(langcode)) do
local t = intllib.load_strings(modpath.."/locale/"..modname.."."..l..".tr") local t = intllib.load_strings(modpath.."/locale/"..modname.."."..l..".tr")
or intllib.load_strings(modpath.."/locale/"..l..".txt") or { } or intllib.load_strings(modpath.."/locale/"..l..".txt") or { }
for k, v in pairs(t) do for k, v in pairs(t) do
msgstr[k] = msgstr[k] or v msgstr[k] = msgstr[k] or v
end
end end
end intllib.strings[modname] = msgstr
intllib.strings[modname] = msgstr
end end
end end
return msgstr return msgstr
end end
function core.get_translator_auto()
-- Surrounded in brackets so there's only one return value
return (intllib.make_gettext_pair())
end

View File

@ -1,5 +1,3 @@
intllib = intllib or {}
local INS_CHAR = "@" local INS_CHAR = "@"
intllib.INSERTION_CHAR = INS_CHAR intllib.INSERTION_CHAR = INS_CHAR
@ -10,7 +8,7 @@ local escapes = {
["t"] = "\t", ["t"] = "\t",
["r"] = "\r", ["r"] = "\r",
["f"] = "\f", ["f"] = "\f",
[INS_CHAR] = INS_CHAR..INS_CHAR, [INS_CHAR] = INS_CHAR..INS_CHAR,
} }
local function unescape(str) local function unescape(str)
@ -23,7 +21,7 @@ local function unescape(str)
local start = 1 local start = 1
while true do while true do
local pos = str:find("\\", start, true) local pos = str:find("[\\@]", start)
if pos then if pos then
add(str:sub(start, pos - 1)) add(str:sub(start, pos - 1))
else else
@ -31,7 +29,13 @@ local function unescape(str)
break break
end end
local c = str:sub(pos + 1, pos + 1) local c = str:sub(pos + 1, pos + 1)
add(escapes[c] or c) if escapes[c] then
add(escapes[c])
elseif str:sub(pos, pos) == "@" then
add("@" .. c)
else
add(c)
end
start = pos + 2 start = pos + 2
end end
return table.concat(parts) return table.concat(parts)