150 lines
4.2 KiB
Lua
150 lines
4.2 KiB
Lua
local logger = require("logger")
|
|
local koreader_gettext = require("gettext")
|
|
|
|
local GetText = {
|
|
translation = {},
|
|
loaded_lang = nil,
|
|
}
|
|
|
|
local function unescapePoString(s)
|
|
s = s:gsub("\\n", "\n")
|
|
s = s:gsub("\\t", "\t")
|
|
s = s:gsub("\\r", "\r")
|
|
s = s:gsub('\\"', '"')
|
|
s = s:gsub("\\\\", "\\")
|
|
return s
|
|
end
|
|
|
|
local function loadPoFile(path)
|
|
local file = io.open(path, "r")
|
|
if not file then
|
|
logger.dbg("Readest i18n: cannot open translation file:", path)
|
|
return false
|
|
end
|
|
|
|
local entry = {}
|
|
local current
|
|
|
|
local function flush()
|
|
if entry.msgid and entry.msgid ~= "" and entry.msgstr and entry.msgstr ~= "" then
|
|
GetText.translation[entry.msgid] = entry.msgstr
|
|
end
|
|
entry = {}
|
|
current = nil
|
|
end
|
|
|
|
for line in file:lines() do
|
|
if line == "" then
|
|
flush()
|
|
elseif not line:match("^#") then
|
|
local key, value = line:match('^%s*(msgid)%s+"(.*)"%s*$')
|
|
if not key then
|
|
key, value = line:match('^%s*(msgstr)%s+"(.*)"%s*$')
|
|
end
|
|
if key then
|
|
current = key
|
|
entry[current] = unescapePoString(value)
|
|
else
|
|
value = line:match('^%s*"(.*)"%s*$')
|
|
if current and value then
|
|
entry[current] = (entry[current] or "") .. unescapePoString(value)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
flush()
|
|
file:close()
|
|
|
|
logger.info("Readest i18n: loaded translation file:", path)
|
|
return true
|
|
end
|
|
|
|
local function getPluginDir()
|
|
local info = debug.getinfo(1, "S")
|
|
local source = info and info.source
|
|
if source and source:sub(1, 1) == "@" then
|
|
source = source:sub(2)
|
|
end
|
|
return source and source:match("(.*/)") or "./"
|
|
end
|
|
|
|
local plugin_dir = getPluginDir()
|
|
|
|
-- KOReader stores locales with an underscore separator (e.g. zh_CN, pt_BR);
|
|
-- our catalog mirrors readest-app's i18next layout which uses hyphens (zh-CN).
|
|
local function getLanguage()
|
|
local lang = G_reader_settings and G_reader_settings:readSetting("language")
|
|
if type(lang) == "string" and lang ~= "" and lang ~= "C" then
|
|
return (lang:gsub("%..*", ""):gsub("_", "-"))
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local function initTranslation()
|
|
GetText.translation = {}
|
|
|
|
local lang = getLanguage()
|
|
GetText.loaded_lang = lang
|
|
if not lang then return end
|
|
|
|
local candidates = { lang }
|
|
local base_lang = lang:match("^(%a+)-")
|
|
if base_lang then
|
|
table.insert(candidates, base_lang)
|
|
end
|
|
if lang:match("^zh") and lang ~= "zh-CN" then
|
|
table.insert(candidates, "zh-CN")
|
|
end
|
|
|
|
for _, candidate in ipairs(candidates) do
|
|
local path = plugin_dir .. "locales/" .. candidate .. "/translation.po"
|
|
if loadPoFile(path) then
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
local function translate(msgid)
|
|
local lang = getLanguage()
|
|
if lang ~= GetText.loaded_lang then
|
|
initTranslation()
|
|
end
|
|
return GetText.translation[msgid]
|
|
end
|
|
|
|
setmetatable(GetText, {
|
|
__call = function(_, msgid)
|
|
return translate(msgid) or koreader_gettext(msgid)
|
|
end,
|
|
})
|
|
|
|
function GetText.ngettext(msgid, msgid_plural, n)
|
|
local translated = translate(n == 1 and msgid or msgid_plural)
|
|
if translated then return translated end
|
|
if koreader_gettext.ngettext then
|
|
return koreader_gettext.ngettext(msgid, msgid_plural, n)
|
|
end
|
|
return n == 1 and GetText(msgid) or GetText(msgid_plural)
|
|
end
|
|
|
|
function GetText.pgettext(msgctxt, msgid)
|
|
local translated = translate(msgctxt .. "\004" .. msgid) or translate(msgid)
|
|
if translated then return translated end
|
|
if koreader_gettext.pgettext then
|
|
return koreader_gettext.pgettext(msgctxt, msgid)
|
|
end
|
|
return GetText(msgid)
|
|
end
|
|
|
|
function GetText.npgettext(msgctxt, msgid, msgid_plural, n)
|
|
local selected = n == 1 and msgid or msgid_plural
|
|
local translated = translate(msgctxt .. "\004" .. selected) or translate(selected)
|
|
if translated then return translated end
|
|
if koreader_gettext.npgettext then
|
|
return koreader_gettext.npgettext(msgctxt, msgid, msgid_plural, n)
|
|
end
|
|
return GetText.ngettext(msgid, msgid_plural, n)
|
|
end
|
|
|
|
return GetText
|