XeGrader plus, currently in development, supports 24 languages worldwide — something that is rarely seen from an individual developer. This article covers how this 24-language support was implemented and the challenges involved.



  • Defining the Multilingual Specification
The predecessor to this game, the MSX2 version, already supported switching between Japanese and English. However, since there was no settings screen, language support was limited to toggling the opening message and title logo display. XeGrader plus runs on Steam. For a PC-based game, a settings screen is unavoidable — and that means a large volume of text requiring translation.

This version also features a specification where descriptions of selectable items are displayed at the bottom of the screen. As a result, the total number of characters requiring translation is explosively larger compared to the previous title. Fortunately, since Steam runs on PC, memory constraints are largely a non-issue, so from the start I decided to implement the system in a way that would be easy to maintain.

After consideration, I proceeded with development under the following specifications:
  1. Default language is English 
  2. On first launch, the language configured in the OS (Steam) is selected 
  3. Unsupported languages fall back to English 
  4. Language can be switched in the settings screen 
  5. Each language's data is managed by myself without relying on external tools 
  6. The selected language is saved to Steam Cloud *
* A local backup is also saved to account for environments without internet access 



  • How Language Data Is Stored
Development uses Godot. GDScript provides not only ordinary arrays but also dictionaries, so I decided to use dictionaries as the foundation for storing data. Dictionary keys use language codes. However, standard language codes such as PT-BR contain a hyphen, which I personally find undesirable as data, so I replace hyphens with underscores.

const LANGUAGE_LIST = [ "en", "ja", "fr", "de", "es", "latam", "pt", "it", "nl", "pl", "pt_br", "hu", "sv", "no", "fi", "et", "tr", "ro", "th", "id", "da", "cs", "vi", "ko", ]
This is the list of language codes adopted for this release. The ordering was decided in consultation with AI. English comes first as the default, Japanese second as the language of the developer (myself), followed by European and then Asian languages. Some minor reordering was also done based on the length of language names. French and German tend to be long across the board...

While it is possible to retrieve characters from the keys of this LANGUAGE_LIST, doing so every time felt redundant, so I set up a dedicated entry for retrieving dictionary data. For example, the Prologue displayed immediately after the game starts:

var prologues: String: get: return _prologues[Common.language] var _prologues: Dictionary = { "en": "The Great Demon King of calamity, Varamos, ...
"fr": "Le Grand Roi Démon de la calamité, Varamos, ...
"it": "Il Grande Re Demone della calamità, Varamos, ...
The dictionary data is _prologues, but a public property prologues is also provided, so that retrieving a string from it automatically returns the string for the currently configured language (Common.language). This means that simply writing print(MSG.prologues) is enough for the language to switch automatically.
LanguageSelection_ENLanguageSelection_JP
LanguageSelection_FRLanguageSelection_DE


  • On Translation Data
Since I am Japanese, the original messages are naturally written in Japanese. I have some knowledge of English, but next to none of any other language. I always believed you could get by in a foreign country with just three phrases — "hello," "please," and "thank you" — and in fact, I visited Mont Saint-Michel in France with exactly those three.

Smartphones today offer AI-powered automatic mutual translation, which is incredibly convenient. So for XeGrader plus as well, I decided to make use of AI translation. My reasoning was that even a rough translation in one's own language is better than nothing — given that AI translation from a foreign language into Japanese does not produce particularly unnatural results.

Store messages also make use of AI translation, and the initial store listing was composed almost entirely of AI translation. As expected, there has been backlash on forums along the lines of "don't use AI." This was within my anticipated range. Getting the game published in each language came first.

After that, I put out a call for volunteers from each country to help with translation, and currently 9 languages have been switched over to translations by native speakers. I believe this was only possible because the game was published first. The following are the languages whose translated store messages are currently officially reflected:

English Japanese Français Deutsch Italiano Nederlands Polski Español (España) Español (Latinoamérica)
Português (Brasil) is also in progress, but has not yet been completed.
Prologue_FR


  • Challenges
First, the wildly different text lengths. Since display areas are more or less fixed, whenever text did not fit, various judgments were required — changing the phrasing, reducing the font size slightly, or in extreme cases leaving the English text as-is. Well, this is something I always struggle with in localization work at my day job, so I am used to it in a sense...

Thai and Korean were actually languages I deliberated over until the very end. The reason is that they unavoidably require dedicated font embedding. European languages could all be covered with a single font, which was convenient, but these languages simply require their own. In that sense, Japanese also requires a dedicated font, but I accept that as inevitable given that I am Japanese.

Free fonts that can be embedded are limited in number, and in the end I rely on Google Fonts for the majority:

Google Fonts used in this game • WDXL Lubrifont JP N • Roboto Flex • Noto Sans Thai • Noto Sans Japanese • Noto Sans Korean • Noto Color Emoji • Ubuntu Mono • Bebas Neue
For English-based text, the following font is used:

Tagesschrift-Regular.ttf by Jan Gerner (Yanone) Licensed under the SIL Open Font License, Version 1.1 (26 February 2007)
The dot font by Mr. Kadoma, used in the retro PC sections, will continue to be used in the DLC:
8×12-dot Japanese font k8x12S
by Namu KADOMA
Free to use, modify, and redistribute commercially or noncommercially.
Provided "as is", without warranty.

And for the Japanese Prologue only, I wanted to convey an eerie atmosphere, so I separately purchased a font and used it as an image. Embedding the font data directly was avoided due to the risk of theft.

g_comickoinM_JISLimit.ttf by GYOKUEI / ZARASU.com Commercial and non-commercial use permitted under the author's original license. Redistribution or resale of the font file is prohibited.
Managing all of these licenses turned out to be surprisingly demanding. Supporting multiple languages means dealing with a wide variety of fonts, and since each font is a copyrighted work created by someone else, strict management is required. I do this kind of work professionally — but I never imagined I would end up doing the same thing for a personal project...

Also, while I can vaguely grasp the feel of something like French, Thai and Korean are entirely unknown languages to me and I have no idea what is written. This means that if translation data gets mixed up, I have absolutely no way of noticing the error. For this reason as well, I need the help of volunteers to verify translations. I have NEXT FES in June as my target, so if no volunteers come forward by the end of March, I will proceed with AI translation as-is. If you speak any of these languages and are willing to help, I sincerely look forward to hearing from you.