Skip to main content

Translations

PrismaUI F4 supports Fallout 4-style translation files and exposes loaded strings to a view through window.L10N and window.t().

In PrismaUI_F4 2.1.0, RegisterTranslations injects those helpers into the current live document through Invoke. It is not a pre-document injection hook, so call it from the view's DOM-ready callback before application code that requires translations.


File format

Translation files use the Fallout 4 UI-string format:

  • Encoding: UTF-16 LE with BOM (FF FE) is the normal release format.
  • UTF-8 is also accepted by PrismaUI for development convenience.
  • One entry per line: $KEY<tab>Translated string
  • Keys start with $
  • Lines that do not start with $ are ignored.
$CLOSE Close
$MY_MENU_TITLE My Menu
$ITEM_COUNT Items: {0}

File location

Data\Interface\Translations\<PluginName>_<lang>.txt
PartExample
PluginNameThe base name passed to RegisterTranslations, for example MyPlugin_F4
langLowercase detected language code

Example:

Data\Interface\Translations\MyPlugin_F4_en.txt

PrismaUI first tries <PluginName>_<lang>.txt. For a non-English language, it falls back to <PluginName>_en.txt when the requested language file is missing.


Language codes

Common supported codes include:

CodeLanguage
enEnglish
deGerman
frFrench
itItalian
esSpanish
esmxSpanish (Mexico)
cnChinese (Simplified)
jaJapanese
plPolish
ruRussian
ptbrPortuguese (Brazil)

C++ setup

Register translations from DOM-ready, then run whatever page initializer consumes them:

static PRISMA_UI_API::IVPrismaUI10* g_api = nullptr;
static PrismaView g_view = 0;

static void OnDomReady(PrismaView view)
{
g_api->RegisterTranslations(view, "MyPlugin_F4");
g_api->Invoke(view, "window.onTranslationsReady && window.onTranslationsReady()");
}

static void CreateMenu()
{
g_view = g_api->CreateView("MyPlugin/menu.html", OnDomReady);
if (g_view) {
g_api->Hide(g_view);
}
}

This ordering matters. In the released 2.1.0 implementation, RegisterTranslations parses the translation file, builds a JavaScript helper script, and sends that script to the view through the normal Invoke path.

Do not rely on window.t from module-level code that runs before DOM-ready.

If the page reloads and the view's DOM-ready callback fires again, register translations again for that document.


JavaScript usage

Prepare an initializer that C++ can call after RegisterTranslations:

window.onTranslationsReady = function () {
const t = (key) => window.t?.(key) ?? key;

document.getElementById('close-btn').textContent = t('$CLOSE');
document.getElementById('title').textContent = t('$MY_MENU_TITLE');
};

After successful registration:

window.t('$CLOSE');
window.L10N['$CLOSE'];

If no translation file was loaded, PrismaUI leaves those globals undefined. Always use a fallback when translations are optional:

const t = (key) => window.t?.(key) ?? key;

Example mod layout

mods/MyPlugin_F4/
├── F4SE/Plugins/
│ └── MyPlugin_F4.dll
├── PrismaUI_F4/
│ └── views/
│ └── MyPlugin/
│ └── menu.html
└── Interface/
└── Translations/
├── MyPlugin_F4_en.txt
├── MyPlugin_F4_de.txt
└── MyPlugin_F4_fr.txt

Notes

  • Keys are case-sensitive.
  • If no requested-language or English fallback file exists, window.L10N / window.t are not injected.
  • Values can contain HTML-like characters. Escape untrusted or user-controlled values before inserting them into innerHTML.
  • Use the DOM-ready callback as the synchronization point between native translation registration and JavaScript that consumes translations.