Table of Contents
- What are XLIFF files
- Anatomy of an XLIFF file
- The golden rules
- File names and folders
- Texts with { }: placeholders and smart strings
- Placeholders: leave them alone
- Smart strings: translate the options
- Using species data from the CSV files
- Notes tell you what the values are
- Texts with [[ ]] and (( )): highlights
- Line breaks
- Original game texts
- Translating with Poedit
- Testing your translation
- Languages that need other characters
- Partial translations and regional locales
- Common mistakes
- Checklist before sharing your translation
What are XLIFF files
XLIFF files are XML files that store texts together with their translations. Every text is a <unit> that holds the original English text in <source> and your translation in <target>.
You only ever write inside <target>.
XLIFF files can be edited with a regular text editor, but a translation tool such as Poedit is easier to use, since it shows the texts as a list and hides the XML.
To create the files for a new language, follow Supporting a new Locale. To see what each file contains, see the XLIFF file reference.
Anatomy of an XLIFF file
This is the beginning of a real file, XWVM.Common.CombatVocab_es.xliff:
<?xml version="1.0" encoding="utf-8"?>
<xliff version="2.0" xmlns="urn:oasis:names:tc:xliff:document:2.0" trgLang="es">
<file id="XWVM.Common.CombatVocab" srcLang="en" trgLang="es">
<unit id="CMD_SPD">
<notes>
<note>As in Speed</note>
</notes>
<segment state="translated">
<source>SPD</source>
<target>VEL</target>
</segment>
</unit>
| Element | What it is | Do you change it? |
|---|---|---|
trgLang |
The locale code of the language you translate to. It appears in two places: on <xliff> and on <file>. |
Yes, set both to your locale code. |
<unit id="..."> |
One text. The id is the name the game uses to find it. |
Never change the id. |
<note> |
A hint for you: where the text appears, what a placeholder means. Read the notes. | No. |
state="translated" |
A marker that translation tools use to remember which texts are done. The game ignores it. | Optional. |
<source> |
The original English text. | Never edit it. |
<target> |
Your translation. | Yes. This is your work. |
The golden rules
- Never change a unit
id. The game finds each text by itsid. - Never edit
<source>. It is the reference that shows what the text said originally. - Do not leave a
<target>empty. The game treats an empty<target>as a missing translation and shows a "Missing translation" message in its place. If a text must be empty in your language, write a single space. - Save the file as UTF-8. Any decent editor does this by default.
- Escape special XML characters if you edit the file in a text editor: write
&for&,<for<, and>for>. Translation tools do this for you. - Mind the special markers
{ },[[ ]]and(( ))explained in the next sections.
File names and folders
Every XLIFF file name follows this pattern:
<TableName>_<locale>.xliff
<TableName>_<locale>.<SplitId>.xliff
For example XWVM.Common.CombatVocab_es.xliff, or XWVM.xwing.OriginalStrings_es.tour1.xliff (a big table split into several files).
Files of a locale live in a folder named with the locale code, inside StreamingAssets/Localization/XLIFF/. For regional locales, the region part is written in capitals, as in zh-CN.
The easiest way to start is to copy the es or it folder, rename the folder to your locale code, and rename every file in it to carry your locale code. Supporting a new Locale explains this step by step.
Texts with { }: placeholders and smart strings
Many texts contain pieces between curly brackets { }. The game replaces those pieces with real values while the game runs. For example Droid {name} saved successfully. becomes Droid R2-D2 saved successfully.
There are two kinds of { } pieces, and you treat them differently.
Placeholders: leave them alone
A piece that contains just one word, possibly with dots, is a placeholder. Copy it exactly into your translation, in the position your language needs.
{name}
{distance}
{species.ABBR}
Do not translate the word, and do not change its capitalization.
Smart strings: translate the options
A piece that contains a name, a colon, and a formatter, such as plural, choose or cond, is a smart string. It lets one text adapt itself to a number, a gender, or a value.
Inside a smart string, some parts are instructions for the game that you must keep, and some parts are texts that you must translate. The rule is:
Keep everything to the left of the formatter and the list in parentheses. Translate the options to the right.
XWVM uses three formatters. The Unity Localization documentation describes all of them and more in the Smart Strings section.
plural: different text depending on a number
<source>Rebel {count:plural:Laser|Lasers}</source>
<target>{count:plural:Láser Rebelde|Láseres Rebeldes}</target>
count is the number sent by the game. After plural: comes a list of texts separated by |. The game picks one depending on the number.
English and Spanish need two texts: one for singular and one for plural. Other languages need more. How many texts your language needs, and in which order, follows the standard plural rules of that language. The Unity documentation links to the list.
You can also change just the part of a word that changes:
<source>Concussion Missil{count:plural:e|es}</source>
<target>Misi{count:plural:l|les} de Impacto</target>
choose: a different text for each value
<source>Mission {status:choose(Unresolved|Complete|Failed):In Progress|Complete|Failed}</source>
<target>Misión {status:choose(Unresolved|Complete|Failed):En Progreso|Completada|Fracasada}</target>
The words in parentheses are the values the game sends. Keep them exactly as they are. After the second colon come the texts to show, one for each value, in the same order. Translate those, and keep the same number of options in the same order.
cond: a text that depends on yes or no
<source>Droid {name} saved{isAssigned:cond: and assigned|} successfully.</source>
The first option is used when the value is true, the second one when it is false. An option can be empty, as the second one here. Spaces inside options count, so keep them where your language needs them.
Nesting. Smart strings can contain other smart strings, as in this one from Spanish, where the word ending depends on the gender and on the amount:
<target>Desconocid{species.GENDER:choose(M|F):{count:plural:o|os}|{count:plural:a|as}}</target>
Take it slowly, one piece at a time: first choose between M and F, and inside each option, plural between singular and plural.
Using species data from the CSV files
Some smart strings use columns from your CSV files. The column name is the part after the dot:
| Placeholder | Meaning |
|---|---|
{species.ONE} |
The craft name in singular form, from the ONE column. |
{species.OTHER} |
The craft name in plural form, from the OTHER column. |
{species.ABBR} |
The craft abbreviation, from the ABBR column. |
{species.GENDER} |
The gender letter you chose for the craft, from the GENDER column. |
{species.<YourColumn>} |
Any extra column that you added to your CSV file. |
Example:
<source>A new [[{species.ONE}]] entered sector at [[{distance} km]]</source>
<target>{species.GENDER:choose(M|F):Un nuevo|Una nueva} [[{species.ONE}]] ha entrado al sector a [[{distance} km]]</target>
Here the letters in parentheses, M|F, are the values you wrote in the GENDER column of your CSV file. If your language uses other letters there, such as C|N for Swedish, write those letters in parentheses.
Some texts offer the columns without the species. prefix, writing {GENDER} instead of {species.GENDER}. The note of the text tells you when this is the case.
Notes tell you what the values are
Many units have a <note> that explains the values that the game sends, such as {minutes} and {seconds} are formatted time. Read them before translating.
Texts with [[ ]] and (( )): highlights
Some texts have pieces wrapped in double square brackets or double parentheses:
Press [[{keyName}]] to [[confirm quitting]] the mission...
These are color highlights in the game. They mark the words that should stand out.
- Translate the words inside, and keep the brackets or parentheses wrapped around the translated words.
- Highlight the part of your sentence that corresponds to the highlighted part of the original. It does not need to be the same number of words.
- Keep the spaces that touch the symbols in the same position. A space right after
]]or right before[[is part of the text, so[[Cannons]] andmust not become[[Cannons]]and, and a space inside[[ ]]stays inside. - Keep the brackets and parentheses in pairs: every
[[needs its]], and every((needs its)).
Line breaks
Some long texts have line breaks. In the original they are written as \n:
<source>A long time ago\nin a galaxy far, far away....</source>
<target>Hace mucho tiempo\nen una galaxia muy, muy lejana...</target>
You can keep writing \n. You can also press Enter in your editing program to insert a real line break at that point. The game treats both the same, and a real line break is easier to read while you translate.
Original game texts
The OriginalStrings files carry the texts that come from the original games: mission titles and descriptions, briefings, tour crawls, cutscene texts, credits, and the intro crawl.
They are split in several files, one per tour, mission group, and so on. They are also the longest files. Keep the structure of the original texts, such as paragraph breaks and line breaks, so the texts still fit on their screens.
The id of each unit, such as Mission.<name>.Title, tells you what the text is. The XLIFF file reference lists the files.
Translating with Poedit
Poedit is a free translation editor that can open XLIFF files. It shows every text of the file as a list, with the original on one side and your translation on the other, so you never see the XML.
- Install Poedit.
- Open an
.xlifffile with File > Open. - Select a text in the list. The original appears in the editing area. Write your translation in the translation box.
- Read the note for translators, if the text has one. Smart strings and highlights follow the rules from the sections above.
- Save with File > Save. Poedit marks the texts you have finished as translated and keeps track of the ones still missing.
- Move to the next text, and repeat.
Tips:
- Texts with no translation yet are easy to find in the list, so you can work through the file from top to bottom.
- Poedit saves into the same file. After you save the first file, open it in a text editor once and check that the
idof each unit is unchanged. - Copy the
{ }pieces from the original text instead of retyping them. - Keep a backup, or work on a copy of the file under version control, until you trust your setup.
Testing your translation
-
Put your files into this folder of your XWVM installation:
- Windows and Linux:
<XWVM-install-dir>/XWVM_Data/StreamingAssets/Localization/XLIFF/<locale>/ - macOS:
/Library/Application Support/XWVM Team/XWVM/StreamingAssets/Localization/XLIFF/<locale>/
<locale>is your locale code, for examplept, and every file name carries the same code. - Windows and Linux:
-
Start the game.
-
Open the settings menu, go to Audio and Language, and select your language. The game may ask you to restart after changing the language.
-
Play and look at your texts in the places where they appear.
After you change your files, you don't need to restart the game to see the changes:
- Press
Escto open the settings window, and press the Game Library button. It takes you back to the Game Library and reloads the localization files. - The game also reloads most localization files on every loading screen, so starting and ending a mission is often enough.
Things to know:
- A text that is missing in your files appears in English in released builds, so the game stays playable while the translation grows.
- A text with an empty
<target>appears as a "Missing translation" message. - If something does not load, the game writes a message to its log file. On Windows the log is
%USERPROFILE%\AppData\LocalLow\XWVM Team\XWVM\Player.log.Locale '<code>' not found. Skipping '<file>'.means the locale code in the file name does not match any locale.XLIFF filename '<file>' doesn't follow expected formatmeans the file name does not follow the pattern described above.- A line like
XLIFF '<file>' -> Table '<table>' [<locale>]: 12 added, 3 updatedmeans the file loaded.
Languages that need other characters
The fonts that come with XWVM support the Latin alphabet, including the accented letters of most European languages, such as Swedish, German, Spanish and French. They don't include Greek or Cyrillic characters. If your language needs characters that those fonts don't have, you can provide fonts for your locale. See Providing fonts for a locale.
Partial translations and regional locales
You do not need to translate everything at once. Texts you leave out keep showing in English.
For a regional locale, such as es-AR, provide only the texts that differ from the general language (es). The rest come from the general translation.
Common mistakes
- Changing a unit
id, so the game cannot find the text. - Translating the words in parentheses of
choose(...), or the word before the formatter. - Changing the number or the order of options in a
choose. - Removing a
{placeholder}, or retyping it with a different capitalization. - Leaving a
<target>empty. - An unescaped
&in a text editor. - A
[[without its]], or a((without its)). - A locale code in the file name that differs from the folder name.
- Species plural columns in the CSV out of order, or a gap between them.
Checklist before sharing your translation
- Every file has your locale code in its name and in
trgLang. - No
<target>is empty. - No unit
idhas changed. - Every
{ },[[ ]]and(( ))is complete and in pairs. - Every
choosehas the same number of options as the original. - You started the game, selected your language, and looked at the texts in the game.