Getting Started with Unity Localization: Bringing Your Game to a Global Audience

Created: 2026-02-05Last updated: 2026-10-10

Learn how to localize your game with Unity's official Localization package. Covers localizing text, images, and audio, plus dynamic text with Smart Strings.

"I'd love to release this game internationally someday..." When that thought crosses your mind, the first hurdle you face is localization. Have you ever pictured a future where you scatter if (language == "en") branches across every screen—and quietly closed that thought away?

The Unity Localization package is Unity's official solution for multilingual support. It manages text, images, audio, fonts, and more per language, and lets you switch between them at runtime. It also integrates with CSV files and Google Spreadsheets, making collaboration with translators seamless.

Tested with: Unity 6 (6000.x), Localization 1.5

Concept of localization: speech bubbles in many languages float around a globe and switch with the toggle below it

What You'll Learn

  • The core concepts of the Localization package (Locale, String Table, Asset Table)
  • Language selection at startup (Locale Selector priority, saving with PlayerPrefs)
  • How to localize text, images, and fonts
  • Smart Strings (variable insertion and plurals)
  • Translation workflows with CSV / Google Spreadsheets integration

Sponsored

Core Concepts

ConceptDescription
LocaleA combination of language and region (e.g., en-US, ja-JP)
String TableA container that manages text per language
Asset TableA container that manages images, audio, and other assets per language
Locale SelectorThe mechanism that decides which Locale to use
Smart StringsA feature for localizing dynamically changing strings

The key idea is a "per-language substitution table". Text goes into a String Table, and images and audio go into an Asset Table; your UI only ever references the keys in those tables.

Diagram of the core Localization concepts: for each Locale such as ja-JP or en-US, a String Table manages text and an Asset Table manages images and audio, and the game screen receives the content of the currently selected language

Installation

Install the package from the Package Manager.

  1. Select Window > Package Manager (in Unity 6.1 and later, Window > Package Management > Package Manager)
  2. Choose Unity Registry in the list on the left
  3. Find and select Localization in the list
  4. Click the Install button in the bottom right

Setup

Creating the Localization Settings

  1. Select Edit > Project Settings > Localization
  2. Click the Create button
  3. Choose where to save the asset

Creating Locales

  1. Click the Add Locale button in the Localization Settings window (older versions called it Locale Generator)
  2. Check the languages you want to support (e.g., English, Japanese)
  3. Click the Add Locales button

Locale Selector: Choosing a Language at Startup

The Locale Selector is the mechanism that decides which language to use when the app starts.

Adding the Player Pref Locale Selector

A newly created Localization Settings asset already contains three selectors: Command Line Locale Selector → System Locale Selector → Specific Locale Selector. That's enough to start in the device's language. To reuse the language the player chose next time, add the Player Pref Locale Selector.

  1. Open Edit > Project Settings > Localization
  2. Click + in the Locale Selectors section
  3. Add a Player Pref Locale Selector
  4. Drag it to the top (selectors are evaluated from top to bottom)

Startup Selector Priority

SelectorDescription
Command Line Locale SelectorSpecifies the language via command-line arguments (for debugging)
System Locale SelectorUses the device's language settings
Specific Locale SelectorForces a specific language
Player Pref Locale SelectorSaves and restores the language chosen by the user

Recommended setup: Put the Player Pref Locale Selector first, followed by the System Locale Selector, and finally a Specific Locale Selector (as a fallback). The language is then resolved in this order: user choice → system language → default language.

Priority flow for deciding the language at startup: 1. if the Player Pref Locale Selector has the language chosen last time, decide on it; 2. otherwise the System Locale Selector uses the device language if available; 3. otherwise the Specific Locale Selector decides on the default language

Saving the Language with the Player Pref Locale Selector

With a Player Pref Locale Selector in place, all your code needs to do is change SelectedLocale. The Selector records the choice when it changes and restores it on the next launch.

using UnityEngine;
using UnityEngine.Localization.Settings;

public class LanguageSettings : MonoBehaviour
{
    // Change the language (with a Player Pref Locale Selector, saving and restoring are automatic)
    public void SetLanguage(string localeCode)
    {
        var locale = LocalizationSettings.AvailableLocales.GetLocale(localeCode);
        if (locale != null)
        {
            LocalizationSettings.SelectedLocale = locale;
        }
    }
}

Warning (use one saving mechanism): the Player Pref Locale Selector saves the language under the key selected-locale. If you add your own separate save like PlayerPrefs.SetString("selected_language", ...), the two stored values can disagree, and a different language gets picked after a restart. Consolidate saving into the Selector; treat hand-rolled saving as the fallback for projects that don't use one.

Sponsored

Localizing Text

Creating a String Table

  1. Open Window > Asset Management > Localization Tables
  2. Click the New Table Collection button at the top
  3. Set Type to String Table Collection
  4. Enter a table name in Name (e.g., UI Texts)
  5. Click the Create button

Localizing UI Text

  1. Select a GameObject with a TextMeshPro component
  2. In the Inspector, right-click the TextMeshPro component's header and choose Localize (this adds a Localize String Event and wires it to the text automatically)
  3. Choose the table and entry in String Reference
Right-clicking the TextMeshPro header and choosing Localize adds a Localize String Event, with Update String already wired to the text

If you add a Localize String Event by hand with Add Component, you must register the TextMeshPro in Update String and pick text. Until it's wired, switching languages doesn't change what's displayed.

Localizing from a 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").Task;
            Debug.Log(localizedString);
        }
        catch (System.Exception e)
        {
            Debug.LogError($"Localization failed: {e.Message}");
        }
    }
}

A word of caution about async void: Exceptions thrown in async void methods do not propagate to the caller, so always handle errors with try-catch. For production projects, consider a UniTask- or Coroutine-based implementation instead.

Localizing Assets

Creating an Asset Table

  1. Open Window > Asset Management > Localization Tables
  2. Click the New Table Collection button and set Type to Asset Table Collection
  3. Enter a table name in Name (e.g., Game Assets)
  4. Click the Create button

Using Localization Scene Controls

  1. Open Window > Asset Management > Localization Scene Controls
  2. Set the Asset Table Collection you created in Asset Table
  3. Turn on Track Changes
  4. Switch languages with Active Locale and assign the assets in your scene for each language

Switching Fonts

When you need different fonts per language—for example, switching between Japanese and English—use an Asset Table.

Managing Fonts with an Asset Table

  1. Create an Asset Table Collection (e.g., Fonts) with an entry (e.g., ui_font)
  2. Register a TextMeshPro Font Asset (TMP_FontAsset) for each language
  3. Swap the font when the language changes with the script below (TextMeshPro has no built-in font-switching component)
using TMPro;
using UnityEngine;
using UnityEngine.Localization;

public class LocalizedFontExample : MonoBehaviour
{
    [SerializeField] private TMP_Text textComponent;
    [SerializeField] private LocalizedAsset<TMP_FontAsset> font = new LocalizedAsset<TMP_FontAsset>(); // Pick Fonts / ui_font in the Inspector

    // Subscribing starts the first load, and it fires again whenever the language changes
    void OnEnable() => font.AssetChanged += ApplyFont;
    void OnDisable() => font.AssetChanged -= ApplyFont;

    void ApplyFont(TMP_FontAsset value)
    {
        textComponent.font = value;
    }
}

TextMeshPro Fallback Fonts

For CJK (Chinese, Japanese, Korean) support, configuring fallback fonts is essential.

  1. Select your main font asset
  2. Open Fallback Font Assets in the Inspector
  3. Add a Japanese (or other CJK) font asset

Font Asset Creator: To use Japanese fonts with TextMeshPro, you need to create a Font Asset containing Japanese characters via Window > TextMeshPro > Font Asset Creator. Set a font that includes Japanese as the Source Font File, and specify the characters you use with a Character Set option such as Characters from File.

Sponsored

Smart Strings

Smart Strings localize text that changes dynamically. They are based on the SmartFormat library. To use them, turn on Smart for each entry in the Localization Tables window.

Inserting Variables

Here is a Japanese entry that means "Hello, {player_name}!":

こんにちは、{player_name}さん!

Handling Plurals

Japanese has no grammatical plural, so the Japanese entry simply inserts the variable.

Japanese entry (meaning "{count} items"):

{count}個のアイテム

English:

{count} {count:plural:item|items}

Smart Strings syntax follows the SmartFormat library. Because plural rules differ between languages, each language needs its own configuration.

Setting Variables from a Script

using UnityEngine;
using UnityEngine.Localization.Components;

public class SmartStringExample : MonoBehaviour
{
    [SerializeField] private LocalizeStringEvent localizeStringEvent;

    void Start()
    {
        // Set variables via Arguments (recommended)
        localizeStringEvent.StringReference.Arguments = new object[] { 5 };
        localizeStringEvent.RefreshString();
    }
}

Smart Strings variables: Use placeholders like {0} and {1}; values are assigned in the order of the Arguments array. For a named variable like {count} above, add a name and a value, as in localizeStringEvent.StringReference.Add("count", new IntVariable { Value = 5 }) (IntVariable lives in UnityEngine.Localization.SmartFormat.PersistentVariables).

Practical: Building a Language Dropdown

An RPG's options screen, a puzzle game's settings, a visual novel's title—every multilingual game has a "language" dropdown somewhere. Let's assemble the parts we've covered so far (Locale, Player Pref Locale Selector) into this classic piece of UI.

Example of a language dropdown: choosing Japanese switches the screen to Start and Quit written in Japanese; choosing English switches to Start/Quit. The choice is saved to PlayerPrefs and restored next time

Line up the available Locales in a TMP_Dropdown and switch on selection.

using System.Collections;
using UnityEngine;
using UnityEngine.Localization.Settings;
using TMPro;

public class LanguageDropdown : MonoBehaviour
{
    [SerializeField] private TMP_Dropdown dropdown;

    IEnumerator Start()
    {
        // Wait until initialization finishes (it can be uninitialized right after launch)
        yield return LocalizationSettings.InitializationOperation;

        // Populate the dropdown with the available Locales
        dropdown.ClearOptions();
        var locales = LocalizationSettings.AvailableLocales.Locales;
        foreach (var locale in locales)
        {
            dropdown.options.Add(new TMP_Dropdown.OptionData(locale.LocaleName));
        }

        // Select the current language and sync the displayed value
        dropdown.value = locales.IndexOf(LocalizationSettings.SelectedLocale);
        dropdown.RefreshShownValue();

        // Switch the language when the selection changes
        dropdown.onValueChanged.AddListener(index =>
        {
            LocalizationSettings.SelectedLocale = locales[index];
            // With a Player Pref Locale Selector configured, the choice is saved and restored automatically
        });
    }
}

There are two key points.

  • Switching is a single assignment to SelectedLocale: every text driven by a Localize String Event is replaced across the whole screen once loading finishes. You don't need to write per-UI update code.
  • Leave saving to the Player Pref Locale Selector: if you set the Player Pref Locale Selector to top priority back in the Locale Selector section, both saving the choice and restoring it on the next launch happen automatically. Writing your own PlayerPrefs.SetString is the fallback for when you don't use a Selector.

Testing

Switching Languages in the Game View

  1. In Play Mode, a language dropdown (Locale Game View Menu) appears at the top of the Game View (if it doesn't, check that it's enabled in Edit > Preferences > Localization; it never appears in a build)
  2. Click it to switch languages
  3. Changes are reflected in real time, even in Play Mode

The Preview Window

  1. Open Window > Asset Management > Localization Tables
  2. Select a table
  3. Click an entry to display the Preview
  4. Check how it renders in each language

Testing from a 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

Managing Tables with CSV

Exporting to CSV

  1. Select a table in the Localization Tables window
  2. Choose CSV... from the Export menu at the top of the window

Importing from CSV

  1. Select a table in the Localization Tables window
  2. Choose CSV... from the Import menu at the top of the window (to keep existing entries and add to them, CSV(Merge)...)
Translation workflow diagram: export a Unity String Table to CSV, hand it to a translator, then import the translated CSV back—a round trip

Google Spreadsheets Integration

The Google Spreadsheets Service makes collaboration with translators even smoother.

Setup Steps

Google Sheets support ships inside the Localization package, so no extra package is needed.

  1. In the Google Cloud Console, enable the Google Sheets API and create an OAuth client ID (desktop app)
  2. In Unity, choose Assets > Create > Localization > Google Sheets Service to create the service asset
  3. On that asset, choose OAuth as the authentication type, load the client ID's credentials (JSON), and click Authorize
  4. In the String Table Collection's Inspector, add a Google Sheets Extension with the + under Extensions, point it at your spreadsheet, and Push / Pull

Important (handling the credentials): the OAuth client's credentials (JSON) are a secret. Never commit it to a Git repository (add it to .gitignore; this matters doubly for public repos). If it leaks, third parties can operate your Google account's resources.

More details: For the full Google Spreadsheets integration procedure, refer to the official Unity documentation.

Addressables Integration

Impact on Build Size

When you add multilingual support, the text and assets for every language are included in the build, which can significantly increase build size. This is especially noticeable when:

  • You support a large number of languages
  • You use a different font for each language
  • You localize large assets such as audio or textures

The Localization package already runs on top of Addressables. Locales, String Tables, and Asset Tables are registered in Addressables groups the moment you create them. For large projects, changing those groups' settings lets players download only the languages they need. The mechanics of Addressables itself are covered in Getting Started with Addressables.

How to Set It Up

  1. Open Window > Asset Management > Addressables > Groups
  2. Find the per-language groups (names such as Localization-String-Tables- followed by the language name)
  3. Switch the groups for languages you want to download later to Remote (loaded from a server; see the remote content article)

Benefits

  • Smaller downloads: Load only the languages you need
  • On-demand loading: Fetch only the required assets when switching languages
  • Remote delivery: Supports distributing language packs from a CDN

Summary

The Unity Localization package is a powerful tool for making your Unity project multilingual.

  • Localize text, images, and audio - Managed with String Tables and Asset Tables
  • Smart Strings - Localize dynamic strings naturally, following each language's grammar
  • CSV / Google Spreadsheets integration - Smooth collaboration with translators
  • Addressables integration - Load only the languages you need and cut download size

If you are aiming for the global market, the Unity Localization package is well worth adopting. Which language region will your game reach next?

Further Learning

Read nextOn to Build
Build

Unity Build Basics: Exporting Your Game for PC, Web, and Mobile

Read this note
Unity Notes in this section100