-
Notifications
You must be signed in to change notification settings - Fork 0
Application. Translations
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:
- 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. - 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).
We use following rules for our translation system:
- One top-level
translations
folder in main repo's folder or somewhere else - Subfolders in this folder that corresponds to each language, i.e.
pl
,en
,ua
,sl
, etc. - Files in each subfolder matching a group or keyword, i.e.
mines
,saloon
,assay
,map
etc. - Each file contains translations in form of simple JSON file where English translation is a key
- Inside your code you have a method that calls translation using group and English translation as a parameters
- Current in-game language is checked inside this method so there's no need to use as a parameter in each method's call
- If there's a translation missing for given language and/or group and/or string, English translation is always used by default
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.
TODO: Fix me!
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!');
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.
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.
We use following rules for our translating whole pages or big blocks of text:
- Again, one top-level
translations
folder in main repo's folder or somewhere else - Again, subfolders in this folder that corresponds to each language, i.e.
pl
,en
,ua
,sl
, etc. - Again, files in each subfolder matching a group or keyword, i.e.
credits
,news
etc. - Each file is a typical Markdown document this time, not a JSON array / file
- Each file is used entirely, as-is (no substitution as in case of "short" translations)
- There is no substitution, so if a file is missing an error must be thrown or app compilation must fail
- We can use images (added to Markdown document using standard
![]()
syntax. - All images used in given document must be stored in corresponding main / group folder.
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 parser used to parse these documents must be able to at least render:
- Basic formatting: bold (
**bold**
) and italics (_italics_
or*italics*
) - Images:
![alt text](filename.ext)
. Note that we are not using file paths!
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.
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).
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>
- find something like:
-
<right>
:- find something like:
<right>Align right</right>
and - replace it with CSS style:
<div style="text-align: right">Align right</div>
- find something like:
- 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
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
- find something like:
__underline__
and - replace it with CSS style:
<span style="text-decoration-line: underline">underline</span>
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.
- Startup: Loop | Credits
- Game: New | Settings | Load | Save | Options
- Interface: Screen | Common | Control Panel
- Stuff: Cash | Health | Food | Tools | Weapons
- World: Map | Temperature | Time and Date
- Player: General | Goal
- Earning: Assay Office | Bank | Jail
- Spending: Mercantile | Saloon | Stable
- Other: Intro | Doctor | Laundry | Newspaper
- Desert: Intro | Indians | Outlaws | Snakes
- River: Intro | Fishing | Panning | Watering
- Mines: Intro | Exploring | Picking | Lost Mine
- Original: The Story | Manual | Description
- New: Game Manual | Extensions
- Core: Coding | Building | Platforms | Support
- Components: Translations | In‐app payments