Skip to content

Latest commit

 

History

History
388 lines (259 loc) · 16.1 KB

README.md

File metadata and controls

388 lines (259 loc) · 16.1 KB

Easy Localization Tool for Unreal Engine

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, 5.4, and 5.5.

Contact

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: zompi2@gmail.com, however there is a risk that it will be filtered as spam.

Example Project

The example project wich uses this plugin can be found in this repository.

Fab

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.5, 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.8.

Unrel Engine 5.3 Issue

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.

Table of content

CSV Format

The tool accepts a CSV file of a defined format:

csvtesteg

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.

Back to top

Using the Tool

To open the tool select:
UE4.27 : Window -> Easy Localization Tool

open

UE5.2, UE5.4 : Tools -> Easy Localization Tool

elt_tools_54

or use a shortcut : Alt + Shift + L

The following window should appear:

eltimg

  • 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.

Back to top

Import

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

Back to top

Adding Localization Directories

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

Back to top

Using Localizations

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:

testexampleloc

To use it in a c++ code use the following macro:

NSLOCTEXT("GAME", "TEST_EXAMPLE", "TEST_EXAMPLE")

Back to top

Cooking localizations

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 to All:
    int support
  • Localization directory added to the Addidiontal Non-Asset Directories to Copy list:
    loccopy

Back to top

LocText Struct

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.

locstructimg locstructbpcast

Back to top

Previewing Localizations

You can use Localization Preview option in the tool, or use the Preview option inside UMG Designer

preview

Back to top

Controlling Localizations

Easy Localization Tool comes with few handy functions to control localization in game:

Get Available Languages

Returns a list of available language codes.

image

GetELT()->GetAvailableLanguages();

Get Current Language

Returns a code of the language which is currently in use.

image

GetELT()->GetCurrentLanguage();

Can Set Language

Checks if a language with the given language code can be set.

image

GetELT()->CanSetLanguage("en");

Set Language

Sets a language with the given language code. Returns false if the language couldn't be set.

image

GetELT()->SetLanguage("en");

On Text Localization Changed Event

Allow to bind delegate which will run every time a Text Localization has been changed.

locchange

GetELT()->OnTextLocalizationChanged.AddDynamic(this, &UMyObject::OnTextLocalizationChangedUFunc);

or

GetELT()->OnTextLocalizationChangedStatic.AddLambda([this]()
{
    // Stuff to do when localization has changed.
});

Refresh Language Resources

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.

image

GetELT()->RefreshLanguageResources();

Back to top

Save File

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 use SetLanguage to setup desired lanugage when you can.

Back to top

Commandlet

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.

Back to top

Utilities

Get Text Data

Gets a Package, Namespace, Key and Source info from FText.

image

FString Package, Namespace, Key, Source;
UELTBlueprintLibrary::GetTextData(MyText, Package, Namespace, Key, Source);

Are Text Keys Equal

Checks if two FTexts' keys are the same. If at least one of them has invalid key it will return false.

image

UELTBlueprintLibrary::AreTextKeysEqual(MyTextA, MyTextB);

Validate Text

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.

image

UELTEditorUtils::ValidateText(MyText);

Replace Text

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.

image

UELTEditorUtils::ReplaceText(this, OriginText, OtherText);

Back to top

Troubleshooting Errors

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 no Namespace Column and the Global Namespace is not set.
  • ERROR: Namespace in row 2 (counting from 1) is empty! - this error will encounter when CSV has Namespace Column, but there is an empty entry under it and the Global 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.

Used In

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:

Back to top

Special Thanks

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!

Back to top