What is 'game_intllib' and why a MT translation effort?
What is the discussion about?
One may ask, what is at the core of the discussion in this forum topic? Why the proposed need for a translation in Minetest anyway?
Why a '
game_intllib' mod for the
minetest_game default mods tree? What is the purpose of the above mentioned (a.m.) so called
S("string") enclosure to user-facing strings and why could this be helpful for a translation?
At the core of the discussion lies the demand of
freedom to enjoy MT in your language of choice.
You are invited to contribute
This is about the
Minetest (MT) game software and how to improve the user experience for any player of the game.
The normal user of MT games may seek some better understanding or may find a way to contribute to the upcoming translation efforts in the future. A free software project needs contributions in many ways and you are invited. Please note one can contribute to a translation without any knowledge of computer programming. How to get involved and further information:
Translation efforts and code development
MT is a
Free and open source software (FOSS) and this definition starts with the word "Free" and one should acknowledge the
liberty of choice.
Thank you in advance and
happy hacking.
Apparently, the combined task of software translation needs some help by the developers to help translators in catching all user-facing strings. It would be good to see co-working and to build a team.
Furthermore, readers with some development skills may follow the technical principles discussed in the tutorial and the code examples included. Some more ambitious translator-developer may even use this tutorial to test the included example code with a MT client at your own risk.
A little tutorial on MT software translation (part 1)
Please note:
This text and the tutorial are WIP i.e. work in progress. I will irregularly edit and plan to gradually improve the text.
Introduction
Please be aware, this is for educational and experimental purposes only. This is not an official MT development documentation.
This little tutorial is about software translation to the
Minetest (MT) game software engine functionalities and how to improve the user experience for any player of the game. The MT game is made happen by software. The GUI i.e. the graphical user interface of the MT game is divided into the outer GUI of the client (the MT client window) and the GUI in the inner world view of the MT client (the view on the world, player hand and tools, inventory etc.).
The so called
mods (short for modifications or modules) are the foundation of games which add or modify various features. Here you find the actual source code of games. Players can also add additional own mods to extend a particular game.
As an english person you may be fully happy with the MT game certainly in the current 5.0.1 stable version. As somebody from a different background you may enjoy the experience of a MT game but at the same time would welcome a MT game GUI and MT interaction with phrases in your language of choice. This is why we discuss translation and why we should have a look into the MT software.
The MT software and translation
The MT game and translation
The developers of the software code of the MT game (comprising the core code and the
minetest_game code) for historically and other reasons started the project by use of the EN locale i.e. English language. This is quite natural and most software programming languages (like C and
Lua) are using english words for the text syntax of source code anyway. Unfortunately, this leads to some complex issues if you want to improve and to translate in a situation where you have a huge amount of source code for a well established software project and many users of many languages.
In general one should consider the
GNU gettext project &
documentation for further information.
All main functionality of a MT game world is established by Lua code. The view of many flowers which look as if growing in some biomes can only be enjoyed because the 'flower' mod provides the code to make this happen in a nice way. The player's
creative inventory GUI is provided by a 'creative' mod in a similar way.
The mods 'game_intllib' and 'intllib'
This forum topic of '[Mod] Internationalization Library [intllib]' and the
'intllib' mod were established by @kaeza as developer. IMHO the 'intllib' mod is a reliable and helpful tool and I have found it to be both robust and compliant to the
GNU gettext tool chain.
My 'game_intllib' mod is a derivation of the 'intllib' mod and just a small migration of the original code. The deviation from 'intllib' is for technical reasons only and I may explain more on this later. Please note the basics of this little tutorial are nothing new and obviously have been the basis to the development of 'intllib' in the past already.
The 'game_intllib' mod is for translation inside the default
minetest_game mod tree and not for other mods. For external mods one should make use of the original 'inttlib' mod in continuity without interference to the game_intllib mod and it's functions.
Example (1): The MT inventory GUI
The MT creative inventory GUI
Anybody playing MT in the creative mode is aware of the
creative inventory of the GUI in the MT client. There are five main tabs named 'Crafting', 'All', 'Nodes', 'Tools' and 'Items'. You may start your MT client and may start a game play in creative mode and have a look. The inventory GUI is popping up as you type the 'I' command key and is providing a view on crafting and items.
This is all fine. But how could we translate the names of the a.m. five tabs if we seek so?
The phrases and names like any other text of a GUI have a representation in software called 'string'. If we want to change the name of a tab we have to find the applicable string defined inside the software code and should change the text of the string respectively.
All the main functionality of a MT game world is established by Lua code. The
creative inventory GUI is provided by the 'creative' mod which is located as a folder
creative inside the
minetest_game mod tree. You could take a look into your files or browse online into the GitHub repository to find the
./minetest_game/mods/creative path for the current
minetest_game-5.0.1 version. In the folder
creative as with any MT mod there is a file named
init.lua which is the entry point for the functionality of this piece of software.
For the benefit of this example we will momentarily ignore the file
init.lua and will have a look into the file
inventory.lua instead. However, we will come back to the file
init.lua later as we will learn that software translation is a more complex task as it may look at first glance.
Like
inventory.lua all main functionality of a MT game world is established by Lua code. This is called the
source code of the MT software. This source code is just readable text in a strange format called the
Lua software syntax (that is why the file suffix is '.lua' and not '.txt' but nevertheless it is holding text). You can have a look into the source code i.e. text of such a file by help of a text editor of your choice.
How to find the name i.e. the string "All" for the a.m. tab named "All" now? If you have a look into
inventory.lua you will find many words containing "all" like "allow" or "all" or other. That is why we make a more targeted search (you may call it advanced search) for the 'entire word' and the 'Case sensitive' word "All" explicitly.
The explicit search for "All" in the file
inventory.lua will give you this code segment:
Code: Select all
creative.register_tab("all", "All", minetest.registered_items)
creative.register_tab("nodes", "Nodes", minetest.registered_nodes)
creative.register_tab("tools", "Tools", minetest.registered_tools)
creative.register_tab("craftitems", "Items", minetest.registered_craftitems)
So we are lucky and did find all four names of the
creative inventory GUI in one place. But wait, did I not mention five main tabs (see above) and not only four tabs? We will come back to this later again as translation of software is a more complex task.
From some common knowledge in coding and from this specific code line we can presume the name "All" of the a.m. tab is defined by the second argument of function
creative.register_tab which is just the
"All" string.
Code: Select all
creative.register_tab("all", "All", minetest.registered_items)
One could now change this user-facing string (i.e. the EN word "All" as the string
"All" in the second argument of function
creative.register_tab in the above code line) to a word in one's language of choice. The same would apply to the three other lines of codes and the user-facing strings "Nodes", "Tools" and "Items" respectively.
On to software translation and a language of choice: The capitalized
EN word "All" is a
pronoun and could presumably become
PT "Tudo" or
FR "Toutes" or
PL "Wszystko" or
HE "הכל" or
RU "Всё" or
ZH "凡事" or
ST "tsohle" or
JA "すべて" or
DE "Alles" or other. Please accept my apologies in advance if one of this examples may be incorrect or you do not find your preferred language included. The
two-letter ISO 639-1 codes apply and you should note
ISO 639 is a
standardized nomenclature used to classify
natural languages.
Obviously, the MT software translation like other software translation needs a sustainable solution for a flexible translation.
A bad idea and poor approach
An impatient and quite ambitious translator-developer may want to experiment with this example already. You can do this at your own risk and should make a copy of the MT game installation under a different name on your computer.
Do not make changes to files of the official MT installation as this may easily break the installation and you would be blocked from enjoying the MT gaming experience in the meantime unfortunately.
In the exemplary DE locale i.e. the German language one appropriate word for the EN pronoun "All" as the name of the a.m.tab is "alles" or more specific the capitalized DE pronoun "Alles" in this case. As an obvious solution we could just put the word "Alles" into the string for a DE i.e. German translation instead of the word "All" of the original code. See the exemplary changed code below. However, this would be a
bad idea and poor approach.
Code: Select all
creative.register_tab("all", "Alles", minetest.registered_items)
Why would the above be a bad idea? Please recall we want to provide a language of choice. Hard coding a string is not providing a choice (that is why it is called 'hard' coded) and we seek a better and more flexible solution naturally. If we would hard code again we would just produce the same problem in another languages as the developers of the code did before. Please note we may not blame the developers (see above).
So a translation by just a change to the hard coding of the string is not a good solution. We need a better idea and an improved approach to provide an sustainable solution for a flexible translation.
A better idea and an improved approach
The goal is to provide a MT software translation by a language of choice. Any selection or choice could be understood as some functionality in software and can be coded as a function. Computers and software are just made for this.
Momentarily, we may accept there is a
function 'S' i.e. 'S()' which takes one (or more?) arguments and can provide a choice for a translation based on the original string which is just the argument in the function call. The return value of 'S()' is either the original string or the translation of the original string or any other value.
The code of the function 'S()' can be defined elsewhere. Please note we have no need for this example to discuss how the choice happens inside the function. We accept there is a function established and can trust there is a computable solution provided.
The solution seems to be a reasonable small change to the original code and the extra code for the function 'S()' can be typed by help of only three characters in a short and easy way presumably. This is the a.m.
S("string") enclosure.
The application of the
S("string") enclosure on all of the four names of the
creative inventory GUI provides the following code:
Code: Select all
creative.register_tab("all", S("All"), minetest.registered_items)
creative.register_tab("nodes", S("Nodes"), minetest.registered_nodes)
creative.register_tab("tools", S("Tools"), minetest.registered_tools)
creative.register_tab("craftitems", S("Items"), minetest.registered_craftitems)
Obviously by somewhat minor changes to the original code and by help of the
S("string") enclosure to user-facing strings of the
creative inventory GUI we and a developer can provide a language of choice for the interface. We may have found an improved approach to provide a sustainable solution for a flexible translation. However, please keep in mind the task of software translation can be a more complex task as it may look at first glance.
The file 'init.lua' of the 'creative' mod
The
creative inventory GUI is provided by the 'creative' mod which is located as a folder
creative inside the
minetest_game mod tree.
The task of addressing strings which directly involve the GUI seems to be obvious and is a "look, search and enclose" misson. However, there may be other user-facing strings embedded in the software which sometimes may be quite obvious or may be hidden and only found by coincidence. Some advice from the developers would be helpful.
A look into the source code for possible user-facing strings in the file 'init.lua' of the 'creative' mod provides the following code and only one user-facing string apparently:
Code: Select all
minetest.register_privilege("creative", {
description = "Allow player to use creative inventory",
give_to_singleplayer = false,
The application of the
S("string") enclosure to the just one identified possibly user-facing string in the file 'init.lua' of the 'creative' mod provides the following code:
Code: Select all
minetest.register_privilege("creative", {
description = S("Allow player to use creative inventory"),
give_to_singleplayer = false,
We now introduced the
S("string") enclosure to five lines of code, four in the file
creative.lua and one in the file
init.lua for this example and the time being.
The file 'gintllib.lua' as a necessary mod addition
The ambitious translator-developer may use this example to test the code and would immediately get errors by starting the MT client after the a.m. changes and will see an apparent failure. This may be obvious to the well established code developer but this is a tutorial and we want to evolve for the benefit of less misunderstanding in the forum and better understanding in the community.
The
S("string") enclosure provides a call to the function 'S()' and this function is not defined. Please note that an already defined but different function 'S()' might be even worse as it could lead to unwanted results.
Obviously, there is a requirement for some additional piece of code which provides a sufficient definition of the 'S()' function to the Lua code without endangering the functionality of the original software. This is where the file 'gintllib.lua' comes into play.
The file 'gintllib.lua' is provided as a template file and normally resides in the
lib folder of the 'game_intllib' mod path. The file 'gintllib.lua' should be copied into all the respective mod folders where at least one of the files holds an user-facing string and where a
S("string") enclosure was or will be added to the original code. However, any such copy of the file 'gintllib.lua' can only provide its code as definition of the 'S()' function successfully if it is somehow included into the Lua code of a respective existing code file in a way compliant to the software syntax.
The inclusion of the definitions of another file into the code of an existing code file is possible by means of the
dofile statement in the
Lua code of a MT mod or any other Lua software. The respective code segment including a commentary line as preface and another line for a path check for including 'gintllib.lua' is:
Code: Select all
-- Load support for game_intllib.
local MP = minetest.get_modpath(minetest.get_current_modname())
local S, NS = dofile(MP .. "/gintllib.lua")
This code segment has to be respectively copied once to the head of any and all '*.lua' files where a
S("string") enclosure was or will be added to the original code. Please note there is an additional
NS("string") enclosure defined hereby. This additional definition is for good reasons and will be explained later.
Furthermore, the code
dofile(MP .. "/gintllib.lua") reads the definitions of the 'gintllib.lua' file in the same folder to be compliant to
the mod security requirements by the MT developers. This is the reason why we have to copy the 'gintllib.lua' file into all applicable mod folders and cannot address a different solution without such copying. Please note the documentation may be outdated and the functionality of the former 'security' mod may be integrated into the MT core code but the principle concepts apply.
Please find a
Beta-release of the discussed 'gintllib.lua' file
in the attach below (see at the foot of this forum contribution). The normal user may investigate the contents of the ZIP-file for the benefit of understanding this tutorial. However, the ambitious translator-developer may use this file for experiments at your own risk. The license included inside the ZIP-file applies.
Inside the 'gintllib.lua' file there is a check for the 'game_intllib.lua' mod being enabled or not. The code definitions provide a sufficient stub if the 'game_intllib.lua' is disabled and the functions 'S()' and 'NS()' will just copy the value of the enclosed original string as return value.
Testing the preliminary 'game_intllib' additions
We now have discussed the code additions to the original Lua code of both the 'init.lua' and the 'ceative.lua' file and the addition of the 'gintllib.lua' file to the folder of the 'creative' mod as an example for a MT software translation. Please consider the preliminary 'game_intllib' additions explained for the purpose of this tutorial.
The ambitious translator-developer may now use again this example to test the code in an improved way. This is at your own risk and please remember to:
- copy the 'gintllib.lua' file into the 'creative' mod folder
- check for all of the a.m. five code changes by S("string") enclosure both in the 'init.lua' and the 'creative.lua' file,
- put all three lines of the a.m. code segment into both the 'init.lua' and the 'creative.lua' file of the same folder.
Afterwards you may start your experimental copy of the MT client with the a.m. code additions. In the creative mode play the inventory GUI should be popping up as you type the 'I' command key and should provide a view on crafting and items. Such experiment should get no errors and you should avoid a code failure if you did follow all steps correctly.
Please note we will momentarily see no change to the view on the names of tabs in the
creative inventory GUI as we did not provide any true translations yet. However, this was intentional for this part of the tutorial and the experimental copy of the MT game software should be running without hassle.
Last not least, the reader and the translator-developer could appreciate there is a way to introduce a 'S()' function by
S("string") enclosure to user-facing strings of the Lua code in the MT software. This is a success to an experimental effort which may lead to a translation solution later and which is not producing a code break in the mean time.
We start small but have high ambitions. We could call this a proof of example.
This is the end of part 1 of the document and you may continue with
the part 2 of my little tutorial if you like. Thank you for your attention.