diff --git a/init.lua b/init.lua index 9eeea6c..5ae02a5 100644 --- a/init.lua +++ b/init.lua @@ -2,67 +2,38 @@ -- Support the old multi-load method intllib = intllib or {} +local MP = minetest.get_modpath("intllib") + +dofile(MP.."/lib.lua") + local strings = {} -local LANG = minetest.setting_get("language") or os.getenv("LANG") or "en" +local LANG = minetest.setting_get("language") +if not (LANG and (LANG ~= "")) then LANG = os.getenv("LANG") end +if not (LANG and (LANG ~= "")) then LANG = "en" end LANG = LANG:sub(1, 2) -local escapes = { - ["\\"] = "\\", - ["n"] = "\n", - ["="] = "=", -} - -local function unescape(s) - return s:gsub("([\\]?)\\(.)", function(slash, what) - if slash and (slash ~= "") then - return "\\"..what - else - return escapes[what] or what - end - end) -end - - -local function find_eq(s) - for slashes, pos in s:gmatch("([\\]*)=()") do - if (slashes:len() % 2) == 0 then - return pos - 1 - end - end -end - - -function load_strings(modname) - local modpath = minetest.get_modpath(modname) - local file, err = io.open(modpath.."/locale/"..LANG..".txt", "r") - if not file then - return nil - end - local strings = {} - for line in file:lines() do - line = line:trim() - if line ~= "" and line:sub(1, 1) ~= "#" then - local pos = find_eq(line) - if pos then - local msgid = unescape(line:sub(1, pos - 1):trim()) - strings[msgid] = unescape(line:sub(pos + 1):trim()) - end - end - end - file:close() - return strings -end - -- Support the old multi-load method intllib.getters = intllib.getters or {} +local function noop_getter(s) + return s +end + function intllib.Getter(modname) modname = modname or minetest.get_current_modname() if not intllib.getters[modname] then - local msgstr = load_strings(modname) or {} - intllib.getters[modname] = function (s) - return msgstr[s] or s + local modpath = minetest.get_modpath(modname) + if modpath then + local filename = modpath.."/locale/"..LANG..".txt" + local msgstr = load_strings(filename) + if msgstr then + intllib.getters[modname] = function (s) + return msgstr[s] or s + end + else + intllib.getters[modname] = noop_getter + end end end return intllib.getters[modname] diff --git a/lib.lua b/lib.lua new file mode 100644 index 0000000..1268b04 --- /dev/null +++ b/lib.lua @@ -0,0 +1,44 @@ + +local escapes = { + ["\\"] = "\\", + ["n"] = "\n", + ["="] = "=", +} + +local function unescape(s) + return s:gsub("([\\]?)\\(.)", function(slash, what) + if slash and (slash ~= "") then + return "\\"..what + else + return escapes[what] or what + end + end) +end + +local function find_eq(s) + for slashes, pos in s:gmatch("([\\]*)=()") do + if (slashes:len() % 2) == 0 then + return pos - 1 + end + end +end + +function load_strings(filename) + local file, err = io.open(filename, "r") + if not file then + return nil + end + local strings = {} + for line in file:lines() do + line = line:trim() + if line ~= "" and line:sub(1, 1) ~= "#" then + local pos = find_eq(line) + if pos then + local msgid = unescape(line:sub(1, pos - 1):trim()) + strings[msgid] = unescape(line:sub(pos + 1):trim()) + end + end + end + file:close() + return strings +end diff --git a/tools/updatetext.lua b/tools/updatetext.lua new file mode 100644 index 0000000..421ee12 --- /dev/null +++ b/tools/updatetext.lua @@ -0,0 +1,141 @@ +#! /usr/bin/env lua + +local basedir = "" +if arg[0]:find("[/\\]") then + basedir = arg[0]:gsub("(.*[/\\]).*$", "%1"):gsub("\\", "/") +end +if basedir == "" then basedir = "./" end + +-- Required by load_strings() +function string.trim(s) + return s:gsub("^%s*(.-)%s*$", "%1") +end + +dofile(basedir.."/../lib.lua") + +local me = arg[0]:gsub(".*[/\\](.*)$", "%1") + +local function err(fmt, ...) + io.stderr:write(("%s: %s\n"):format(me, fmt:format(...))) + os.exit(1) +end + +local template +local catalogs = { } + +local function usage() + print([[ +Usage: ]]..me..[[ [OPTIONS] TEMPLATE CATALOG... + +Update a catalog with new strings from a template. + +Available options: + -h,--help Show this help screen and exit. + -o,--output X Set output file (default: stdout). + +Messages in the template that are not on the catalog are added to the +catalog at the end. + +This tool also checks messages that are in the catalog but not in the +template, and reports such lines. It's up to the user to remove such +lines, if so desired. +]]) + os.exit(0) +end + +local i = 1 + +while i <= #arg do + local a = arg[i] + if (a == "-h") or (a == "--help") then + usage() + elseif (a == "-o") or (a == "--output") then + i = i + 1 + if i > #arg then + err("missing required argument to `%s'", a) + end + elseif (a == "-c") or (a == "--comment") then + old_msg_mode = "c" + elseif (a == "-d") or (a == "--delete") then + old_msg_mode = "d" + elseif a:sub(1, 1) ~= "-" then + if not template then + template = a + else + table.insert(catalogs, a) + end + else + err("unrecognized option `%s'", a) + end + i = i + 1 +end + +if not template then + err("no template specified") +elseif #catalogs == 0 then + err("no catalogs specified") +end + +local f, e = io.open(template, "r") +if not f then + err("error opening template: %s", e) +end + +local function printf(fmt, ...) + outfile:write(fmt:format(...)) +end + +local escapes = { ["\n"] = "\\n", ["="] = "\\=", ["\\"] = "\\\\", } +local function escape(s) + return s:gsub("[\\\n=]", escapes) +end + +if output then + local e + outfile, e = io.open(output, "w") + if not outfile then + err("error opening file for writing: %s", e) + end +end + +local function printf(fmt, ...) + io.stdout:write(fmt:format(...)) +end + +local template_msgs = load_strings(template) + +for _, file in ipairs(catalogs) do + print("Processing: "..file) + local catalog_msgs = load_strings(file) + local dirty_lines = { } + if catalog_msgs then + -- Add new entries from template. + for k in pairs(template_msgs) do + if not catalog_msgs[k] then + print("NEW: "..k) + table.insert(dirty_lines, escape(k).." =") + end + end + -- Check for old messages. + for k, v in pairs(catalog_msgs) do + if not template_msgs[k] then + print("OLD: "..k) + end + end + if #dirty_lines > 0 then + local outf, e = io.open(file, "a+") + if outf then + outf:write("\n") + for _, line in ipairs(dirty_lines) do + outf:write(line) + outf:write("\n") + end + outf:close() + else + io.stderr:write(("%s: WARNING: cannot write: %s\n"):format(me, e)) + end + end + else + io.stderr:write(("%s: WARNING: could not load catalog\n"):format(me)) + end +end