Located at
The Localizer is used for two things: text translation and locale-aware formatting of numbers, dates and relative time.
Quick start
If you want to make localization as easy as possible, just:
- set
langto<html>, - create
window.translations = new Map(), - register the translation via
Localizer.registerTranslation(...), - create
new Localizer(...), - call
translate(),translateWithParams(),translatePlural(),formatNumber(),formatDate(), andrelativeTime().
index.html
<!doctype html>
<html lang="sk-sk">
<head>
<script>
window.translations = new Map();
</script>
<script type="module" src="/src/main.js"></script>
</head>
<body></body>
</html>
main.js
import 'wj-elements';
import { Localizer } from 'wj-elements';
Localizer.registerTranslation({
code: 'en-sk',
name: 'Slovak',
dir: 'ltr',
'app.hello': 'Hi',
'app.greeting': 'Hi {name}',
'cart.items.one': '{count} item',
'cart.items.few': '{count} items',
'cart.items.other': '{count} items',
});
const localizer = new Localizer(document.documentElement);
console.log(localizer.translate('app.hello'));
console.log(localizer.translateWithParams('app.greeting', { name: 'Ján' }));
const template = localizer.translatePlural('cart.items', 3);
console.log(template.replace('{count}', 3));
console.log(localizer.formatNumber(1234.56, {
style: 'currency',
currency: 'EUR',
}));
console.log(localizer.formatDate(new Date(), { dateStyle: 'long' }));
console.log(localizer.relativeTime(undefined, -1, 'day'));
In this example, the language is taken from <html lang="sk-sk">, the translations are registered when the application starts, and the localizer is then used anywhere in the code.
Language
Localizer searches for language in the following order:
element.langdocument.documentElement.lang- internal default
en-GB
In practice, do not rely on the default. Always set lang explicitly and use lowercase language codes such as en-eng and en-gb. Registered translations are stored lowercase, and the current implementation expects the same form.
Component
The most common pattern in the web component is:
import { Localizer, WJElement } from 'wj-elements';
export default class AppGreeting extends WJElement {
constructor() {
super();
this.localizer = new Localizer(this);
}
draw() {
const div = document.createElement('div');
div.textContent = this.localizer.translateWithParams('app.greeting', {
name: 'Ján',
});
return div;
}
}
Outside of the component, new Localizer(document.body) or new Localizer(document.documentElement) is typically used.
Setup
new Localizer()
Creates a new instance of the localizer.
| Parameter | Type | Description |
|---|---|---|
element | HTMLElement | Element | object with optional lang and dir | The element from which lang and dir are read. |
Most common use:
const appLocalizer = new Localizer(document.documentElement);
const serviceLocalizer = new Localizer(document.body);
const componentLocalizer = new Localizer(this);
registerTranslation()
Registers one or more translation objects.
| Parameter | Type | Description |
|---|---|---|
...translation | object[] | One or more objects with the code field. |
A translation object is an ordinary object:
| Field | Type | Required | Description |
|---|---|---|---|
code | string | Yes | A language code, for example en-eng, en-gb, de-de-de. |
name | string | No | Legible name of the language. |
dir | string | No | The direction of the text, usually ltr or rtl. |
| other fields | string | No | Translation keys and their values. |
Example:
window.translations = new Map();
Localizer.registerTranslation(
{
code: 'en-sk',
name: 'Slovak',
'global.save': 'Save',
},
{
code: 'en-gb',
name: 'English',
'global.save': 'Save',
}
);
Behavior:
- The
window.translationsmust exist before the first call, - if you register the same language multiple times, the keys will be merged,
- if the new object contains an existing key, overwrites it,
- if the object does not have a
code, an error is printed to the console.
localizer.setLanguage()
Re-evaluates the active language according to localizer.lang.
Use it after you change the lang while the application is running.
document.documentElement.lang = 'en-gb';
localizer.lang = 'en-gb';
localizer.setLanguage();
convertLangCode()
Converts frontend language code to a form that is often used in API data.
localizer.convertLangCode('en-sk');
// en_SK
Practical example:
const apiKey = localizer.convertLangCode(localizer.currentLang);
const label = item.name?.values?.[apiKey];
Translations
translate()
Returns the translation for the given key.
| Parameter | Type | Description |
|---|---|---|
key | string | Translation key. |
If the key does not exist, the original key is returned.
localizer.translate('app.hello');
// 'hello'
translateWithParams()
Translates the text and adds placeholders in the format {name}.
| Parameter | Type | Default value | Description |
|---|---|---|---|
key | string | - | Translation key. |
params | Record<string, unknown> | {} | Values for placeholders. |
Behavior:
- placeholder is replaced if the value exists,
- the value is converted to a string,
- if the value is missing or
null, the placeholder remains unchanged.
localizer.translateWithParams('app.greeting', {
name: 'Jan',
});
// 'Hi Jan'
translatePlural()
Selects the correct pluralization form via Intl.PluralRules.
| Parameter | Type | Default value | Possible values | Description |
|---|---|---|---|---|
key | string | - | - | Basic key without suffix. |
count | number | 0 | any number | The number by which the shape is selected. |
type | string | 'cardinal' | 'cardinal', 'ordinal' | Type of pluralization. |
The method looks for keys in the shape:
<key>.zero<key>.one<key>.two<key>.few<key>.many<key>.other
If the exact shape does not exist, it uses the fallback <key>.other.
const template = localizer.translatePlural('cart.items', 3);
const text = template.replace('{count}', 3);
// '3 items'
translatePlural() just selects the correct string. If you have placeholders such as {count} in the text, fill them in yourself.
Formatting
formatNumber()
The function for numbers is called formatNumber() in the API. There is no separate translateNumber().
Formats the number via Intl.NumberFormat.
| Parameter | Type | Description |
|---|---|---|
number | number | Number for formatting. |
options | Intl.NumberFormatOptions | Formatting options. |
The most common choices:
| Option | Possible values |
|---|---|
style | 'decimal', 'currency', 'percent', 'unit' |
currency | for example 'EUR', 'USD' |
currencyDisplay | 'code', 'symbol', 'narrowSymbol', 'name' |
currencySign | 'standard', 'accounting' |
unit | for example 'byte', 'kilobyte', 'meter', 'celsius' |
unitDisplay | 'short', 'long', 'narrow' |
notation | 'standard', 'scientific', 'engineering', 'compact' |
compactDisplay | 'short', 'long' |
signDisplay | 'auto', 'never', 'always', 'exceptZero', 'negative' |
useGrouping | true, false, 'auto', 'always', 'min2' |
minimumIntegerDigits | number |
minimumFractionDigits | number |
maximumFractionDigits | number |
minimumSignificantDigits | number |
maximumSignificantDigits | number |
roundingPriority | 'auto', 'morePrecision', 'lessPrecision' |
roundingIncrement | 1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000 |
roundingMode | 'ceil', 'floor', 'expand', 'trunc', 'halfCeil', 'halfFloor', 'halfExpand', 'halfTrunc', 'halfEven' |
trailingZeroDisplay | 'auto', 'stripIfInteger' |
Examples:
localizer.formatNumber(1234.56, {
style: 'currency',
currency: 'EUR',
});
localizer.formatNumber(2048, {
style: 'unit',
unit: 'kilobyte',
unitDisplay: 'short',
});
formatDate()
Formats the date via Intl.DateTimeFormat.
| Parameter | Type | Description |
|---|---|---|
date | `string \ | Date \ |
options | Intl.DateTimeFormatOptions | Formatting options. |
The most common choices:
| Option | Possible values |
|---|---|
dateStyle | 'full', 'long', 'medium', 'short' |
timeStyle | 'full', 'long', 'medium', 'short' |
weekday | 'long', 'short', 'narrow' |
era | 'long', 'short', 'narrow' |
year | 'numeric', '2-digit' |
month | 'numeric', '2-digit', 'long', 'short', 'narrow' |
day | 'numeric', '2-digit' |
dayPeriod | 'narrow', 'short', 'long' |
hour | 'numeric', '2-digit' |
minute | 'numeric', '2-digit' |
second | 'numeric', '2-digit' |
fractionalSecondDigits | 1, 2, 3 |
hour12 | true, false |
hourCycle | 'h11', 'h12', 'h23', 'h24' |
timeZone | for example 'Europe/Bratislava', 'UTC' |
timeZoneName | 'short', 'long', 'shortOffset', 'longOffset', 'shortGeneric', 'longGeneric' |
calendar | for example 'gregory' |
numberingSystem | For example, 'latn', 'arab' |
localeMatcher | lookup, best fit |
formatMatcher | 'basic', 'best fit' |
Examples:
localizer.formatDate(new Date(), {
dateStyle: 'long',
});
localizer.formatDate('2026-03-29T15:45:00Z', {
dateStyle: 'short',
timeStyle: 'short',
timeZone: 'Europe/Bratislava',
});
relativeTime()
Formats the relative time via Intl.RelativeTimeFormat.
| Parameter | Type | Default value | Possible values | Description |
|---|---|---|---|---|
lang | string | this.currentLang | locale code or undefined | Output language. |
value | number | 0 | negative and positive numbers | A shift in time. |
unit | string | 'day' | 'year', 'years', 'quarter', 'quarters', 'month', 'months', 'weeks', 'weeks', 'day', 'days', 'hour', 'hours', 'minutes', 'minutes', 'seconds' | Unit of time. |
options | Intl.RelativeTimeFormatOptions | { numeric: 'auto' } | see below | Formatting options. |
Options options:
| Option | Possible values |
|---|---|
numeric | 'always', 'auto' |
style | 'long', 'short', 'narrow' |
localeMatcher | lookup, best fit |
Examples:
localizer.relativeTime(undefined, -1, 'day');
// for example 'yesterday'
localizer.relativeTime('en-gb', 3, 'week', {
numeric: 'always',
style: 'short',
});
// 'in 3 wk.
The first parameter is lang. To use the current language of the localizer, send undefined, null or an empty string.