On this page

All pages






Overview

For consistency across all of the Totara products, the front end experience produced by Tui needs to be fully translatable.

In order to achieve this without introducing duplication we use the existing translation system within Totara Core.

Implementation

The Tui component exposes an i18n (internationalisation) module and integrates with the Tui framework in order to support translatable strings within Tui components.

Requiring strings within a component

Tui has defined a custom <lang-strings> block that can appear in a single component file.

Strings you want to use must be declared upfront in the <lang-strings> block, and will be loaded ahead of time, before the component is mounted.

Strings can be retrieved and formatted in the template using $str(), which is also available in the script block as this.$str().

In order for strings in imported components to work, each imported component used by a component must be declared within the components: {} section, even if you are using <component :is="" />If that isn't possible, you can load the component as an async component, or call tui.loadRequirements() with the component definition to load strings.

If you have a requirement to load strings outside of the regular <lang-strings> block definition, you can use the langString() and loadLangStrings() APIs from tui/i18n.

Synchronous example

The following is a basic example illustrating how to require a string in the lang-strings block, and how to use the string within the template block.

<template>
  <p>Hello, {{ $str('localised', 'totara_tui') }} world.</p>
</template>

<lang-strings>
{
  "totara_tui": [
    "localised"
  ]
}
</lang-strings>

Asynchronous example

This is how things look if you have a component that is loaded asynchronously.

ComponentA.vue
<template>
  <p>{{ $str('first_component, 'totara_tui' }}</p>
  <component :is="dynamicVar" />
</template>
<script>
export default {
  data() {
    return { dynamicVar: null };
  },
  mounted() {
    this.dynamicVar = tui.asyncComponent('path/to/ComponentB');
  }
};
</script>
<lang-strings>
{ "totara_tui": ["first_component"] }
</lang-strings>
ComponentB.vue
<template>
  <p>{{ $str('second_component, 'totara_tui' }}</p>
</template>
<script>
<lang-strings>
{ "totara_tui": ["second_component"] }
</lang-strings>

Manual loading example

If you need to load language strings manually, you can do something like this:

<template>
  <p>{{ text }}</p>
</template>
<script>
import { langString, loadLangStrings } from 'tui/i18n';

export default {
  data() {
    return { text: null };
  },
  async mounted() {
    const str = langString('manual_text', 'totara_tui');
    await loadLangStrings([str]);
    this.text = str.toString();
  }
};
</script>

API

this.$str(key, component, [param])

Get a localised string. In development mode, this will log a warning to the console if the string was not declared in <lang-strings>.

this.$tryStr(key, component, [param])

Get a localised string. If the string is not loaded, returns null. This method does not check for the presence of the string in <lang-strings>.

this.$hasStr(key, component)

Check if the provided string has been loaded.

Tips and known limitations

  • You will likely need to purge caches to get new language strings to show up.
  • Don't use language strings from other Totara components that your plugin does not specify as a requirement.