Skip to content

Latest commit

 

History

History
746 lines (560 loc) · 19.8 KB

File metadata and controls

746 lines (560 loc) · 19.8 KB

Usage Guide

Complete API documentation for PicoShot Localization system.

Table of Contents


Initialization

The localization system initializes automatically on startup. No manual initialization is required.

// Check if initialized
if (LocalizationManager.IsInitialized)
{
    // System is ready
}

// Manual initialization (optional, system auto initialize itself)
LocalizationManager.Initialize();

Getting System Language

Detect the user's system language and convert it to a supported language code.

// Get system language as ISO code (e.g., "en", "es", "ja")
string systemLanguage = LocalizationManager.DetectSystemLanguage();

// Direct conversion from Unity's SystemLanguage
string langCode = LanguageDefinitions.FromSystemLanguage(Application.systemLanguage);

Language Code Examples

System Language Code
English en
Spanish es
French fr
German de
Japanese ja
Chinese (Simplified) zh-hans
Arabic ar

Enumerating Available Languages

Get all languages that have translation files available at runtime.

// Get language codes only
IEnumerable<string> codes = LocalizationManager.GetAvailableLanguageCodes();
foreach (string code in codes)
{
    Debug.Log($"Available: {code}");
}

// Get display names (English names)
IEnumerable<string> names = LocalizationManager.GetAvailableLanguages();
foreach (string name in names)
{
    Debug.Log($"Available: {name}");  // e.g., "English", "Spanish"
}

// Get display names with native names
IEnumerable<string> namesWithNative = LocalizationManager.GetAvailableLanguages(withNativeNames: true);
foreach (string name in namesWithNative)
{
    Debug.Log($"Available: {name}");  // e.g., "English (English)", "Spanish (español)"
}

Check Language Availability

// Check if a specific language is available
bool hasSpanish = LocalizationManager.IsLanguageAvailable("es");
bool hasJapanese = LocalizationManager.IsLanguageAvailable("ja");

Getting Native Language Names

Display language names in their native form (e.g., "日本語" for Japanese).

// Get display name in English (default)
string englishName = LocalizationManager.GetLanguageDisplayName("ja");     // "Japanese"
string spanishName = LocalizationManager.GetLanguageDisplayName("es");     // "Spanish"

// Get native display name
string nativeJapanese = LocalizationManager.GetLanguageDisplayName("ja", native: true);  // "日本語"
string nativeSpanish = LocalizationManager.GetLanguageDisplayName("es", native: true);   // "español"

Get Language Code from Name

// Convert display name back to code
string code = LocalizationManager.GetLanguageCode("Japanese");           // "ja"
string codeNative = LocalizationManager.GetLanguageCode("日本語", nativeName: true);  // "ja"

Supported Language Properties

// Check if language is RTL (Right-to-Left)
bool isRtl = LanguageDefinitions.IsRightToLeft("ar");  // true for Arabic
bool isRtl = LanguageDefinitions.IsRightToLeft("he");  // true for Hebrew

// Get fallback language
string fallback = LanguageDefinitions.GetFallbackLanguage("en-US");  // "en"

Setting Language

Change the current language at runtime. All bound text components will update automatically.

// Set language by code
LocalizationManager.SetLanguage("es");  // Switch to Spanish
LocalizationManager.SetLanguage("ja");  // Switch to Japanese

// Set with fallback option (default: true)
// If the requested language isn't available, it will try fallback or use default
LocalizationManager.SetLanguage("en-GB", useFallback: true);

Current Language Info

// Get current language code
string current = LocalizationManager.CurrentLanguage;  // e.g., "en"

// Check if current language is RTL
bool isRtl = LocalizationManager.IsRightToLeft;  // true for Arabic, Hebrew, etc.

// Get default language from config
string defaultLang = LocalizationManager.DefaultLanguage;

Text Retrieval

Get Simple Text

// Basic translation
string text = LocalizationManager.GetText("greeting");

// With format parameters
string welcome = LocalizationManager.GetText("welcome", "Player");
string stats = LocalizationManager.GetText("stats", "100", "50");

// Translation file example:
// "welcome": "Welcome, {0}!"
// "stats": "Health: {0}, Mana: {1}"

Parameter Key Resolution

The system supports resolving parameters as localization keys using the Key struct.

// Localization data:
// "welcome": "Welcome to {0}"
// "game_name": "My Game Name"

// All of these output: "Welcome to My Game Name"

// 1. Pass literal string (no resolution)
LocalizationManager.GetText("welcome", "My Game Name");

// 2. Cast string to Key (resolves as localization key)
LocalizationManager.GetText("welcome", (Key)"game_name");

// 3. Use Key.From() method
LocalizationManager.GetText("welcome", Key.From("game_name"));

// 4. Implicit conversion from string
Key gameKey = "game_name";
LocalizationManager.GetText("welcome", gameKey);

// 5. All parameters resolved as keys (convenience method)
LocalizationManager.GetTextWithParamKeys("welcome", "game_name");

// 6. Mixed parameters - some literal, some keys
// "player_welcome": "Welcome {0}, you have {1} new messages"
// "player_name": "Hero"
LocalizationManager.GetText("player_welcome", (Key)"player_name", "5");
// Output: "Welcome Hero, you have 5 new messages"

Extension Methods

Cleaner syntax using string extensions:

// String extension for GetText
"welcome".Localized("My Game Name");           // literal
"welcome".Localized((Key)"game_name");         // key resolved

// Array extensions
string[] options = "graphics".LocalizedArray();           // GetArray
string quality = "graphics".LocalizedArrayElement(0);     // GetArrayText

Get Array Text

For translations stored as arrays (e.g., dropdown options).

// Get entire array
string[] options = LocalizationManager.GetArray("difficulty_options");
// Returns: ["Easy", "Normal", "Hard", "Expert"]

// Get specific element
string difficulty = LocalizationManager.GetArrayText("difficulty_options", 2);  // "Hard"

// Get with bounds checking (returns placeholder if out of range)
string invalid = LocalizationManager.GetArrayText("difficulty_options", 10);  // "[difficulty_options:10]"

// Using Key struct (supports implicit conversion)
string[] graphics = LocalizationManager.GetArray((Key)"graphics_options");
string quality = LocalizationManager.GetArrayText(Key.From("graphics_options"), 0);

// Extension methods
string[] difficulties = "difficulty_options".LocalizedArray();
string easy = "difficulty_options".LocalizedArrayElement(0);

Check Key Existence

// Check if key exists in current language
bool hasKey = LocalizationManager.HasKey("greeting");

// Check if key exists in default language
bool hasInDefault = LocalizationManager.HasKeyInDefault("greeting");

// Get all available keys
IEnumerable<string> allKeys = LocalizationManager.GetAllKeys();

Bind Functions (Components)

The LocalizationTextComponent automatically binds text components to the localization system.

Quick Bind Methods

The easiest way to bind text components is using the BindText methods on LocalizationManager:

TMP_Text

// Simple binding
LocalizationManager.BindText(myTextComponent, "greeting");

// With format parameters
LocalizationManager.BindText(myTextComponent, "welcome_message", args: "Player");
LocalizationManager.BindText(myTextComponent, "stats", args: new object[] { 100, 50 });

// With array index (for array-type translations)
LocalizationManager.BindText(myTextComponent, "difficulty_options", arrayIndex: 2);

// With text processor
LocalizationManager.BindText(myTextComponent, "greeting", textProcessor: text => text.ToUpper());

// Full example
LocalizationManager.BindText(
    myTextComponent,
    "welcome_message",
    arrayIndex: -1,
    textProcessor: text => $"<color=green>{text}</color>",
    args: "Player"
);

TMP_Dropdown

// Bind dropdown to array translation
LocalizationManager.BindText(myDropdown, "difficulty_options");

// Limit number of options
LocalizationManager.BindText(myDropdown, "difficulty_options", arrayMaxSize: 5);

// With text processor applied to each option
LocalizationManager.BindText(
    myDropdown,
    "menu_items",
    arrayMaxSize: 10,
    textProcessor: text => text.ToUpper()
);

Legacy Text (UnityEngine.UI.Text)

// Same API as TMP_Text
LocalizationManager.BindText(legacyText, "greeting");
LocalizationManager.BindText(legacyText, "welcome", args: "Player");
LocalizationManager.BindText(legacyText, "stats", arrayIndex: -1, args: new object[] { 100, 50 });

Legacy Dropdown (UnityEngine.UI.Dropdown)

// Same API as TMP_Dropdown
LocalizationManager.BindText(legacyDropdown, "difficulty_options");
LocalizationManager.BindText(legacyDropdown, "menu_items", arrayMaxSize: 5);

TextMesh (3D Text)

// Same API as TMP_Text
LocalizationManager.BindText(textMesh, "greeting");
LocalizationManager.BindText(textMesh, "welcome", args: "Player");
LocalizationManager.BindText(textMesh, "title", arrayIndex: 0);

Manual Component Usage

For more control, you can work with LocalizationTextComponent directly:

Properties

// Set translation key
component.TranslationKey = "welcome_message";

// For array values: get specific index (-1 for string value)
component.ArrayIndex = 2;  // Get 3rd element from array

// For dropdowns: limit number of options
component.ArraySizeLimit = 5;  // Show max 5 options

// Format parameters
component.FormatParameters = new[] { "Player", "100" };
// Or use the method:
component.SetFormatParameters("Player", "100");

// Set individual parameter
component.SetFormatParameter(0, "New Name");

Methods

// Force text update
component.UpdateText();

// Force complete refresh (re-initializes components)
component.ForceRefresh();

// Add text processor (modifies text before display)
component.AddTextProcessor(text => text.ToUpper());
component.AddTextProcessor(text => $"[ {text} ]");

// Remove processor
component.RemoveTextProcessor(myProcessor);

// Clear all processors
component.ClearTextProcessors();

Text Processors

Text processors allow you to modify the translated text before it's displayed.

// Example: Add color tags
component.AddTextProcessor(text => $"<color=green>{text}</color>");

// Example: Truncate long text
component.AddTextProcessor(text =>
    text.Length > 20 ? text.Substring(0, 17) + "..." : text);

// Example: Add prefix based on language
component.AddTextProcessor(text =>
    LocalizationManager.CurrentLanguage == "ja" ? $"【{text}】" : text);

Events

// Subscribe to text update event
component.onTextUpdated.AddListener(updatedText =>
{
    Debug.Log($"Text updated to: {updatedText}");
});

Component Type

// Check component type
TextComponentType type = component.ComponentType;
// Values: TMPText, TMPDropdown, LegacyText, LegacyDropdown, TextMesh, None

// Check if attached to dropdown
bool isDropdown = component.IsDropdown;

// Get current displayed text
string currentText = component.CurrentText;

Events

Subscribe to localization events to react to language changes.

OnLanguageChanged

Triggered when the language is changed. All localized components update automatically.

// Subscribe
LocalizationManager.OnLanguageChanged += OnLanguageChanged;

// Handler
void OnLanguageChanged()
{
    Debug.Log($"Language changed to: {LocalizationManager.CurrentLanguage}");
    // Update UI, reload textures, etc.
}

// Unsubscribe
LocalizationManager.OnLanguageChanged -= OnLanguageChanged;

OnLanguageLoadError

Triggered when there's an error loading a language file.

LocalizationManager.OnLanguageLoadError += OnLanguageError;

void OnLanguageError(string errorMessage)
{
    Debug.LogError($"Language load error: {errorMessage}");
}

OnMissingTranslation

Triggered when a translation key is not found.

LocalizationManager.OnMissingTranslation += OnMissingKey;

void OnMissingKey(string key)
{
    Debug.LogWarning($"Missing translation: {key}");
}

Advanced Usage

Manual File Operations (Editor Only)

#if UNITY_EDITOR
// Save locale data
LocalizationManager.SaveLocaleToFile(path, localeData, compress: true);

// Load locale data
LocaleData data = LocalizationManager.LoadLocaleFromFile(path);

// Get file path for language
string filePath = LocalizationManager.GetLanguageFilePath("en");

// Refresh available languages
LocalizationManager.RefreshAvailableLanguages();
#endif

Configuration Properties

// Get languages directory path
string path = LocalizationManager.LanguagesPath;

// Check anti-tamper status
bool antiTamper = LocalizationManager.IsAntiTamperEnabled;

// Get selected languages (when protection is enabled)
IReadOnlyList<string> selected = LocalizationManager.SelectedLanguages;

Cleanup

// Dispose resources (called automatically on application quit)
LocalizationManager.Dispose();

Examples

Language Selection Dropdown

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

    void Start()
    {
        // Get available languages
        var languages = LocalizationManager.GetAvailableLanguages().ToList();
        var codes = LocalizationManager.GetAvailableLanguageCodes().ToList();

        // Populate dropdown
        dropdown.ClearOptions();
        dropdown.AddOptions(languages);

        // Set current selection
        dropdown.value = codes.IndexOf(LocalizationManager.CurrentLanguage);

        // Handle selection
        dropdown.onValueChanged.AddListener(index =>
        {
            LocalizationManager.SetLanguage(codes[index]);
        });
    }
}

Dynamic Text Update

public class ScoreDisplay : MonoBehaviour
{
    [SerializeField] private LocalizationTextComponent localizedText;

    void Update()
    {
        // Update score display with current values
        localizedText.SetFormatParameters(
            ScoreManager.CurrentScore.ToString(),
            ScoreManager.HighScore.ToString()
        );
    }
}

Using BindText Methods

public class MainMenuBinder : MonoBehaviour
{
    [SerializeField] private TMP_Text titleText;
    [SerializeField] private TMP_Text playButtonText;
    [SerializeField] private TMP_Text scoreText;
    [SerializeField] private TMP_Dropdown difficultyDropdown;
    [SerializeField] private TextMesh versionText3D;

    void Start()
    {
        // Simple bindings
        LocalizationManager.BindText(titleText, "game_title");
        LocalizationManager.BindText(playButtonText, "play_button");
        LocalizationManager.BindText(versionText3D, "version_info", args: "1.0.0");

        // Score with format parameters
        UpdateScore(0, 0);

        // Dropdown with difficulty options
        LocalizationManager.BindText(difficultyDropdown, "difficulty_options", arrayMaxSize: 4);

        // Subscribe to score changes
        ScoreManager.OnScoreChanged += UpdateScore;
    }

    void UpdateScore(int current, int high)
    {
        LocalizationManager.BindText(
            scoreText,
            "score_display",
            args: new object[] { current, high }
        );
    }
}

BindText with Text Processor

public class StyledTextBinder : MonoBehaviour
{
    [SerializeField] private TMP_Text headerText;
    [SerializeField] private TMP_Text warningText;

    void Start()
    {
        // Header with color styling
        LocalizationManager.BindText(
            headerText,
            "level_header",
            textProcessor: text => $"<size=32><b>{text}</b></size>"
        );

        // Warning with color and icon
        LocalizationManager.BindText(
            warningText,
            "warning_message",
            textProcessor: text => $"<color=red>⚠ {text}</color>"
        );
    }
}

RTL Layout Adjustment

public class RtlLayoutHandler : MonoBehaviour
{
    [SerializeField] private RectTransform contentPanel;

    void Start()
    {
        LocalizationManager.OnLanguageChanged += AdjustLayout;
        AdjustLayout();
    }

    void AdjustLayout()
    {
        // Adjust anchor/pivot for RTL languages
        if (LocalizationManager.IsRightToLeft)
        {
            contentPanel.anchorMin = new Vector2(1, 0);
            contentPanel.anchorMax = new Vector2(1, 1);
            contentPanel.pivot = new Vector2(1, 0.5f);
        }
        else
        {
            contentPanel.anchorMin = new Vector2(0, 0);
            contentPanel.anchorMax = new Vector2(0, 1);
            contentPanel.pivot = new Vector2(0, 0.5f);
        }
    }
}

Using Key Resolution for Dynamic Content

public class GameMessageSystem : MonoBehaviour
{
    [SerializeField] private TMP_Text welcomeText;
    [SerializeField] private TMP_Text equipText;
    [SerializeField] private TMP_Dropdown graphicsDropdown;

    void Start()
    {
        // Localization data:
        // "welcome": "Welcome to {0}!"
        // "game_name": "Epic Adventure"
        // "player_equip": "{0} equipped {1}"
        // "player_name": "Hero"
        // "weapon_sword": "Iron Sword"
        // "graphics_options": ["Low", "Medium", "High", "Ultra"]

        // Welcome with resolved game name
        welcomeText.text = "welcome".Localized((Key)"game_name");
        // Output: "Welcome to Epic Adventure!"

        // Mixed parameters - player name as key, weapon as literal
        equipText.text = LocalizationManager.GetText(
            "player_equip",
            (Key)"player_name",  // Resolved: "Hero"
            "Wooden Staff"       // Literal
        );
        // Output: "Hero equipped Wooden Staff"

        // Using convenience method when all params are keys
        equipText.text = LocalizationManager.GetTextWithParamKeys(
            "player_equip",
            "player_name",   // Both resolved as keys
            "weapon_sword"
        );
        // Output: "Hero equipped Iron Sword"

        // Populate dropdown using array extension
        string[] options = "graphics_options".LocalizedArray();
        graphicsDropdown.ClearOptions();
        graphicsDropdown.AddOptions(options.ToList());
    }

    void ShowDynamicMessage(string messageKey, params object[] args)
    {
        // Pass mixed args directly - Key objects resolved, others treated as literals
        string message = LocalizationManager.GetText(messageKey, args);
        Debug.Log(message);
    }

    void ExampleUsage()
    {
        // Can mix types in the array
        ShowDynamicMessage(
            "reward_message",
            (Key)"player_name",     // Resolved as key
            100,                    // Converted to string "100"
            "Gold"                  // Literal string
        );
    }
}