{"id":13589313,"url":"https://github.com/zompi2/UE4EasyLocalizationTool","last_synced_at":"2025-04-08T09:32:30.100Z","repository":{"id":136343008,"uuid":"351567866","full_name":"zompi2/UE4EasyLocalizationTool","owner":"zompi2","description":"This plugin introduces a way simpler method of localizing game made in Unreal Engine by simply importing CSV file into engine's localization files.","archived":false,"fork":false,"pushed_at":"2024-08-28T06:28:43.000Z","size":47850,"stargazers_count":75,"open_issues_count":5,"forks_count":8,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-08-28T11:38:21.476Z","etag":null,"topics":["localization","localization-tool","ue4","ue4-plugin","ue5","ue5-plugin"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zompi2.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog.txt","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"zompi2","ko_fi":"zompi2","buy_me_a_coffee":"zompi2"}},"created_at":"2021-03-25T20:31:36.000Z","updated_at":"2024-08-28T06:28:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"afe3f766-c26a-4ea5-a0b8-1ff2c4bbf3c0","html_url":"https://github.com/zompi2/UE4EasyLocalizationTool","commit_stats":null,"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zompi2%2FUE4EasyLocalizationTool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zompi2%2FUE4EasyLocalizationTool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zompi2%2FUE4EasyLocalizationTool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zompi2%2FUE4EasyLocalizationTool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zompi2","download_url":"https://codeload.github.com/zompi2/UE4EasyLocalizationTool/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223314056,"owners_count":17124993,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["localization","localization-tool","ue4","ue4-plugin","ue5","ue5-plugin"],"created_at":"2024-08-01T16:00:27.816Z","updated_at":"2025-04-08T09:32:30.092Z","avatar_url":"https://github.com/zompi2.png","language":"C++","funding_links":["https://github.com/sponsors/zompi2","https://ko-fi.com/zompi2","https://buymeacoffee.com/zompi2"],"categories":["Localization"],"sub_categories":[],"readme":"# Easy Localization Tool for Unreal Engine\n\nThis plugin introduces a way simplier method of localizing game made in Unreal Engine. \n\nIt simply allow to import CSV file with localization.\n\nThe plugin has been tested and it works on the Engine's versions: 4.27, 5.2, 5.4, and 5.5.\n\n# Contact\n\nIf 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.\n\n# Example Project\n\nThe example project wich uses this plugin can be found in **[this repository](https://github.com/zompi2/UE4EasyLocalizationToolExample)**.\n\n# Fab\n\nThe plugin is available on the Unreal Engine Fab! It is free, of course.  \nYou can **[download it from here](https://www.fab.com/listings/c0b87152-0c7a-453d-aea9-58c93936fc32)**.  \nCurrently plugin is available for UE version 5.5, 5.4 and 5.2 (5.3 is not available, because of **[this reason](#unrel-engine-53-issue)**.  \nIf you are using 4.27 you can download the precompiled package **[from here](https://github.com/zompi2/UE4EasyLocalizationTool/raw/build-4.27/EasyLocalizationTool-4.27-Compiled.zip)**.  \nThe plugin's version that's on the Marketplace is **1.5.8**.\n\n# Unrel Engine 5.3 Issue\nUE5.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.  \nThe best solution is to use the newest version of Unreal Engine.  \nIf 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](#loctext-struct).  \n\n# Table of content\n\n- [CSV Format](#csv-format)\n- [Using the Tool](#using-the-tool)\n- [Import](#import)\n- [Adding Localization Directories](#adding-localization-directories)\n- [Using Localizations](#using-localizations)\n- [Cooking Localizations](#cooking-localizations)\n- [LocText Struct](#loctext-struct)\n- [Previewing Localizations](#previewing-localizations)\n- [Controlling Localizations](#controlling-localizations)\n- [Save File](#save-file)\n- [Commandlet](#commandlet)\n- [Utilities](#utilities)\n- [Troubleshooting Errors](#troubleshooting-errors)\n- [Used In](#used-in)\n- [Special Thanks](#special-thanks)\n\n## CSV Format\n\nThe tool accepts a CSV file of a defined format:\n\n![csvtesteg](https://user-images.githubusercontent.com/7863125/143495161-338a59b2-a41f-43a2-85cb-6a3b28078ab1.png)\n\n``` csv\nNamespace,Key,lang-en,lang-pl,lang-de,Comments\nGAME,TEST_EXAMPLE,\"Hello, world!\",Witaj świecie!,Hallo Welt!,Anything you wish to type\n```\n\n* **Namespace** - a namespace in which current entry is located. This column is **optional**, but without it a **Global Namespace** must be defined.\n* **Key** - a key of this entry, used later in text implementation.\n* **lang-x** - a value in a **x** language. **x** is a language code, such as *en*, *pl*, *de*, etc.\n\u003e Unreal Engine uses ICU codes. The full list of them can be found here: https://www.localeplanet.com/icu/\n* **Comments** - just a row for comments\n\n\u003e **!!! VERY IMPORTANT !!!**  \n\u003e \n\u003e 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!   \n\u003e **Namespace** and **Key** must be first columns. The order of other columns doesn't matter.  \n\u003e Any column that isn't **Namespace**, **Key** or **lang-x** is ignored by the tool.\n\n[Back to top](#table-of-content)\n\n## Using the Tool\n\nTo open the tool select:  \n**UE4.27** : `Window -\u003e Easy Localization Tool`  \n\n![open](https://user-images.githubusercontent.com/7863125/143495187-8ceab883-f00f-463b-af32-0effd64f642b.png)  \n\n**UE5.2, UE5.4, UE5.5** : `Tools -\u003e Easy Localization Tool`  \n\n ![open55](https://github.com/user-attachments/assets/b2f79602-1ce7-4fa8-a5b1-2db9ae4e3e12)\n\nor use a shortcut : `Alt + Shift + L`  \n\nThe following window should appear:  \n\n![ELTSShot](https://github.com/user-attachments/assets/cc5039e2-4363-4611-ac51-2c5b1d40d4a0)\n\n* **Localization Name** - Name of currently selected Localization. The game can have multiple localization directories.\n* **Available Languages in Selected Localization** - list of language codes that are implemented in selected localization directory.\n* **Available Languages** - list of language codes that are implemented by every localization directory.\n* **Reimport on editor startup** - reimports the lastly selected localization with the last used CSV file when editor starts.\n* **Localization Preview** - enabled the preview of the localization in the editor.\n* **Manually Set Last Language** - if enabled it won't save and load lastly set language automatically. \n* **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`.\n* **CSV File** - CSV files to import. You can import mutliple files at once to the same Localization.\n* **Global Namespace** - this namespace will be assigned to every key in localization.\n* **Log Debug** - select this option to see additional informations in Output Log. Be aware that big CSVs might generate a lot of logs. \n\n[Back to top](#table-of-content)\n\n## Import\n\nIn order to import localization from CSV simply select the CSV file in the tool's window and click **Import**.  \nIf your CSV doesn't have a **Namespace** column, fill **Globl Namespace** property. That's it!\n\n\u003e After first import ever the editor might need to be restarted for localizations to work correctly.\n\n\u003e If you've been using built-in engine's Localization Dashboard clear the Localization directory first. \n\nThe Localization directory should contain only these files:\n\n```\nContent\n| - Localization\n|   | - Game\n|   |   | - de\n|   |   |   | - Game.locres\n|   |   | - en\n|   |   |   | - Game.locres\n|   |   | - pl\n|   |   |   | - Game.locres\n|   |   | - Game.locmeta\n```\n\n[Back to top](#table-of-content)\n\n## Adding Localization Directories\n\nThe **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`.\n\n```\n[Internationalization]\n+LocalizationPaths=%GAMEDIR%Content/Localization/MyLocalizationName\n```\n\n[Back to top](#table-of-content)\n\n## Using Localizations\n\nIn order to use a localized phrase type a **KEY** into the Text form and then set a Namespace and Key values for this Text:\n\n![testexampleloc](https://github.com/zompi2/UE4EasyLocalizationTool/assets/7863125/e28d1a4f-cd9f-4ce8-a966-e4dd388e1c67)\n\nTo use it in a c++ code use the following macro:\n\n``` cpp\nNSLOCTEXT(\"GAME\", \"TEST_EXAMPLE\", \"TEST_EXAMPLE\")\n```\n\n[Back to top](#table-of-content)\n\n## Cooking localizations\nIn 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:\n* `Internationalization Support` set to `All`:  \n![int support](https://github.com/zompi2/UE4EasyLocalizationTool/assets/7863125/fbac259c-fec0-4656-b0f1-d830298385b9)\n* Localization directory added to the `Addidiontal Non-Asset Directories to Copy` list:  \n![loccopy](https://github.com/zompi2/UE4EasyLocalizationTool/assets/7863125/0f244d7c-2744-411f-ac77-b85dedc46e0e)\n\n[Back to top](#table-of-content)\n\n## LocText Struct\n\nThere is an unwanted behaviour of `FText` - it keeps creating a new Key for every child Blueprint it's in.  \nIt means that if there is a `FText` in a Blueprint, this `FText` will not be valid in this Blueprints's children.  \n\nIn 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.  \n\n``` cpp\nFLocText LocalizedStruct(\"GAME\", \"TEST_EXAMPLE\");\nFText LocalizedText = LocalizedStruct.GetText();\nFString LocalizedString = LocalizedStruct.ToString();\n```\nStruct is supported in Blueprints too, of course.\n\n![locstructimg](https://user-images.githubusercontent.com/7863125/147063762-8501121a-50f9-4dca-bfd4-fad096b63437.png)\n![locstructbpcast](https://user-images.githubusercontent.com/7863125/147063770-e669c169-273b-4b09-97df-14ba834cf8c8.png)\n\n[Back to top](#table-of-content)\n\n## Previewing Localizations\n\nYou can use **Localization Preview** option in the tool, or use the Preview option inside UMG Designer\n\n![preview](https://user-images.githubusercontent.com/7863125/144485817-09998bdb-a27b-4d10-b139-4db271880996.png)\n\n[Back to top](#table-of-content)\n\n## Controlling Localizations\n\nEasy Localization Tool comes with few handy functions to control localization in game:\n\n#### Get Available Languages\n\nReturns a list of available language codes.\n\n![image](https://github.com/zompi2/UE4EasyLocalizationTool/assets/7863125/acc12392-9879-4306-8c5e-e0ee36bf6283)\n\n``` cpp\nGetELT()-\u003eGetAvailableLanguages();\n```\n\n#### Get Current Language\n\nReturns a code of the language which is currently in use.\n\n![image](https://github.com/zompi2/UE4EasyLocalizationTool/assets/7863125/b27e6c1b-0683-4f10-bc26-c915b8be732d)\n\n``` cpp\nGetELT()-\u003eGetCurrentLanguage();\n```\n\n#### Can Set Language\n\nChecks if a language with the given language code can be set.\n\n![image](https://github.com/zompi2/UE4EasyLocalizationTool/assets/7863125/6f051be5-58e0-4171-958f-e24292eaad19)\n\n``` cpp\nGetELT()-\u003eCanSetLanguage(\"en\");\n```\n\n#### Set Language\n\nSets a language with the given language code. Returns false if the language couldn't be set.\n\n![image](https://github.com/zompi2/UE4EasyLocalizationTool/assets/7863125/70e6e9a0-0ecc-4fac-b04e-7de390a701f9)\n\n``` cpp\nGetELT()-\u003eSetLanguage(\"en\");\n```\n\n#### On Text Localization Changed Event\n\nAllow to bind delegate which will run every time a Text Localization has been changed.\n\n![locchange](https://user-images.githubusercontent.com/7863125/152312310-7beafb2b-616b-4cfe-b757-305519985721.png)\n\n``` cpp\nGetELT()-\u003eOnTextLocalizationChanged.AddDynamic(this, \u0026UMyObject::OnTextLocalizationChangedUFunc);\n```\nor\n``` cpp\nGetELT()-\u003eOnTextLocalizationChangedStatic.AddLambda([this]()\n{\n    // Stuff to do when localization has changed.\n});\n```\n\n#### Refresh Language Resources\nThere might be a rare situation when texts won't be displayed in a localized form.  \nThere is a high chance running this function will fix this issue.\n\n![image](https://github.com/zompi2/UE4EasyLocalizationTool/assets/7863125/7aa102b3-dcee-466d-86e8-81b458bac1bb)\n\n``` cpp\nGetELT()-\u003eRefreshLanguageResources();\n```\n\n[Back to top](#table-of-content)\n\n## Save File\n\nEasy Localization Tool saves lastly used language and sets it when starting a game.  \nThe save file is located in `MyGame\\Saved\\SaveGames\\ELTSave.sav`  \n\n\u003e 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.\n\n[Back to top](#table-of-content)\n\n## Commandlet\n\nYou can generate localization without starting the editor, but via command line.  \nIt might be useful when building a game via CI platform like Jenkins.\n\nYou can use the following script (win64) to generate localization files:\n\n**UE4.27** :  \n\n```\nset UE4_PATH=C:\\UE4\nset PROJECT_PATH=C:\\MyGame\n\ncall %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\n```\n\n**UE5.2, UE5.4, UE5.5** :  \n\n```\nset UE5_PATH=C:\\UE5\nset PROJECT_PATH=C:\\MyGame\n\ncall %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\n```\n\nWhere:\n\n* **-CSVPath** - is a path to the csv file to import.\n* **-LocPath** - is a directory where localization files should be stored.\n* **-Namespace** - optional parameter which sets a **Global Namespace** value.\n\n[Back to top](#table-of-content)\n\n## Utilities\n\n#### Get Text Data\n\nGets a Package, Namespace, Key and Source info from FText.\n\n![image](https://github.com/zompi2/UE4EasyLocalizationTool/assets/7863125/b9612997-0536-419e-b46b-3b5d8380fd5a)\n\n``` cpp\nFString Package, Namespace, Key, Source;\nUELTBlueprintLibrary::GetTextData(MyText, Package, Namespace, Key, Source);\n```\n\n#### Are Text Keys Equal\n\nChecks if two FTexts' keys are the same. If at least one of them has invalid key it will return false.\n\n![image](https://github.com/zompi2/UE4EasyLocalizationTool/assets/7863125/c72f24f3-026b-4aa2-8de7-cee17052a92a)\n\n``` cpp\nUELTBlueprintLibrary::AreTextKeysEqual(MyTextA, MyTextB);\n```\n\n#### Validate Text\n\n*This is Editor Scripting only utility.*  \nIt checks if the given FText is properly localized - it means it checks if Source and Key are the same.  \nIt will return false if given FText is empty or if it is Culture Invariant.\n\n![image](https://github.com/zompi2/UE4EasyLocalizationTool/assets/7863125/3943435e-436a-409f-9f03-9d83a692ad17)\n\n``` cpp\nUELTEditorUtils::ValidateText(MyText);\n```\n\n#### Replace Text\n\n*This is Editor Scripting only utility.*  \nIt replaces the OriginText with ReplaceWithText while keeping the OriginText's package id.  \nUse this instead of normal FText copy operator when using editor scripts, because it copies the package id which leads to broken FText localizations.  \nOriginTextOwner might be required when the OriginText is empty and has not package id assigned yet.\n\n![image](https://github.com/zompi2/UE4EasyLocalizationTool/assets/7863125/13c83c4f-c4f4-4fa2-8fe8-f6c32fe5cfe0)\n\n``` cpp\nUELTEditorUtils::ReplaceText(this, OriginText, OtherText);\n```\n\n[Back to top](#table-of-content)\n\n# Troubleshooting Errors\nCSV 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:\n* `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.\n*  `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.\n* `ERROR: CSV file not found!` - this error will encounter when the given CSV file does not exist.\n* `ERROR: Namespaces in CSV not found!` - this error will encounter when CSV has no `Namespace` Column and the `Global Namespace` is not set.\n* `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.\n* `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.  \n\nIf the text displays a Key value instead of the localized value:\n* If this is a child widget blueprint and the Text is defined in it's parent you might need to use a [LocText Struct](#loctext-struct).\n* Otherwise you might need to call [Refresh Language Resources](#refresh-language-resources) function before displaying the text.\n\nIf the Text key keeps changing into a new key:\n* Ensure that if the localization value has a new line character it is a CRLF character.\n\n# Used In\n\nEasy Localization Tool has been used in:\n* [Achilles: Legends Untold](https://store.steampowered.com/app/1314000/Achilles_Legends_Untold)\n\nThe workflow of importing CSV into localization files has been implemented with success in many other titles, such as:\n* [SUCCUBUS](https://store.steampowered.com/app/985830/SUCCUBUS)\n* [Real Boxing 2](https://play.google.com/store/apps/details?id=com.vividgames.realboxing2)\n\n[Back to top](#table-of-content)\n\n# Special Thanks\n\nI 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](https://github.com/cziter15) for the idea of how it should work and to everyone that contributed to this project.  \nAlso, I want to thank You for using this plugin! It is very important for me that my work is useful for someone!  \nHappy coding!\n\n[Back to top](#table-of-content)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzompi2%2FUE4EasyLocalizationTool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzompi2%2FUE4EasyLocalizationTool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzompi2%2FUE4EasyLocalizationTool/lists"}