Skip to main content
The @talosjs/translation component is an internationalization layer for multi-language applications. You extend the Translation base class, point it at a dictionary, and resolve localized strings with trans(key, options), which handles dot-notation keys, {{ param }} interpolation, and count-driven pluralization. The dictionary is keyed by locale, with en as the always-present fallback, across 31 supported locale codes.

How lookups resolve

One dictionary covers every locale: each leaf carries its translations keyed by locale code (en, fr, es, …), and en is the guaranteed fallback when a target locale is missing. You reach nested entries with dot-notation keys like trans("user.profile.name"), however deep the dictionary nests. {{ param }} placeholders are filled through params, so there’s no string concatenation, and pluralization picks the right sibling key (<key>, <key>_plural, <key>_zero) from the count you pass. Register a translation class with a decorator and resolve it from the container.

How it works

You extend Translation and implement two methods: getName() returns a stable identifier for the domain, and getDict() returns the dictionary. Lookups go through has() and trans(), which resolve the requested locale, fall back to en, interpolate, and pick the right plural form. trans() accepts a TransOptionsType: Resolution order: the requested lang is tried first, then the en fallback. A missing key throws with KEY_NOT_FOUND; a key present but absent in both the locale and the en fallback throws with LOCALE_NOT_FOUND. Pluralization picks <key> when count === 1, <key>_plural when count > 1 or count < 0, and <key>_zero when count === 0 (falling back to _plural if _zero is absent). The supported locale codes are exported as locales:

Usage

Extend Translation, load a dictionary, and resolve keys through trans().
Resolve it from the container and translate keys:
The dictionary is a tree of nested keys; each leaf is an object keyed by locale code. Interpolation uses {{ param }} placeholders, and pluralization uses sibling keys selected by count:

Exceptions

The component throws TranslationException when a key cannot be resolved. It carries a machine-readable key, a human-readable message, and a data object (with the lookup key and lang).

Keeping dictionaries reliable

Always provide an en value, since it’s the fallback for every locale; a key without one throws LOCALE_NOT_FOUND whenever the target locale is missing. Group keys by domain along stable dot-notation paths like user.profile.name so dictionaries stay navigable and getName() maps cleanly to a domain. Keep placeholders verbatim: {{ name }} and {{ count }} have to appear identically across locales, with only the surrounding words changing. For pluralized keys, pass count and provide the <key>, <key>_plural, and optionally <key>_zero siblings so the correct form is selected. Translate meaning rather than words, phrasing each string the way a native speaker writing the product UI would and following the locale’s capitalization and punctuation conventions. When you complete locales, fill blanks only; keep keys stable and existing entries intact.

CLI command

Scaffold a translation class, its test file, and a sibling translations.yml dictionary with the generator. It writes the class under modules/<module>/src/translations/<Name>Translation.ts and installs @talosjs/translation if it is missing.
The generated class extends Translation and loads the sibling translations.yml as its dictionary, ready for you to fill the keys:
The sibling translations.yml is written once per folder, so translation classes in the same translations/ directory share one dictionary. See translation:create for the full command reference.

Use with Claude and Codex

The generator ships matching translation:create and translation:translate skills. The first runs the scaffold and guides your AI agent through filling the dictionary; the second translates existing dictionaries meaning-for-meaning, completing every target locale from the en source. Initialize the skills once for your agent.
Then ask Claude in natural language. It maps the request to the generator, runs it, and fills in the translations:
Prompt
For example, the prompt above maps to translation:create --name=Checkout, then fills the translations.yml dictionary with the en and fr entries for each key.