Translating
Translating Wildermyth
Wildermyth is developed in US English and has official translations for Simplified Chinese, Brazilian Portuguese, Spanish (Latin America), German and French. It's possible we'll be able to provide additional official languages in the future, but it might be a while, so we are working on tools to support community translation into other languages.
Let us know what would make your life easier as a translator!
We use UTF-8 for Everything
All files are encoded in UTF-8. You need to set your text editor to UTF-8 when editing properties files if you're using characters outside of the lower 128 (ASCII).
File Structure
Nearly all the text in the game is stored in .properties files. Properties files are very simple, it's one "string" (piece of text) to a line. The "key" is first, don't change that. Just change the text after the =
The properties files are found in the /assets/text/ folder. There are many many files in here, 1 file for each "effect" (event or combat ability) and some very large files for interface, history lines, aspects, and other things. For mods (such as campaigns, for example Age of Ulstryx is a mod) the text is in the mod folder, so, mods/builtIn/villain_ulstryx/assets/text/...
To translate the files, make a copy but put your locale code as the suffix, with underscores, like this:
interface.properties | source file (US English) |
interface_zh_CN.properties | Simplified Chinese |
interface_fr.properties | French |
See the /assets/data/knownLocales.json file for a list of country codes that the game lets players pick. If you want additional ones, contact us and ask. See this list.
Put the translated files right next to the source files. (You may want to make periodic backups of your translated files, too.)
Name Generator
If you want to create localized generated names, the name generator source data files are /assets/data/generation/group.names.json and /assets/data/generation/human.names.json
You'll see how it works, it's pretty simple.
In Game Editors
The Comic Editor is the best way to translate comics, because it offers side-by-side text, real time tag validation, and lets you tweak text box positions as needed. Use the button on the top bar to set your target language:
Set the language to the language you're translating to. The dropdown uses the "knownLocales" file mentioned earlier. You can also change "translate mode" to be "from Source" or you can translate from another language, which might be helpful once we have more translations.
The editor also lets you import/export a loc kit, which is just a copy of the game assets with only the text files for one language. This is helpful for collaboration or for exporting to a mod.
Finally, there are some buttons for making effect text bundles. This take all of the effect properties files and bundles them up into one file for translation, but right now I don't recommend using this - Wildermyth has tech to skip untranslated events, but that tech only works if no file exists in that language. Bundling effect text > translating some > unbundling will create files for all the effects, so the game won't know which ones are translated. I might change the button to skip effects with comic panels, and export a list of those, or something like that.
In order to understand the structure of the data and tools, these links may also be helpful (which are also linked to on the editor landing page). While it's not strictly necessary to understand all of the underlying structure in order to translate the game, many of the things you'll be translating are events, abilities, and aspects (which are discussed in more detail in the Data Format Overview), and understanding how the comics are written and how splits and branches work and are shown in the comic editor will almost certainly be necessary.
- Data Format Overview (A broad overview of the files in Wildermyth and how they work together)
- Comic Editor Reference (How to create events, explanations of some of the editor tools)
Workflow
We recommend starting with interface.properties. Get the interface showing up correctly. If your target language cannot be rendered in the game's font, please contact us and we'll work out a font set, and add it as an option for you to choose. You'll have to choose "Use Local Fonts" while translating.
After the interface bundle, tackle dynamic, presentation, scenarios, errors, and aspects.
"story" can largely be editing in the "History" tab of the editor and should be done there. "effects" including comics should be edited in the comic editor. The flow for non-comic events is not finished yet but might use the bundling/un-bundling option discussed above.
When translating comics, you'll need to understand how tags work, particularly gender splits, since you may have to write your own depending on your language. The Writer's Guide and Tag Reference goes over how they work. The comic editor is highly recommended because it will give you feedback that your tags are correct, let you see the stories in context, and reroll parties to make sure all variations work. It will also let you adjust individual text box positions and sizes. These adjustments are saved to the .properties file of the event as ~TWEAK lines, you will see them in there. ONLY text boxes can be adjusted this way, actors or other comic details can not.
Testing Translations
The easiest way to test translations for comics is via the comic editor. You can find more information about testing in the Comic Editor (Testing your Event in the Editor). Specifically, the Reroll button and Auto-Match option are your friends here.
Delivering Translations
It's easiest to work "in place," in the game folder itself. When you want to share your work, export a loc kit. Another player can import that loc kit the same way. To import/export, the language must be set, and only those files will be copied. It's also possible to bundle your translations up in a mod. If you do that, take all translated text from the "mods" folders and just lump them together in your main assets folder. That whole thing becomes your mod and should work fine. The mod approach allows you to add support for a new langauge by including a "/assets/data/knownLocales.json" file. Th
Translating Mods
To translate a mod, copy it to your install folder, e.g. /mods/user/[mod id or number] Then translate in place. When you're done, coordinate with the mod author to integrate your translations, or release them as your own mod.
Translation Tags
There are several tags that are specifically for translation.
Articles and Gender
For text like "Let's go to <site>" or "Give me the <item>", <site> and <item> may need different articles before them depending on whether the site/item name is masculine, feminine, neutral, plural, starts with a vowel, etc.
[m], [f], [p], and [n] can be used to designate a name as masculine, feminine, plural, and neutral in several places:
- In name generation files like assets/data/generation/human.names (where all the item and site names are created). For example, if you put the following in human.names, then "Swampy Bog" would return masculine, and "Swampy Marshes" would return feminine plural.
"swampTile": ["Swampy <SwampWord>"], "swampWord": ["bog[m]", "marshes[f][p]"],
- In custom item, monster, or site names in dynamic.properties. For example:
item.antlerbow=Antler Bow[f] gorgon.name=Gorgon[f] vultureLord_graymountain=Graymountain[m]
Once the genders of those names are set, they can be accessed using the following article split tags:
articleDe | German | <site.articleDe:none/male/female/neutral/plural> | |
articleEs | Spanish | <site.articleEs:none/male/female/plural masculine/plural feminine> | |
articleFr | French | <site.articleFr:none/male/female/starts with vowel/plural> | Priority, where 1 is highest, is none(1)/male(4)/female(4)/starts with vowel(3)/plural(2) |
articleFrFrom | French | <site.articleFrFrom:none/male/female/none vowel/male or female vowel/plural> | Priority, where 1 is highest, is none(3)/male(3)/female(3)/none vowel(2)/male or female vowel(2)/plural(1) |
possessiveFr | French | <hero.possessiveFr:starts with vowel/starts with consonant> |
For example: "Ils sont allés <site.articleFr:à /au /à la /à l'/aux ><Site>"
Side note: determining whether a word starts with a vowel uses the following regex: (?i)^[aeiouÀÂÆÉÈÊËÎÏÔŒÙÛÜŸàâæéèêëîïôœùûüÿ].*$
In some cases where you can't use gender tags but still need to use different articles for a type of something, like biome type or weapon type, the best option will often be to separate it out into a split tag so different articles can be used in each split. Here are some examples of where that may be necessarry:
English Tag | Replace With |
---|---|
<overlandTile.biomeShort> or <overlandTile.biomeLong> | <overlandTile.bghps:broadleaf forest (deciduous) / grassland / hills / pine forest (coniferous) / swamp> |
<weapon.element> or <weapon.elementSpaceAfter> | <weapon.element:fire/water/leaf/stone/none> |
<season> | <season:spring/summer/fall/autumn/winter> |
Item Descriptions
In interface.properties, baseItemDescription=A {0} {1}
uses tierDescription.0 - tierDescription.3 to write things like "A powerful mace." However, that doesn't work well if the language requires certain articles based on weapon type. Instead, these lines can be used in dynamic.properties, and will be used in place of the "A {0} {1}" structure:
fullItemDescription.axe.0=A roughly made axe. fullItemDescription.axe.twoHandedAxe.0=A roughly made greataxe. fullItemDescription.bow.0=A roughly made bow. fullItemDescription.crossbow.0=A roughly made crossbow. fullItemDescription.dagger.0=A roughly made dagger. fullItemDescription.mace.0=A roughly made mace. fullItemDescription.mace.twoHandedMace.0=A roughly made hammer. fullItemDescription.spear.0=A roughly made spear. fullItemDescription.spear.twoHandedSpear.0=A roughly made greatspear. fullItemDescription.staff.0=A roughly made staff. fullItemDescription.sword.0=A roughly made sword. fullItemDescription.sword.greatsword.0=A roughly made greatsword. fullItemDescription.sword.rapier.0=A roughly made dueling sword. fullItemDescription.wand.0=A roughly made wand. fullItemDescription.axe.1=A well-made axe. fullItemDescription.axe.twoHandedAxe.1=A well-made greataxe. fullItemDescription.bow.1=A well-made bow. fullItemDescription.crossbow.1=A well-made crossbow. fullItemDescription.dagger.1=A well-made dagger. fullItemDescription.mace.1=A well-made mace. fullItemDescription.mace.twoHandedMace.1=A well-made hammer. fullItemDescription.spear.1=A well-made spear. fullItemDescription.spear.twoHandedSpear.1=A well-made greatspear. fullItemDescription.staff.1=A well-made staff. fullItemDescription.sword.1=A well-made sword. fullItemDescription.sword.greatsword.1=A well-made greatsword. fullItemDescription.sword.rapier.1=A well-made dueling sword. fullItemDescription.wand.1=A well-made wand. fullItemDescription.axe.2=A powerful axe. fullItemDescription.axe.twoHandedAxe.2=A powerful greataxe. fullItemDescription.bow.2=A powerful bow. fullItemDescription.crossbow.2=A powerful crossbow. fullItemDescription.dagger.2=A powerful dagger. fullItemDescription.mace.2=A powerful mace. fullItemDescription.mace.twoHandedMace.2=A powerful hammer. fullItemDescription.spear.2=A powerful spear. fullItemDescription.spear.twoHandedSpear.2=A powerful greatspear. fullItemDescription.staff.2=A powerful staff. fullItemDescription.sword.2=A powerful sword. fullItemDescription.sword.greatsword.2=A powerful greatsword. fullItemDescription.sword.rapier.2=A powerful dueling sword. fullItemDescription.wand.2=A powerful wand. fullItemDescription.axe.3=A mythic axe. fullItemDescription.axe.twoHandedAxe.3=A mythic greataxe. fullItemDescription.bow.3=A mythic bow. fullItemDescription.crossbow.3=A mythic crossbow. fullItemDescription.dagger.3=A mythic dagger. fullItemDescription.mace.3=A mythic mace. fullItemDescription.mace.twoHandedMace.3=A mythic hammer. fullItemDescription.spear.3=A mythic spear. fullItemDescription.spear.twoHandedSpear.3=A mythic greatspear. fullItemDescription.staff.3=A mythic staff. fullItemDescription.sword.3=A mythic sword. fullItemDescription.sword.greatsword.3=A mythic greatsword. fullItemDescription.sword.rapier.3=A mythic dueling sword. fullItemDescription.wand.3=A mythic wand.