aboutsummaryrefslogtreecommitdiff
path: root/advtrains/poconvert.lua
diff options
context:
space:
mode:
Diffstat (limited to 'advtrains/poconvert.lua')
-rw-r--r--advtrains/poconvert.lua159
1 files changed, 159 insertions, 0 deletions
diff --git a/advtrains/poconvert.lua b/advtrains/poconvert.lua
new file mode 100644
index 0000000..c7704f6
--- /dev/null
+++ b/advtrains/poconvert.lua
@@ -0,0 +1,159 @@
+local unescape_string
+do
+ local schartbl = { -- https://en.wikipedia.org/wiki/Escape_sequences_in_C
+ a = "\a",
+ b = "\b",
+ e = string.char(0x1b),
+ f = "\f",
+ n = "\n",
+ r = "\r",
+ t = "\t",
+ v = "\v",
+ }
+ local function replace_single(pfx, c)
+ local pl = #pfx
+ if pl % 2 == 0 then
+ return pfx .. c
+ end
+ return string.sub(pfx, 1, math.floor(pl/2)) .. (schartbl[c] or c)
+ end
+ unescape_string = function(str)
+ return (string.gsub(str, [[(\+)([abefnrtv'"?])]], replace_single):gsub([[\\]], [[\]]))
+ end
+end
+
+local function readstring_aux(str, pos)
+ local _, spos = string.find(str, [[^%s*"]], pos)
+ if not spos then
+ return nil
+ end
+ local ipos = spos
+ while true do
+ local _, epos, m = string.find(str, [[(\*)"]], ipos+1)
+ if not epos then
+ return error("String extends beyond the end of input")
+ end
+ ipos = epos
+ if #m % 2 == 0 then
+ return unescape_string(string.sub(str, spos+1, epos-1)), epos+1
+ end
+ end
+end
+
+local function readstring(str, pos)
+ local st = {}
+ local nxt = pos
+ while true do
+ local s, npos = readstring_aux(str, nxt)
+ if not s then
+ if not st[1] then
+ return nil, nxt
+ else
+ return table.concat(st), nxt
+ end
+ end
+ nxt = npos
+ table.insert(st, s)
+ end
+end
+
+local function readtoken(str, pos)
+ local _, epos, tok = string.find(str, [[^%s*(%S+)]], pos)
+ if not epos then
+ return nil, pos
+ end
+ return tok, epos+1
+end
+
+local function readcomment_aux(str, pos)
+ local _, epos, sval = string.find(str, "^\n*#%s*([^\n]*)", pos)
+ if not epos then
+ return nil
+ end
+ return sval, epos+1
+end
+
+local function readcomment(str, pos)
+ local st = {}
+ local nxt = pos
+ while true do
+ local s, npos = readcomment_aux(str, nxt)
+ if not npos then
+ return table.concat(st, "\n"), nxt
+ end
+ table.insert(st, s)
+ nxt = npos
+ end
+end
+
+local function readpo(str)
+ local st = {}
+ local pos = 1
+ while true do
+ local tok
+ local _, npos = readcomment(str, pos)
+ tok, npos = readtoken(str, npos)
+ if not tok then
+ return st
+ end
+ assert(tok == "msgid", "Invalid token: " .. tok)
+ local orig, tr
+ orig, npos = readstring(str, npos)
+ assert(orig ~= nil, "Missing untranslated string")
+ tok, npos = readtoken(str, npos)
+ assert(tok == "msgstr", "Invalid token: " .. tok)
+ tr, npos = readstring(str, npos)
+ assert(tr ~= nil, "Missing translated string")
+ if not (orig == "" or tr == "") then
+ st[orig] = tr
+ end
+ pos = npos
+ end
+end
+
+local escape_lookup = {
+ ["="] = "@=",
+ ["\n"] = "@n"
+}
+local function escape_string(st)
+ return (string.gsub(st, "[=\n]", escape_lookup))
+end
+
+local function convert_po_string(textdomain, str)
+ local st = {string.format("# textdomain: %s", textdomain)}
+ for k, v in pairs(readpo(str)) do
+ table.insert(st, ("%s=%s"):format(escape_string(k), escape_string(v)))
+ end
+ return table.concat(st, "\n")
+end
+
+local function convert_po_file(textdomain, inpath, outpath)
+ local f, err = io.open(inpath, "rb")
+ assert(f, err)
+ local str = convert_po_string(textdomain, f:read("*a"))
+ f:close()
+ minetest.safe_file_write(outpath, str)
+ return str
+end
+
+local function convert_flat_po_directory(textdomain, modpath)
+ assert(textdomain, "No textdomain specified for po file conversion")
+ local mp = modpath or minetest.get_modpath(textdomain)
+ assert(mp ~= nil, "No path to write for " .. textdomain)
+ local popath = mp .. "/po"
+ local trpath = mp .. "/locale"
+ for _, infile in pairs(minetest.get_dir_list(popath, false)) do
+ local lang = string.match(infile, [[^([^%.]+)%.po$]])
+ if lang then
+ local inpath = popath .. "/" .. infile
+ local outpath = ("%s/%s.%s.tr"):format(trpath, textdomain, lang)
+ convert_po_file(textdomain, inpath, outpath)
+ end
+ end
+end
+
+return {
+ from_string = convert_po_string,
+ from_file = convert_po_file,
+ from_flat = convert_flat_po_directory,
+}