pax_global_header00006660000000000000000000000064131553454430014521gustar00rootroot0000000000000052 comment=9192771dcc826c23c6f34f1c3c717e16e631dc12 intllib-20180811/000077500000000000000000000000001315534544300134245ustar00rootroot00000000000000intllib-20180811/.gitignore000066400000000000000000000000111315534544300154040ustar00rootroot00000000000000.* _* *~ intllib-20180811/.luacheckrc000066400000000000000000000002141315534544300155260ustar00rootroot00000000000000 read_globals = { "minetest", } globals = { "intllib", } files["intltest/init.lua"] = { ignore = { "212", -- Unused argument. }, } intllib-20180811/LICENSE.md000066400000000000000000000022741315534544300150350ustar00rootroot00000000000000 This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to intllib-20180811/README-es.md000066400000000000000000000025401315534544300153110ustar00rootroot00000000000000 # 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 intllib-20180811/README-it.md000066400000000000000000000030461315534544300153200ustar00rootroot00000000000000 # Libreria di internazionalizzazione per Minetest Di Diego Martínez (kaeza). Rilasciata sotto licenza Unlicense. Si veda `LICENSE.md` per i dettagli. Questo modulo è un tentativo per fornire il supporto di internazionalizzazione per i moduli (cosa che attualmente manca a Minetest). Se aveste qualunque commento o suggerimento, per piacere scriveteli nella [discussione sul forum][topic]. Per i rapporti sui bug, usate il [tracciatore di bug][bugtracker] su Github. ## Come usarla Se siete un* giocatrice/tore che vuole i testi tradotti, [installate][installing_mods] questo modulo come qualunque altro, poi abilitatelo tramite l'interfaccia grafica. Il modulo tenta di rilevare la vostra lingua, ma dato che al momento non c'è un metodo portabile per farlo, prova diverse alternative: * `language` impostazione in `minetest.conf`. * `LANGUAGE` variabile d'ambiente. * `LANG` variabile d'ambiente. * Se nessuna funziona, usa `en`. In ogni caso, il risultato finale dovrebbe essere il [codice di lingua ISO 639-1][ISO639-1] del linguaggio desiderato. ### Sviluppatrici/tori di moduli Se siete un* sviluppatrice/tore di moduli desideros* di aggiungere il supporto per l'internazionalizzazione al vostro modulo, leggete `doc/developer-it.md`. ### Traduttrici/tori Se siete un* traduttrice/tore, leggete `doc/translator-it.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://it.wikipedia.org/wiki/ISO_639-1 intllib-20180811/README-ms.md000066400000000000000000000027721315534544300153300ustar00rootroot00000000000000 # Pustaka Pengantarabangsaan untuk Minetest Oleh Diego Martínez (kaeza). Diterbitkan bawah Unlicense. Lihat `LICENSE.md` untuk maklumat lanjut. Mods ini ialah suatu usaha untuk menyediakan sokongan pengantarabangsaan kepada mods (sesuatu yang Minetest tiada ketika ini). Jika anda mempunyai sebarang komen/cadangan, sila tulis ke dalam [topik forum][topik]. Untuk melaporkan pepijat, sila gunakan [penjejak pepijat][pepijat] Github. ## Bagaimanakah cara untuk menggunakannya? Jika anda pemain biasa yang mencari teks terjemahan, hanya [pasangkan][pasang_mods] mods ini seperti mods lain, kemudian bolehkannya melalui GUI. Mods ini cuba untuk mengesan bahasa anda, tetapi oleh kerana tiada cara mudah alih untuk melakukannya, ia cuba beberapa cara yang lain: * Tetapan `language` di dalam fail `minetest.conf`. * Pembolehubah sekitaran `LANGUAGE`. * Pembolehubah sekitaran `LANG`. * Jika semua di atas gagal, ia gunakan `en`. Dalam apa jua keadaan, hasil akhirnya sepatutnya menjadi [Kod Bahasa ISO 639-1][ISO639-1] untuk bahasa yang dikehendaki. ### Pembangun mods Jika anda seorang pembangun mods yang ingin menambah sokongan pengantarabangsaan kepada mods anda, sila lihat `doc/developer.md`. ### Penterjemah Jika anda seorang penterjemah, sila lihat `doc/translator.md`. [topik]: https://forum.minetest.net/viewtopic.php?id=4929 [pepijat]: https://github.com/minetest-mods/intllib/issues [pasang_mods]: https://wiki.minetest.net/Installing_Mods/ms [ISO639-1]: https://ms.wikipedia.org/wiki/Senarai_kod_ISO_639-1 intllib-20180811/README-pt_BR.md000066400000000000000000000032671315534544300157170ustar00rootroot00000000000000# 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 intllib-20180811/README.md000066400000000000000000000025301315534544300147030ustar00rootroot00000000000000 # 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 intllib-20180811/description.txt000066400000000000000000000002341315534544300165070ustar00rootroot00000000000000Internationalization library. This mod provides a way to internationalize/localize mods to other languages in an easy way. See the README file for details. intllib-20180811/doc/000077500000000000000000000000001315534544300141715ustar00rootroot00000000000000intllib-20180811/doc/developer-it.md000066400000000000000000000053621315534544300171200ustar00rootroot00000000000000 # Intllib - documentazione per sviluppatrici/tori ## Abilitare l'internazionalizzazione Per abilitare l'internazionalizzazione del vostro modulo, dovete copiare il file `lib/intllib.lua` nella cartella principale del vostro modulo, poi inserite questo codice standard nei file che necessitano la traduzione: -- Load support for intllib. local MP = minetest.get_modpath(minetest.get_current_modname()) local S, NS = dofile(MP.."/intllib.lua") Dovrete anche aggiungere la dipendenza facoltativa da intllib per il vostro modulo, per farlo aggiungete `intllib?` su una riga vuota nel vostro `depends.txt`. Si noti anche che se intllib non è installata, le funzioni di acquisizione del testo sono fatte in modo da restituire la stringa di testo originale. Questo è stato fatto in modo che non dobbiate spargere tonnellate di `if` (o costrutti simili) per controllare se la libreria è installata. Dopo avere messo il codice, dovete marcare le stringhe di testo che necessitano una traduzione. Per ciascuna stringa traducibile nei vostri codici sorgenti, usate la funzione `S` (si veda sopra) per restituire la stringa tradotta. Per esempio: minetest.register_node("miomod:mionodo", { -- Stringa semplice: description = S("Il mio fantastico nodo"), -- Stringa con inserti: description = S("Macchina @1", "Blu"), -- ... }) La funzione `NS` è l'equivalente di `ngettext`. Dovrebbe essere usata quando la stringa da tradurre ha forma singolare e plurale. Per esempio: -- Il primo `count` è per consentire a `ngettext` di stabilire quale forma -- usare. Il secondo `count` è per il sostituto effettivo. print(NS("Avete un oggetto.", "Avete @1 oggetti.", count, count)) ## Generare e aggiornare cataloghi Questo è il procedimento di base per lavorare con [gettext][gettext] Ogni volta che avete nuove stringhe da tradurre, dovreste fare quanto segue: cd /percorso/del/modulo /percorso/degli/strumenti/intllib/xgettext.sh file1.lua file2.lua ... Lo script creerà una cartella chiamata `locale` se non esiste già, e genererà il file `template.pot` (un modello con tutte le stringhe traducibili). Se avete già delle traduzioni, lo script provvederà al loro aggiornamento con le nuove stringhe. Lo script fornisce alcune opzioni al vero `xgettext` che dovrebbero essere sufficienti per la maggior parte dei casi. Se lo desiderate potete specificare altre opzioni: xgettext.sh -o file.pot --keyword=blaaaah:4,5 a.lua b.lua ... NOTA: C'è anche un file batch di Windows `xgettext.bat` per gli utenti di Windows, ma dovrete installare separatamente gli strumenti di gettext per la riga di comando. Si veda la parte superiore del file per la configurazione. [gettext]: https://www.gnu.org/software/gettext/ intllib-20180811/doc/developer.md000066400000000000000000000047331315534544300165070ustar00rootroot00000000000000 # Intllib developer documentation ## Enabling internationalization In order to enable internationalization for your mod, you will need to copy the file `lib/intllib.lua` into the root directory of your mod, then include this boilerplate code in files needing localization: -- Load support for intllib. local MP = minetest.get_modpath(minetest.get_current_modname()) local S, NS = dofile(MP.."/intllib.lua") You will also need to optionally depend on intllib, to do so add `intllib?` to an empty line in your `depends.txt`. Also note that if intllib is not installed, the getter functions are defined so they return the string unchanged. This is done so you don't have to sprinkle tons of `if`s (or similar constructs) to check if the lib is actually installed. Once you have the code in place, you need to mark strings that need translation. For each translatable string in your sources, use the `S` function (see above) to return the translated string. For example: minetest.register_node("mymod:mynode", { -- Simple string: description = S("My Fabulous Node"), -- String with insertions: description = S("@1 Car", "Blue"), -- ... }) The `NS` function is the equivalent of `ngettext`. It should be used when the string to be translated has singular and plural forms. For example: -- The first `count` is for `ngettext` to determine which form to use. -- The second `count` is the actual replacement. print(NS("You have one item.", "You have @1 items.", count, count)) ## Generating and updating catalogs This is the basic workflow for working with [gettext][gettext] Each time you have new strings to be translated, you should do the following: cd /path/to/mod /path/to/intllib/tools/xgettext.sh file1.lua file2.lua ... The script will create a directory named `locale` if it doesn't exist yet, and will generate the file `template.pot` (a template with all the translatable strings). If you already have translations, the script will proceed to update all of them with the new strings. The script passes some options to the real `xgettext` that should be enough for most cases. You may specify other options if desired: xgettext.sh -o file.pot --keyword=blargh:4,5 a.lua b.lua ... NOTE: There's also a Windows batch file `xgettext.bat` for Windows users, but you will need to install the gettext command line tools separately. See the top of the file for configuration. [gettext]: https://www.gnu.org/software/gettext/ intllib-20180811/doc/localefile-it.md000066400000000000000000000040041315534544300172220ustar00rootroot00000000000000 # Formato del file di traduzione *Nota: Questo documento spiega il vecchio formato in stile conf/ini. La nuova interfaccia usa file [gettext][gettext] `.po`. Si veda [Il formato dei file PO][PO-Files] per ulteriori informazioni.* Questo è un esempio per un file di traduzione in Italiano (`it.txt`): # Un commento. # Un altro commento. Questa riga viene ignorata dato che non ha il segno di uguale. Hello, World! = Ciao, Mondo! String with\nnewlines = Stringa con\na capo String with an \= equals sign = Stringa con un segno di uguaglianza \= I file "locale" (o di traduzione) sono file di testo semplice formati da righe nel formato `testo originale = testo tradotto`. Il file deve stare nella sottocartella `locale` del modulo, e il suo nome deve essere lo stesso del [codice di lingua ISO 639-1][ISO639-1] della lingua che volete fornire. I file di traduzione dovrebbero usare la codifica UTF-8. Le righe che iniziano con un cancelletto sono commenti e vengono ignorate dal lettore. Si noti che i commenti si estendono solo fino al termine della riga; non c'è nessun supporto per i commenti multiriga. Le righe senza un segno di uguale sono anch'esse ignorate. I caratteri che sono considerati "speciali" possono essere "escaped" di modo che siano presi letteralmente. Inoltre esistono molte sequenze di escape che possono essere utilizzate: * Qualsiasi `#`, `=` può essere escaped di modo da essere preso letteralmente. La sequenza `\#` è utile se il vostro testo sorgente inizia con `#`. * Le sequenze di escape comuni `\n` e `\t`, significano rispettivamente newline (a capo) e tabulazione orizzontale. * La sequenza speciale di escape`\s` rappresenta il carattere di spazio. È utile principalmente per aggiungere spazi prefissi o suffissi ai testi originali o tradotti, perché altrimenti quegli spazi verrebbero rimossi. [gettext]: https://www.gnu.org/software/gettext [PO-Files]: https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html [ISO639-1]: https://it.wikipedia.org/wiki/ISO_639-1 intllib-20180811/doc/localefile.md000066400000000000000000000034741315534544300166220ustar00rootroot00000000000000 # Locale file format *Note: This document explains the old conf/ini-like file format. The new interface uses [gettext][gettext] `.po` files. See [The Format of PO Files][PO-Files] for more information.* Here's an example for a Spanish locale file (`es.txt`): # A comment. # Another comment. This line is ignored since it has no equals sign. Hello, World! = Hola, Mundo! String with\nnewlines = Cadena con\nsaltos de linea String with an \= equals sign = Cadena con un signo de \= igualdad Locale (or translation) files are plain text files consisting of lines of the form `source text = translated text`. The file must reside in the mod's `locale` subdirectory, and must be named after the two-letter [ISO 639-1 Language Code][ISO639-1] of the language you want to support. The translation files should use the UTF-8 encoding. Lines beginning with a pound sign are comments and are effectively ignored by the reader. Note that comments only span until the end of the line; there's no support for multiline comments. Lines without an equals sign are also ignored. Characters that are considered "special" can be "escaped" so they are taken literally. There are also several escape sequences that can be used: * Any of `#`, `=` can be escaped to take them literally. The `\#` sequence is useful if your source text begins with `#`. * The common escape sequences `\n` and `\t`, meaning newline and horizontal tab respectively. * The special `\s` escape sequence represents the space character. It is mainly useful to add leading or trailing spaces to source or translated texts, as these spaces would be removed otherwise. [gettext]: https://www.gnu.org/software/gettext [PO-Files]: https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html [ISO639-1]: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes intllib-20180811/doc/translator-it.md000066400000000000000000000012651315534544300173220ustar00rootroot00000000000000 # Intllib - documentazione per traduttrici/tori #### Nuova interfaccia Usate i vostri strumenti preferiti per modificare i file `.po`. #### Vecchia interfaccia Per tradurre nella lingua che desiderate un modulo che supporta intllib, copiate il file `locale/template.txt` come `locale/LINGUA.txt` (dove `LINGUA` è il [codice di lingua ISO 639-1][ISO639-1] del vostro linguaggio. Aprite il nuovo file nel vostro editor preferito, e traducete ciascuna riga inserendo il testo tradotto dopo il segno di uguale. Si veda `localefile-it.md` per ulteriori informazioni sul formato del file. [gettext]: https://www.gnu.org/software/gettext/ [ISO639-1]: https://it.wikipedia.org/wiki/ISO_639-1 intllib-20180811/doc/translator.md000066400000000000000000000011731315534544300167060ustar00rootroot00000000000000 # Intllib translator documentation #### New interface Use your favorite tools to edit the `.po` files. #### Old interface To translate an intllib-supporting mod to your desired language, copy the `locale/template.txt` file to `locale/LANGUAGE.txt` (where `LANGUAGE` is the [ISO 639-1 Language Code][ISO639-1] of your language. Open up the new file in your favorite editor, and translate each line putting the translated text after the equals sign. See `localefile.md` for more information about the file format. [gettext]: https://www.gnu.org/software/gettext/ [ISO639-1]: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes intllib-20180811/gettext.lua000066400000000000000000000115601315534544300156160ustar00rootroot00000000000000 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 intllib-20180811/init.lua000066400000000000000000000113421315534544300150730ustar00rootroot00000000000000 -- 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) local info = debug and debug.getinfo and debug.getinfo(2) local loc = info and info.short_src..":"..info.currentline minetest.log("deprecated", "intllib.Getter is deprecated." .." Please use intllib.make_gettext_pair instead." ..(info and " (called from "..loc..")" or "")) 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 intllib-20180811/intllib.lua000066400000000000000000000001371315534544300155650ustar00rootroot00000000000000-- Support for the old multi-load method dofile(minetest.get_modpath("intllib").."/init.lua") intllib-20180811/intltest/000077500000000000000000000000001315534544300152725ustar00rootroot00000000000000intllib-20180811/intltest/README.md000066400000000000000000000004361315534544300165540ustar00rootroot00000000000000 # Intllib example This is a simple mod showing how to use intllib. It defines a test `intltest:test` item whose description is translated according to the user's language. Additionally, it demonstrates how to use plural forms by counting the number of times the item has been used. intllib-20180811/intltest/depends.txt000066400000000000000000000000111315534544300174450ustar00rootroot00000000000000intllib? intllib-20180811/intltest/init.lua000066400000000000000000000014731315534544300167450ustar00rootroot00000000000000 -- Load support for intllib. local MP = minetest.get_modpath(minetest.get_current_modname()) local S, NS = dofile(MP.."/intllib.lua") local use_count = 0 minetest.log("action", S("Hello, world!")) minetest.register_craftitem("intltest:test", { -- Example use of replacements. -- Translators: @1 is color, @2 is object. description = S("Test: @1 @2", S("Blue"), S("Car")), inventory_image = "default_sand.png", on_use = function(stack, user, pt) use_count = use_count + 1 -- Example use of `ngettext` function. -- First `use_count` is `n` for ngettext; -- Second one is actual replacement. -- Translators: @1 is use count. local message = NS("Item has been used @1 time.", "Item has been used @1 times.", use_count, use_count) minetest.chat_send_player(user:get_player_name(), message) end, }) intllib-20180811/intltest/intllib.lua000066400000000000000000000002021315534544300174240ustar00rootroot00000000000000 -- This file should be replaced by `intllib/lib/intllib.lua`. return dofile(minetest.get_modpath("intllib").."/lib/intllib.lua") intllib-20180811/intltest/locale/000077500000000000000000000000001315534544300165315ustar00rootroot00000000000000intllib-20180811/intltest/locale/es.po000066400000000000000000000021501315534544300174760ustar00rootroot00000000000000# I18N Test Mod. # Copyright (C) 2013-2017 Diego Martínez # This file is distributed under the same license as the intllib mod. # Diego Martínez , 2013-2017. # msgid "" msgstr "" "Project-Id-Version: I18N Test Mod 0.1.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-25 20:40-0300\n" "PO-Revision-Date: 2017-01-23 17:36-0300\n" "Last-Translator: Diego Martnez \n" "Language-Team: Spanish\n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: init.lua msgid "Hello, world!" msgstr "¡Hola, mundo!" #. Translators: @1 is color, @2 is object. #: init.lua msgid "Blue" msgstr "Azul" #: init.lua msgid "Car" msgstr "Carro" #. Translators: @1 is color, @2 is object. #: init.lua msgid "Test: @1 @2" msgstr "Prueba: @2 @1" #. Translators: @1 is use count. #: init.lua msgid "Item has been used @1 time." msgid_plural "Item has been used @1 times." msgstr[0] "El objeto ha sido usado @1 vez." msgstr[1] "El objeto ha sido usado @1 veces." intllib-20180811/intltest/locale/template.pot000066400000000000000000000020121315534544300210630ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-02-25 20:40-0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #: init.lua msgid "Hello, world!" msgstr "" #. Translators: @1 is color, @2 is object. #: init.lua msgid "Blue" msgstr "" #: init.lua msgid "Car" msgstr "" #. Translators: @1 is color, @2 is object. #: init.lua msgid "Test: @1 @2" msgstr "" #. Translators: @1 is use count. #: init.lua msgid "Item has been used @1 time." msgid_plural "Item has been used @1 times." msgstr[0] "" msgstr[1] "" intllib-20180811/lib.lua000066400000000000000000000023051315534544300146750ustar00rootroot00000000000000 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 intllib-20180811/lib/000077500000000000000000000000001315534544300141725ustar00rootroot00000000000000intllib-20180811/lib/intllib.lua000066400000000000000000000021421315534544300163310ustar00rootroot00000000000000 -- Fallback functions for when `intllib` is not installed. -- Code released under Unlicense . -- 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 intllib-20180811/mod.conf000066400000000000000000000000201315534544300150420ustar00rootroot00000000000000 name = intllib intllib-20180811/tools/000077500000000000000000000000001315534544300145645ustar00rootroot00000000000000intllib-20180811/tools/findtext.lua000077500000000000000000000046021315534544300171210ustar00rootroot00000000000000#! /usr/bin/env 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 output local inputs = { } local lang local author local i = 1 local function usage() print([[ Usage: ]]..me..[[ [OPTIONS] FILE... Extract translatable strings from the given FILE(s). Available options: -h,--help Show this help screen and exit. -o,--output X Set output file (default: stdout). -a,--author X Set author. -l,--lang X Set language name. ]]) os.exit(0) end 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 output = arg[i] elseif (a == "-a") or (a == "--author") then i = i + 1 if i > #arg then err("missing required argument to `%s'", a) end author = arg[i] elseif (a == "-l") or (a == "--lang") then i = i + 1 if i > #arg then err("missing required argument to `%s'", a) end lang = arg[i] elseif a:sub(1, 1) ~= "-" then table.insert(inputs, a) else err("unrecognized option `%s'", a) end i = i + 1 end if #inputs == 0 then err("no input files") end local outfile = io.stdout local function printf(fmt, ...) outfile:write(fmt:format(...)) 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 if author or lang then outfile:write("\n") end if lang then printf("# Language: %s\n", lang) end if author then printf("# Author: %s\n", author) end if author or lang then outfile:write("\n") end local escapes = { ["\n"] = "\\n", ["="] = "\\=", ["\\"] = "\\\\", } local function escape(s) return s:gsub("[\\\n=]", escapes) end local messages = { } for _, file in ipairs(inputs) do local infile, e = io.open(file, "r") if infile then for line in infile:lines() do for s in line:gmatch('S%("([^"]*)"') do table.insert(messages, s) end end infile:close() else io.stderr:write(("%s: WARNING: error opening file: %s\n"):format(me, e)) end end table.sort(messages) local last_msg for _, msg in ipairs(messages) do if msg ~= last_msg then printf("%s =\n", escape(msg)) end last_msg = msg end if output then outfile:close() end --[[ TESTS: S("foo") S("bar") S("bar") S("foo") ]] intllib-20180811/tools/updatetext.lua000066400000000000000000000056131315534544300174630ustar00rootroot00000000000000#! /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) -- luacheck: ignore 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 output, outfile, 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 output = arg[i] 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 escapes = { ["\n"] = "\\n", ["="] = "\\=", ["\\"] = "\\\\", } local function escape(s) return s:gsub("[\\\n=]", escapes) end if output then outfile, e = io.open(output, "w") if not outfile then err("error opening file for writing: %s", e) end end local template_msgs = intllib.load_strings(template) for _, file in ipairs(catalogs) do print("Processing: "..file) local catalog_msgs = intllib.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) table.insert(dirty_lines, "OLD: "..escape(k).." = "..escape(v)) end end if #dirty_lines > 0 then local outf 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 intllib-20180811/tools/xgettext.bat000066400000000000000000000013201315534544300171240ustar00rootroot00000000000000@echo off setlocal set me=%~n0 rem # Uncomment the following line if gettext is not in your PATH. rem # Value must be absolute and end in a backslash. rem set gtprefix=C:\path\to\gettext\bin\ if "%1" == "" ( echo Usage: %me% FILE... 1>&2 exit 1 ) set xgettext=%gtprefix%xgettext.exe set msgmerge=%gtprefix%msgmerge.exe md locale > nul 2>&1 echo Generating template... 1>&2 echo %xgettext% --from-code=UTF-8 -kS -kNS:1,2 -k_ -o locale/template.pot %* %xgettext% --from-code=UTF-8 -kS -kNS:1,2 -k_ -o locale/template.pot %* if %ERRORLEVEL% neq 0 goto done cd locale for %%f in (*.po) do ( echo Updating %%f... 1>&2 %msgmerge% --update %%f template.pot ) echo DONE! 1>&2 :done intllib-20180811/tools/xgettext.sh000077500000000000000000000010121315534544300167710ustar00rootroot00000000000000#! /bin/bash me=$(basename "${BASH_SOURCE[0]}"); if [[ $# -lt 1 ]]; then echo "Usage: $me FILE..." >&2; exit 1; fi mkdir -p locale; echo "Generating template..." >&2; xgettext --from-code=UTF-8 \ --keyword=S \ --keyword=NS:1,2 \ --keyword=N_ \ --add-comments='Translators:' \ --add-location=file \ -o locale/template.pot \ "$@" \ || exit; find locale -name '*.po' -type f | while read -r file; do echo "Updating $file..." >&2; msgmerge --update "$file" locale/template.pot; done echo "DONE!" >&2;