Skip to content

Application. Translations

Mr. Fat Guy edited this page Mar 12, 2024 · 37 revisions

Strings translation

Introduction

We are re-using a translation concept from Yii 2 PHP framework. A separate .json file per each language and translation category that stores translations to given language identified by English translation string.

This solution gives two very important advantages:

  1. Since translation method is called using actual English string, not some kind of weird placeholder (like river-pan-button) it will display that English string, not a placeholder, in case translation is missing or the whole translation mechanism is failing. This produces much more professional effect.
  2. It is much easier to translate each string and file, because you always have English (base) translation on your left side (as a identification key).

Details

We use following rules for our translation system:

  1. One top-level translations folder in main repo's folder or somewhere else
  2. Subfolders in this folder that corresponds to each language, i.e. pl, en, ua, sl, etc.
  3. Files in each subfolder matching a group or keyword, i.e. mines, saloon, assay, map etc.
  4. Each file contains translations in form of simple JSON file where English translation is a key
  5. Inside your code you have a method that calls translation using group and English translation as a parameters
  6. Current in-game language is checked inside this method so there's no need to use as a parameter in each method's call
  7. If there's a translation missing for given language and/or group and/or string, English translation is always used by default

Groups

To make navigation through translations easier, we have split translation strings into groups:

  • assay
  • bank
  • credits
  • doctor
  • end
  • events
  • health
  • jail
  • mercantile
  • mines
  • newspaper
  • options
  • other
  • river
  • saloon
  • stable
  • startup
  • time

New groups maybe introduced later, if found necessary.

Paths

TODO: Fix me!

Examples

Example simple translation file for river group and pl language (translations\pl\river.json):

{
    "Too many items to carry!": "Zbyt wiele przedmiotów do niesienia",
    "Fish": "Łowienie",
    "Water": "Picie",
    "Pan": "Przesiewanie",
    "Exit": "Wyjście",
}

Example translation file for end group and ua language (translations\ua\end.json) with multi-line support:

{
    "And so ends the life\\n\\nof yet another poor\\n\\nprospector who, like\\n\\nso many before him,\\n\\ndied looking for but\\n\\nnever finding the...\\n\\n\\n\\nLOST DUTCHMAN MINE": "І так закінчується життя\\n\\nще одного бідного\\n\\nстаратель, який, як\\n\\nтак багато до нього,\\n\\nпомер у пошуках але\\n\\nніколи не знайти...\\n\\n\\n\\nЗАГУБЛЕНА ГОЛЛАНДСЬКА МІНА",
    "Play Again?": "Грай знову?",
    "Yup": "Так",
    "Nope": "ні",
}

Example call of translation method in your code:

let obj = sys.t('river', 'Too many items to carry!');

Providing Translations

Since translation files are stored in the repository, as a regular files (that are fed into application during build), adding new translation or correcting existing one is a matter of simple update + commit + push. And can be achieved by anyone.

Only:

  • new groups or new languages
  • changes to existing English translation
  • entirely new translations that introduces new key (new English translation)

Requires developer's attention as it introduces changes to the core code as well.

Translation of big blocks of text

Introduction

The ability of being able to change big blocks of text (like credits) by me or anyone else other than developer is crucial since we want to run a crowdfunding campaign and award each backer with adding their name or nick at the end of credits text. We strongly believe that we will have a lot of backers and that at some point we will be updating credits file sometimes more often than the rest of code.

Editable big blocks of text or whole-page text will also be used in newspaper.

For big blocs of text we are using Markdown instead of JSON.

Details

We use following rules for our translating whole pages or big blocks of text:

  1. Again, one top-level translations folder in main repo's folder or somewhere else
  2. Again, subfolders in this folder that corresponds to each language, i.e. pl, en, ua, sl, etc.
  3. Again, files in each subfolder matching a group or keyword, i.e. credits, news etc.
  4. Each file is a typical Markdown document this time, not a JSON array / file
  5. Each file is used entirely, as-is (no substitution as in case of "short" translations)
  6. There is no substitution, so if a file is missing an error must be thrown or app compilation must fail
  7. We can use images (added to Markdown document using standard ![]() syntax.
  8. All images used in given document must be stored in corresponding main / group folder.

Images and Languages

Image filename can be anything you like. There's no automatic image file-translation matching. If you want to use the same image in many language versions of given document then you use it in typical way (i.e.: ![niner-games-logo](niner-games.png) added to \en\news.md, \pl\news.md, de\news.md, etc.

If you really, really need a language-specific image then you must create all those images, name them independently and add each to the corresponding document (i.e. put ![title-english](title-english.png) to \en\credits.md, ![title-polish](title-polish.png) to \pl\credits.md and so on).

Markdown Basics

Markdown parser used to parse these documents must be able to at least render:

  1. Basic formatting: bold (**bold**) and italics (_italics_ or *italics*)
  2. Images: ![alt text](filename.ext). Note that we are not using file paths!

Markdown Extensions

This chapter assumes that the developed Markdown renderer can parse Markdown code only.

If it is able to render simple HTML as well (<div> and <span> elements and style="" attribute), then the entire below chapter can be skipped. An above motioned regular HTML and CSS will be used instead to render all the files.

Introduction

In addition to the above and Markdown standard we need to introduce three extensions.

Font face in all below scenarios is always default game font, that is Pixelify Sans (#51).

Block Text Align

We need <left> and <right> HTML tags support in addition to Markdown internal HTML support to align text when needed.

  • <left>:
    • find something like: <left>Align left</left> and
    • replace it with CSS style: <div style="text-align: left">Align left</div>
  • <right>:
    • find something like: <right>Align right</right> and
    • replace it with CSS style: <div style="text-align: right">Align right</div>
  • we are not using <center>:
    • text aligned center is default and so
    • entire text in file (and all images) must be center-aligned if not otherwise specified
  • we are not using <justify> at all

Bigger Font

HTML has <small> tag, but doesn't have its <big> counter-part, so we need to introduce one.

  • find something like: <big>This is bigger</big> and
  • replace it with CSS style: <span style="font-size: #px">This is bigger</span> where # is generally bigger than default text / viewport font size
  • you can use container query units or React calculation algorithm or any other method, if using <span style="font-size: #px"> is not OK

In-line Text Underlining

  • find something like: __underline__ and
  • replace it with CSS style: <span style="text-decoration-line: underline">underline</span>

Example

Example Markdown file (part) for credits group and en language (translations\en\credits.md):

Game development and __swiss-army-knife__:

<big>**Maciej Madejczyk**</big>

![Maciej Madejczyk](madej-pixelized-avatar.png)

The whole idea, design and a __nasty dictatorship__:

<big>**Tomasz Trejderowski**</big>

![Tomasz Trejderowski](trejder-pixelized-avatar.png)

This example assumes that Markdown Extensions are developed. If not, a regular HTML and CSS will be used instead.

Home

Game

Town

Locations

Gameplay

Development

Clone this wiki locally