This plugin introduces a way simplier method of localizing game made in Unreal Engine.
It simply allow to import CSV file with localization.
The plugin has been tested and it works on the Engine's versions: 4.27, 5.2 and 5.4.
If you have any question or suggestion regardles this plugin simply add an Issue to the github project. I will try my best to answer it quickly :) You can also write an e-mail to me: [email protected], however there is a risk that it will be filtered as spam.
The example project wich uses this plugin can be found in this repository.
The plugin is available on the Unreal Engine Fab! It is free, of course.
You can download it from here.
Currently plugin is available for UE version 5.4 and 5.2 (5.3 is not available, because of this reason.
If you are using 4.27 you can download the precompiled package from here.
The plugin's version that's on the Marketplace is 1.5.7.
UE5.3 for some reasons doesn't generate package id for localizable texts in widgets editor. Because of that the plugin can't work as intended.
The best solution is to use the newest version of Unreal Engine.
If it is not possible, the workaround would be to set the widget text value in PreConstruct event based on the Text variable or LocText Struct.
- CSV Format
- Using the Tool
- Import
- Adding Localization Directories
- Using Localizations
- Cooking Localizations
- LocText Struct
- Previewing Localizations
- Controlling Localizations
- Save File
- Commandlet
- Utilities
- Troubleshooting Errors
- Used In
- Special Thanks
The tool accepts a CSV file of a defined format:
Namespace,Key,lang-en,lang-pl,lang-de,Comments
GAME,TEST_EXAMPLE,"Hello, world!",Witaj świecie!,Hallo Welt!,Anything you wish to type
- Namespace - a namespace in which current entry is located. This column is optional, but without it a Global Namespace must be defined.
- Key - a key of this entry, used later in text implementation.
- lang-x - a value in a x language. x is a language code, such as en, pl, de, etc.
Unreal Engine uses ICU codes. The full list of them can be found here: https://www.localeplanet.com/icu/
- Comments - just a row for comments
!!! VERY IMPORTANT !!!
The newline character for every entry MUST be a CRLF, otherwise UE's Slate will constantly try to replace the given text Source, leading to errors!
Namespace and Key must be first columns. The order of other columns doesn't matter.
Any column that isn't Namespace, Key or lang-x is ignored by the tool.
To open the tool select:
UE4.27 : Window -> Easy Localization Tool
UE5.2, UE5.4 : Tools -> Easy Localization Tool
or use a shortcut : Alt + Shift + L
The following window should appear:
- Localization Name - Name of currently selected Localization. The game can have multiple localization directories.
- Available Languages in Selected Localization - list of language codes that are implemented in selected localization directory.
- Available Languages - list of language codes that are implemented by every localization directory.
- Reimport on editor startup - reimports the lastly selected localization with the last used CSV file when editor starts.
- Localization Preview - enabled the preview of the localization in the editor.
- Manually Set Last Language - if enabled it won't save and load lastly set language automatically.
- Override Language on Startup - if enabled, when the game starts for the very first time the selected language will be used. Normally, the system language will be used or it will fallback to
en
. - CSV File - CSV file to import.
- Global Namespace - this namespace will be assigned to every key in localization.
In order to import localization from CSV simply select the CSV file in the tool's window and click Import.
If your CSV doesn't have a Namespace column, fill Globl Namespace property. That's it!
After first import ever the editor might need to be restarted for localizations to work correctly.
If you've been using built-in engine's Localization Dashboard clear the Localization directory first.
The Localization directory should contain only these files:
Content
| - Localization
| | - Game
| | | - de
| | | | - Game.locres
| | | - en
| | | | - Game.locres
| | | - pl
| | | | - Game.locres
| | | - Game.locmeta
The Game localization is the default one. In order to add another localization directory (and name) add the localization path to the project's DefaultGame.ini
.
[Internationalization]
+LocalizationPaths=%GAMEDIR%Content/Localization/MyLocalizationName
In order to use a localized phrase type a KEY into the Text form and then set a Namespace and Key values for this Text:
To use it in a c++ code use the following macro:
NSLOCTEXT("GAME", "TEST_EXAMPLE", "TEST_EXAMPLE")
In order to make localization work on standnalone build there are two options in Project Settings
in the Packaging
section (under Advanced options
!) that need to be set:
Internationalization Support
set toAll
:
- Localization directory added to the
Addidiontal Non-Asset Directories to Copy
list:
There is an unwanted behaviour of FText
- it keeps creating a new Key for every child Blueprint it's in.
It means that if there is a FText
in a Blueprint, this FText
will not be valid in this Blueprints's children.
In order to workaround this issue the FLocText
has been introduce. It is a structure that holds Namespace and Key and it can give a corresponding to it FText
. The structrue is immune to the inheritence problems.
FLocText LocalizedStruct("GAME", "TEST_EXAMPLE");
FText LocalizedText = LocalizedStruct.GetText();
FString LocalizedString = LocalizedStruct.ToString();
Struct is supported in Blueprints too, of course.
You can use Localization Preview option in the tool, or use the Preview option inside UMG Designer
Easy Localization Tool comes with few handy functions to control localization in game:
Returns a list of available language codes.
GetELT()->GetAvailableLanguages();
Returns a code of the language which is currently in use.
GetELT()->GetCurrentLanguage();
Checks if a language with the given language code can be set.
GetELT()->CanSetLanguage("en");
Sets a language with the given language code. Returns false if the language couldn't be set.
GetELT()->SetLanguage("en");
Allow to bind delegate which will run every time a Text Localization has been changed.
GetELT()->OnTextLocalizationChanged.AddDynamic(this, &UMyObject::OnTextLocalizationChangedUFunc);
or
GetELT()->OnTextLocalizationChangedStatic.AddLambda([this]()
{
// Stuff to do when localization has changed.
});
There might be a rare situation when texts won't be displayed in a localized form.
There is a high chance running this function will fix this issue.
GetELT()->RefreshLanguageResources();
Easy Localization Tool saves lastly used language and sets it when starting a game.
The save file is located in MyGame\Saved\SaveGames\ELTSave.sav
The lastly used language will not be saved and loaded when
Manually Set Last Language
is enabled! This option might be needed if the game is not allowed to read save files on startup (i.e.: in console builds). In such situations useSetLanguage
to setup desired lanugage when you can.
You can generate localization without starting the editor, but via command line.
It might be useful when building a game via CI platform like Jenkins.
You can use the following script (win64) to generate localization files:
UE4.27 :
set UE4_PATH=C:\UE4
set PROJECT_PATH=C:\MyGame
call %UE4_PATH%\Engine\Binaries\Win64\UE4Editor-Cmd.exe %PROJECT_PATH%\MyGame.uproject -run=ELTCommandlet -CSVPath=%PROJECT_PATH%\Lockit.csv -LocPath=%PROJECT_PATH%\Content\Localization\Game -Namespace=GAME
UE5.2, UE5.4 :
set UE5_PATH=C:\UE5
set PROJECT_PATH=C:\MyGame
call %UE5_PATH%\Engine\Binaries\Win64\UnrealEditor-Cmd.exe %PROJECT_PATH%\MyGame.uproject -run=ELTCommandlet -CSVPath=%PROJECT_PATH%\Lockit.csv -LocPath=%PROJECT_PATH%\Content\Localization\Game -Namespace=GAME
Where:
- -CSVPath - is a path to the csv file to import.
- -LocPath - is a directory where localization files should be stored.
- -Namespace - optional parameter which sets a Global Namespace value.
Gets a Package, Namespace, Key and Source info from FText.
FString Package, Namespace, Key, Source;
UELTBlueprintLibrary::GetTextData(MyText, Package, Namespace, Key, Source);
Checks if two FTexts' keys are the same. If at least one of them has invalid key it will return false.
UELTBlueprintLibrary::AreTextKeysEqual(MyTextA, MyTextB);
This is Editor Scripting only utility.
It checks if the given FText is properly localized - it means it checks if Source and Key are the same.
It will return false if given FText is empty or if it is Culture Invariant.
UELTEditorUtils::ValidateText(MyText);
This is Editor Scripting only utility.
It replaces the OriginText with ReplaceWithText while keeping the OriginText's package id.
Use this instead of normal FText copy operator when using editor scripts, because it copies the package id which leads to broken FText localizations.
OriginTextOwner might be required when the OriginText is empty and has not package id assigned yet.
UELTEditorUtils::ReplaceText(this, OriginText, OtherText);
CSV must have the same amount of entries in every row (entries can be empty, but they must exist). There also should be a Namespace column if global namespace is not set. When importing CSV you might encounter such errors:
ERROR: Failed loading CSV! Trying to add a word: 'Dies, ist ein Beispiel, mit Interpunktionen!' to a row 3, column 5 (counting from 1) while there are 4 columns.
- this error might encounter when a row has more entries than the first "header" row. Check if the first row has every entry required and if any other row has no more entries than the "header" row.ERROR: Invalid CSV! Column 5 (counting from 1) has 6 values while Column 1 has 7 values. Every Column must have the same amount of values!
- this error might encounter when there are less entries in a row than in a "header" row.ERROR: CSV file not found!
- this error will encounter when the given CSV file does not exist.ERROR: Namespaces in CSV not found!
- this error will encounter when CSV has noNamespace
Column and theGlobal Namespace
is not set.ERROR: Namespace in row 2 (counting from 1) is empty!
- this error will encounter when CSV hasNamespace
Column, but there is an empty entry under it and theGlobal Namespace
is not set.ERROR: CSV has not enough Columns!
- this error will enncounter when CSV is empty or if it has only one Column. This tool requires at least two Columns in a CSV file to work.
If the text displays a Key value instead of the localized value:
- If this is a child widget blueprint and the Text is defined in it's parent you might need to use a LocText Struct.
- Otherwise you might need to call Refresh Language Resources function before displaying the text.
If the Text key keeps changing into a new key:
- Ensure that if the localization value has a new line character it is a CRLF character.
Easy Localization Tool has been used in:
The workflow of importing CSV into localization files has been implemented with success in many other titles, such as:
I want to send special thanks to Monika, because she always supports me and believes in me, to Pawel, for allowing me to test this plugin on his project, to cziter15 for the idea of how it should work and to everyone that contributed to this project.
Also, I want to thank You for using this plugin! It is very important for me that my work is useful for someone!
Happy coding!