Add 'intllib' mod:
Commit: https://github.com/minetest-mods/intllib/tree/49e965d Patch: https://github.com/AntumMT/mtmod-intllib/tree/48d1914master
parent
997a7e7648
commit
1d031f3204
|
@ -48,6 +48,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
|
||||||
* [jukebox][] ([WTFPL / CC0][lic.jukebox]) -- version: [e6a507f Git][ver.jukebox] *2016-05-23*
|
* [jukebox][] ([WTFPL / CC0][lic.jukebox]) -- version: [e6a507f Git][ver.jukebox] *2016-05-23*
|
||||||
* [trampoline][] ([GPL][lic.gpl3.0]) -- version: [ab1c289 Git][ver.trampoline] *2017-05-26*
|
* [trampoline][] ([GPL][lic.gpl3.0]) -- version: [ab1c289 Git][ver.trampoline] *2017-05-26*
|
||||||
* [trash_can][] ([MIT][lic.trash_can]) -- version: [5fd3df7 Git][ver.trash_can] *2016-01-14* ([patched][patch.trash_can])
|
* [trash_can][] ([MIT][lic.trash_can]) -- version: [5fd3df7 Git][ver.trash_can] *2016-01-14* ([patched][patch.trash_can])
|
||||||
|
* [intllib][] ([Unilicense][lic.unilicense]) -- version: [49e965d Git][ver.intllib] ** ([patched][patch.intllib])
|
||||||
* inventory/
|
* inventory/
|
||||||
* [bags][] ([BSD 3-Clause][lic.bags]) -- version: [f17d829 Git][ver.bags] *2015-10-11* ([patched][patch.bags])
|
* [bags][] ([BSD 3-Clause][lic.bags]) -- version: [f17d829 Git][ver.bags] *2015-10-11* ([patched][patch.bags])
|
||||||
* [inventory_plus][] ([BSD 3-Clause][lic.inventory_plus]) -- version: [fd71e3d Git][ver.inventory_plus] *2016-05-13*
|
* [inventory_plus][] ([BSD 3-Clause][lic.inventory_plus]) -- version: [fd71e3d Git][ver.inventory_plus] *2016-05-13*
|
||||||
|
@ -239,6 +240,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
|
||||||
[hudbars]: https://forum.minetest.net/viewtopic.php?t=11153
|
[hudbars]: https://forum.minetest.net/viewtopic.php?t=11153
|
||||||
[hudmap]: https://github.com/stujones11/hudmap
|
[hudmap]: https://github.com/stujones11/hudmap
|
||||||
[ilights]: https://forum.minetest.net/viewtopic.php?t=12200
|
[ilights]: https://forum.minetest.net/viewtopic.php?t=12200
|
||||||
|
[intllib]: https://forum.minetest.net/viewtopic.php?t=4929
|
||||||
[invisibility]: https://forum.minetest.net/viewtopic.php?t=14846
|
[invisibility]: https://forum.minetest.net/viewtopic.php?t=14846
|
||||||
[invisible]: https://forum.minetest.net/viewtopic.php?t=14399
|
[invisible]: https://forum.minetest.net/viewtopic.php?t=14399
|
||||||
[inventory_plus]: https://forum.minetest.net/viewtopic.php?t=3100
|
[inventory_plus]: https://forum.minetest.net/viewtopic.php?t=3100
|
||||||
|
@ -451,6 +453,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
|
||||||
[ver.hudbars]: http://repo.or.cz/minetest_hudbars.git/tree/bd0641a
|
[ver.hudbars]: http://repo.or.cz/minetest_hudbars.git/tree/bd0641a
|
||||||
[ver.hudmap]: https://github.com/stujones11/hudmap/tree/09d40f3
|
[ver.hudmap]: https://github.com/stujones11/hudmap/tree/09d40f3
|
||||||
[ver.ilights]: https://github.com/minetest-mods/ilights/tree/7060243
|
[ver.ilights]: https://github.com/minetest-mods/ilights/tree/7060243
|
||||||
|
[ver.intllib]: https://github.com/minetest-mods/intllib/tree/49e965d
|
||||||
[ver.inventory_plus]: https://github.com/cornernote/minetest-inventory_plus/tree/fd71e3d
|
[ver.inventory_plus]: https://github.com/cornernote/minetest-inventory_plus/tree/fd71e3d
|
||||||
[ver.invisibility]: https://github.com/tenplus1/invisibility/tree/bf4156b
|
[ver.invisibility]: https://github.com/tenplus1/invisibility/tree/bf4156b
|
||||||
[ver.jukebox]: https://github.com/minetest-mods/jukebox/tree/e6a507f
|
[ver.jukebox]: https://github.com/minetest-mods/jukebox/tree/e6a507f
|
||||||
|
@ -538,6 +541,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
|
||||||
[patch.hovercraft]: https://github.com/AntumMT/mtmod-hovercraft/tree/73a6223
|
[patch.hovercraft]: https://github.com/AntumMT/mtmod-hovercraft/tree/73a6223
|
||||||
[patch.hud]: https://github.com/AntumMT/mtmod-hud/tree/6846e20
|
[patch.hud]: https://github.com/AntumMT/mtmod-hud/tree/6846e20
|
||||||
[patch.hudbars]: https://github.com/AntumMT/mtmod-hudbars/tree/31926a0
|
[patch.hudbars]: https://github.com/AntumMT/mtmod-hudbars/tree/31926a0
|
||||||
|
[patch.intllib]: https://github.com/AntumMT/mtmod-intllib/tree/48d1914
|
||||||
[patch.invisibility]: https://github.com/AntumMT/mtmod-invisibility/tree/f045c7c
|
[patch.invisibility]: https://github.com/AntumMT/mtmod-invisibility/tree/f045c7c
|
||||||
[patch.mesecons]: https://github.com/AntumMT/mtmp-mesecons/tree/830823a
|
[patch.mesecons]: https://github.com/AntumMT/mtmp-mesecons/tree/830823a
|
||||||
[patch.minetest_game]: https://github.com/AntumMT/mtgame-minetest/tree/2e390d0
|
[patch.minetest_game]: https://github.com/AntumMT/mtgame-minetest/tree/2e390d0
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
# Bilioteca de internacionalización para Minetest
|
||||||
|
|
||||||
|
Por Diego Martínez (kaeza).
|
||||||
|
Lanzada bajo Unlicense. Véase `LICENSE.md` para más detalles.
|
||||||
|
|
||||||
|
Éste mod es un intento por proveer soporte para internacionalización
|
||||||
|
de los mods (algo que a Minetest le falta de momento).
|
||||||
|
|
||||||
|
Si tienes alguna duda/comentario, por favor publica en el
|
||||||
|
[tema del foro][topic]. Por reporte de errores, use el
|
||||||
|
[bugtracker][bugtracker] en Github.
|
||||||
|
|
||||||
|
## Cómo usar
|
||||||
|
|
||||||
|
Si eres un jugador regular en busca de textos traducidos, simplemente
|
||||||
|
[instala][installing_mods] éste mod como cualquier otro.
|
||||||
|
|
||||||
|
El mod trata de detectar tu idioma, pero ya que no hay una forma portable de
|
||||||
|
hacerlo, prueba varias alternativas:
|
||||||
|
|
||||||
|
* `language` setting in `minetest.conf`.
|
||||||
|
* `LANGUAGE` environment variable.
|
||||||
|
* `LANG` environment variable.
|
||||||
|
|
||||||
|
En cualquier caso, el resultado final debería ser el
|
||||||
|
[Código de idioma ISO 639-1][ISO639-1] del idioma deseado.
|
||||||
|
|
||||||
|
### Desarrolladores
|
||||||
|
|
||||||
|
Si desarrollas mods y estás buscando añadir soporte de internacionalización
|
||||||
|
a tu mod, ve el fichero `doc/developer.md`.
|
||||||
|
|
||||||
|
### Traductores
|
||||||
|
|
||||||
|
Si eres un traductor, ve el fichero `doc/translator.md`.
|
||||||
|
|
||||||
|
[topic]: https://forum.minetest.net/viewtopic.php?id=4929
|
||||||
|
[bugtracker]: https://github.com/minetest-mods/intllib/issues
|
||||||
|
[installing_mods]: https://wiki.minetest.net/Installing_mods/es
|
||||||
|
[ISO639-1]: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
|
|
@ -0,0 +1,50 @@
|
||||||
|
# Lib de Internacionalização para Minetest
|
||||||
|
|
||||||
|
Por Diego Martínez (kaeza).
|
||||||
|
Lançado sob Unlicense. Veja `LICENSE.md` para detalhes.
|
||||||
|
|
||||||
|
Este mod é uma tentativa de fornecer suporte de internacionalização para mods
|
||||||
|
(algo que Minetest atualmente carece).
|
||||||
|
|
||||||
|
|
||||||
|
Se você tiver algum comentário/sugestão, favor postar no
|
||||||
|
[tópico do fórum][topico]. Para reportar bugs, use o
|
||||||
|
[rastreador de bugs][bugtracker] no GitHub.
|
||||||
|
|
||||||
|
|
||||||
|
## Como usar
|
||||||
|
|
||||||
|
Se você é um jogador regular procurando por textos traduzidos,
|
||||||
|
basta instalar este mod como qualquer outro, e então habilite-lo na GUI.
|
||||||
|
|
||||||
|
O mod tenta detectar o seu idioma, mas como não há atualmente nenhuma
|
||||||
|
maneira portátil de fazer isso, ele tenta várias alternativas:
|
||||||
|
|
||||||
|
Para usar este mod, basta [instalá-lo][instalando_mods]
|
||||||
|
e habilita-lo na GUI.
|
||||||
|
|
||||||
|
O modificador tenta detectar o idioma do usuário, mas já que não há atualmente
|
||||||
|
nenhuma maneira portátil para fazer isso, ele tenta várias alternativas, e usa
|
||||||
|
o primeiro encontrado:
|
||||||
|
|
||||||
|
* `language` definido em `minetest.conf`.
|
||||||
|
* Variável de ambiente `LANGUAGE`.
|
||||||
|
* Variável de ambiente `LANG`.
|
||||||
|
* Se todos falharem, usa `en` (inglês).
|
||||||
|
|
||||||
|
Em todo caso, o resultado final deve ser um
|
||||||
|
[Código de Idioma ISO 639-1][ISO639-1] do idioma desejado.
|
||||||
|
|
||||||
|
### Desenvolvedores de mods
|
||||||
|
|
||||||
|
Se você é um desenvolvedor de mod procurando adicionar suporte de
|
||||||
|
internacionalização ao seu mod, consulte `doc/developer.md`.
|
||||||
|
|
||||||
|
### Tradutores
|
||||||
|
|
||||||
|
Se você é um tradutor, consulte `doc/translator.md`.
|
||||||
|
|
||||||
|
[topico]: https://forum.minetest.net/viewtopic.php?id=4929
|
||||||
|
[bugtracker]: https://github.com/minetest-mods/intllib/issues
|
||||||
|
[instalando_mods]: http://wiki.minetest.net/Installing_Mods/pt-br
|
||||||
|
[ISO639-1]: https://pt.wikipedia.org/wiki/ISO_639
|
|
@ -0,0 +1,43 @@
|
||||||
|
|
||||||
|
# Internationalization Lib for Minetest
|
||||||
|
|
||||||
|
By Diego Martínez (kaeza).
|
||||||
|
Released under Unlicense. See `LICENSE.md` for details.
|
||||||
|
|
||||||
|
This mod is an attempt at providing internationalization support for mods
|
||||||
|
(something Minetest currently lacks).
|
||||||
|
|
||||||
|
Should you have any comments/suggestions, please post them in the
|
||||||
|
[forum topic][topic]. For bug reports, use the [bug tracker][bugtracker]
|
||||||
|
on Github.
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
If you are a regular player looking for translated texts, just
|
||||||
|
[install][installing_mods] this mod like any other one, then enable it
|
||||||
|
in the GUI.
|
||||||
|
|
||||||
|
The mod tries to detect your language, but since there's currently no
|
||||||
|
portable way to do this, it tries several alternatives:
|
||||||
|
|
||||||
|
* `language` setting in `minetest.conf`.
|
||||||
|
* `LANGUAGE` environment variable.
|
||||||
|
* `LANG` environment variable.
|
||||||
|
* If all else fails, uses `en`.
|
||||||
|
|
||||||
|
In any case, the end result should be the [ISO 639-1 Language Code][ISO639-1]
|
||||||
|
of the desired language.
|
||||||
|
|
||||||
|
### Mod developers
|
||||||
|
|
||||||
|
If you are a mod developer looking to add internationalization support to
|
||||||
|
your mod, see `doc/developer.md`.
|
||||||
|
|
||||||
|
### Translators
|
||||||
|
|
||||||
|
If you are a translator, see `doc/translator.md`.
|
||||||
|
|
||||||
|
[topic]: https://forum.minetest.net/viewtopic.php?id=4929
|
||||||
|
[bugtracker]: https://github.com/minetest-mods/intllib/issues
|
||||||
|
[installing_mods]: https://wiki.minetest.net/Installing_mods
|
||||||
|
[ISO639-1]: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
|
|
@ -0,0 +1,3 @@
|
||||||
|
Internationalization library.
|
||||||
|
This mod provides a way to internationalize/localize mods to other languages in an easy way.
|
||||||
|
See the README file for details.
|
|
@ -0,0 +1,226 @@
|
||||||
|
|
||||||
|
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 function unescape(str)
|
||||||
|
return (strgsub(str, "(\\+)([nrt]?)", function(bs, c)
|
||||||
|
local bsl = #bs
|
||||||
|
local realbs = strrep("\\", bsl/2)
|
||||||
|
if bsl%2 == 1 then
|
||||||
|
c = escapes[c] or c
|
||||||
|
end
|
||||||
|
return realbs..c
|
||||||
|
end))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function parse_po(str)
|
||||||
|
local state, msgid, msgid_plural, msgstrind
|
||||||
|
local texts = { }
|
||||||
|
local lineno = 0
|
||||||
|
local function perror(msg)
|
||||||
|
return error(msg.." at line "..lineno)
|
||||||
|
end
|
||||||
|
for _, line in ipairs(str:split("\n")) do repeat
|
||||||
|
lineno = lineno + 1
|
||||||
|
line = trim(line)
|
||||||
|
|
||||||
|
if line == "" or strmatch(line, "^#") then
|
||||||
|
state, msgid, msgid_plural = nil, nil, nil
|
||||||
|
break -- continue
|
||||||
|
end
|
||||||
|
|
||||||
|
local mid = strmatch(line, "^%s*msgid%s*\"(.*)\"%s*$")
|
||||||
|
if mid then
|
||||||
|
if state == "id" then
|
||||||
|
return perror("unexpected msgid")
|
||||||
|
end
|
||||||
|
state, msgid = "id", unescape(mid)
|
||||||
|
break -- continue
|
||||||
|
end
|
||||||
|
|
||||||
|
mid = strmatch(line, "^%s*msgid_plural%s*\"(.*)\"%s*$")
|
||||||
|
if mid then
|
||||||
|
if state ~= "id" then
|
||||||
|
return perror("unexpected msgid_plural")
|
||||||
|
end
|
||||||
|
state, msgid_plural = "idp", unescape(mid)
|
||||||
|
break -- continue
|
||||||
|
end
|
||||||
|
|
||||||
|
local ind, mstr = strmatch(line,
|
||||||
|
"^%s*msgstr([0-9%[%]]*)%s*\"(.*)\"%s*$")
|
||||||
|
if ind then
|
||||||
|
if not msgid then
|
||||||
|
return perror("missing msgid")
|
||||||
|
elseif ind == "" then
|
||||||
|
msgstrind = 0
|
||||||
|
elseif strmatch(ind, "%[[0-9]+%]") then
|
||||||
|
msgstrind = tonumber(strsub(ind, 2, -2))
|
||||||
|
else
|
||||||
|
return perror("malformed msgstr")
|
||||||
|
end
|
||||||
|
texts[msgid] = texts[msgid] or { }
|
||||||
|
if msgid_plural then
|
||||||
|
texts[msgid_plural] = texts[msgid]
|
||||||
|
end
|
||||||
|
texts[msgid][msgstrind] = unescape(mstr)
|
||||||
|
state = "str"
|
||||||
|
break -- continue
|
||||||
|
end
|
||||||
|
|
||||||
|
mstr = strmatch(line, "^%s*\"(.*)\"%s*$")
|
||||||
|
if mstr then
|
||||||
|
if state == "id" then
|
||||||
|
msgid = msgid..unescape(mstr)
|
||||||
|
break -- continue
|
||||||
|
elseif state == "idp" then
|
||||||
|
msgid_plural = msgid_plural..unescape(mstr)
|
||||||
|
break -- continue
|
||||||
|
elseif state == "str" then
|
||||||
|
local text = texts[msgid][msgstrind]
|
||||||
|
texts[msgid][msgstrind] = text..unescape(mstr)
|
||||||
|
break -- continue
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return perror("malformed line")
|
||||||
|
|
||||||
|
-- luacheck: ignore
|
||||||
|
until true end -- end for
|
||||||
|
|
||||||
|
return texts
|
||||||
|
end
|
||||||
|
|
||||||
|
local M = { }
|
||||||
|
|
||||||
|
local function warn(msg)
|
||||||
|
minetest.log("warning", "[intllib] "..msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- hax!
|
||||||
|
-- This function converts a C expression to an equivalent Lua expression.
|
||||||
|
-- It handles enough stuff to parse the `Plural-Forms` header correctly.
|
||||||
|
-- Note that it assumes the C expression is valid to begin with.
|
||||||
|
local function compile_plural_forms(str)
|
||||||
|
local plural = strmatch(str, "plural=([^;]+);?$")
|
||||||
|
local function replace_ternary(s)
|
||||||
|
local c, t, f = strmatch(s, "^(.-)%?(.-):(.*)")
|
||||||
|
if c then
|
||||||
|
return ("__if("
|
||||||
|
..replace_ternary(c)
|
||||||
|
..","..replace_ternary(t)
|
||||||
|
..","..replace_ternary(f)
|
||||||
|
..")")
|
||||||
|
end
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
plural = replace_ternary(plural)
|
||||||
|
plural = strgsub(plural, "&&", " and ")
|
||||||
|
plural = strgsub(plural, "||", " or ")
|
||||||
|
plural = strgsub(plural, "!=", "~=")
|
||||||
|
plural = strgsub(plural, "!", " not ")
|
||||||
|
local f, err = loadstring([[
|
||||||
|
local function __if(c, t, f)
|
||||||
|
if c and c~=0 then return t else return f end
|
||||||
|
end
|
||||||
|
local function __f(n)
|
||||||
|
return (]]..plural..[[)
|
||||||
|
end
|
||||||
|
return (__f(...))
|
||||||
|
]])
|
||||||
|
if not f then return nil, err end
|
||||||
|
local env = { }
|
||||||
|
env._ENV, env._G = env, env
|
||||||
|
setfenv(f, env)
|
||||||
|
return function(n)
|
||||||
|
local v = f(n)
|
||||||
|
if type(v) == "boolean" then
|
||||||
|
-- Handle things like a plain `n != 1`
|
||||||
|
v = v and 1 or 0
|
||||||
|
end
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function parse_headers(str)
|
||||||
|
local headers = { }
|
||||||
|
for _, line in ipairs(str:split("\n")) do
|
||||||
|
local k, v = strmatch(line, "^([^:]+):%s*(.*)")
|
||||||
|
if k then
|
||||||
|
headers[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return headers
|
||||||
|
end
|
||||||
|
|
||||||
|
local function load_catalog(filename)
|
||||||
|
local f, data, err
|
||||||
|
|
||||||
|
local function bail(msg)
|
||||||
|
warn(msg..(err and ": " or "")..(err or ""))
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
f, err = io.open(filename, "rb")
|
||||||
|
if not f then
|
||||||
|
return --bail("failed to open catalog")
|
||||||
|
end
|
||||||
|
|
||||||
|
data, err = f:read("*a")
|
||||||
|
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
if not data then
|
||||||
|
return bail("failed to read catalog")
|
||||||
|
end
|
||||||
|
|
||||||
|
data, err = parse_po(data)
|
||||||
|
if not data then
|
||||||
|
return bail("failed to parse catalog")
|
||||||
|
end
|
||||||
|
|
||||||
|
err = nil
|
||||||
|
local hdrs = data[""]
|
||||||
|
if not (hdrs and hdrs[0]) then
|
||||||
|
return bail("catalog has no headers")
|
||||||
|
end
|
||||||
|
|
||||||
|
hdrs = parse_headers(hdrs[0])
|
||||||
|
|
||||||
|
local pf = hdrs["Plural-Forms"]
|
||||||
|
if not pf then
|
||||||
|
-- XXX: Is this right? Gettext assumes this if header not present.
|
||||||
|
pf = "nplurals=2; plural=n != 1"
|
||||||
|
end
|
||||||
|
|
||||||
|
data.plural_index, err = compile_plural_forms(pf)
|
||||||
|
if not data.plural_index then
|
||||||
|
return bail("failed to compile plural forms")
|
||||||
|
end
|
||||||
|
|
||||||
|
--warn("loaded: "..filename)
|
||||||
|
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.load_catalogs(path)
|
||||||
|
local langs = intllib.get_detected_languages()
|
||||||
|
|
||||||
|
local cats = { }
|
||||||
|
for _, lang in ipairs(langs) do
|
||||||
|
local cat = load_catalog(path.."/"..lang..".po")
|
||||||
|
if cat then
|
||||||
|
cats[#cats+1] = cat
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return cats
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
|
@ -0,0 +1,210 @@
|
||||||
|
|
||||||
|
-- Old multi-load method compatibility
|
||||||
|
if rawget(_G, "intllib") then return end
|
||||||
|
|
||||||
|
intllib = {
|
||||||
|
getters = {},
|
||||||
|
strings = {},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
local MP = minetest.get_modpath("intllib")
|
||||||
|
|
||||||
|
dofile(MP.."/lib.lua")
|
||||||
|
|
||||||
|
|
||||||
|
local LANG = minetest.settings:get("language")
|
||||||
|
if not (LANG and (LANG ~= "")) then LANG = os.getenv("LANG") end
|
||||||
|
if not (LANG and (LANG ~= "")) then LANG = "en" end
|
||||||
|
|
||||||
|
|
||||||
|
local INS_CHAR = intllib.INSERTION_CHAR
|
||||||
|
local insertion_pattern = "("..INS_CHAR.."?)"..INS_CHAR.."(%(?)(%d+)(%)?)"
|
||||||
|
|
||||||
|
local function do_replacements(str, ...)
|
||||||
|
local args = {...}
|
||||||
|
-- Outer parens discard extra return values
|
||||||
|
return (str:gsub(insertion_pattern, function(escape, open, num, close)
|
||||||
|
if escape == "" then
|
||||||
|
local replacement = tostring(args[tonumber(num)])
|
||||||
|
if open == "" then
|
||||||
|
replacement = replacement..close
|
||||||
|
end
|
||||||
|
return replacement
|
||||||
|
else
|
||||||
|
return INS_CHAR..open..num..close
|
||||||
|
end
|
||||||
|
end))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function make_getter(msgstrs)
|
||||||
|
return function(s, ...)
|
||||||
|
local str
|
||||||
|
if msgstrs then
|
||||||
|
str = msgstrs[s]
|
||||||
|
end
|
||||||
|
if not str or str == "" then
|
||||||
|
str = s
|
||||||
|
end
|
||||||
|
if select("#", ...) == 0 then
|
||||||
|
return str
|
||||||
|
end
|
||||||
|
return do_replacements(str, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function Getter(modname)
|
||||||
|
modname = modname or minetest.get_current_modname()
|
||||||
|
if not intllib.getters[modname] then
|
||||||
|
local msgstr = intllib.get_strings(modname)
|
||||||
|
intllib.getters[modname] = make_getter(msgstr)
|
||||||
|
end
|
||||||
|
return intllib.getters[modname]
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function intllib.Getter(modname)
|
||||||
|
minetest.log("deprecated", "intllib.Getter is deprecated."
|
||||||
|
.."Please use intllib.make_gettext_pair instead.")
|
||||||
|
return Getter(modname)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local strfind, strsub = string.find, string.sub
|
||||||
|
local langs
|
||||||
|
|
||||||
|
local function split(str, sep)
|
||||||
|
local pos, endp = 1, #str+1
|
||||||
|
return function()
|
||||||
|
if (not pos) or pos > endp then return end
|
||||||
|
local s, e = strfind(str, sep, pos, true)
|
||||||
|
local part = strsub(str, pos, s and s-1)
|
||||||
|
pos = e and e + 1
|
||||||
|
return part
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function intllib.get_detected_languages()
|
||||||
|
if langs then return langs end
|
||||||
|
|
||||||
|
langs = { }
|
||||||
|
|
||||||
|
local function addlang(l)
|
||||||
|
local sep
|
||||||
|
langs[#langs+1] = l
|
||||||
|
sep = strfind(l, ".", 1, true)
|
||||||
|
if sep then
|
||||||
|
l = strsub(l, 1, sep-1)
|
||||||
|
langs[#langs+1] = l
|
||||||
|
end
|
||||||
|
sep = strfind(l, "_", 1, true)
|
||||||
|
if sep then
|
||||||
|
langs[#langs+1] = strsub(l, 1, sep-1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local v
|
||||||
|
|
||||||
|
v = minetest.settings:get("language")
|
||||||
|
if v and v~="" then
|
||||||
|
addlang(v)
|
||||||
|
end
|
||||||
|
|
||||||
|
v = os.getenv("LANGUAGE")
|
||||||
|
if v then
|
||||||
|
for item in split(v, ":") do
|
||||||
|
langs[#langs+1] = item
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
v = os.getenv("LANG")
|
||||||
|
if v then
|
||||||
|
addlang(v)
|
||||||
|
end
|
||||||
|
|
||||||
|
langs[#langs+1] = "en"
|
||||||
|
|
||||||
|
return langs
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local gettext = dofile(minetest.get_modpath("intllib").."/gettext.lua")
|
||||||
|
|
||||||
|
|
||||||
|
local function catgettext(catalogs, msgid)
|
||||||
|
for _, cat in ipairs(catalogs) do
|
||||||
|
local msgstr = cat and cat[msgid]
|
||||||
|
if msgstr and msgstr~="" then
|
||||||
|
local msg = msgstr[0]
|
||||||
|
return msg~="" and msg or nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function catngettext(catalogs, msgid, msgid_plural, n)
|
||||||
|
n = math.floor(n)
|
||||||
|
for _, cat in ipairs(catalogs) do
|
||||||
|
local msgstr = cat and cat[msgid]
|
||||||
|
if msgstr then
|
||||||
|
local index = cat.plural_index(n)
|
||||||
|
local msg = msgstr[index]
|
||||||
|
return msg~="" and msg or nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return n==1 and msgid or msgid_plural
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local gettext_getters = { }
|
||||||
|
function intllib.make_gettext_pair(modname)
|
||||||
|
modname = modname or minetest.get_current_modname()
|
||||||
|
if gettext_getters[modname] then
|
||||||
|
return unpack(gettext_getters[modname])
|
||||||
|
end
|
||||||
|
local localedir = minetest.get_modpath(modname).."/locale"
|
||||||
|
local catalogs = gettext.load_catalogs(localedir)
|
||||||
|
local getter = Getter(modname)
|
||||||
|
local function gettext_func(msgid, ...)
|
||||||
|
local msgstr = (catgettext(catalogs, msgid)
|
||||||
|
or getter(msgid))
|
||||||
|
return do_replacements(msgstr, ...)
|
||||||
|
end
|
||||||
|
local function ngettext_func(msgid, msgid_plural, n, ...)
|
||||||
|
local msgstr = (catngettext(catalogs, msgid, msgid_plural, n)
|
||||||
|
or getter(msgid))
|
||||||
|
return do_replacements(msgstr, ...)
|
||||||
|
end
|
||||||
|
gettext_getters[modname] = { gettext_func, ngettext_func }
|
||||||
|
return gettext_func, ngettext_func
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function get_locales(code)
|
||||||
|
local ll, cc = code:match("^(..)_(..)")
|
||||||
|
if ll then
|
||||||
|
return { ll.."_"..cc, ll, ll~="en" and "en" or nil }
|
||||||
|
else
|
||||||
|
return { code, code~="en" and "en" or nil }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function intllib.get_strings(modname, langcode)
|
||||||
|
langcode = langcode or LANG
|
||||||
|
modname = modname or minetest.get_current_modname()
|
||||||
|
local msgstr = intllib.strings[modname]
|
||||||
|
if not msgstr then
|
||||||
|
local modpath = minetest.get_modpath(modname)
|
||||||
|
msgstr = { }
|
||||||
|
for _, l in ipairs(get_locales(langcode)) do
|
||||||
|
local t = intllib.load_strings(modpath.."/locale/"..l..".txt") or { }
|
||||||
|
for k, v in pairs(t) do
|
||||||
|
msgstr[k] = msgstr[k] or v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
intllib.strings[modname] = msgstr
|
||||||
|
end
|
||||||
|
return msgstr
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
-- Support for the old multi-load method
|
||||||
|
dofile(minetest.get_modpath("intllib").."/init.lua")
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
|
||||||
|
intllib = intllib or {}
|
||||||
|
|
||||||
|
local INS_CHAR = "@"
|
||||||
|
intllib.INSERTION_CHAR = INS_CHAR
|
||||||
|
|
||||||
|
local escapes = {
|
||||||
|
["\\"] = "\\",
|
||||||
|
["n"] = "\n",
|
||||||
|
["s"] = " ",
|
||||||
|
["t"] = "\t",
|
||||||
|
["r"] = "\r",
|
||||||
|
["f"] = "\f",
|
||||||
|
[INS_CHAR] = INS_CHAR..INS_CHAR,
|
||||||
|
}
|
||||||
|
|
||||||
|
local function unescape(str)
|
||||||
|
local parts = {}
|
||||||
|
local n = 1
|
||||||
|
local function add(s)
|
||||||
|
parts[n] = s
|
||||||
|
n = n + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local start = 1
|
||||||
|
while true do
|
||||||
|
local pos = str:find("\\", start, true)
|
||||||
|
if pos then
|
||||||
|
add(str:sub(start, pos - 1))
|
||||||
|
else
|
||||||
|
add(str:sub(start))
|
||||||
|
break
|
||||||
|
end
|
||||||
|
local c = str:sub(pos + 1, pos + 1)
|
||||||
|
add(escapes[c] or c)
|
||||||
|
start = pos + 2
|
||||||
|
end
|
||||||
|
return table.concat(parts)
|
||||||
|
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 intllib.load_strings(filename)
|
||||||
|
local file, err = io.open(filename, "r")
|
||||||
|
if not file then
|
||||||
|
return nil, err
|
||||||
|
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
|
|
@ -0,0 +1,45 @@
|
||||||
|
|
||||||
|
-- Fallback functions for when `intllib` is not installed.
|
||||||
|
-- Code released under Unlicense <http://unlicense.org>.
|
||||||
|
|
||||||
|
-- Get the latest version of this file at:
|
||||||
|
-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua
|
||||||
|
|
||||||
|
local function format(str, ...)
|
||||||
|
local args = { ... }
|
||||||
|
local function repl(escape, open, num, close)
|
||||||
|
if escape == "" then
|
||||||
|
local replacement = tostring(args[tonumber(num)])
|
||||||
|
if open == "" then
|
||||||
|
replacement = replacement..close
|
||||||
|
end
|
||||||
|
return replacement
|
||||||
|
else
|
||||||
|
return "@"..open..num..close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
|
||||||
|
end
|
||||||
|
|
||||||
|
local gettext, ngettext
|
||||||
|
if minetest.get_modpath("intllib") then
|
||||||
|
if intllib.make_gettext_pair then
|
||||||
|
-- New method using gettext.
|
||||||
|
gettext, ngettext = intllib.make_gettext_pair()
|
||||||
|
else
|
||||||
|
-- Old method using text files.
|
||||||
|
gettext = intllib.Getter()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Fill in missing functions.
|
||||||
|
|
||||||
|
gettext = gettext or function(msgid, ...)
|
||||||
|
return format(msgid, ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
ngettext = ngettext or function(msgid, msgid_plural, n, ...)
|
||||||
|
return format(n==1 and msgid or msgid_plural, ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
return gettext, ngettext
|
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
name = intllib
|
Loading…
Reference in New Issue