Skip to content

t

Finds the translation message and fills its arguments with the provided data.

gts
import type { TOC } from '@ember/component/template-only';
import { t } from 'ember-intl';

interface HelloSignature {
  Args: {};
}

const Hello: TOC<HelloSignature> = <template>
  {{t "hello.message"}}
</template>;

export default Hello;
yaml
hello.message: Hallo!
yaml
hello.message: Hello!

Pass data

We use the ICU message syntax to pass data to a translation. Data can also be formatted if you specify their type in the translation.

gts
import type { TOC } from '@ember/component/template-only';
import { t } from 'ember-intl';

interface HelloSignature {
  Args: {};
}

const Hello: TOC<HelloSignature> = <template>
  {{t "hello.call-by-name" name="Zoey"}}
</template>;

export default Hello;
yaml
# A simple argument
hello.message: Hallo, {name}!
yaml
# A simple argument
hello.message: Hello, {name}!

Named vs. positional

You can pass data to the t helper using named arguments, the 2nd positional argument, or a combination of named and positional. In the combined case, data passed as named arguments will take precedence.

gts
import type { TOC } from '@ember/component/template-only';
import { hash } from '@ember/helper';
import { t } from 'ember-intl';

interface PhotoAlbumSignature {
  Args: {};
}

const PhotoAlbum: TOC<PhotoAlbumSignature> = <template>
  <div>
    {{! Use a named argument }}
    {{t "photo-album.summary" numPhotos=3}}
  </div>

  <div>
    {{! Use the 2nd positional argument }}
    {{t "photo-album.summary" (hash numPhotos=3)}}
  </div>
</template>;

export default PhotoAlbum;
yaml
# A plural-type argument
photo-album.summary: "Du hast {numPhotos, plural, =0 {keine Fotos} =1 {ein Foto} other {# Fotos}}."
yaml
# A plural-type argument
photo-album.summary: "You have {numPhotos, plural, =0 {no photos} =1 {one photo} other {# photos}}."

What to avoid

IMPORTANT

When a translation's argument is missing its value, @formatjs/intl will throw a FORMAT_ERROR error. Even when you ignore this error, @formatjs/intl will return the raw message, instead of trying to fill the arguments.

Suppose <PhotoAlbum> now allows an optional argument @numPhotos. Your users will see the raw message when @numPhotos is undefined.

gts
import type { TOC } from '@ember/component/template-only';
import { t } from 'ember-intl';

interface PhotoAlbumSignature {
  Args: {
    numPhotos?: number;
  };
}

const PhotoAlbum: TOC<PhotoAlbumSignature> = <template>
  {{t "photo-album.summary" numPhotos=@numPhotos}}
</template>;

export default PhotoAlbum;
html
You have {numPhotos, plural, =0 {no photos} =1 {one photo} other {# photos}}.

To avoid this scenario, please ensure that all arguments are well-defined before calling t. Some strategies include:

  • Use if to assert that all arguments are well-defined.

    gts
    import type { TOC } from '@ember/component/template-only';
    import { t } from 'ember-intl';
    import { gte } from 'ember-truth-helpers';
    
    interface PhotoAlbumSignature {
      Args: {
        numPhotos?: number;
      };
    }
    
    const PhotoAlbum: TOC<PhotoAlbumSignature> = <template>
      {{#if (gte @numPhotos 0)}}
        {{t "photo-album.summary" numPhotos=@numPhotos}}
      {{/if}}
    </template>;
    
    export default PhotoAlbum;
  • Use a getter to provide a default value.

    gts
    import Component from '@glimmer/component';
    import { t } from 'ember-intl';
    
    interface PhotoAlbumSignature {
      Args: {
        numPhotos?: number;
      };
    }
    
    export default class PhotoAlbum extends Component<PhotoAlbumSignature> {
      get numPhotos(): number {
        return this.args.numPhotos ?? 0;
      }
    
      <template>
        {{t "photo-album.summary" numPhotos=this.numPhotos}}
      </template>
    }
  • Pass a fallback object.

    gts
    import type { TOC } from '@ember/component/template-only';
    import { hash } from '@ember/helper';
    import { t } from 'ember-intl';
    
    interface PhotoAlbumSignature {
      Args: {
        numPhotos?: number;
      };
    }
    
    const PhotoAlbum: TOC<PhotoAlbumSignature> = <template>
      {{#let (hash numPhotos=0) as |fallback|}}
        {{t "photo-album.summary" fallback numPhotos=@numPhotos}}
      {{/let}}
    </template>;
    
    export default PhotoAlbum;

Options

htmlSafe

To render an HTML in a translation message, set htmlSafe to true. The t helper returns a SafeString (casted as string to improve DX).

gts
import { t } from 'ember-intl';

<template>
  {{t "visit-homepage" htmlSafe=true}}
</template>
yaml
visit-homepage: Visit <a href="https://www.emberjs.com">Ember.js</a>.

CAUTION

Do not use triple curly braces, e.g. {{{t "call-to-action"}}}. It allows cross-site scripting (XSS).

To pass data to an HTML tag, escape the angle brackets:

gts
import { t } from 'ember-intl';

<template>
  {{t "visit-legal" htmlSafe=true url="https://emberjs.com/about/legal"}}
</template>
yaml
visit-legal: See our '<'a href="{url}"'>'Terms and Conditions'</a>'.

locale

You can display the text in another locale (i.e. independently from the user's preferred locale). Pass the name of the locale to locale.

gts
import type { TOC } from '@ember/component/template-only';
import { t } from 'ember-intl';

interface HelloSignature {
  Args: {};
}

const Hello: TOC<HelloSignature> = <template>
  <div lang="en-us">
    {{t "hello.message" locale="en-us"}}
  </div>

  <div lang="de-de">
    {{t "hello.message" locale="de-de"}}
  </div>
</template>;

export default Hello;