> ## Documentation Index
> Fetch the complete documentation index at: https://docs-unity.molca.id/llms.txt
> Use this file to discover all available pages before exploring further.

# Localization Implementation

> Guide to implementing multi-language support in VR scenarios using DynamicLocalization, ModalConfirmation, QuestionStep, and StepInfoDisplayAuxiliary.

**Core Concepts:**

* **DynamicLocalization** — Supports multi-language strings with automatic asset key generation
* **Localized Modals** — ModalConfirmation with DynamicLocalization and QuestionStep with localized content
* **Info Auxiliary Display** — World-space localized annotations and callouts
* **Async String Retrieval** — Using `GetLocalizedString()` for runtime localization

## When to use

Localization And Role Based Content — use this guide when implementing this interaction pattern in a VR training scenario.

## Role

This guide covers **localization and multi-language support** in VR training scenarios:

* **DynamicLocalization** — Automatic string localization with Unity Localization
* **Modal Localization** — Creating ModalConfirmation modals with multi-language support
* **Question Modal Localization** — Localizing question content and answer options
* **StepInfoDisplayAuxiliary** — Displaying world-space localized information and annotations
* **Async Localization Flow** — Properly fetching and displaying localized strings at runtime

These patterns enable training scenarios that adapt to learner language preferences while maintaining consistent UI and feedback.

## Understanding Localization in Molca

### What is DynamicLocalization?

**DynamicLocalization** is a wrapper around Unity's Localization system that:

1. **Automatically generates asset keys** based on context and field names
2. **Supports async string fetching** via `GetLocalizedString()`
3. **Works with Unity Localization tables** for multi-language content management
4. **Integrates with Editor** for easy string translation workflows

Key properties:

* **locale** — The underlying `LocalizedString` reference to the translation table
* **String** — Synchronous property for getting the current localized value (or fallback)
* **GetLocalizedString()** — Async method to fetch localized string (preferred)
* **disabled** — Flag to skip localization for optional fields

### Key Files

* `Packages/com.molca.core/Runtime/Modals/ModalConfirmation.cs` — Confirmation modal component
* `Assets/_MolcaSDK/_Core/Scripts/Localization/DynamicLocalization.cs` — Localization wrapper
* `Assets/_MolcaSDK/_VR/Scripts/Scenario/Steps/Auxiliary/StepInfoDisplayAuxiliary.cs` — Info display with localization

***

## Pattern 1: Localized Confirmation Modal

### Concept

Create a confirmation modal using **ModalConfirmation** with DynamicLocalization for multi-language title, message, and button labels.

### Core Component

**File:** `Packages/com.molca.core/Runtime/Modals/ModalConfirmation.cs`

ModalConfirmation provides a reusable confirmation dialog with:

* **titleText** — Modal headline
* **subtitleText** — Subtitle (optional)
* **mainMessageText** — Primary message content
* **detailsText** — Extended details (optional, scrollable)
* **yesButton** — Confirm action button
* **noButton** — Cancel/dismiss button

### Setup Steps

#### 1. Create Localization Strings for Confirmation

Define DynamicLocalization fields with keys for your confirmation dialog:

```
Localization Keys needed:
  - modal_confirm_title — Modal title (e.g., "Confirm Action")
  - modal_confirm_subtitle — Subtitle (optional)
  - modal_confirm_message — Main message
  - modal_confirm_details — Extended details (optional)
  - modal_confirm_yes — Confirm button text
  - modal_confirm_no — Cancel button text
```

<Frame hint="Unity Localization table showing keys for confirmation modal content with entries in multiple languages." caption="Localization Table Setup for Confirmation Modal">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/ptmolcateknologinusantara/images/features/vr/implementation/localization-confirmation-keys.png" alt="Localization table with confirmation modal keys" />
</Frame>

#### 2. Create DynamicLocalization Wrappers

In your confirmation logic (PopupStep, Step callback, or helper script), create DynamicLocalization instances:

```csharp theme={null}
// Example: In PopupStep or confirmation handler
DynamicLocalization titleLocale = new DynamicLocalization();
titleLocale.Init("modal_confirm_title", false);

DynamicLocalization messageLocale = new DynamicLocalization();
messageLocale.Init("modal_confirm_message", false);

DynamicLocalization yesButtonLocale = new DynamicLocalization();
yesButtonLocale.Init("modal_confirm_yes", false);

DynamicLocalization noButtonLocale = new DynamicLocalization();
noButtonLocale.Init("modal_confirm_no", false);
```

#### 3. Fetch Localized Strings Asynchronously

When you need to show the modal, fetch localized strings:

```csharp theme={null}
// Fetch all localized strings
string title = await titleLocale.GetLocalizedString();
string message = await messageLocale.GetLocalizedString();
string yesText = await yesButtonLocale.GetLocalizedString();
string noText = await noButtonLocale.GetLocalizedString();
```

#### 4. Setup and Show ModalConfirmation

Call `Setup()` method with localized strings and callbacks:

```csharp theme={null}
ModalConfirmation modal = GetComponent<ModalConfirmation>();
modal.Setup(
  title: title,                           // Localized title
  subtitle: "",                           // Optional
  mainMessage: message,                   // Localized message
  details: "",                            // Optional extended details
  yesText: yesText,                       // Localized "Yes"/"Confirm"
  noText: noText,                         // Localized "No"/"Cancel"
  onYes: () => { /* Handle confirmation */ },
  onNo: () => { /* Handle cancellation */ },
  showNoButton: true
);

modal.Show(); // Display modal
```

<Frame hint="ModalConfirmation showing localized title, subtitle, message, and button labels with yes/no actions." caption="Localized ModalConfirmation Setup and Display">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/ptmolcateknologinusantara/images/features/vr/implementation/modal-confirmation-localized.png" alt="ModalConfirmation with localized content" />
</Frame>

### Expected Results

* **Multi-Language Support**: Modal displays title, message, and buttons in user's current language
* **Async Localization**: `GetLocalizedString()` ensures translations are loaded before display
* **No Hard-Coded Text**: All user-facing strings come from Localization table
* **Runtime Language Switching**: App language changes are reflected on next modal display
* **Clean Callbacks**: `onYes` and `onNo` callbacks handle confirmation logic without UI concerns

### Complete Example Flow

```csharp theme={null}
public async void ShowConfirmation()
{
  // Initialize localization strings
  var titleLoc = new DynamicLocalization();
  var msgLoc = new DynamicLocalization();
  var yesBtnLoc = new DynamicLocalization();
  var noBtnLoc = new DynamicLocalization();

  titleLoc.Init("modal_confirm_title", false);
  msgLoc.Init("modal_confirm_message", false);
  yesBtnLoc.Init("modal_confirm_yes", false);
  noBtnLoc.Init("modal_confirm_no", false);

  // Fetch localized strings (async)
  string title = await titleLoc.GetLocalizedString();
  string message = await msgLoc.GetLocalizedString();
  string yesText = await yesBtnLoc.GetLocalizedString();
  string noText = await noBtnLoc.GetLocalizedString();

  // Setup and show modal
  var modal = FindObjectOfType<ModalConfirmation>();
  modal.Setup(
    title: title,
    subtitle: "",
    mainMessage: message,
    details: "",
    yesText: yesText,
    noText: noText,
    onYes: OnConfirmed,
    onNo: OnCancelled,
    showNoButton: true
  );
  modal.Show();
}

private void OnConfirmed()
{
  Debug.Log("User confirmed");
  // Execute confirmation action
}

private void OnCancelled()
{
  Debug.Log("User cancelled");
  // Execute cancellation action
}
```

### Troubleshooting

| Issue                                       | Solution                                                                                                                                                                            |
| ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Modal shows untranslated keys or blank**  | Verify DynamicLocalization.Init() called with correct key; check Unity Localization table has entry for key; ensure language supported in project; test GetLocalizedString() result |
| **Text not updating when language changes** | Modal displays localized strings at show time; change language before calling ShowConfirmation(); test with different languages                                                     |
| **Button callbacks not firing**             | Verify onYes/onNo callbacks assigned in Setup(); check buttons properly wired in Inspector; test with Debug.Log in callbacks                                                        |
| **Modal not visible**                       | Verify ModalConfirmation prefab in scene or instantiated; check Canvas is active; ensure Show() called after Setup(); test with simple non-localized modal first                    |

***

## Pattern 2: Localized Question Modal with Answers

### Concept

Create a QuestionStep modal where question text, answer options, and feedback are all multi-language.

### Setup Steps

#### 1. Create Localized QuestionData

QuestionData structure should support DynamicLocalization:

```
QuestionData:
  - questionTextLocale (DynamicLocalization) — The question prompt
  - answerOptions (array):
    - optionTextLocale (DynamicLocalization) — Each answer choice
    - isCorrect (bool)
  - feedbackCorrectLocale (DynamicLocalization) — "Correct! Well done."
  - feedbackIncorrectLocale (DynamicLocalization) — "Incorrect. Try again."
```

#### 2. Configure Question Asset

1. Create new QuestionData ScriptableObject (e.g., "SafetyProcedureQuestion")
2. Set **Question Text Locale** → Localization key (e.g., `q_safety_text`)
3. For each **Answer Option**:
   * Set **Option Text Locale** → Key (e.g., `q_safety_option_a`, `q_safety_option_b`)
   * Mark **Is Correct** on one option
4. Set **Feedback Correct Locale** → Key (e.g., `q_safety_feedback_correct`)
5. Set **Feedback Incorrect Locale** → Key (e.g., `q_safety_feedback_incorrect`)

<Frame hint="QuestionData showing question text, answer options, and feedback feedback all as DynamicLocalization fields." caption="Localized QuestionData Configuration">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/ptmolcateknologinusantara/images/features/vr/implementation/question-localized-content.png" alt="QuestionData with DynamicLocalization for question, answers, and feedback" />
</Frame>

#### 3. Add QuestionStep with Localized Content

1. Create or select a GameObject for **QuestionStep**
2. Add **QuestionStep** component
3. Configure:
   * **Trigger Mode**: `On Activated` or `Manual Trigger`
   * **Question Data Ref**: Assign localized QuestionData asset from Step 2
   * **Modal Manager Ref**: Auto-find
   * **Complete On Correct**: Enable
   * **Show Feedback**: Enable

#### 4. Modal Population Flow

QuestionStep automatically:

1. **Resolves QuestionData**
2. **Fetches localized question text** via `GetLocalizedString()`
3. **Fetches localized answer options** for each option in array
4. **Fetches feedback messages** (correct/incorrect)
5. **Populates QuestionModalUI** with all translated content

### Expected Results

* **Multi-Language Questions**: Question text displays in user's language
* **Localized Answers**: All answer option texts are translated
* **Localized Feedback**: Feedback messages ("Correct!" / "Incorrect") show in current language
* **Answer Validation**: Correct answer detection works regardless of displayed language
* **Dynamic Language Switching**: App language change updates all displayed text on next question modal

### Troubleshooting

| Issue                        | Solution                                                                                                                                     |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| **Answer options blank**     | Verify each answer option has optionTextLocale assigned; check Unity Localization table has keys for all options; test with language changed |
| **Feedback not showing**     | Verify feedbackCorrectLocale and feedbackIncorrectLocale assigned; check Show Feedback enabled in QuestionStep; test GetLocalizedString()    |
| **Wrong language displayed** | Verify active language set in Localization Settings; check all locale fields reference correct table/keys; test with multiple languages      |

***

## Pattern 3: World-Space Info Displays with Localization

### Concept

Display world-space callouts and annotations with localized text using **StepInfoDisplayAuxiliary**.

### Setup Steps

#### 1. Understand StepInfoDisplayAuxiliary

StepInfoDisplayAuxiliary creates world-space info callouts for active steps:

```
Entry (per callout):
  - target (Transform) — What to annotate
  - title (DynamicLocalization) — Callout heading
  - description (DynamicLocalization) — Callout detail text
  - useHighlight (bool) — Show mesh highlight
  - customPrefab (optional) — Custom callout UI
```

#### 2. Add StepInfoDisplayAuxiliary to Step

1. Select a Step (GrabStep, PopupStep, QuestionStep, etc.)
2. In Inspector, expand **Auxiliaries** section
3. Click **Add Auxiliary** → Select `VR/Info Display (World)`

#### 3. Configure Info Display Entries

For each callout you want:

1. **Target**: Assign Transform of the object to annotate (e.g., a button, control panel, etc.)
2. **Title**: Configure DynamicLocalization
   * Set **locale** to Unity Localization key (e.g., `info_button_label`)
   * Can disable if highlight-only desired
3. **Description**: Configure DynamicLocalization (optional detail)
   * Set **locale** to key (e.g., `info_button_description`)
   * Leave unassigned for title-only display
4. **Use Highlight**: Enable to show mesh highlight on target

<Frame hint="StepInfoDisplayAuxiliary configured with multiple entries showing localized titles and descriptions for world-space objects." caption="Localized StepInfoDisplayAuxiliary Setup">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/ptmolcateknologinusantara/images/features/vr/implementation/info-display-localized.png" alt="StepInfoDisplayAuxiliary with DynamicLocalization entries" />
</Frame>

#### 4. How It Works

When step activates:

1. **OnStepBegin()** fires
2. For each entry in StepInfoDisplayAuxiliary:
   * **Initialize** DynamicLocalization fields
   * **Fetch localized title** via `await title.GetLocalizedString()`
   * **Fetch localized description** via `await description.GetLocalizedString()`
   * **Create InfoDisplay** at target position with translated text and optional highlight
3. Callouts appear in world-space with localized annotations
4. **OnStepEnd()** removes displays

### Expected Results

* **World-Space Callouts**: Annotated objects appear with localized labels
* **Multi-Language Support**: Switching app language updates callout text
* **Highlight Feedback**: Objects show visual highlight while displaying annotations
* **Flexible Layout**: Multiple objects can be annotated with different callout text
* **Performance**: Info displays created/destroyed with step lifecycle (no extra overhead)

### Example Scenario

Step for "Inspect Control Panel":

```
Entry 1:
  target: PowerButton
  title: "Power Switch"  (key: panel_power_button)
  description: "Turn on main power"  (key: panel_power_desc)
  useHighlight: true

Entry 2:
  target: StatusLED
  title: "Status Light"  (key: panel_status_light)
  description: "Green = Ready, Red = Error"  (key: panel_status_desc)
  useHighlight: true
```

When step runs with French language selected:

* "Power Switch" → "Commutateur d'alimentation"
* "Turn on main power" → "Activez l'alimentation principale"
* "Status Light" → "Voyant de statut"
* Etc.

### Troubleshooting

| Issue                       | Solution                                                                                                                                                                                   |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Callouts not appearing**  | Verify StepInfoDisplayAuxiliary added to step; check InfoDisplayUtility in scene (auto-finds or assign); verify target transforms assigned; check UseHighlight enabled if titles are unset |
| **Text not localized**      | Verify DynamicLocalization fields have locale references; check Unity Localization table for keys; test with language changed; ensure GetLocalizedString() awaited properly                |
| **Callouts stay on screen** | Verify OnStepEnd() fires properly; check step completion logic; test step transitions in Play mode                                                                                         |

***

## Best Practices

1. **Consistent Key Naming**: Use hierarchical naming for Localization keys
   * Example: `popup_confirm_title`, `popup_confirm_message`, `popup_confirm_button_yes`
   * Helps with organization and prevents key collisions

2. **Separate Localization Assets**: Group related keys by feature
   * Keep question localization in "questions" table
   * Keep UI localization in "ui" table
   * Keep role localization in "roles" table

3. **Async Localization**: Always use `await GetLocalizedString()` in async contexts
   * Don't rely on synchronous `.String` property for dynamic content
   * Ensures translations are fully loaded before display

4. **Language Change Handling**: Test app language switching mid-scenario
   * Modals should update on next display
   * Info displays should refresh on step activation/deactivation
   * Verify no hard-coded English fallbacks leak through

5. **Fallback Text**: Provide meaningful fallback in case localization lookup fails
   * Use untranslated key as last resort (e.g., "popup\_title" shows if translation missing)
   * Don't show blank modals — always display something readable

***

## Related

* [Popup Modal Confirmation](/vr/implementation/popup-modal-confirmation) — PopupStep modal implementation
* [Question Modal Answer](/vr/implementation/question-modal-answer) — Question modal with answer validation
* [StepInfoDisplayAuxiliary](/vr/steps/vr-step-auxiliaries) — World-space info display auxiliary
* [General Interaction Patterns](/vr/implementation/general-interaction-patterns) — Combining steps and interactions
* [ModalConfirmation](/core/modals) — Base confirmation modal component
* [Unity Localization](/core/localization) — Localization system setup and management
