Enterprise applications often necessitate translation capabilities. Given the vastness of our world and its linguistic diversity, companies operating across multiple nations are typically expected to offer multilingual support. Generally, you only need to retain one language in memory, determined by the user’s preference. The binding engine doesn’t handle the storage of terms for every available language. Instead, it provides a method to enlist these terms in a lookup table. This empowers users to introduce any essential translation to the binding engine. The origin of this data is at the user’s discretion. The binding engine merely expects the keys in binding expressions to be registered prior to the initiation of the parsing phase. In the following segment, we’ll delve into the translations manager facilitated by crs-binding.

class TranslationsManager {
  async function add(obj, context);
  async function delete(context);
  async function get(key);
  async function getWithMarkup(key);
  async function parseElement(element);
  async function parseAttribute(attribute);

As you can see there are a number of key components.

  • Internal glossary for storing translations.
  • Methods for creating, modifying, removing, and retrieving translations in the glossary.
  • Parsing tools that examine elements and attributes, modifying their content if they have translation annotations.

There are two ranges for translations.

  1. Universal – meant for generic translations accessible throughout the application. Such as common terms like “Save,” “New,” and “Delete” that appear consistently across the application irrespective of the present context.
  2. Component-specific – these translations are tailored to a particular view or component. They remain pertinent only when that specific view or component is active. To optimize memory usage, these translations can be discarded once the context is no longer active. Typically, the translation path begins with the context identifier.

While incorporating translations, you provide a dictionary that encompasses the translations, organizing them in a structure that is logical to you. Moreover, you have the option to specify a context string if applicable. Be mindful that introducing a context will also influence the pathway utilized to retrieve the translation.

The way you organize the translations will dictate the string pathway utilized to retrieve the corresponding translation value, akin to a property path.

// Universal example without context
await crs.binding.translations.add({
    buttons: {
        save: "Save"

// Component-spesific with context
await crs.binding.translations.add({
    labels: {
        code: "Code"
}, "ctx");

You can access these translations using code.

const saveValue = await crs.binding.translations.get("");

// note the context prefix "ctx" in the path.
const codeValue = await crs.binding.translations.get("ctx.labels.code");

These translations can also be applied in binding expressions.

// use only the translation value

// embed the translation value within a more extensive string.
<label for="edtCode">&{ctx.labels.code} input</label>

It’s important to highlight that the markup for translations differs from typical binding expressions. While standard expressions employ ${} with a dollar sign, translations utilize &{}. This distinction clearly differentiates between a property path meant for binding and one intended for translations. Due to this differentiation, you have the flexibility to amalgamate both within a more comprehensive string if necessary.


“&{}: ${person.firstName} ${person.lastName}”

would translate to

“Name: John Doe”.

Only context-specific translations have a temporary duration within the application, making them the sole type that can be removed from the translations manager. To eliminate all translations of that context, the delete method requires the context name that was initially used during the addition process.

await crs.binding.translations.delete("ctx")