Difference between revisions of "Translation"

From Minetest Developer Wiki
Jump to navigation Jump to search
(clarify Weblate project name)
 
(46 intermediate revisions by 6 users not shown)
Line 1: Line 1:
This page explains how to translate Minetest, mods and games and how translations are handled and maintained.
+
This page explains how to translate Luanti, along with mods.
  
== Translating Minetest ==
+
== Translating the engine ==
This section is dedicated for translators.
+
Translations of the Luanti engine are [https://hosted.weblate.org/projects/minetest/minetest/ automated using Weblate]. Register an account, select the “Minetest” project (or “Luanti” if it has been renamed) and start translating. Translation is a continuous effort and the texts will change almost at every version.
 
 
=== How to translate ===
 
Translations of Minetest are automated using Weblate at [https://hosted.weblate.org/projects/minetest/minetest/ here]. Register an account, select the Minetest project and start translating.
 
 
 
Translation is a continuous effort and the texts will change almost at every version.
 
  
 
The developers usually will update the translation templates shortly before a new release. If you translate a long time before a release, your translation updates will still be included, but your translation will likely be incomplete because almost every new version comes with new things to translate. Check out the [https://forum.minetest.net/viewforum.php?f=18 News forum] to see if a new release is imminent.
 
The developers usually will update the translation templates shortly before a new release. If you translate a long time before a release, your translation updates will still be included, but your translation will likely be incomplete because almost every new version comes with new things to translate. Check out the [https://forum.minetest.net/viewforum.php?f=18 News forum] to see if a new release is imminent.
  
In case you wish to translate a new language, [[How to communicate|contact a core dev]].
+
In case you wish to translate a new language, send a message in #minetest-dev and a coredev can add it.
  
==== Language-specific notes ====
+
=== Language-specific notes ===
 
Here is a list of wiki pages for translating specific languages:
 
Here is a list of wiki pages for translating specific languages:
 
* [[Translating/de|German]]
 
* [[Translating/de|German]]
  
==== Special strings ====
+
=== Special strings ===
In the translations you will find two special strings with a special meaning. They must '''not''' be translated literally. They are used internally by Minetest to trigger certain settings. You must enter a special value into the translation field.
+
In the translations you will find one string with a special meaning. It must '''not''' be translated literally. They are used internally by Luanti to trigger certain settings. You must enter a special value into the translation field.
 +
 
 +
* <code>LANG_CODE</code>: The language code of the language you're translating (e.g. "de" for German).
 +
 
 +
=== Builtin ===
 +
Builtin is another core part of Luanti which includes texts for server commands, privilege descriptions, and many other server-related messages. Builtin is translated with a different method, you can't use Weblate here. Builtin is translated like mods (read the section below to learn how) and the translation files work the same like for the mod translation files. You can find the builtin translation files in the Luanti source directory under <code>builtin/locale</code>.
 +
 
 +
For example, if you want to translate Builtin into German, you need to edit <code>builtin/locale/__builtin.de.tr</code>.
 +
 
 +
== Translating mods and games ==
 +
Mods and games are translated with special ".tr" files. This includes Minetest Game. This is a different system than the engine translation system.
 +
 
 +
=== For translators ===
 +
 
 +
To translate a mod, you first need to know if it can even be translated. Check if the following is true:
 +
 
 +
* The directory <code>locale</code> exists '''and'''
 +
* The file <code>template.txt</code> exists in the <code>locale</code> directory.
 +
 
 +
If both conditions are true, the mod is ready for translation. Otherwise, it is not. In that case, ask the project maintainers to add translation support '''and''' the <code>template.txt</code> file.
 +
 
 +
To translate a mod (or update an existing translation), follow these steps:
 +
 
 +
# Check if a file named <code>[MODNAME].[LANG_CODE].tr</code> exists in <code>locale/</code>. If yes, skip to step 3. Otherwise, go to step 2.
 +
# Copy the provided <code>template.txt</code> to a file named <code>[MODNAME].[LANG_CODE].tr</code>
 +
# Open the <code>.tr</code> file in a text editor
 +
# You will encounter a list of texts that end in equals signs. Put the translation of each text after the equals sign (note the special rules below)
 +
# Save the file
 +
 
 +
(Note: <code>[MODNAME]</code> is the name of the mod and <code>[LANG_CODE]</code> is the language code)
 +
 
 +
Done. Now you probably want to test this translation in-game and submit your changes to the mod/game maintainers.
 +
 
 +
To translate an entire game, you translate all the mods within that game.
 +
 
 +
==== Special text rules ====
 +
 
 +
Here are the detailed rules of how the ".tr" file is structured.
 +
 
 +
* The lines that matter for you are all non-empty lines that do not start with "#". These are the translation lines. On the left side of the equals sign, the original text is written. On the right side of the equals sign, the translation has to be written. If the translation is empty, Luanti will display the original text instead.
 +
* Do not change lines that start with "# textdomain:". These are need for technical reasons.
 +
* You can add as many empty lines you want. They will be ignored
 +
* Other lines that start with "#" are comments. Luanti will ignore them but they might contain some information for you. It is up to you whether you keep or remove these lines.
 +
 
 +
In the texts (both original and translated texts), some characters will be replaced in the actual game:
 +
 
 +
* "@1", "@2", ... to "@9" are placeholders. The game will replace it with another text. You '''MUST''' include all placeholders in the translation, but the order can be different.
 +
* To produce the "@" character, you '''MUST''' write "@@"
 +
* To produce the "=" character, you '''MUST''' write "@="
 +
* To produce a newline, you '''MUST''' write "@n". Alternatively, you can also write "@" followed by an actual newline
 +
 
 +
==== Example ====
  
* <code>needs_fallback_font</code>: Whether this language should use the fallback font or not. The fallback font contains some characters that are required by languages like Chinese. For most Latin-script languages, the fallback font is not needed. Enter “yes” if the fallback font is needed, “no” if not. Please try to test your translation when you enable the fallback font.
+
Consider the example mod <code>example</code>. You will find the file <code>template.txt</code> with this content:
* <code>LANG_CODE</code>: The language code of the language you're translating (e.g. “de” for German).
 
  
== The Minetest translation system ==
+
<pre># textdomain:example
This section is dedicated to developers.
+
Apple=
 +
Pickaxe=
 +
#This is a comment, not a translation. You can ignore this line.
 +
Welcome, @1!=
 +
@1 has killed @2 and gained @3 EXP.=
 +
E-mail: <somebody@@example.org>=
 +
“@=” is the equals sign=
 +
This text@nhas 2 lines.=Dieser Text@nhat 2 Zeilen.</pre>
  
=== Overview ===
+
A possible translation in German would be stored under <code>example.de.tr</code> with this content:
Minetest can use the '''gettext''' library to translate the texts in Minetest. To enable internationalization support, the game must be built with the <code>-DENABLE_GETTEXT=1</code> option to <code>cmake</code>, which is enabled by default.
 
  
Games and mods are translated using a different method (see below).
+
<pre># textdomain:example
 +
Apple=Apfel
 +
Pickaxe=Spitzhacke
 +
#This is a comment, not a translation. You can ignore this line.
 +
Welcome, @1!=Willkommen, @1!
 +
@1 has killed @2 and gained @3 EXP.=@1 hat @2 getötet und @3 EXP erhalten.
 +
E-mail: <somebody@@example.org>=E-Mail: <somebody@@example.org>
 +
“@=” is the equals sign.=»@=« ist das Gleichheitszeichen.
 +
This text@nhas 2 lines.=Dieser Text@nhat 2 Zeilen.</pre>
  
=== Language detection ===
+
For reference, this is how the English texts could ''actually'' show up in Luanti (with the placeholders resolved):
Minetest detects the current language by inspecting the <code>LANG</code> environment variable. This is not a problem on Unix-based systems (such as GNU/Linux) since the system already defines this variable at login. On Windows platforms, the system language is used.
 
  
=== Available translations ===
+
* Apple
The available translations are found in source form in the <code>po/</code> directory. The <code>cmake</code> detects them, and they are built as part of the build process.
+
* Pickaxe
 +
* Welcome, Merlin!
 +
* Gnerf has killed Hormel and gained 500 EXP.
 +
* E-mail: <somebody@example.org>
 +
* “=” is the equals sign
 +
* This text<br>
 +
has 2 lines
  
The main translation file must be updated now and then using the [https://github.com/minetest/minetest/blob/master/builtin/mainmenu/dlg_settings_advanced.lua this script] (configuration, bottom of the file) and [https://github.com/minetest/minetest/blob/master/util/updatepo.sh this one] (C++ and Lua translations). Submit a PR after running the generator or poke a core dev to update the translations when it's needed.
+
=== For developers ===
  
== Maintaining translations ==
+
As a mod or game developer, if you want to implement translation support, please refer to the official Lua API documentation (<code>lua_api.md</code>) and [https://rubenwardy.com/minetest_modding_book/en/quality/translations.html the modding book chapter on Translation].
=== Contributing a new translation ===
 
To create a new translation, one must create a directory named after the [http://www.mathguide.de/info/tools/languagecode.html language code], creating a copy of the <code>po/minetest.pot</code> file as <code>po/''LANG''/minetest.po</code>, and translating the original english text into your language; then <code>cmake</code> will detect it and <code>make</code> builds the language.
 
  
However, it is recomended to contact a core dev to create the .po file for you language and then use [https://hosted.weblate.org/projects/minetest/minetest/ weblate] to translate.
+
[https://github.com/minetest-tools/update_translations update_translations.py] is an extremely useful tool that can automatically generate and update translation files for mods. Using the <code>-t -O</code> flags are recommended as it will truncate old translated strings that aren't being used anymore.
  
=== How to merge translations from Hosted Weblate ===
+
== The Luanti engine translation system ==
 +
This section is dedicated to developers.
  
Translations should be merged in bulk, and not too often, to not create too large "noise" in the commit log. A good schedule is once per month. Right now, nerzhul manages translations. This section explains the neccessary steps for core devs, in the case nerzhul isn't around. You will need owner access to the hosted repo though, in order to be able to push the "Rebase" button.  As of Mar 2017, est31, PilzAdam, ShadowNinja, and nerzhul have such access.
+
=== Overview ===
 +
For most strings, Luanti uses the '''gettext''' library to translate the texts in Luanti. To enable internationalization support, the game must be built with the <code>-DENABLE_GETTEXT=1</code> option to <code>cmake</code>, which is enabled by default.
  
==== Setting up ====
+
Games, mods and builtin are translated using a different method (see below).
  
Add weblate as remote: <code>git remote add weblate git://git.weblate.org/minetest.git</code>.
+
=== Language detection ===
 +
Luanti detects the current language by inspecting the <code>LANG</code> environment variable. This is not a problem on Unix-based systems (such as GNU/Linux) since the system already defines this variable at login. On Windows platforms, the system language is used.
  
==== Once every translation ====
+
=== Available translations ===
 +
The available translations are found in source form in the <code>po/</code> directory. The <code>cmake</code> detects them, and they are built as part of the build process.
  
# Visit [https://hosted.weblate.org/projects/minetest/#repository Repo maintenance], and lock the repository to prevent changes from users while you are editing.
+
The main translation file must be updated now and then using the [https://github.com/minetest/minetest/blob/master/builtin/mainmenu/dlg_settings_advanced.lua this script] (configuration, bottom of the file) and [https://github.com/minetest/minetest/blob/master/util/updatepo.sh this one] (C++ and Lua translations). Submit a PR after running the generator or poke a core dev to update the translations when it's needed. Note that builtin translations are handled separately, see the maintenance notes below.
# Generate a clean history, without merge commits. Push the "Rebase" button on the repository.
 
# Do <code>git remote update weblate</code>. Confirm e.g. with <code>gitk weblate/master</code> that it bases on upstream's master, and only has "Translated using Weblate" as additional commits, no merge commits.
 
# As every weblate user can freely edit translations, there can be vandalism. Therefore, check the translation commits, e.g. with help from online translator services like Google Translate, other core devs, or trusted members from the community. It might be helpful to push the commits to your GitHub clone's branch, then you have commit http links to share. In the case of required changes, let them do it over the weblate interface (after you've unlocked), and start with 2. again. Of course, its up to you to how much you want to follow this rule, as checking changes can be quite time consuming. Feel free to refine your scope e.g. to new and not yet trusted contributors.
 
# Reorder the commits from the same author, and squash them. <code>git rebase -i</code> is your friend (especially after you set it up to show the author, see [http://stackoverflow.com/a/35851846 this Stack Overflow answer] on how to do it). As a good tip, rather do multiple runs of such an interactive rebase where you do small changes each, than one big run which then fails in the middle of the business.
 
# Confirm that <code>git diff weblate/master</code> is empty, to make sure that you didn't mess up at step 5. Otherwise use <code>git reflog</code> to find the latest rebase pass that worked, and retry the commits
 
# If required/desired, do this:
 
## (if required/desired) Update the <code>settingtypes.txt</code> and the dummy <code>*.cpp</code> translation file and commit. There are automatic tools for this in the main menu code.
 
## (if required/desired) Run <code>util/updatepo.sh</code>, and commit. Note that it creates lots of unneccessary changes, and enlarges repository size disproportionately, therefore run it even less often.
 
# Push to the [https://github.com/minetest/minetest GitHub repo]
 
# Reset the Weblate remote ("Reset" button), rebase it to match now current master, and unlock it.
 
  
== Translating mods and games ==
+
== Maintaining engine translations ==
Minetest supports translating mods and games. Games are translated on a per-mod basis, i.e. by translating each mod.
+
There are two types of translations that need maintenance: Client-side (using Gettext) and server-side translations for builtin (using <code>minetest.get_translator</code>).
  
=== How to translate ===
+
=== Client-side translations (Gettext) ===
First, the mod in question must support the Minetest translation system. If you can find a <code>locale</code> directory within the mod directory, this mod can be translated.
+
==== Contributing a new translation ====
 +
To create a new translation, one must create a directory named after the [http://www.mathguide.de/info/tools/languagecode.html language code], creating a copy of the <code>po/minetest.pot</code> file as <code>po/''LANG''/minetest.po</code>, and translating the original english text into your language; then <code>cmake</code> will detect it and <code>make</code> builds the language.
  
In this directory, you will find:
+
However, it is recomended to contact a core dev to create the .po file for you language and then use [https://hosted.weblate.org/projects/minetest/minetest/ weblate] to translate.
  
* <code>template.txt</code> (or similar name): Translation template for new languages
+
''Note to coredevs'': Creating a new language directly from weblate is sufficient, no need to mess with the files directly in the repository.
* <code><CONTEXT>.<LANGUAGE CODE>.tr</code>: Text file containing translations, where <code><CONTEXT></code> is an arbitrary identifier (usually the same as the technical mod name) and <code><LANGUAGE CODE></code> is the language code. Example: The German translation file for the <code>default</code> mod is called “default.de.tr”.
 
  
The *.tr files follow a simple syntax:
+
==== How to merge translations from Hosted Weblate ====
  
* Lines of the form “<code># textdomain:<CONTEXT></code>” specify the context. Translators: ignore this
+
Translations should be merged in bulk, and not too often, to not create too large "noise" in the commit log. A good schedule is once every few months and at the start of the '''feature freeze'''. This section explains the necessary steps for coredevs. You will need owner access to the hosted repo in order to be able to push the "Rebase" button.
* Empty lines and other lines that start with “#” are ignored. They might contain some comments for translators, however
 
* All other lines must contain translations of the form <code><ENGLISH>=<TRANSLATION></code>
 
  
Translators only need to care about the last point. The English original text comes left from the equals sign, the translation is right from the equals sign. Do not insert trailing or leading spaces.
+
As of Oct 2019, ShadowNinja, nerzhul, sfan5, rubenwardy, Krock and possibly some other coredevs have such access.
  
To start a new translation, simply copy the file <code>template.txt</code> and create a *.tr file with the appropriate name.
+
===== Setting up =====
  
==== Example ====
+
Add weblate as remote: <code>git remote add weblate https://hosted.weblate.org/git/minetest/minetest/</code>.
Take for example this translation template:
 
  
<pre>
+
===== Once every translation =====
# textdomain:example
 
Apple=
 
Pineapple=
 
Silver Ingot=
 
</pre>
 
  
A valid German translation would look like this:
+
# Visit [https://hosted.weblate.org/projects/minetest/minetest/#repository Repo maintenance], and lock the repository to prevent changes from users while you are editing.
<pre>
+
# Generate a clean history, without merge commits. Push the "Rebase" button on the repository.
# textdomain:example
+
# Do <code>git remote update weblate</code>. Confirm e.g. with <code>git log --graph weblate/master</code> that it bases on upstream's master, and only has "Translated using Weblate" as additional commits, no merge commits.
Apple=Apfel
+
# As every weblate user can freely edit translations, there can be vandalism. Therefore, check the translation commits, e.g. with help from online translator services like Google Translate, other core devs, or trusted members from the community. It might be helpful to push the commits to your GitHub clone's branch, then you have commit http links to share. In the case of required changes, let them do it over the weblate interface (after you've unlocked), and start with 2. again. Of course, its up to you to how much you want to follow this rule, as checking changes can be quite time consuming. Feel free to refine your scope e.g. to new and not yet trusted contributors.
Pineapple=Ananas
+
# Check out the branch from Weblate's repo: <code>git checkout weblate/master</code>
Silver Ingot=Silberbarren
+
# Reorder the commits from the same author, and squash them. <code>git rebase -i</code> is your friend (especially after you set it up to show the author, see [http://stackoverflow.com/a/35851846 this Stack Overflow answer] on how to do it). As a good tip, rather do multiple runs of such an interactive rebase where you do small changes each, than one big run which then fails in the middle of the business. '''<code>./util/reorder_translation_commits.py</code> can do the commit reordering for you.'''
</pre>
+
# Confirm that <code>git diff weblate/master</code> is empty, to make sure that you didn't mess up at step 6. Otherwise use <code>git reflog</code> to find the latest rebase pass that worked, and retry the commits
 +
# If ''required/desired'', do these: (<code>--author="updatepo.sh <script@mt>"</code> should be used when committing changes made by the scripts)
 +
## Update <code>minetest.conf.example</code> and the dummy <code>*.cpp</code> translation file and commit. Do this by uncommenting the lines at the end of builtin/mainmenu/settings/init.lua
 +
## Run <code>util/updatepo.sh</code>, and commit. Note that it creates lots of unneccessary changes, and enlarges repository size disproportionately, therefore run it even less often.
 +
# Push to the [https://github.com/minetest/minetest GitHub repo] with e.g. <code>git push origin HEAD:master</code>
 +
# Reset the Weblate remote ("Reset" button), rebase it to match now current master, and unlock it. If pushed commits do not yet show up in Weblate you may have to press the "Pull" button.
  
==== Special character sequences ====
+
=== Server-side builtin translations (<code>minetest.get_translator</code>) ===
 +
The server-side translations of builtin are located in <code>builtin/locale</code> with <code>template.txt</code> being used as the template file.
  
Some characters like the equals sign cannot be used directly in the texts. Therefore, you must sometimes use special character sequences.
+
The template file as well as all locale files need to be updated before release to allow translators to translate.
  
* <code>@@</code>: Will be replaced with <code>@</code>.
+
To update the builtin locale files, run <code>../util/mod_translation_updater.py</code> from the builtin directory (requires Python 3).
* <code>@=</code>: Will be replaced with <code>=</code>.
 
* <code>@n</code>: Will be replaced by a newline.
 
* <code>@</code> followed by an actual newline: Will be replaced by a newline.
 
* <code>@1</code>, ..., <code>@9</code>: A placeholder. Minetest will replace this with an arbitrary text, for example, a word or a number.
 
  
=== How to make a mod or game translatable ===
+
To start a new translation, copy <code>template.txt</code> to create <code>__builtin.<LANGUAGE_CODE>.tr</code>.
Please refer to the official Lua API documentation (<code>lua_api.txt</code>).
 
  
 
== Untranslatable texts ==
 
== Untranslatable texts ==
Please note: A couple of things in Minetest can '''not''' be translated yet:
+
Please note: A couple of things in Luanti can '''not''' be translated yet:
  
 
* Setting help texts for settings of games and mods (<code>settingtypes.txt</code>)  ([https://github.com/minetest/minetest/issues/9070 #9070])
 
* Setting help texts for settings of games and mods (<code>settingtypes.txt</code>)  ([https://github.com/minetest/minetest/issues/9070 #9070])
* Everything that comes from <code>builtin</code>, including the help texts for the built-in server commands and privileges ([https://github.com/minetest/minetest/issues/7883 #7883])
 
 
* Description of mods, modpacks, games and texture packs ([https://github.com/minetest/minetest/issues/9071 #9071])
 
* Description of mods, modpacks, games and texture packs ([https://github.com/minetest/minetest/issues/9071 #9071])
* Other ([https://github.com/minetest/minetest/issues/7880 #7880])
 
  
 
[[Category:Core Engine]]
 
[[Category:Core Engine]]

Latest revision as of 17:40, 23 October 2024

This page explains how to translate Luanti, along with mods.

Translating the engine

Translations of the Luanti engine are automated using Weblate. Register an account, select the “Minetest” project (or “Luanti” if it has been renamed) and start translating. Translation is a continuous effort and the texts will change almost at every version.

The developers usually will update the translation templates shortly before a new release. If you translate a long time before a release, your translation updates will still be included, but your translation will likely be incomplete because almost every new version comes with new things to translate. Check out the News forum to see if a new release is imminent.

In case you wish to translate a new language, send a message in #minetest-dev and a coredev can add it.

Language-specific notes

Here is a list of wiki pages for translating specific languages:

Special strings

In the translations you will find one string with a special meaning. It must not be translated literally. They are used internally by Luanti to trigger certain settings. You must enter a special value into the translation field.

  • LANG_CODE: The language code of the language you're translating (e.g. "de" for German).

Builtin

Builtin is another core part of Luanti which includes texts for server commands, privilege descriptions, and many other server-related messages. Builtin is translated with a different method, you can't use Weblate here. Builtin is translated like mods (read the section below to learn how) and the translation files work the same like for the mod translation files. You can find the builtin translation files in the Luanti source directory under builtin/locale.

For example, if you want to translate Builtin into German, you need to edit builtin/locale/__builtin.de.tr.

Translating mods and games

Mods and games are translated with special ".tr" files. This includes Minetest Game. This is a different system than the engine translation system.

For translators

To translate a mod, you first need to know if it can even be translated. Check if the following is true:

  • The directory locale exists and
  • The file template.txt exists in the locale directory.

If both conditions are true, the mod is ready for translation. Otherwise, it is not. In that case, ask the project maintainers to add translation support and the template.txt file.

To translate a mod (or update an existing translation), follow these steps:

  1. Check if a file named [MODNAME].[LANG_CODE].tr exists in locale/. If yes, skip to step 3. Otherwise, go to step 2.
  2. Copy the provided template.txt to a file named [MODNAME].[LANG_CODE].tr
  3. Open the .tr file in a text editor
  4. You will encounter a list of texts that end in equals signs. Put the translation of each text after the equals sign (note the special rules below)
  5. Save the file

(Note: [MODNAME] is the name of the mod and [LANG_CODE] is the language code)

Done. Now you probably want to test this translation in-game and submit your changes to the mod/game maintainers.

To translate an entire game, you translate all the mods within that game.

Special text rules

Here are the detailed rules of how the ".tr" file is structured.

  • The lines that matter for you are all non-empty lines that do not start with "#". These are the translation lines. On the left side of the equals sign, the original text is written. On the right side of the equals sign, the translation has to be written. If the translation is empty, Luanti will display the original text instead.
  • Do not change lines that start with "# textdomain:". These are need for technical reasons.
  • You can add as many empty lines you want. They will be ignored
  • Other lines that start with "#" are comments. Luanti will ignore them but they might contain some information for you. It is up to you whether you keep or remove these lines.

In the texts (both original and translated texts), some characters will be replaced in the actual game:

  • "@1", "@2", ... to "@9" are placeholders. The game will replace it with another text. You MUST include all placeholders in the translation, but the order can be different.
  • To produce the "@" character, you MUST write "@@"
  • To produce the "=" character, you MUST write "@="
  • To produce a newline, you MUST write "@n". Alternatively, you can also write "@" followed by an actual newline

Example

Consider the example mod example. You will find the file template.txt with this content:

# textdomain:example
Apple=
Pickaxe=
#This is a comment, not a translation. You can ignore this line.
Welcome, @1!=
@1 has killed @2 and gained @3 EXP.=
E-mail: <somebody@@example.org>=
“@=” is the equals sign=
This text@nhas 2 lines.=Dieser Text@nhat 2 Zeilen.

A possible translation in German would be stored under example.de.tr with this content:

# textdomain:example
Apple=Apfel
Pickaxe=Spitzhacke
#This is a comment, not a translation. You can ignore this line.
Welcome, @1!=Willkommen, @1!
@1 has killed @2 and gained @3 EXP.=@1 hat @2 getötet und @3 EXP erhalten.
E-mail: <somebody@@example.org>=E-Mail: <somebody@@example.org>
“@=” is the equals sign.=»@=« ist das Gleichheitszeichen.
This text@nhas 2 lines.=Dieser Text@nhat 2 Zeilen.

For reference, this is how the English texts could actually show up in Luanti (with the placeholders resolved):

  • Apple
  • Pickaxe
  • Welcome, Merlin!
  • Gnerf has killed Hormel and gained 500 EXP.
  • E-mail: <somebody@example.org>
  • “=” is the equals sign
  • This text

has 2 lines

For developers

As a mod or game developer, if you want to implement translation support, please refer to the official Lua API documentation (lua_api.md) and the modding book chapter on Translation.

update_translations.py is an extremely useful tool that can automatically generate and update translation files for mods. Using the -t -O flags are recommended as it will truncate old translated strings that aren't being used anymore.

The Luanti engine translation system

This section is dedicated to developers.

Overview

For most strings, Luanti uses the gettext library to translate the texts in Luanti. To enable internationalization support, the game must be built with the -DENABLE_GETTEXT=1 option to cmake, which is enabled by default.

Games, mods and builtin are translated using a different method (see below).

Language detection

Luanti detects the current language by inspecting the LANG environment variable. This is not a problem on Unix-based systems (such as GNU/Linux) since the system already defines this variable at login. On Windows platforms, the system language is used.

Available translations

The available translations are found in source form in the po/ directory. The cmake detects them, and they are built as part of the build process.

The main translation file must be updated now and then using the this script (configuration, bottom of the file) and this one (C++ and Lua translations). Submit a PR after running the generator or poke a core dev to update the translations when it's needed. Note that builtin translations are handled separately, see the maintenance notes below.

Maintaining engine translations

There are two types of translations that need maintenance: Client-side (using Gettext) and server-side translations for builtin (using minetest.get_translator).

Client-side translations (Gettext)

Contributing a new translation

To create a new translation, one must create a directory named after the language code, creating a copy of the po/minetest.pot file as po/LANG/minetest.po, and translating the original english text into your language; then cmake will detect it and make builds the language.

However, it is recomended to contact a core dev to create the .po file for you language and then use weblate to translate.

Note to coredevs: Creating a new language directly from weblate is sufficient, no need to mess with the files directly in the repository.

How to merge translations from Hosted Weblate

Translations should be merged in bulk, and not too often, to not create too large "noise" in the commit log. A good schedule is once every few months and at the start of the feature freeze. This section explains the necessary steps for coredevs. You will need owner access to the hosted repo in order to be able to push the "Rebase" button.

As of Oct 2019, ShadowNinja, nerzhul, sfan5, rubenwardy, Krock and possibly some other coredevs have such access.

Setting up

Add weblate as remote: git remote add weblate https://hosted.weblate.org/git/minetest/minetest/.

Once every translation
  1. Visit Repo maintenance, and lock the repository to prevent changes from users while you are editing.
  2. Generate a clean history, without merge commits. Push the "Rebase" button on the repository.
  3. Do git remote update weblate. Confirm e.g. with git log --graph weblate/master that it bases on upstream's master, and only has "Translated using Weblate" as additional commits, no merge commits.
  4. As every weblate user can freely edit translations, there can be vandalism. Therefore, check the translation commits, e.g. with help from online translator services like Google Translate, other core devs, or trusted members from the community. It might be helpful to push the commits to your GitHub clone's branch, then you have commit http links to share. In the case of required changes, let them do it over the weblate interface (after you've unlocked), and start with 2. again. Of course, its up to you to how much you want to follow this rule, as checking changes can be quite time consuming. Feel free to refine your scope e.g. to new and not yet trusted contributors.
  5. Check out the branch from Weblate's repo: git checkout weblate/master
  6. Reorder the commits from the same author, and squash them. git rebase -i is your friend (especially after you set it up to show the author, see this Stack Overflow answer on how to do it). As a good tip, rather do multiple runs of such an interactive rebase where you do small changes each, than one big run which then fails in the middle of the business. ./util/reorder_translation_commits.py can do the commit reordering for you.
  7. Confirm that git diff weblate/master is empty, to make sure that you didn't mess up at step 6. Otherwise use git reflog to find the latest rebase pass that worked, and retry the commits
  8. If required/desired, do these: (--author="updatepo.sh <script@mt>" should be used when committing changes made by the scripts)
    1. Update minetest.conf.example and the dummy *.cpp translation file and commit. Do this by uncommenting the lines at the end of builtin/mainmenu/settings/init.lua
    2. Run util/updatepo.sh, and commit. Note that it creates lots of unneccessary changes, and enlarges repository size disproportionately, therefore run it even less often.
  9. Push to the GitHub repo with e.g. git push origin HEAD:master
  10. Reset the Weblate remote ("Reset" button), rebase it to match now current master, and unlock it. If pushed commits do not yet show up in Weblate you may have to press the "Pull" button.

Server-side builtin translations (minetest.get_translator)

The server-side translations of builtin are located in builtin/locale with template.txt being used as the template file.

The template file as well as all locale files need to be updated before release to allow translators to translate.

To update the builtin locale files, run ../util/mod_translation_updater.py from the builtin directory (requires Python 3).

To start a new translation, copy template.txt to create __builtin.<LANGUAGE_CODE>.tr.

Untranslatable texts

Please note: A couple of things in Luanti can not be translated yet:

  • Setting help texts for settings of games and mods (settingtypes.txt) (#9070)
  • Description of mods, modpacks, games and texture packs (#9071)