<script>
NoJS.i18n({
defaultLocale: 'en',
fallbackLocale: 'en',
locales: {
en: {
greeting: 'Hello, {name}!',
items: '{count} item | {count} items', // Pluralization
nav: {
home: 'Home',
about: 'About'
}
},
'pt-BR': {
greeting: 'Olá, {name}!',
items: '{count} item | {count} itens',
nav: {
home: 'Início',
about: 'Sobre'
}
}
}
});
</script>Instead of inlining all translations in JavaScript, load them from external JSON files.
/locales/en.json
/locales/es.json
<script>
NoJS.i18n({
defaultLocale: 'en',
loadPath: '/locales/{locale}.json'
});
</script>/locales/en/common.json
/locales/en/dashboard.json
<script>
NoJS.i18n({
defaultLocale: 'en',
loadPath: '/locales/{locale}/{ns}.json',
ns: ['common'] // Loaded at init
});
</script><template route="/dashboard" src="./pages/dashboard.tpl" i18n-ns="dashboard"></template><div i18n-ns="settings">
<h2 t="settings.title"></h2>
<p t="settings.desc"></p>
</div>Fetched JSON files are cached in memory by default. Disable in development:
<script>
NoJS.i18n({ loadPath: '/locales/{locale}.json', cache: false });
</script><!-- Simple translation -->
<h1 t="greeting" t-name="user.name"></h1>
<!-- Output: "Hello, John!" or "Olá, John!" -->
<!-- Nested keys -->
<a route="/" t="nav.home"></a>
<!-- Pluralization -->
<span t="items" t-count="cart.items.length"></span>
<!-- Output: "1 item" or "5 items" -->
<!-- Switch locale -->
<button on:click="$i18n.locale = 'pt-BR'">Português</button>
<button on:click="$i18n.locale = 'en'">English</button>
<!-- Current locale -->
<span bind="$i18n.locale"></span>Add the t-html attribute to render a translation value as sanitized HTML instead of plain text.
<!-- Translation: "Read our <a href='/terms'>terms</a>" -->
<div t="legal.notice" t-html></div>The output is passed through _sanitizeHtml() to prevent XSS.
<!-- Currency -->
<span bind="price | currency"></span> <!-- $1,234.56 -->
<span bind="price | currency:'BRL'"></span> <!-- R$ 1.234,56 -->
<!-- Date -->
<span bind="createdAt | date"></span> <!-- 02/25/2026 -->
<span bind="createdAt | date:'long'"></span> <!-- February 25, 2026 -->
<span bind="createdAt | datetime"></span> <!-- 02/25/2026 3:45 PM -->
<span bind="createdAt | relative"></span> <!-- 2 hours ago -->
<!-- Number -->
<span bind="value | number"></span> <!-- 1,234.56 -->
<span bind="value | number:0"></span> <!-- 1,235 -->
<span bind="value | percent"></span> <!-- 45% -->Next: Filters & Pipes →