PVR
GitHub

Internationalization

How runtime translation works via data-i18n attributes and JSON locale files.

2 min read
Updated June 20, 2026

The kit translates text at runtime — no rebuild needed. You mark elements with data-i18n attributes, and the engine in app.js swaps in the right string for the current language.

Marking text

<!-- Element text (default target) -->
<h5 data-i18n="roleMaster.mainPanelTitle">Role Master</h5>
 
<!-- Attribute targets via data-i18n-target -->
<input data-i18n="header.searchPlaceholder" data-i18n-target="placeholder">
<button data-i18n="panelCard.refresh" data-i18n-target="title" title="Refresh">…</button>

The text inside the element is the fallback shown if a translation is missing.

data-i18n-target values

TargetEffect
(omitted)Sets the element's text content.
htmlSets innerHTML (use for strings with markup).
placeholderSets the placeholder attribute.
titleSets the title attribute (tooltips).
aria-labelSets the aria-label attribute.
valueSets a form control's value.

Parameters

<span data-i18n="greeting" data-i18n-params='{"name":"John"}'></span>
{ "greeting": "Hello, {name}!" }

Key naming: file.key

A data-i18n value is {file}.{key}:

  • file = the JSON file name (which matches the page name).
  • key = a flat, camelCase key inside that file.

So roleMaster.mainPanelTitle reads the mainPanelTitle key from roleMaster.json.

Where the strings live

assets/locales/
├── en/                  English
│   ├── manifest.json    lists which JSON files to load
│   ├── header.json
│   ├── roleMaster.json
│   └── … (one file per page/section)
├── fr/  de/  es/  pt/  zh/  ja/  nl/   other languages (same file names)

Each JSON file is flat key/value pairs in camelCase:

{
  "mainPanelTitle": "Role Master",
  "mainPanelSubtitle": "Manage user roles and permissions",
  "columnRole": "Role",
  "columnStatus": "Status"
}

Bundled languages

en, fr, de, es, pt, zh, ja, nl — eight languages. Each has its own folder under assets/locales/ with the same set of JSON files. The in-page language switcher in the header lets users change language; you can also switch in code:

window.i18n.setLocale('fr');

Editing or adding text

  • Change wording: edit the value in the relevant JSON file (in each language folder you support). The page picks it up on next load.
  • Add a new string: add the key to the JSON file, then reference it with data-i18n="file.key" in the HTML.
  • Add a new page's strings: create assets/locales/en/<page>.json, then add its file name to assets/locales/en/manifest.json so the engine loads it. (The manifest.json in each language folder lists the files to fetch.)

Translations are loaded with fetch(). When opening pages from file://, some browsers block those requests and you'll see raw keys instead of text — serve the folder over HTTP (see 01 — Getting started).

Reference

  • data-i18n="file.key" — translate text.
  • data-i18n-target="placeholder|title|html|…" — translate an attribute.
  • data-i18n-params='{"name":"…"}' — interpolate values.
  • window.i18n.setLocale(code) / getLocale() / t(key) — runtime control (see 08 — JavaScript).

Was this page helpful?