From 9e6461b93c9e8b52a36d40221304f8d3fcf37ae5 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Mon, 20 Feb 2023 15:22:43 +0100 Subject: [PATCH 1/4] Explain supported helper functions in README --- README.md | 121 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 86 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index ecfc2c0..aedba39 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,104 @@ -This Python script is intended for use with localized Minetest mods, ie, mods that contain translatable strings of the form ``S("This string can be translated")``. It extracts the strings from the mod's source code and updates the localization files accordingly. +# Minetest Update Translations -Place it in the root directory of a mod and run it, and it will update the ``template.txt`` and any ``*.tr`` files present in that mod's ``/locale`` folder. If the ``/locale`` folder or ``template.txt`` file don't exist yet they will be created. +This Python script is intended for use with localized Minetest mods, i.e., mods that contain translatable strings of the form `S("This string can be translated")`. It extracts the strings from the mod's source code and updates the localization files accordingly. Minetest version 5.0.0 or later is required. + +## Preparing your source code + +This script makes assumptions about your source code. Before it is usable, you first have to prepare your source code accordingly. + +### Choosing the translation domain name + +You should always set translation domain name (for `minetest.get_translator`) to be identical to the mod name. The script currently does not support custom domain names. If you want to choose a different domain name regardless, the script is still usable, but you have to manually fix the output later (usually just the header of the `*.tr` files). + +### Defining the helper functions + +In any source code file with translatable strings, you have to manually define helper functions at the top with something like `local S = minetest.get_translator("")`. Optionally, you can also define additional helper functions `FS`, `NS` and `NFS` if needed. + +Here is the list of all recognized function names. All functions return a string. + +* `S`: Returns translation of input. See Minetest's `lua_api.txt`. You should always have at least this function defined. +* `NS`: Returns the input. Useful to make a string visible to the script without actually translating it here. +* `FS`: Same as `S`, but returns a formspec-escaped version of the translation of the input. Supported for convenience. +* `NFS`: Returns a formspec-escaped version of the input, but not translated. Supported for convenience. + +Here is the boilerplate code you have to add at the top of your source code file: + + local S = minetest.get_translator("") + local NS = function(s) return s end + local FS = function(s) return minetest.formspec_escape(S(s)) end + local NFS = function(s) return minetest.formspec_escape(s) end + +Replace `` above and optionally delete `NS`, `FS` and/or `NFS` if you don't need them. + +### Preparing the strings + +Enclose any translatable strings in a function of the form `S("Some string")`. For the string to be detected correctly, there must be exactly *one* uninterrupted string within the function; string concatenation, etc. is not allowed. If the thing between the function brackets is anything else (including a variable), it will be ignored by this script. + +### A minimal example + +This minimal code example sends "Hello world!" to all players, but translated according to each player's language: + + local S = minetest.get_translator("example") + minetest.chat_send_all(S("Hello world!")) + +### How to use `NS` + +The reason why `NS` exists is for cases like this: Sometimes, you want to define a list of strings to they can be later output in a function. Like so: + + local fruit = { "Apple", "Orange", "Pear" } + local function return_fruit(fruit_id) + return fruit[fruit_id] + end + +If you want to translate the fruit names when `return_fruit` is run, but have the *untranslated* fruit names in the `fruit` table stored, this is where `NS` will help. It will show the script the string without Minetest translating it. The script could be made translatable like this: + + local fruit = { NS("Apple"), NS("Orange"), NS("Pear") } + local function return_fruit(fruit_id) + return S(fruit[fruit_id]) + end + +## How to run the script + +Place the script in the root directory of a mod and run it, and it will update the `template.txt` and any `*.tr` files present in that mod's `/locale` folder. If the `/locale` folder or `template.txt` file don't exist yet they will be created. This script will also work in the root directory of a modpack. It will run on each mod inside the modpack in that situation. It has the following command line options: -``` -i18n.py [OPTIONS] [PATHS...] - ---help, -h: prints this help message ---recursive, -r: run on all subfolders of paths given ---mods, -m: run on locally installed modules ---no-old-file, -O: do not create *.old files ---sort, -s: sort output strings alphabetically ---break-long-lines, -b: add extra line-breaks before and after long strings ---print-source, -p: add comments denoting the source file ---verbose, -v: add output information ---truncate-unused, -t: delete unused strings from files -``` + i18n.py [OPTIONS] [PATHS...] -The script will preserve any comments in an existing ``template.txt`` or the various ``*.tr`` files, associating them with the line that follows them. So for example: + --help, -h: prints this help message + --recursive, -r: run on all subfolders of paths given + --mods, -m: run on locally installed modules + --no-old-file, -O: do not create *.old files + --sort, -s: sort output strings alphabetically + --break-long-lines, -b: add extra line-breaks before and after long strings + --print-source, -p: add comments denoting the source file + --verbose, -v: add output information + --truncate-unused, -t: delete unused strings from files -``` -# This comment pertains to Some Text -Some text= +The script will preserve any comments in an existing `template.txt` or the various `*.tr` files, associating them with the line that follows them. So for example: -# Multi-line comments -# are also supported -Text as well= -``` + # This comment pertains to Some Text + Some text= + + # Multi-line comments + # are also supported + Text as well= -Note that whenever the translation files are regenerated the translation lines will be grouped by source lua filename and sorted alphabetically, so don't bother manually organizing the order of the lines in the file yourself. +Note that whenever the translation files are regenerated, the translation lines will be grouped by source `.lua` filename and sorted alphabetically, so don't bother manually organizing the order of the lines in the file yourself. If the mod's source changes in such a way that a line with an existing translation or comment is no longer present, the unused line will be moved to the bottom of the translation file under the header: -``` -##### not used anymore ##### -``` + ##### not used anymore ##### -This allows for old translations and comments to be reused with new lines where appropriate. This script doesn't attempt "fuzzy" matching of old strings to new, so even a single change of punctuation or spelling will put strings into the "not used anymore" section and require manual reassociation with the new string. +This allows for old translations and comments to be reused with new lines where appropriate. This script doesn't attempt "fuzzy" matching of old strings to new, so even a single change of punctuation or spelling will put strings into the "not used anymore" section and require manual re-association with the new string. -## bash autocompletion +## bash auto-completion -When running on linux to install bash_completion for i18n, you can run +When running on Linux to install `bash_completion` for `i18n`, you can run -``` -mkdir -p ${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion/completions -ln -s $PWD/bash-completion/completions/i18n ${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion/completions/i18n.py -``` + mkdir -p ${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion/completions + ln -s $PWD/bash-completion/completions/i18n ${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion/completions/i18n.py -This will provide bash autocompletion for this script (you have to run it without using `python3 i18n` command, use `./i18n.py` instead (or `i18n.py` if provided by `$PATH`)). +This will provide bash auto-completion for this script (you have to run it without using `python3 i18n` command, use `./i18n.py` instead (or `i18n.py` if provided by `$PATH`)). From 6d885755597ba425c478174c99764d1e8e2a2239 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Mon, 20 Feb 2023 15:29:17 +0100 Subject: [PATCH 2/4] Document PO file conversion --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index aedba39..bcfa8e7 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,14 @@ If the mod's source changes in such a way that a line with an existing translati This allows for old translations and comments to be reused with new lines where appropriate. This script doesn't attempt "fuzzy" matching of old strings to new, so even a single change of punctuation or spelling will put strings into the "not used anymore" section and require manual re-association with the new string. +## PO files conversion + +This script will automatically convert `.po` files (from GNU gettext and the like) +if they exist in the `locale/` directory and a corresponding `.tr` file +*doesn't* exist. The .tr file that results will be reprocessed in +later runs so any "no longer used" strings will be preserved. +Note that "fuzzy" tags will be lost in this process. + ## bash auto-completion When running on Linux to install `bash_completion` for `i18n`, you can run From 94d6db272ce56dbd4f4554033a0be62ff25d0ba1 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Mon, 20 Feb 2023 15:51:00 +0100 Subject: [PATCH 3/4] Fix README boilerplate of FS() --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bcfa8e7..be714e7 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Here is the boilerplate code you have to add at the top of your source code file local S = minetest.get_translator("") local NS = function(s) return s end - local FS = function(s) return minetest.formspec_escape(S(s)) end + local FS = function(...) return minetest.formspec_escape(S(...)) end local NFS = function(s) return minetest.formspec_escape(s) end Replace `` above and optionally delete `NS`, `FS` and/or `NFS` if you don't need them. From 3560277a64155631a6545631b591acff76e554c3 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Mon, 20 Feb 2023 16:40:44 +0100 Subject: [PATCH 4/4] Update "how to run" section in README --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index be714e7..1623a30 100644 --- a/README.md +++ b/README.md @@ -59,9 +59,11 @@ If you want to translate the fruit names when `return_fruit` is run, but have th ## How to run the script -Place the script in the root directory of a mod and run it, and it will update the `template.txt` and any `*.tr` files present in that mod's `/locale` folder. If the `/locale` folder or `template.txt` file don't exist yet they will be created. +First, change the working directory to the directory of the mod you want the files to be updated. From this directory, run the script. -This script will also work in the root directory of a modpack. It will run on each mod inside the modpack in that situation. +When you run the script, it will update the `template.txt` and any `*.tr` files present in that mod's `/locale` folder. If the `/locale` folder or `template.txt` file don't exist yet, they will be created. + +This script will also work in the root directory of a modpack. It will run on each mod inside the modpack in that situation. Alternatively, you can run the script to update the files of all mods in subdirecories with the `-r` option, which is useful to update the locale files in an entire game. It has the following command line options: