Skip to main content

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.

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

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

  • Assets/_Molca/_Core/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: Assets/_Molca/_Core/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

Unity Localization table showing keys for confirmation modal content with entries in multiple languages.

Localization table with confirmation modal keys

2. Create DynamicLocalization Wrappers

In your confirmation logic (PopupStep, Step callback, or helper script), create DynamicLocalization instances:
// 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:
// 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:
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

ModalConfirmation showing localized title, subtitle, message, and button labels with yes/no actions.

ModalConfirmation with localized content

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

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

IssueSolution
Modal shows untranslated keys or blankVerify 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 changesModal displays localized strings at show time; change language before calling ShowConfirmation(); test with different languages
Button callbacks not firingVerify onYes/onNo callbacks assigned in Setup(); check buttons properly wired in Inspector; test with Debug.Log in callbacks
Modal not visibleVerify 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)

QuestionData showing question text, answer options, and feedback feedback all as DynamicLocalization fields.

QuestionData with DynamicLocalization for question, answers, and feedback

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

IssueSolution
Answer options blankVerify each answer option has optionTextLocale assigned; check Unity Localization table has keys for all options; test with language changed
Feedback not showingVerify feedbackCorrectLocale and feedbackIncorrectLocale assigned; check Show Feedback enabled in QuestionStep; test GetLocalizedString()
Wrong language displayedVerify 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

StepInfoDisplayAuxiliary configured with multiple entries showing localized titles and descriptions for world-space objects.

StepInfoDisplayAuxiliary with DynamicLocalization entries

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

IssueSolution
Callouts not appearingVerify 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 localizedVerify DynamicLocalization fields have locale references; check Unity Localization table for keys; test with language changed; ensure GetLocalizedString() awaited properly
Callouts stay on screenVerify 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