Localising Your Game
Localising your dialogue with the Yarn Project’s localisations takes five steps:
flowchart TB
yarn["Yarn Scripts"]
tags["Yarn Scripts with line tags"]
csv["Strings CSV"]
translated["Translated CSV,<br>from your translators"]
project[("Yarn Project,<br>with a localisation for each language")]
game["Your game, in another language"]
yarn -->|"1. add line tags"| tags
tags -->|"2. export"| csv
csv -->|"3. translate"| translated
translated -->|"4. add to the Yarn Project"| project
project -->|"5. choose the language"| gameThe plugin doesn’t add localisation buttons to the editor. Steps 1 and 2 use the Yarn Spinner Console, ysc, which you installed with the plugin. Step 4 is an edit to your .yarnproject file. See Installing Yarn Spinner for Unreal Engine.
If your game uses Unreal’s String Tables, you can keep your lines in a String Table instead. Steps 1 and 2 are the same. See Using Unreal’s String Tables.
1. Add line tags
A line tag is an ID at the end of a line, like #line:a1b2c3d. Translations are matched to lines by their IDs. A line without a tag gets an ID made from where it is in the file. That ID changes when you edit the Yarn Script, and the line’s translations stop matching it.
To tag every line that doesn’t have one, run ysc tag with your Yarn Scripts:
ysc tag Start.yarn Tower.yarnIt edits your Yarn Scripts and adds a tag to the end of each untagged line. Lines that already have a tag keep it. To write the tagged files to another folder instead, add -o and the folder’s path. Every line ID must be unique across all your Yarn Scripts.
The plugin watches your Yarn Scripts, so the Yarn Project is reimported with the new tags. Tag your lines before you export them, and tag new lines as you write them.
2. Export your lines
Run ysc compile with your .yarnproject file, and -o with the folder to write to:
ysc compile Dialogue.yarnproject -o Translationsysc writes three files, named after the .yarnproject file. The strings file, Dialogue-Lines.csv, has a row for each line, with its ID and its text in your base language:
id,text,file,node,lineNumber
line:a1b2c3d,Rosa: The lamp's been out for days.,.../Start.yarn,Start,3
line:c3d4e5f,Rosa: You've got {0} coins.,.../Start.yarn,Start,4| Column | What it holds |
|---|---|
id | The line’s ID. This is how the translation is matched to the line. |
text | The line’s text. |
file, node, lineNumber | Where the line is in your Yarn Scripts. |
The metadata file, Dialogue-Metadata.csv, tells translators where each line comes from, and lists each line’s tags. The .yarnc file is the compiled dialogue. The plugin doesn’t read either of them back in, so you can delete them.
A spreadsheet for translators, from Blueprints
The plugin can also write a CSV file that’s easier for people to read. Call Export Strings To CSV from any Blueprint, like a button in an Editor Utility Widget, with your Yarn Project asset, a File Path on disk, and the Options to use. Get Default Export Path gives you a path next to the Yarn Project asset, in your project’s Content folder, ending in _strings.csv. From C++, call UYarnLocalizationExportLibrary::ExportStringsToCSV(), in YarnLocalizationExport.h.
id,node,character,text,Translation
line:a1b2c3d,Start,Rosa,The lamp's been out for days.,
line:c3d4e5f,Start,Rosa,You've got {0} coins.,| Option | Default | What it does |
|---|---|---|
| Include Line ID | on | Add the id column. |
| Include Node Name | on | Add the node column. |
| Include Character | on | Add the character column. |
| Include Tags | off | Add a tags column, with each line’s tags. |
| Include Translation Column | on | Add an empty column for translators. |
| Translation Column Header | Translation | The heading of that column. |
| Delimiter | , | The character between columns. |
| Sort Lines | on | Sort the rows by node, then by line ID. |
The result tells you if it worked, how many lines it wrote, and the error if it didn’t.
text column doesn’t have the character’s name, and the plugin doesn’t read the Translation column. To make a strings file you can add to the Yarn Project, use ysc compile.3. Translate
Make a copy of the strings file for each language, and give each copy to its translator. Translators replace the text column with their translation:
id,text,file,node,lineNumber
line:a1b2c3d,Rosa: Die Lampe ist seit Tagen aus.,.../Start.yarn,Start,3
line:c3d4e5f,Rosa: Du hast {0} Münzen.,.../Start.yarn,Start,4Translators should leave the id column alone. If the id changes, Yarn Spinner can’t match the translation to its line. The plugin only reads the id and text columns, so the other columns are there for the translator.
Each line’s text starts with the character’s name, like Rosa:. Translators should keep the name and the colon at the start, but they can translate the name itself.
4. Add the translations to the Yarn Project
Add a localisation section to your .yarnproject file, with an entry for each language. The key is the language’s code, like de for German or pt-BR for Brazilian Portuguese, and strings is the path to its strings file, from the folder the .yarnproject file is in:
{
"projectFileVersion": 3,
"sourceFiles": ["**/*.yarn"],
"baseLanguage": "en",
"localisation": {
"de": {
"strings": "Translations/de.csv"
}
}
}The plugin watches the .yarnproject file, so saving it reimports the Yarn Project. The Output Log then shows how many lines it read for each language, like Loaded 2 strings for culture 'de' from Translations/de.csv. If the file isn’t there, or it doesn’t have id and text columns, the Output Log shows a warning, and that language has no translations.
The plugin doesn’t watch the strings files. When a translator sends you an updated file, reimport the Yarn Project yourself: right-click it in the Content Browser and choose Reimport.
5. Choose the language
The game’s language is set on the Dialogue Runner’s Line Provider. Unless you’ve given the Dialogue Runner a Line Provider of your own, it makes a Yarn Builtin Line Provider when play begins.
The Yarn Builtin Line Provider follows the game’s language. Its Auto Detect Culture setting is on, so for each line, it uses Unreal’s current language, if the Yarn Project has a translation for it. It tries the two-letter code first, like de, then the full code, like de-AT. If the Yarn Project has neither, it uses your base language.
So with Auto Detect Culture on, Unreal’s own Set Current Culture and Set Current Language nodes switch your dialogue’s language too.
To choose the language for your dialogue alone, call Set Locale Code on the Line Provider. It turns Auto Detect Culture off, and uses the language you give it from then on:
- Get your Yarn Dialogue Runner’s Line Provider.
- Connect it to a Cast To YarnBuiltinLineProvider node.
- From the cast’s result, call Set Locale Code, with the language’s code in Locale Code, like
de. - Call Refresh Asset Provider Context on the Yarn Dialogue Runner, so its Asset Provider knows the language has changed.
In C++:
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "YarnDialogueRunner.h"
#include "YarnLocalization.h"
#include "LanguageLibrary.generated.h"
UCLASS()
class ULanguageLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category = "Dialogue")
static void SetDialogueLanguage(UYarnDialogueRunner* DialogueRunner, const FString& LocaleCode)
{
if (!DialogueRunner)
{
return;
}
if (UYarnBuiltinLineProvider* LineProvider = Cast<UYarnBuiltinLineProvider>(DialogueRunner->LineProvider))
{
LineProvider->SetLocaleCode(LocaleCode);
}
DialogueRunner->RefreshAssetProviderContext();
}
};SetDialogueLanguage(DialogueRunner, TEXT("de")) to switch to German.Get Locale Code gives you the language the Line Provider is using, and Get Available Locales gives you the codes of the languages in the .yarnproject file’s localisation section.
If a line is on screen when the language changes, it stays in the old language. The next line is in the new one.
Voice clips in other languages
The Asset Provider that comes with the plugin finds a line’s voice clip from an #audio: tag on the line, like #audio:/Game/Dialogue/Voice/a1b2c3d. The tag is the same in every language, so it finds the same clip in every language.
To play a different clip in each language, give the Dialogue Runner an Asset Provider of your own, which picks the clip by language. See Writing your own Asset Provider.
When a line isn’t translated
If a line has no translation in the current language, the Yarn Builtin Line Provider shows the text from your Yarn Script. A translation that’s empty in the strings file counts as no translation.
To try another translation first, set the Line Provider’s Fallback Locale Code. For example, a game with Brazilian Portuguese and European Portuguese can show a line in pt when it isn’t in pt-BR yet.
| Property | Default | What it does |
|---|---|---|
| Auto Detect Culture | on | Use Unreal’s current language. Set Locale Code turns it off. |
| Text Locale Code | empty | The language to use when Auto Detect Culture is off. Leave it empty to use your base language. |
| Use Fallback | on | Try the Fallback Locale Code language when a line isn’t translated. |
| Fallback Locale Code | empty | The language to try. Leave it empty to use the text from your Yarn Script. |
The Line Provider isn’t in the Details panel, because the Dialogue Runner makes it when play begins. Set these from a Blueprint, from the result of the Cast To YarnBuiltinLineProvider node in step 5, or from C++, where they’re bAutoDetectCulture, TextLocaleCode, bUseFallback and FallbackLocaleCode.
If the line isn’t in the fallback language either, the Line Provider uses the text from your Yarn Script. If even that’s missing, the Output Log shows Missing localized line: and the line’s ID.
Adding translations while the game runs
Add Localized String adds a translation for one line, while the game runs. Give it the Line ID, the Locale Code and the Text. It’s used in place of the translation from the strings file, and it isn’t saved: it’s gone the next time the game starts.
Plurals and ordinals in other languages
[plural] and [ordinal] pick the right word for a number, following the rules of the line’s language. See Markup.
The Yarn Builtin Line Provider uses its current language’s rules. Yarn Spinner for Unreal Engine gets those rules from Unreal’s own language data. Yarn Spinner for Unity has rules for about 150 languages, and Unreal has them for about 130. For a language Unreal doesn’t have rules for, you might get the other form where Unity would pick another one, like few. Test your [plural] and [ordinal] lines in each language.
Unreal only puts language data for some languages into a packaged game. Choose which in Internationalization Support, in the advanced settings of . If a line’s language isn’t in the packaged game, [plural] and [ordinal] use the rules of Unreal’s current language.
Using Unreal’s String Tables
If your game already uses Unreal’s String Tables for the rest of its text, you can keep your lines in String Tables too. The plugin comes with two Line Providers that read String Tables:
| Line Provider | Where it gets text |
|---|---|
| Yarn String Table Line Provider | One String Table. |
| Yarn Culture Aware Line Provider | One String Table for each language, picked by Unreal’s current language. |
Each entry’s key is the line’s ID without line: at the start. The text for #line:a1b2c3d is in the entry a1b2c3d.
Filling a String Table with your lines
Import Yarn Project To String Table adds an entry to a String Table for each line in a Yarn Project, with the line’s text in your base language. Give it the Yarn Project in In Yarn Project and the String Table in In String Table. It only works in the editor, so call it from an Editor Utility Blueprint or Editor Utility Widget, then save the String Table. In a packaged game, it does nothing, and the Output Log shows an error.
The String Table Line Provider
The Yarn String Table Line Provider reads each line from its String Table. It reads the entry’s source text, so it doesn’t use translations made in Unreal’s Localization Dashboard. To use those, write your own Line Provider. See Writing your own Line Provider.
| Property | Default | What it does |
|---|---|---|
| String Table | none | The String Table to read lines from. You can also set it with Set String Table. |
| Fallback To Base Text | on | When a line isn’t in the String Table, use the text from your Yarn Script. If it’s off, the line shows its ID. |
| Log Missing Entries | off | Show a warning in the Output Log for each line that isn’t in the String Table. |
The Culture Aware Line Provider
The Yarn Culture Aware Line Provider has a String Table for each language, in its Culture String Tables map, with the language’s code as the key. Each table has the same keys, with the text in that table’s language. For each line, it uses the table for Unreal’s current language, like de-AT. If there isn’t one, it tries the two-letter code, like de, then Default Culture.
| Property | Default | What it does |
|---|---|---|
| Culture String Tables | empty | The String Table for each language. You can also add one with Add Culture String Table. |
| Default Culture | en | The table to use when there isn’t one for the current language. |
| Fallback To Base Text | on | When a line isn’t in the table, use the text from your Yarn Script. If it’s off, the line shows its ID. |
To switch language, use Unreal’s Set Current Culture or Set Current Language node. Get Current Culture and Get Current Base Culture give you Unreal’s current language, like de-AT, and its two-letter code, like de.
Giving the Dialogue Runner a String Table Line Provider
The Dialogue Runner only makes a Yarn Builtin Line Provider for itself, so make the String Table Line Provider yourself, before the dialogue starts:
- Check that the Yarn Dialogue Runner’s Auto Start is off, so the dialogue doesn’t start before the Line Provider is ready. It’s off by default.
- In Event BeginPlay, call Construct Object from Class, with Class set to Yarn String Table Line Provider and Outer set to Self.
- From the new object, call Set String Table with your String Table.
- Call Set Yarn Project on the new object, with the Yarn Dialogue Runner’s Yarn Project.
- Set the Yarn Dialogue Runner’s Line Provider to the new object.
- Call Start Dialogue on the Yarn Dialogue Runner.
UYarnStringTableLineProvider* LineProvider = NewObject<UYarnStringTableLineProvider>(this);
LineProvider->SetStringTable(DialogueStrings);
LineProvider->SetYarnProject(DialogueRunner->YarnProject);
DialogueRunner->LineProvider = LineProvider;
DialogueRunner->StartDialogue(TEXT("Start"));DialogueStrings is a UStringTable* property on the Actor, and DialogueRunner is its Yarn Dialogue Runner. The Line Provider classes are in YarnLocalization.h. A Culture Aware Line Provider goes in the same way: call Add Culture String Table for each language instead of Set String Table.
[plural] and [ordinal] in lines from the String Table Line Provider follow the rules of your base language, whatever the game’s language is. The Culture Aware Line Provider follows the rules of Unreal’s current language.