Overview
"I want to release this game internationally..." When that thought crosses your mind, the first challenge you face is multi-language support.
This article covers Unity Localization 1.0 and later (Unity 2022.3 LTS recommended).
The Unity Localization package is Unity's official multi-language support package. It manages text, images, audio, fonts, and more per language, allowing runtime switching. Integration with CSV and Google Spreadsheets is also supported, making collaboration with translators seamless.
Key Concepts
| Concept | Description |
|---|---|
| Locale | A combination of language and region (e.g., en-US, ja-JP) |
| String Table | A container that manages text per language |
| Asset Table | A container that manages images, audio, etc. per language |
| Locale Selector | A mechanism that determines which Locale to use |
| Smart Strings | A feature for localizing dynamically changing text |
Installation
Install from the Package Manager.
- Select
Window > Package Manager - Choose
Unity Registryfrom the dropdown at the top-left - Find and select
Localizationfrom the list - Click the
Installbutton at the bottom-right
Setup
Creating Localization Settings
- Select
Edit > Project Settings > Localization - Click the
Createbutton - Choose a save location
Creating Locales
- Click the
Locale Generatorbutton in the Localization Settings screen - Check the languages you want to use (e.g., English, Japanese)
- Click the
Generate Localesbutton
Locale Selector: Language Selection at Startup
The Locale Selector is a mechanism that determines which language to use when the app launches.
Configuring the System Language Selector
This automatically selects a language based on the device's language settings.
- Open
Edit > Project Settings > Localization - Select Localization Settings
- Click
+in theLocale Selectorssection - Add
System Language Selector - Adjust the priority order (evaluated from top to bottom)
Startup Selector Priority
| Selector | Description |
|---|---|
| Command Line Selector | Specifies language via command-line arguments (for debugging) |
| System Language Selector | Uses the device's language settings |
| Specific Locale Selector | Locks to a specific language |
| PlayerPrefs Selector | Saves and restores the user's language selection |
Recommended setup: Set
PlayerPrefs Selectoras the highest priority, followed bySystem Language Selector, and finallySpecific Locale Selector(as a fallback). This creates a resolution order of: user selection -> system language -> default language.
Saving Language with PlayerPrefs Selector
Here is an example of saving and restoring the user's language selection.
using UnityEngine;
using UnityEngine.Localization.Settings;
public class LanguageSettings : MonoBehaviour
{
private const string LANGUAGE_KEY = "selected_language";
// Change and save the language
public void SetLanguage(string localeCode)
{
var locale = LocalizationSettings.AvailableLocales.GetLocale(localeCode);
if (locale != null)
{
LocalizationSettings.SelectedLocale = locale;
PlayerPrefs.SetString(LANGUAGE_KEY, localeCode);
PlayerPrefs.Save();
}
}
}
Note: When using the
PlayerPrefs Selector, it automatically loads and applies the saved language code at startup.
Text Localization
Creating a String Table
- Open
Window > Asset Management > Localization Tables - Select the
New Table Collectiontab - Set
TypetoString Table Collection - Enter a table name in
Name(e.g.,UI Texts) - Click the
Createbutton
Localizing UI Text
- Select the GameObject with a TextMeshPro component
- Add a
Localize String EventviaAdd Component - Select the table and entry in
String Reference
Localization from Script
using UnityEngine;
using UnityEngine.Localization.Settings;
public class LocalizedTextExample : MonoBehaviour
{
async void Start()
{
try
{
var localizedString = await LocalizationSettings.StringDatabase
.GetLocalizedStringAsync("UI Texts", "menu_start");
Debug.Log(localizedString);
}
catch (System.Exception e)
{
Debug.LogError($"Localization failed: {e.Message}");
}
}
}
Note about async void: Since
async voiddoes not propagate exceptions to the caller, always usetry-catchfor error handling. For production projects, consider usingUniTaskorCoroutine-based implementations.
Asset Localization
Creating an Asset Table
- Open
Window > Asset Management > Localization Tables - Set
TypetoAsset Table Collection - Enter a table name in
Name(e.g.,Game Assets) - Click the
Createbutton
Using Localization Scene Controls
- Open
Window > Asset Management > Localization Scene Controls - Set the
Asset Tableto the created Asset Table Collection - Turn on
Track Changes - Configure assets in the scene for each language
Font Switching
When you need to change fonts per language (e.g., Japanese to English), use Asset Tables.
Managing Fonts with Asset Tables
- Create an Asset Table Collection (e.g.,
Fonts) - Register font assets for each language
- Use the
Localize Font Eventcomponent on TextMeshPro
using UnityEngine;
using UnityEngine.Localization.Components;
using TMPro;
public class LocalizedFontExample : MonoBehaviour
{
[SerializeField] private TMP_Text textComponent;
[SerializeField] private LocalizeAssetEvent fontEvent;
void Start()
{
fontEvent.OnUpdateAsset.AddListener(asset =>
{
if (asset is TMP_FontAsset font)
{
textComponent.font = font;
}
});
}
}
TextMeshPro Fallback Font
Fallback Font configuration is important for CJK (Chinese, Japanese, Korean) support.
- Select the main font asset
- Open
Fallback Font Assetsin the Inspector - Add the Japanese font asset
Font Asset Creator: When using Japanese fonts with TextMeshPro, you need to create a Font Asset that includes Japanese characters via
Window > TextMeshPro > Font Asset Creator. Use presets such as "Japanese Hiragana + Katakana + CJK".
Smart Strings
Smart Strings are a feature for localizing dynamically changing text. They are based on the SmartFormat library.
Variable Embedding
Hello, {player_name}!
Pluralization
Japanese does not distinguish between singular and plural forms, so variables are simply embedded.
Japanese:
{count}個のアイテム
English:
{count} {count:plural:item|items}
Smart Strings syntax follows the SmartFormat library. Since pluralization rules differ by language, you need to configure them for each language accordingly.
Setting Variables from Script
using UnityEngine;
using UnityEngine.Localization.Components;
public class SmartStringExample : MonoBehaviour
{
[SerializeField] private LocalizeStringEvent localizeStringEvent;
void Start()
{
// Setting variables using Arguments (recommended)
localizeStringEvent.StringReference.Arguments = new object[] { 5 };
localizeStringEvent.RefreshString();
}
}
Smart Strings variables: Variables are embedded in the format
{0},{1}, and values are set based on the order of theArgumentsarray. To use named variables, add Variables usingLocalizedString.Add().
Switching Languages
using UnityEngine.Localization.Settings;
public void ChangeToJapanese()
{
var locale = LocalizationSettings.AvailableLocales.GetLocale("ja");
LocalizationSettings.SelectedLocale = locale;
}
Asynchronous Switching
IEnumerator Start()
{
yield return LocalizationSettings.InitializationOperation;
ChangeToJapanese();
}
Testing
Switching Languages in the Game View
- A
Localedropdown appears in the toolbar at the top of the Game View - Click to switch languages
- Changes can be verified in real-time even during play mode
Preview Window
- Open
Window > Asset Management > Localization Tables - Select a table
- Click an entry to display the Preview
- Verify the display for each language
Testing from Script
#if UNITY_EDITOR
[UnityEditor.MenuItem("Debug/Switch to Japanese")]
static void SwitchToJapanese()
{
var locale = LocalizationSettings.AvailableLocales.GetLocale("ja");
LocalizationSettings.SelectedLocale = locale;
}
[UnityEditor.MenuItem("Debug/Switch to English")]
static void SwitchToEnglish()
{
var locale = LocalizationSettings.AvailableLocales.GetLocale("en");
LocalizationSettings.SelectedLocale = locale;
}
#endif
CSV Management
Exporting CSV
- Select a table in the Localization Tables window
- Choose
Export > CSV...from the menu at the top-right
Importing CSV
- Select a table in the Localization Tables window
- Choose
Import > CSV...from the menu at the top-right
Google Spreadsheets Integration
Using Google Spreadsheets Service makes collaboration with translators even smoother.
Setup Steps
- Install
Google Sheets for Unityfrom the Package Manager (in Samples) - Create a service account in Google Cloud Console
- Download the JSON key and place it in the project
- Add
Google Sheets Servicein Localization Settings - Configure the authentication credentials
Details: For detailed steps on Google Spreadsheets integration, refer to the Unity Documentation.
Addressables Integration
Impact on Build Size
When implementing multi-language support, all language text and assets are included in the build, resulting in significantly increased build sizes. This is particularly noticeable when:
- Supporting many languages
- Using different fonts per language
- Localizing large assets such as audio and textures
Integrating with Addressables solves this problem. For large-scale projects, integration with Addressables allows downloading only the required languages.
Configuration
- Install the Addressables package
- Open Localization Settings
- Change from
Asset DatabasetoAddressables - Place each Locale in a separate Addressable group
Benefits
- Reduced download size: Only loads the required languages
- On-demand loading: Fetches only necessary assets when switching languages
- Remote delivery: Supports language pack delivery via CDN
Summary
The Unity Localization package is a powerful tool for adding multi-language support to Unity projects.
- Text, image, and audio localization - Managed with String Tables and Asset Tables
- Smart Strings - Naturally localizes dynamic text according to each language's grammar
- CSV/Google Spreadsheets integration - Smooth collaboration with translators
- Addressables integration - Reduces download size by loading only the required languages
If you are planning to distribute globally, make the most of the Unity Localization package.