Translation: Add chapter

This commit is contained in:
rubenwardy 2022-06-17 17:34:22 +01:00
parent a5b822122f
commit 8163b0cb37
4 changed files with 253 additions and 62 deletions

191
_en/quality/translations.md Normal file
View File

@ -0,0 +1,191 @@
---
title: Translation (i18n / l10n)
layout: default
root: ../..
idx: 8.05
marked_text_encoding:
level: info
title: Marked Text Encoding
message: |
You don't need to know the exact format of marked text, but it might help
you understand.
```
"\27(T@mymod)Hello everyone!\27E"
```
* `\27` is the escape character - it's used to tell Minetest to pay attention as
something special is coming up. This is used for both translations and text
colorisation.
* `(T@mymod)` says that the following text is translatable using the `mymod`
textdomain.
* `Hello everyone!` is the translatable text in English, as passed to the
translator function.
* `\27E` is the escape character again and `E`, used to signal that the end has
been reached.
---
## Introduction <!-- omit in toc -->
Adding support for translation to your mods and games allows more people to
enjoy them. According to Google Play, 64% of Minetest Android users don't have
English as their primary language. Minetest doesn't track stats for user
languages across all platforms, but there's likely to be a high proportion of
non-English speaking users.
Minetest allows you to translate your mods and games into different languages by
writing your text in English, and using translation files to map into other
languages. Translation is done on each player's client, allowing each player to
see a different language.
- [How does client-side translation work?](#how-does-client-side-translation-work)
- [Marked text](#marked-text)
- [Translation files](#translation-files)
- [Format strings](#format-strings)
- [Best practices and Common Falsehoods about Translation](#best-practices-and-common-falsehoods-about-translation)
- [Server-side translations](#server-side-translations)
- [Conclusion](#conclusion)
## How does client-side translation work?
### Marked text
The server needs to tell clients how to translate text. This is done by marking
text as translatable using a translator function (`S()`), returned by
`minetest.get_translator(textdomain)`:
```lua
local S = minetest.get_translator("mymod")
minetest.register_craftitem("mymod:item", {
description = S("My Item"),
})
```
The first argument of `get_translator` is the `textdomain`, which acts as a
namespace. Rather than having all translations for a language stored in the same
file, translations are separated into textdomains, with a file per textdomain
per language. The textdomain should be the same as the mod name, as it helps
avoid mod conflicts.
Marked text can be used in most places where human-readable text is accepted,
including formspecs, item def fields, infotext, and more. When including marked
text in formspecs, you need to escape the text using
`minetest.formspec_escape`.
When the client encounters marked text, such as that passed to `description`, it
looks it up in the player's language's translation file. If a translation cannot
be found, it falls back to the English translation.
Marked text contains the English source text, the textdomain, and any additional
arguments passed to `S()`. It's essentially a text encoding of the `S` call,
containing all the required information.
{% include notice.html notice=page.marked_text_encoding %}
### Translation files
Translation files are media files that can be found in the `locale` folder for
each mod. Currently, the only supported format is `.tr`, but support for more
common formats is likely in the future. Translation files must be named
in the following way: `[textdomain].[lang].tr`.
Files in the `.tr` start with a comment specifying the textdomain, and then
further lines mapping from the English source text to the translation.
For example, `mymod.fr.tr`:
```
# textdomain: mymod
Hello everyone!=Bonjour à tous !
I like grapefruit=J'aime le pamplemousse
```
You should create translation files based on your mod/game's source code,
using a tool like
[update_translations](https://github.com/minetest-tools/update_translations).
This tool will look for `S(` in your Lua code, and automatically create a
template that translators can use to translate into their language.
It also handles updating the translation files when your source changes.
## Format strings
It's common to need to include variable information within a translation
string. It's important that text isn't just concatenated, as that prevents
translators from changing the order of variables within a sentence. Instead,
you should use the translation system's format/arguments system:
```lua
minetest.register_on_joinplayer(function(player)
minetest.chat_send_all(S("Everyone, say hi to @1!", player:get_player_name()))
end)
```
If you want to include a literal `@` in your translation, you'll need to escape
by writing `@@`.
You should avoid concatenation *within* a sentence, but it's recommended that
you join multiple sentences using concatenation. This helps translators by
keeping strings smaller.
```lua
S("Hwllo @1!", player_name) .. " " .. S("You have @1 new messages.", #msgs)
```
## Best practices and Common Falsehoods about Translation
* Avoid concatenating text and use format arguments instead. This gives
translators full control over changing the order of things.
* Create translation files automatically, using
[update_translations](https://github.com/minetest-tools/update_translations).
* It's common for variables to change the surrounding text, for example, with
gender and pluralisation. This is often hard to deal with, so is
frequently glossed over or worked around with gender neutral phrasings.
* Translations may be much longer or much smaller than the English text. Make
sure to leave plenty of space.
* Other languages may write numbers in a different way, for example, with commas
as decimal points. `1.000,23`, `1'000'000,32`
* Don't assume that other languages use capitalisation in the same way.
## Server-side translations
Sometimes you need to know the translation of text on the server, for example,
to sort or search text. You can use `get_player_information` to get a player's
lang,uage and `get_translated_string` to translate marked text.
```lua
local list = {
S("Hello world!"),
S("Potato")
}
minetest.register_chatcommand("find", {
func = function(name, param)
local info = minetest.get_player_information(name)
local language = info and info.language or "en"
for _, line in ipairs(list) do
local trans = minetest.get_translated_string(language, line)
if trans:contains(query) then
return line
end
end
end,
})
```
## Conclusion
The translation API allows making mods and games more accessible, but care is
needed in order to use it correctly.
Minetest is continuously improving, and the translation API is likey to be
extended in the future. For example, support for gettext translation files will
allow common translator tools and platforms (like weblate) to be used, and
there's likely to be support for pluralisation and gender added.

View File

@ -33,68 +33,6 @@ figure {
padding: 0 0 0 6px;
}
.notice-info {
background: #ececec !important;
border: 1px solid #aaa !important;
}
.notice-danger {
background: #fcc !important;
border: 1px solid #a66 !important;
}
.notice-warning {
background: #FED;
border: 1px solid #fc9;
}
.notice-tip {
background: #ccf;
border: 1px solid #66a;
}
.notice-green {
background: #161;
border: 1px solid #393;
}
.notice {
margin: 10px;
display: block;
padding: 5px;
border-radius: 5px;
position: relative;
}
.notice p {
margin: 0 0 17px 0;
}
.notice p:last-child {
margin: 0;
}
.notice > span {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 40px;
font-size: 24px;
text-align: center;
display: block;
}
.notice > div {
margin-left: 35px;
}
.notice h2 {
margin: 0 0 5px 0;
padding: 0 0 2px 0;
font-size: 100%;
}
.header-link, .anchor {
text-decoration: none;
color: #bbb;

61
_sass/_notice.scss Normal file
View File

@ -0,0 +1,61 @@
.notice {
margin: 2em 0;
display: block;
padding: 0.5rem;
border-radius: 0.5rem;
position: relative;
p {
margin: 0 0 1em 0;
}
p:last-child {
margin: 0;
}
& > span {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 40px;
font-size: 24px;
text-align: center;
display: block;
}
& > div {
margin-left: 35px;
}
h2 {
margin: 0 0 5px 0;
padding: 0 0 2px 0;
font-size: 100%;
}
}
.notice-info {
background: #ececec !important;
border: 1px solid #aaa !important;
}
.notice-danger {
background: #fcc !important;
border: 1px solid #a66 !important;
}
.notice-warning {
background: #FED;
border: 1px solid #fc9;
}
.notice-tip {
background: #ccf;
border: 1px solid #66a;
}
.notice-green {
background: #161;
border: 1px solid #393;
}

View File

@ -4,3 +4,4 @@
@import "main";
@import "content";
@import "code";
@import "notice";