Localization

An example of Spanish localization in UI Toolkit Sample - Dragon Crashers
How it works
-
String Localization: The LocalizedString class lets you manage strings that automatically update when switching Locales at runtime. With Smart Strings, you can add placeholders, handle plurals, and adjust for other language-specific nuances.
-
Asset localization: Swap textures and other assets based on the Locale, allowing you to create region-specific content beyond simple text.
-
Data Binding: The Localization package integrates with UI Toolkit's runtime data binding, linking UI elements to String and Asset Tables. Changes in data, Locale, or load state trigger automatic updates.
-
String and Asset Table management: String and Asset Tables store key-value pairs for translating text or other assets into Locale-specific equivalents. A centralized UI interface provides a high-level overview of all localized text and assets in your project.
-
Locale Switching: Switch languages in real-time without restarting the application. At runtime, select a new Locale, and the UI updates immediately to reflect the change.
Localization setup

Install the Localization package from the Package Manager.
-
Set Up Localization Settings: Install the Localization package from the Package Manager, then go to Project Settings > Localization to create and configure your Localization Settings asset, which will manage all localized assets.

Create and configure your Localization Settings in the Project Settings.
-
Create Locales: Define the languages and regions your project will support using the Locale Generator. This creates assets for each Locale, identified by a unique two-letter code (e.g., "en" for English, "fr" for French, "es" for Spanish, etc.). Set a default Locale to use when the application starts.

Add a Locale.
-
Create String and Asset Tables: Use String Tables to store text entries for each Locale. Add entries for UI text elements like labels, buttons, and dropdown options.

Create String Tables and Asset Tables.
-
In the Localization Tables window (Window > Asset Management > Localization Tables), add key-value pairs for each text element in the UI. Each key represents a specific text item (like a label or button), and each value is the translated text for that item in each Locale.
-
Store region-specific assets like images or GameObjects in Asset Tables. For instance, you might add sprites or textures for icons representing each Locale. For each key, link assets that are specific to each Locale to reflect regional or cultural preferences.

Key-value pairs represent each element to localize.
-
Define a UXML interface: Use UI Builder to create a UXML file with elements such as Buttons, DropdownFields, and Labels. In the demo scene, this UXML shows a few elements ready to be localized. For text fields, use an entry from a String Table. For non-text fields, such as textures, use an Asset Table.Demo sceneYou can find a sample implementation of Localization in the LocalizationDemo scene included in the QuizU project.To access it, navigate at runtime to the main menu and select Demos Localization, or load the LocalizationDemo scene directly after disabling the bootloader (Quiz > Don't Load Bootstrap Scene on Play).

Add data bindings in the UI Builder to localized strings and assets.
-
Bind data to UI Elements in UI Builder: This is where the power of UI Toolkit's runtime data binding system comes into play. In UI Builder, select the element you want to localize. Open the Inspector panel and select Add Binding in the content field (e.g.,for Labels or
textfor images).backgroundImageChoose LocalizedString or other localized asset as the binding type, and link to the corresponding entry in your String or Asset Table. Add more entries to the tables as you need to localize more elements.
Use the Game View Locale drop-down to preview the localization.
-
To test, use the Game View Locale drop-down to preview the UI in different languages, ensuring elements display correctly in each Locale.
<Bindings><UnityEngine.Localization.LocalizedString property="text"table="GUID:6aaa262cde38a4024bc3fc7f5ce6d50d"entry="Id(104135776002048)" /></Bindings>
Use the Localization API
Select a Locale
LocalizationSettingsclickedRegisterCallback<ClickEvent>LocalizationDemovoid SelectLocale(string localeCode){ Locale locale = LocalizationSettings.AvailableLocales.GetLocale(localeCode); LocalizationSettings.SelectedLocale = locale;}void RegisterCallbacks(){ m_ButtonDanish.clicked += () => SelectLocale("da"); m_ButtonEnglish.clicked += () => SelectLocale("en"); m_ButtonSpanish.clicked += () => SelectLocale("es"); m_ButtonFrench.clicked += () => SelectLocale("fr");}

The buttons can change Locales.
Use SetBinding
textusing UnityEngine;using UnityEngine.Localization;using UnityEngine.UIElements;public class LocalizationDemo : MonoBehaviour{ // Set in Inspector [SerializeField] LocalizedString m_LocalizedText; Label m_LocalizedLabel; UIDocument m_UIDocument; void Start() { m_LocalizedLabel = m_UIDocument.rootVisualElement.Q<Label>("text__label"); m_LocalizedLabel.SetBinding("text", m_LocalizedText); }}
m_LocalizedTexttextm_LocalizedLabelListen for Locale changes
using UnityEngine;using UnityEngine.Localization;using UnityEngine.Localization.Settings;public class LocalizationExample: MonoBehaviour{ void OnEnable() { LocalizationSettings.SelectedLocaleChanged += OnLocaleChanged; } void OnDisable() { LocalizationSettings.SelectedLocaleChanged -= OnLocaleChanged; } void OnLocaleChanged(Locale newLocale) { // Perform actions when the Locale changes, like updating UI elements Debug.Log($"Locale changed to: {newLocale.Identifier.Code}"); }}
OnLocaleChangedWork with String Tables
Import and export string data
CSV files

Import or export CSV files.
Google Sheets synchronization

Create a Google Sheets Service and authorize.

Add the Google Sheets Service to the StringTable's extensions.
Use Smart Strings

Enable Smart Strings in either the StringTable window or Inspector.
Set up a Smart String in your script
-
Set Up the Localized String with Placeholders: A Smart String consists of literal text with placeholders in brackets, similar tobut with added flexibility. In your String Table, create an entry with placeholders, like
String.Format. Here,"Welcome, {0}!"is a placeholder for runtime data.{0} -
Use a LocalizedString and Arguments: In your script, create a LocalizedString for this entry and specify the runtime data using the Arguments property. For example, this snippet from theshows how to replace a single placeholder:
SmartStringDemo
// Replaces placeholder with player name (e.g.,// "Welcome, {0}!" => "Welcome, Player One!")m_PlaceholderLabel = root.Q<Label>("welcome__label");m_PlaceholderMessage.Arguments = new object[] { m_PlayerName };m_PlaceholderLabel.SetBinding("text", m_PlaceholderMessage);
"Welcome, Player One!"Understand placeholders
{0}- Selector: This determines which data to use (e.g., {player.name} selects the name property of a player object).
- Formatter Name: This defines the formatter to apply (e.g., for pluralization).
plural - Formatter Options: This customizes the formatter's behavior (e.g., specifying singular and plural forms).
- Format: This determines how the output is presented (e.g., converting a number to a plural word, formatting a date or time, or selecting a phrase based on input).

A placeholder can consist of several parts.
{gameObject.name}{slider.value}- Choose Formatter: selects "morning," "afternoon," or "evening" based on input.
{0:choose(1|2|3):morning|afternoon|evening|anytime} - Plural Formatter: adjusts text for singular or plural forms.
{0:plural:one item| items}

Smart Strings are an alternative to String.Format.
- Choose Formatter: Allows you to apply conditional logic based on numeric input
- Plural Formatter: Automatically applies pluralization rules based on quantity
- Time Formatter: Displays date and time
- Conditional Formatter: For if/else-like logic
- List Formatter: Formats arrays or lists
- Is Match Formatter: For conditional text display based on regex patterns
String pre-processing
GetLocalizedString
GetLocalizedString[SerializeField] int m_PlayerLevel = 1;LocalizedString m_LevelMessage = new LocalizedString("My_Table", "My_ Entry");// A property that retrieves the localized string and replaces the placeholder {0} with the player's level[CreateProperty] public string LevelMessage => m_LevelMessage.GetLocalizedString(m_PlayerLevel);
LevelMessage{0}CreatePropertyLevelMessageUse the StringChanged event
My_Table StringTableMy_Entry entryLocalizedString localizedString = new LocalizedString("My_Table", "My_Entry");localizedString.StringChanged += OnLocalizedStringChanged;
OnLocalizedStringChangedvoid OnLocalizedStringChanged(string value){ // Example: Add a prefix based on certain conditions string processedString = $"[Prefix] {value}"; // Update the UI element with the processed string m_TextLabel.text = processedString;}
Dynamic UI controls
choicesPreprocessDemo
Pre-process a LocalizedString using the StringChanged event.
PreprocessDemo[SerializeField] LocalizedString m_Choice1LocalizedString;[SerializeField] LocalizedString m_Choice2LocalizedString;[SerializeField] LocalizedString m_Choice3LocalizedString;[SerializeField] LocalizedString m_Choice4LocalizedString;public void Initialize(VisualElement root){ m_DropdownField = root.Q<DropdownField>("dropdown__field"); m_Choice1LocalizedString.StringChanged += UpdateDropdownChoices; m_Choice2LocalizedString.StringChanged += UpdateDropdownChoices; // ... register other choices // Initial population UpdateDropdownChoices(null);}
void UpdateDropdownChoices(string value){ if (m_DropdownField == null) return; // Save the current selection int selection = m_DropdownField.index; // Remove previous choices m_DropdownField.choices.Clear(); // Add current localized values m_DropdownField.choices.Add(m_Choice1LocalizedString.GetLocalizedString()); m_DropdownField.choices.Add(m_Choice2LocalizedString.GetLocalizedString()); // ... Add other choices // Restore selected index and value m_DropdownField.index = selection; m_DropdownField.SetValueWithoutNotify(m_DropdownField.choices[selection]);}
SetValueWithoutNotifyLocalize assets

The flag and "Hello, world" icons represent each Locale.
Set up asset localization
style.backgroundImage- One element has its data binding defined in UXML via the UI Builder.
- Another element's binding is set up in a C# script.

The LocalizedTextures update with each Locale.
Asset Tables versus String Tables
-
Event Handling: Asset Tables use an AssetChanged event to notify changes in localized assets instead of the StringChanged event for strings.
-
Binding Methods: Both string and asset bindings work with SetBinding, but the bound properties (e.g., text for strings vs. style.backgroundImage for textures) depend on the asset type.
style.backgroundImagem_LocalizedTexture = new LocalizedTexture(){ TableReference = "DemoAssetTable", TableEntryReference = "HelloWorld_Icon"};m_IconElement = root.Q<VisualElement>("icon__hello-world");m_IconElement.SetBinding("style.backgroundImage", m_LocalizedTexture);
Common localized assets in UI Toolkit
- Localized textures: Ideal for icons, backgrounds, and other decorative visuals, these can be bound directly to visual element properties, such as .
style.backgroundImage - Localized sprites: These are less common but useful for custom components or sprite-based visuals.
- Localized fonts: These allow for switching fonts to support specific scripts or typographic styles required by different languages.
- Localized objects: These are useful for referencing complex resources, such as prefabs or data-driven assets, that need to vary based on the Locale.
Localization in the Dragon Crashers sample

Select a Locale from the Language drop-down menu.
-
SettingsScreen Locale selection: The Settings screen allows users to select a Locale via a drop-down menu. This UI listens for changes into detect new Locale selections, updating in real-time as the drop-down changes.
LocalizationSettings -
Data binding techniques: The UI features a combination of localization techniques. Static properties are bound directly in UI Builder and stored in the UXML.
- Meanwhile, dynamically populated fields rely on runtime scripts for data binding. The method connects text properties to
SetBindingobjects, ensuring the UI reflects the selected Locale.LocalizedString
- Meanwhile, dynamically populated fields rely on runtime scripts for data binding. The
-
Pre-formatted LocalizedStrings in ScriptableObjects: Some ScriptableObject assets contain pre-formattedproperties. For example, in the Settings screen, the Theme and Language drop-down fields dynamically rebuild lists from localized values, translating the available choices.
LocalizedString- Other elements like the RadioButtonGroup and custom SlideToggle also pre-process the LocalizedStrings by handling the event.
StringChanged
- Other elements like the RadioButtonGroup and custom SlideToggle also pre-process the LocalizedStrings by handling the

UI Toolkit Sample -- Dragon Crashers