mirror of
https://github.com/minetest-mods/intllib.git
synced 2025-01-23 16:30:18 +01:00
[WIP] Add support for gettext message catalogs.
This commit is contained in:
parent
4e067ec219
commit
6a4eea7a9c
25
LICENSE.md
Normal file
25
LICENSE.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
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 <http://unlicense.org/>
|
41
README-es.md
Normal file
41
README-es.md
Normal file
@ -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
|
136
README-es_UY.md
136
README-es_UY.md
@ -1,136 +0,0 @@
|
|||||||
|
|
||||||
# Biblioteca de Internacionalización para Minetest
|
|
||||||
|
|
||||||
Por Diego Martínez (kaeza).
|
|
||||||
Lanzada bajo WTFPL.
|
|
||||||
|
|
||||||
Éste mod es un intento de proveer soporte para internacionalización para otros mods
|
|
||||||
(lo cual Minetest carece actualmente).
|
|
||||||
|
|
||||||
## Cómo usar
|
|
||||||
|
|
||||||
### Para usuarios finales
|
|
||||||
|
|
||||||
Para usar éste mod, simplemente [instálalo](http://wiki.minetest.net/Installing_Mods)
|
|
||||||
y habilítalo en la interfaz.
|
|
||||||
|
|
||||||
Éste mod intenta detectar el idioma del usuario, pero ya que no existe una solución
|
|
||||||
portable para hacerlo, éste intenta varias alternativas, y utiliza la primera
|
|
||||||
encontrada:
|
|
||||||
|
|
||||||
* Opción `language` en `minetest.conf`.
|
|
||||||
* Si ésta no está definida, usa la variable de entorno `LANG` (ésta está
|
|
||||||
siempre definida en SOs como Unix).
|
|
||||||
* Si todo falla, usa `en` (lo cual básicamente significa textos sin traducir).
|
|
||||||
|
|
||||||
En todo caso, el resultado final debe ser el In any case, the end result should be the
|
|
||||||
[Código de Idioma ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
|
|
||||||
del idioma deseado. Tenga en cuenta tambien que (de momento) solo los dos primeros
|
|
||||||
caracteres son usados, así que por ejemplo, las opciones `de_DE.UTF-8`, `de_DE`,
|
|
||||||
y `de` son iguales.
|
|
||||||
|
|
||||||
Algunos códigos comúnes: `es` para Español, `pt` para Portugués, `fr` para Francés,
|
|
||||||
`it` para Italiano, `de` para Aleman.
|
|
||||||
|
|
||||||
### Para desarrolladores
|
|
||||||
|
|
||||||
Para habilitar funcionalidad en tu mod, copia el siguiente fragmento de código y pégalo
|
|
||||||
al comienzo de tus archivos fuente:
|
|
||||||
|
|
||||||
```lua
|
|
||||||
-- Boilerplate to support localized strings if intllib mod is installed.
|
|
||||||
local S
|
|
||||||
if minetest.get_modpath("intllib") then
|
|
||||||
S = intllib.Getter()
|
|
||||||
else
|
|
||||||
-- Si no requieres patrones de reemplazo (@1, @2, etc) usa ésto:
|
|
||||||
S = function(s) return s end
|
|
||||||
|
|
||||||
-- Si requieres patrones de reemplazo, pero no escapes, usa ésto:
|
|
||||||
S = function(s,a,...)a={a,...}return s:gsub("@(%d+)",function(n)return a[tonumber(n)]end)end
|
|
||||||
|
|
||||||
-- Usa ésto si necesitas funcionalidad completa:
|
|
||||||
S = function(s,a,...)if a==nil then return s end a={a,...}return s:gsub("(@?)@(%(?)(%d+)(%)?)",function(e,o,n,c)if e==""then return a[tonumber(n)]..(o==""and c or"")else return"@"..o..n..c end end) end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
Tambien necesitarás depender opcionalmente de intllib. Para hacerlo, añade `intllib?`
|
|
||||||
a tu archivo `depends.txt`. Ten en cuenta tambien que si intllib no está instalado,
|
|
||||||
la función `S` es definida para regresar la cadena sin cambios. Ésto se hace para
|
|
||||||
evitar la necesidad de llenar tu código con montones de `if`s (o similar) para verificar
|
|
||||||
que la biblioteca está instalada.
|
|
||||||
|
|
||||||
Luego, para cada cadena de texto a traducir en tu código, usa la función `S`
|
|
||||||
(definida en el fragmento de arriba) para regresar la cadena traducida. Por ejemplo:
|
|
||||||
|
|
||||||
```lua
|
|
||||||
minetest.register_node("mimod:minodo", {
|
|
||||||
-- Cadena simple:
|
|
||||||
description = S("My Fabulous Node"),
|
|
||||||
-- Cadena con patrones de reemplazo:
|
|
||||||
description = S("@1 Car", "Blue"),
|
|
||||||
-- ...
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
Nota: Las cadenas en el código fuente por lo general deben estar en ingles ya que
|
|
||||||
es el idioma que más se habla. Es perfectamente posible especificar las cadenas
|
|
||||||
fuente en español y proveer una traducción al ingles, pero no se recomienda.
|
|
||||||
|
|
||||||
Luego, crea un directorio llamado `locale` dentro del directorio de tu mod, y crea
|
|
||||||
un archivo "plantilla" (llamado `template.txt` por lo general) con todas las cadenas
|
|
||||||
a traducir (ver *Formato de archivo de traducciones* más abajo). Los traductores
|
|
||||||
traducirán las cadenas en éste archivo para agregar idiomas a tu mod.
|
|
||||||
|
|
||||||
### Para traductores
|
|
||||||
|
|
||||||
Para traducir un mod que tenga soporte para intllib al idioma deseado, copia el
|
|
||||||
archivo `locale/template.txt` a `locale/IDIOMA.txt` (donde `IDIOMA` es el
|
|
||||||
[Código de Idioma ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
|
|
||||||
de tu idioma (`es` para español).
|
|
||||||
|
|
||||||
Abre el archivo en tu editor favorito, y traduce cada línea colocando el texto
|
|
||||||
traducido luego del signo de igualdad.
|
|
||||||
|
|
||||||
Ver *Formato de archivo de traducciones* más abajo.
|
|
||||||
|
|
||||||
## Formato de archivo de traducciones
|
|
||||||
|
|
||||||
He aquí un ejemplo de archivo de idioma para el español (`es.txt`):
|
|
||||||
|
|
||||||
```cfg
|
|
||||||
# Un comentario.
|
|
||||||
# Otro comentario.
|
|
||||||
Ésta línea es ignorada porque no tiene un signo de igualdad.
|
|
||||||
Hello, World! = Hola, Mundo!
|
|
||||||
String with\nnewlines = Cadena con\nsaltos de linea
|
|
||||||
String with an \= equals sign = Cadena con un signo de \= igualdad
|
|
||||||
```
|
|
||||||
|
|
||||||
Archivos de idioma (o traducción) son archivos de texto sin formato que consisten de
|
|
||||||
líneas con el formato `texto fuente = texto traducido`. El archivo debe ubicarse en el
|
|
||||||
subdirectorio `locale` del mod, y su nombre debe ser las dos letras del
|
|
||||||
[Código de Idioma ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
|
|
||||||
del lenguaje al cual se desea traducir.
|
|
||||||
|
|
||||||
Los archivos deben usar la codificación UTF-8.
|
|
||||||
|
|
||||||
Las líneas que comienzan en el símbolo numeral (`#`) son comentarios y son ignoradas
|
|
||||||
por el lector. Tenga en cuenta que los comentarios terminan al final de la línea;
|
|
||||||
no hay soporte para comentarios multilínea. Las líneas que no contengan un signo
|
|
||||||
de igualdad (`=`) tambien son ignoradas.
|
|
||||||
|
|
||||||
## Palabras finales
|
|
||||||
|
|
||||||
Gracias por leer hasta aquí.
|
|
||||||
Si tienes algún comentario/sugerencia, por favor publica en el
|
|
||||||
[tema en los foros](https://forum.minetest.net/viewtopic.php?id=4929). Para
|
|
||||||
reportar errores, usa el [rastreador](https://github.com/minetest-mods/intllib/issues/new)
|
|
||||||
en Github.
|
|
||||||
|
|
||||||
¡Que se hagan las traducciones! :P
|
|
||||||
|
|
||||||
\--
|
|
||||||
|
|
||||||
Suyo,
|
|
||||||
Kaeza
|
|
160
README.md
160
README.md
@ -2,142 +2,42 @@
|
|||||||
# Internationalization Lib for Minetest
|
# Internationalization Lib for Minetest
|
||||||
|
|
||||||
By Diego Martínez (kaeza).
|
By Diego Martínez (kaeza).
|
||||||
Released as WTFPL.
|
Released under Unlicense. See `LICENSE.md` for details.
|
||||||
|
|
||||||
This mod is an attempt at providing internationalization support for mods
|
This mod is an attempt at providing internationalization support for mods
|
||||||
(something Minetest currently lacks).
|
(something Minetest currently lacks).
|
||||||
|
|
||||||
## How to use
|
|
||||||
|
|
||||||
### For end users
|
|
||||||
|
|
||||||
To use this mod, just [install it](http://wiki.minetest.net/Installing_Mods)
|
|
||||||
and enable it in the GUI.
|
|
||||||
|
|
||||||
The mod tries to detect the user's language, but since there's currently no
|
|
||||||
portable way to do this, it tries several alternatives, and uses the first one
|
|
||||||
found:
|
|
||||||
|
|
||||||
* `language` setting in `minetest.conf`.
|
|
||||||
* If that's not set, it uses the `LANG` environment variable (this is
|
|
||||||
always set on Unix-like OSes).
|
|
||||||
* If all else fails, uses `en` (which basically means untranslated strings).
|
|
||||||
|
|
||||||
In any case, the end result should be the
|
|
||||||
[ISO 639-1 Language Code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
|
|
||||||
of the desired language. Also note that (currently) only up to the first two
|
|
||||||
characters are used, so for example, the settings `de_DE.UTF-8`, `de_DE`,
|
|
||||||
and `de` are all equal.
|
|
||||||
|
|
||||||
Some common codes are `es` for Spanish, `pt` for Portuguese, `fr` for French,
|
|
||||||
`it` for Italian, `de` for German.
|
|
||||||
|
|
||||||
### For mod developers
|
|
||||||
|
|
||||||
In order to enable it for your mod, copy the following code snippet and paste
|
|
||||||
it at the beginning of your source file(s):
|
|
||||||
|
|
||||||
```lua
|
|
||||||
-- Boilerplate to support localized strings if intllib mod is installed.
|
|
||||||
local S
|
|
||||||
if minetest.get_modpath("intllib") then
|
|
||||||
S = intllib.Getter()
|
|
||||||
else
|
|
||||||
-- If you don't use insertions (@1, @2, etc) you can use this:
|
|
||||||
S = function(s) return s end
|
|
||||||
|
|
||||||
-- If you use insertions, but not insertion escapes this will work:
|
|
||||||
S = function(s,a,...)a={a,...}return s:gsub("@(%d+)",function(n)return a[tonumber(n)]end)end
|
|
||||||
|
|
||||||
-- Use this if you require full functionality
|
|
||||||
S = function(s,a,...)if a==nil then return s end a={a,...}return s:gsub("(@?)@(%(?)(%d+)(%)?)",function(e,o,n,c)if e==""then return a[tonumber(n)]..(o==""and c or"")else return"@"..o..n..c end end) end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
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 `S` function is defined so it returns 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.
|
|
||||||
|
|
||||||
Next, for each translatable string in your sources, use the `S` function
|
|
||||||
(defined in the snippet) to return the translated string. For example:
|
|
||||||
|
|
||||||
```lua
|
|
||||||
minetest.register_node("mymod:mynode", {
|
|
||||||
-- Simple string:
|
|
||||||
description = S("My Fabulous Node"),
|
|
||||||
-- String with insertions:
|
|
||||||
description = S("@1 Car", "Blue"),
|
|
||||||
-- ...
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, you create a `locale` directory inside your mod directory, and create
|
|
||||||
a "template" file (by convention, named `template.txt`) with all the
|
|
||||||
translatable strings (see *Locale file format* below). Translators will
|
|
||||||
translate the strings in this file to add languages to your mod.
|
|
||||||
|
|
||||||
### For translators
|
|
||||||
|
|
||||||
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](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
|
|
||||||
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 *Locale file format* below for more information about the file format.
|
|
||||||
|
|
||||||
## Locale file format
|
|
||||||
|
|
||||||
Here's an example for a Spanish locale file (`es.txt`):
|
|
||||||
|
|
||||||
```cfg
|
|
||||||
# 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](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
|
|
||||||
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.
|
|
||||||
|
|
||||||
## Final words
|
|
||||||
|
|
||||||
Thanks for reading up to this point.
|
|
||||||
Should you have any comments/suggestions, please post them in the
|
Should you have any comments/suggestions, please post them in the
|
||||||
[forum topic](https://forum.minetest.net/viewtopic.php?id=4929). For bug
|
[forum topic][topic]. For bug reports, use the [bug tracker][bugtracker]
|
||||||
reports, use the [bug tracker](https://github.com/minetest-mods/intllib/issues/new)
|
|
||||||
on Github.
|
on Github.
|
||||||
|
|
||||||
Let there be translated texts! :P
|
## 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.
|
||||||
|
|
||||||
Yours Truly,
|
The mod tries to detect your language, but since there's currently no
|
||||||
Kaeza
|
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
|
||||||
|
96
doc/developer.md
Normal file
96
doc/developer.md
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
|
||||||
|
# Intllib developer documentation
|
||||||
|
|
||||||
|
In order to enable it for your mod, copy some boilerplate into your
|
||||||
|
source file(s). What you need depends on what you want to support.
|
||||||
|
|
||||||
|
There are now two main interfaces: one using the old plain text file method,
|
||||||
|
and one using the new support for [gettext][gettext] message catalogs (`.mo`).
|
||||||
|
Read below for details on each one.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## New interface
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
Use the usual gettext tools (`xgettext`, `msgfmt`, etc.), to generate your
|
||||||
|
catalog files in a directory named `locale`.
|
||||||
|
|
||||||
|
Note: Drop the `.mo` file directly as `locale/$lang.mo`. **Not** in
|
||||||
|
`locale/$lang/LC_MESSAGES/$domain.mo`!
|
||||||
|
|
||||||
|
You should also provide the source `.po` and `.pot` files.
|
||||||
|
|
||||||
|
### Basic workflow
|
||||||
|
|
||||||
|
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`. 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.
|
||||||
|
|
||||||
|
Once a translator submits an updated translation, you should run the `msgfmt`
|
||||||
|
tool:
|
||||||
|
|
||||||
|
msgfmt locale/ll_CC.po -o locale/ll_CC.mo
|
||||||
|
|
||||||
|
## Old interface
|
||||||
|
|
||||||
|
You will need this boilerplate code:
|
||||||
|
|
||||||
|
-- Boilerplate to support localized strings if intllib mod is installed.
|
||||||
|
local S
|
||||||
|
if minetest.get_modpath("intllib") then
|
||||||
|
S = intllib.Getter()
|
||||||
|
else
|
||||||
|
-- If you don't use insertions (@1, @2, etc) you can use this:
|
||||||
|
S = function(s) return s end
|
||||||
|
|
||||||
|
-- If you use insertions, but not insertion escapes this will work:
|
||||||
|
S = function(s,a,...)a={a,...}return s:gsub("@(%d+)",function(n)return a[tonumber(n)]end)end
|
||||||
|
|
||||||
|
-- Use this if you require full functionality
|
||||||
|
S = function(s,a,...)if a==nil then return s end a={a,...}return s:gsub("(@?)@(%(?)(%d+)(%)?)",function(e,o,n,c)if e==""then return a[tonumber(n)]..(o==""and c or"")else return"@"..o..n..c end end) end
|
||||||
|
end
|
||||||
|
|
||||||
|
Next, for each translatable string in your sources, use the `S` function
|
||||||
|
(defined in the snippet) 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"),
|
||||||
|
-- ...
|
||||||
|
})
|
||||||
|
|
||||||
|
Then, you create a `locale` directory inside your mod directory, and create
|
||||||
|
a "template" file (by convention, named `template.txt`) with all the
|
||||||
|
translatable strings (see *Locale file format* below). Translators will
|
||||||
|
translate the strings in this file to add languages to your mod.
|
||||||
|
|
||||||
|
[gettext]: https://www.gnu.org/software/gettext/
|
20
doc/translator.md
Normal file
20
doc/translator.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
# 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
|
288
gettext.lua
Normal file
288
gettext.lua
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
|
||||||
|
local strfind, strsub, strrep = string.find, string.sub, string.rep
|
||||||
|
local strmatch, strgsub = string.match, string.gsub
|
||||||
|
local floor = math.floor
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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]
|
||||||
|
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 split(str, "\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")
|
||||||
|
|
||||||
|
until true end -- end for
|
||||||
|
|
||||||
|
return texts
|
||||||
|
end
|
||||||
|
|
||||||
|
local M = { }
|
||||||
|
|
||||||
|
local domains = { }
|
||||||
|
local dgettext_cache = { }
|
||||||
|
local dngettext_cache = { }
|
||||||
|
local langs
|
||||||
|
|
||||||
|
local function detect_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 = rawget(_G, "minetest") and minetest.setting_get("language")
|
||||||
|
if v and v~="" then
|
||||||
|
addlang(v)
|
||||||
|
end
|
||||||
|
|
||||||
|
v = os.getenv("LANGUAGE")
|
||||||
|
if v then
|
||||||
|
for item in split(v, ":") do
|
||||||
|
addlang(item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
v = os.getenv("LANG")
|
||||||
|
if v then
|
||||||
|
addlang(v)
|
||||||
|
end
|
||||||
|
|
||||||
|
return langs
|
||||||
|
end
|
||||||
|
|
||||||
|
local function warn(msg)
|
||||||
|
if rawget(_G, "minetest") then
|
||||||
|
minetest.log("warning", msg)
|
||||||
|
else
|
||||||
|
io.stderr:write("WARNING: ", msg, "\n")
|
||||||
|
end
|
||||||
|
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(str)
|
||||||
|
local c, t, f = strmatch(str, "^(.-)%?(.-):(.*)")
|
||||||
|
if c then
|
||||||
|
return ("__if("
|
||||||
|
..replace_ternary(c)
|
||||||
|
..","..replace_ternary(t)
|
||||||
|
..","..replace_ternary(f)
|
||||||
|
..")")
|
||||||
|
end
|
||||||
|
return str
|
||||||
|
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 split(str, "\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 ": ")..(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
|
||||||
|
print(dump(hdrs))
|
||||||
|
return bail("catalog has no headers")
|
||||||
|
end
|
||||||
|
|
||||||
|
hdrs = parse_headers(hdrs[0])
|
||||||
|
|
||||||
|
local pf = hdrs["Plural-Forms"]
|
||||||
|
if not pf then
|
||||||
|
return bail("failed to load catalog:"
|
||||||
|
.." catalog has no Plural-Forms header")
|
||||||
|
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)
|
||||||
|
detect_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
|
90
init.lua
90
init.lua
@ -21,6 +21,22 @@ if not (LANG and (LANG ~= "")) then LANG = "en" end
|
|||||||
local INS_CHAR = intllib.INSERTION_CHAR
|
local INS_CHAR = intllib.INSERTION_CHAR
|
||||||
local insertion_pattern = "("..INS_CHAR.."?)"..INS_CHAR.."(%(?)(%d+)(%)?)"
|
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)
|
local function make_getter(msgstrs)
|
||||||
return function(s, ...)
|
return function(s, ...)
|
||||||
local str
|
local str
|
||||||
@ -33,24 +49,12 @@ local function make_getter(msgstrs)
|
|||||||
if select("#", ...) == 0 then
|
if select("#", ...) == 0 then
|
||||||
return str
|
return str
|
||||||
end
|
end
|
||||||
local args = {...}
|
return do_replacements(str, ...)
|
||||||
str = 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)
|
|
||||||
return str
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function intllib.Getter(modname)
|
local function Getter(modname)
|
||||||
modname = modname or minetest.get_current_modname()
|
modname = modname or minetest.get_current_modname()
|
||||||
if not intllib.getters[modname] then
|
if not intllib.getters[modname] then
|
||||||
local msgstr = intllib.get_strings(modname)
|
local msgstr = intllib.get_strings(modname)
|
||||||
@ -60,6 +64,64 @@ function intllib.Getter(modname)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function intllib.Getter(modname)
|
||||||
|
minetest.log("deprecated", "intllib.Getter is deprecated."
|
||||||
|
.."Please use intllib.make_gettext_pair instead.")
|
||||||
|
return Getter(modname)
|
||||||
|
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 then
|
||||||
|
return msgstr[0]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function catngettext(catalogs, msgid, msgid_plural, n)
|
||||||
|
n = math.floor(n)
|
||||||
|
for i, cat in ipairs(catalogs) do
|
||||||
|
print(i, dump(cat))
|
||||||
|
local msgstr = cat and cat[msgid]
|
||||||
|
if msgstr then
|
||||||
|
local index = cat.plural_index(n)
|
||||||
|
print("catngettext:", index, msgstr[index])
|
||||||
|
return msgstr[index]
|
||||||
|
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(msgid, ...)
|
||||||
|
local msgstr = (catgettext(catalogs, msgid)
|
||||||
|
or getter(msgid))
|
||||||
|
return do_replacements(msgstr, ...)
|
||||||
|
end
|
||||||
|
local function ngettext(msgid, msgid_plural, n, ...)
|
||||||
|
local msgstr = (catngettext(catalogs, msgid, msgid_plural, n)
|
||||||
|
or getter(msgid))
|
||||||
|
return do_replacements(msgstr, ...)
|
||||||
|
end
|
||||||
|
gettext_getters[modname] = { gettext, ngettext }
|
||||||
|
return gettext, ngettext
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
local function get_locales(code)
|
local function get_locales(code)
|
||||||
local ll, cc = code:match("^(..)_(..)")
|
local ll, cc = code:match("^(..)_(..)")
|
||||||
if ll then
|
if ll then
|
||||||
|
45
lib/intllib.lua
Normal file
45
lib/intllib.lua
Normal file
@ -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
|
33
tools/xgettext.bat
Normal file
33
tools/xgettext.bat
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
@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
|
23
tools/xgettext.sh
Executable file
23
tools/xgettext.sh
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
#! /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 -kS -kNS:1,2 -k_ \
|
||||||
|
-o locale/template.pot "$@" \
|
||||||
|
|| exit;
|
||||||
|
|
||||||
|
cd locale;
|
||||||
|
|
||||||
|
for file in *.po; do
|
||||||
|
echo "Updating $file..." >&2;
|
||||||
|
msgmerge --update "$file" template.pot;
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "DONE!" >&2;
|
Loading…
Reference in New Issue
Block a user