mirror of
https://github.com/luanti-org/minetest_game.git
synced 2025-05-31 02:56:26 -04:00
i18n mod using gettext tools and logic.
This commit is contained in:
parent
794a436d86
commit
966b3c41a6
4 changed files with 257 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,4 +4,5 @@
|
||||||
*bak*
|
*bak*
|
||||||
tags
|
tags
|
||||||
*.vim
|
*.vim
|
||||||
|
*.mo
|
||||||
|
|
||||||
|
|
76
mods/i18n/README.txt
Normal file
76
mods/i18n/README.txt
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
i18n mod for minetest_game, using gettext logic
|
||||||
|
===============================================
|
||||||
|
|
||||||
|
Into init.lua some parts of code were originally released as WTFPL or
|
||||||
|
as public domain. See init.lua for details.
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
Remaining code is released with following license
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (C) 2015 netfab <netbox253@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------
|
||||||
|
How do I enable i18n in my foo mod ?
|
||||||
|
------------------------------------
|
||||||
|
0 - You need following gettext tools on your system to use scripts/i18n.sh
|
||||||
|
bash script :
|
||||||
|
- xgettext
|
||||||
|
- msgfmt
|
||||||
|
|
||||||
|
1 - Add i18n dependency to mods/foo/depends.txt
|
||||||
|
|
||||||
|
2 - In your code, set strings as translatable.
|
||||||
|
Example (in patch format) :
|
||||||
|
|
||||||
|
- minetest.chat_send_player(name, "You can only sleep at night.")
|
||||||
|
+ minetest.chat_send_player(name, _("You can only sleep at night."))
|
||||||
|
|
||||||
|
3 - In mods/foo/init.lua, load *your own* mo file by using
|
||||||
|
i18n.load_mo_file() function :
|
||||||
|
|
||||||
|
local modpath = minetest.get_modpath("foo")
|
||||||
|
+ i18n.load_mo_file(modpath, "foo")
|
||||||
|
|
||||||
|
Above example is loading :
|
||||||
|
|
||||||
|
mods/foo/i18n/«language_code»/foo.mo
|
||||||
|
|
||||||
|
Language_code is auto-detected from minetest language setting, or from LANG
|
||||||
|
env variable. Default is : en
|
||||||
|
|
||||||
|
4 - Generate a po template file that will be usable by translators :
|
||||||
|
|
||||||
|
$ cd scripts/
|
||||||
|
$ bash i18n.sh --po-templates
|
||||||
|
entering ../mods/foo ... created i18n/template.po
|
||||||
|
|
||||||
|
For each mod which depends on the i18n mod, this script will create an i18n/
|
||||||
|
directory and will (re)generate a template.po file. Each mod will have its
|
||||||
|
own i18n/template.po.
|
||||||
|
|
||||||
|
5 - Prepare translation file (for example in french) :
|
||||||
|
|
||||||
|
$ cd mods/foo/i18n/
|
||||||
|
$ mkdir fr
|
||||||
|
$ cp template.po fr/foo.po
|
||||||
|
|
||||||
|
Now you can translate strings from mods/foo/i18n/fr/foo.po
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------
|
||||||
|
How do I build all mo files for packaging ?
|
||||||
|
-------------------------------------------
|
||||||
|
$ cd scripts/
|
||||||
|
$ bash i18n.sh --build-mo
|
||||||
|
../mods/foo/i18n/fr/foo.po : 9 translated messages.
|
||||||
|
../mods/bar/i18n/fr/bar.po : 7 translated messages.
|
||||||
|
|
100
mods/i18n/init.lua
Normal file
100
mods/i18n/init.lua
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
-- minetest_game/mods/i18n/init.lua
|
||||||
|
|
||||||
|
i18n = {}
|
||||||
|
i18n.hash = {}
|
||||||
|
|
||||||
|
-- Following 4 lines coming from https://github.com/kaeza/minetest-intllib
|
||||||
|
-- (released as WTFPL)
|
||||||
|
local LANG = minetest.setting_get("language")
|
||||||
|
if not (LANG and (LANG ~= "")) then LANG = os.getenv("LANG") end
|
||||||
|
if not (LANG and (LANG ~= "")) then LANG = "en" end
|
||||||
|
i18n.LANG = LANG:sub(1, 2)
|
||||||
|
|
||||||
|
function i18n.gettext(text)
|
||||||
|
return i18n.hash[text] or text
|
||||||
|
end
|
||||||
|
|
||||||
|
_=assert(i18n.gettext)
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Original load_mo_file() function coming from :
|
||||||
|
-- http://lua-users.org/lists/lua-l/2010-04/msg00005.html
|
||||||
|
-- (released as public domain)
|
||||||
|
--
|
||||||
|
-- Function sligthly modified, original comment is below.
|
||||||
|
--
|
||||||
|
-----------------------------------------------------------
|
||||||
|
-- load an mo file and return a lua table
|
||||||
|
-- @param mo_file name of the file to load
|
||||||
|
-- @return table on success
|
||||||
|
-- @return nil,string on failure
|
||||||
|
-- @copyright J.Jorgen von Bargen
|
||||||
|
-- @licence I provide this as public domain
|
||||||
|
-- @see http://www.gnu.org/software/hello/manual/gettext/MO-Files.html
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
function i18n.load_mo_file(modpath, modname)
|
||||||
|
local mo_file = modpath.."/i18n/"..i18n.LANG.."/"..modname..".mo"
|
||||||
|
|
||||||
|
--------------------------------
|
||||||
|
-- open file and read data
|
||||||
|
--------------------------------
|
||||||
|
local fd,err=io.open(mo_file,"rb")
|
||||||
|
if not fd then return nil,err end
|
||||||
|
local mo_data=fd:read("*all")
|
||||||
|
fd:close()
|
||||||
|
|
||||||
|
--------------------------------
|
||||||
|
-- precache some functions
|
||||||
|
--------------------------------
|
||||||
|
local byte=string.byte
|
||||||
|
local sub=string.sub
|
||||||
|
|
||||||
|
--------------------------------
|
||||||
|
-- check format
|
||||||
|
--------------------------------
|
||||||
|
local peek_long --localize
|
||||||
|
local magic=sub(mo_data,1,4)
|
||||||
|
-- intel magic 0xde120495
|
||||||
|
if magic=="\222\018\004\149" then
|
||||||
|
peek_long=function(offs)
|
||||||
|
local a,b,c,d=byte(mo_data,offs+1,offs+4)
|
||||||
|
return ((d*256+c)*256+b)*256+a
|
||||||
|
end
|
||||||
|
-- motorola magic = 0x950412de
|
||||||
|
elseif magic=="\149\004\018\222" then
|
||||||
|
peek_long=function(offs)
|
||||||
|
local a,b,c,d=byte(mo_data,offs+1,offs+4)
|
||||||
|
return ((a*256+b)*256+c)*256+d
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return nil,"no valid mo-file"
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------
|
||||||
|
-- version
|
||||||
|
--------------------------------
|
||||||
|
local V=peek_long(4)
|
||||||
|
if V~=0 then
|
||||||
|
return nul,"unsupported version"
|
||||||
|
end
|
||||||
|
|
||||||
|
------------------------------
|
||||||
|
-- get number of offsets of table
|
||||||
|
------------------------------
|
||||||
|
local N,O,T=peek_long(8),peek_long(12),peek_long(16)
|
||||||
|
------------------------------
|
||||||
|
-- traverse and get strings
|
||||||
|
------------------------------
|
||||||
|
local hash={}
|
||||||
|
for nstr=1,N do
|
||||||
|
local ol,oo=peek_long(O),peek_long(O+4) O=O+8
|
||||||
|
local tl,to=peek_long(T),peek_long(T+4) T=T+8
|
||||||
|
hash[sub(mo_data,oo+1,oo+ol)]=sub(mo_data,to+1,to+tl)
|
||||||
|
end
|
||||||
|
-- return function(text)
|
||||||
|
-- return hash[text] or text
|
||||||
|
-- end
|
||||||
|
i18n.hash = hash
|
||||||
|
end
|
||||||
|
|
80
scripts/i18n.sh
Normal file
80
scripts/i18n.sh
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# i18n.sh -- Shell script to update/build gettext files
|
||||||
|
# -- Released with minetest_game mods/i18n mod
|
||||||
|
#
|
||||||
|
# Copyright (C) 2015 netfab <netbox253@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
ROOT_DIRECTORY=..
|
||||||
|
|
||||||
|
function display_help() {
|
||||||
|
echo
|
||||||
|
echo "Usage :"
|
||||||
|
echo " $ $0 --po-templates"
|
||||||
|
echo " $ $0 --build-mo"
|
||||||
|
echo
|
||||||
|
echo "If your mod depends on the i18n mod, « --po-templates » will create"
|
||||||
|
echo "an i18n/ directory into your mod path, then it will extract gettext"
|
||||||
|
echo "strings from your lua files. Finally, result will be saved as i18n/template.po"
|
||||||
|
echo
|
||||||
|
echo "« --build-mo » will scan for po files in mods/*/i18n/ subdirs and will"
|
||||||
|
echo "compile them to binary format (using gettext's msgfmt)."
|
||||||
|
echo
|
||||||
|
echo "See also mods/i18n/README.txt."
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_mods_templates() {
|
||||||
|
for MOD_DIR in ${ROOT_DIRECTORY}/mods/*; do
|
||||||
|
depfile="$MOD_DIR/depends.txt"
|
||||||
|
if [[ -f "$depfile" ]]; then
|
||||||
|
i18n=$(grep -c i18n "$depfile")
|
||||||
|
if [[ $i18n -gt 0 ]]; then
|
||||||
|
OLDPWD=$PWD
|
||||||
|
cd "$MOD_DIR" || exit 7
|
||||||
|
echo -n "entering $MOD_DIR ... "
|
||||||
|
mkdir -p i18n || exit 8
|
||||||
|
xgettext -L Lua *.lua --from-code=UTF-8 -o i18n/template.po
|
||||||
|
echo "created i18n/template.po"
|
||||||
|
cd "$OLDPWD" || exit 9
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function compile_catalogs() {
|
||||||
|
for x in $(find ${ROOT_DIRECTORY}/mods/ -mindepth 4 -name *.po); do
|
||||||
|
pofile=${x##*/}
|
||||||
|
pofile=${pofile:0:-3}
|
||||||
|
filepath=${x%/*}
|
||||||
|
echo -n "${filepath}/${pofile}.po : "
|
||||||
|
msgfmt "${filepath}/${pofile}.po" -cv -o "${filepath}/${pofile}.mo"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
'--po-templates')
|
||||||
|
update_mods_templates
|
||||||
|
;;
|
||||||
|
'--build-mo')
|
||||||
|
compile_catalogs
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
display_help
|
||||||
|
;;
|
||||||
|
esac
|
Loading…
Add table
Reference in a new issue