Skip to content

Translation and Localization

Garrett Guillotte edited this page Jan 9, 2023 · 19 revisions

This page documents the ongoing effort of facilitating the translation of EmptyEpsilon for different languages.

There are five major aspects that need to be worked on:

  1. Updating the C++ code to allow for translations
  2. Updating shared Lua code to allow for translations
  3. Updating scenarios to allow for translations
  4. Adding translations of game text
  5. Adding translations of shared Lua script and scenario text

Updating the C++ code to allow for translations

EmptyEpsilon was not designed for translation or localization, and many parts still need to be updated.

Most translation patches look like this: https://github.com/daid/EmptyEpsilon/pull/1732/commits/3bfbc7deb2f720a677d85f232a9605ba8e95b563

The tr() function is added around static strings in the code so they can be translated. The function can be used with either one or two parameters.

Using tr() with two parameters provides context for the string in the first parameter. This context can help clarify the string's translation. For example, translating the string "Both" can be difficult without context, but the context "jump/warp" indicates that this is about jump/warp selection, which helps translators use the correct word for their language.

Pull requests to add translation contexts are welcome, but try to make small changes in order to make reviews easier and avoid introducing bugs. Some updates are more complex than simply combining translation contexts or strings and require more complex changes to properly format or implement.

Updating shared Lua code to allow for translations

To update common Lua-language content shared across scenarios and game features, such as ship templates, science database, and main comms scripts, use the _() function.

Just like the tr() function in C++, the _() function in Lua can accept either one or two parameters, with the first parameter in two-parameter usage providing the context. (Example)

Some strings that replace a part of the content with a dynamic value might require the string.format() function instead of simple string concatenation ("" .. ""). Take care when adding or translating strings that use the string.format() function, because the replacement value might unexpectedly change the translation context.

Updating scenarios to allow for translations

Like shared Lua code, Lua-language scenarios use _() function calls to provide translation contexts. However, scenarios often contain more string.format() functions than shared Lua scripts. (Example)

To reduce the burden of maintenance, please work on only a single scenario at a time and per pull request.

Adding translations of game text

Translations of the EmptyEpsilon interface and non-scenario game text are stored in gettext catalog (.po) files in the resources/locale directory, currently copies of https://github.com/daid/EmptyEpsilon/blob/master/resources/locale/main.en.po with different filenames for each translated language. You can use Poedit, a free and open-source translation editor, to add and edit translations in such files.

After someone changes or adds a feature in the EmptyEpsilon user interface involving a string, the game's main English translation file must be updated first. Copies can then be made for other language translations to update.

To update the main English translation file, run the Makefile target "update_locale" (make update_locale). However, please do not update the main English locale file in pull requests. This will be done by a project maintainer directly on the master branch. (Example)

Adding translations of shared Lua script and scenario text

Each scenario file, including the tutorials, and shared Lua script file should also have a corresponding .po translation file in the scripts/locale directory. For example, the French translation file for scripts/scenario_03_waves.lua is located at scripts/locale/scenario_03_waves.fr.po.

While EmptyEpsilon loads translations automatically if present, no script generates the initial translation file.

Best practices

Non-Latin characters in translations

EmptyEpsilon has basic Unicode support for text labels, but not text input boxes, since version 2021.03.16. Non-ASCII characters should work. Test changes that introduce non-ASCII characters before filing a pull request.

Earlier versions of EmptyEpsilon did not support Unicode or ISO-encoding. If you are translating scenarios for older versions of EmptyEpsilon, if possible use no letters outside of the Latin alphabet and use substitution rules if they exist for the target language.

Standardization of translation contexts

The contexts of translation tags in scenarios included in EmptyEpsilon are standardized in order to facilitate translation, but also to demonstrate to authors of future scenarios how to add the tags themselves. A lot of retroactive work has been done on translations of scenarios, but ideally scenario authors can add translation tags when writing a scenario.

In a translation context, there are two distinct components separated by a dash "-":

  1. The place where the text to be translated is found in the game, such as the shipLog, science, comms, etc. This sometimes helps to indicate that the available space for text is limited, such as for button, Tab, and msgMainscreen text. For example, French translations often result in longer text than the original English, so this context helps French translators use more concise or abbreviated text.
  2. Contextualizing the text in the scenario's plot, which allows translators to better understand the text's meaning and avoid off-topic or mistaken translations of expressions with no equivalent in the translated language. This particularly helps translators who do not know the scenario well.

In translation software like Poedit, translators can sort by context. Depending on the scenario, it is sometimes more judicious to reorder these components for sorting. (Example)

Reusing common text in scenarios

To save time when translating scenarios authored by @Xansta, translators can also copy and paste from the common text "database" that Xansta sometimes uses in these scenarios. For example, in scenario_55_defenderHunter.lua, 400 translatable strings are also used in other scenarios.

List of contexts

trad1

trad2

trad3

trad4

trad5

Clone this wiki locally