v6.4.0
版本发布时间: 2023-12-12 19:02:31
ember-intl/ember-intl最新发布版本:v7.0.0-beta.3(2024-05-07 02:23:14)
What changed?
- Allowed test helpers
setLocale()
andaddTranslation()
to callsettled()
- Updated documentation for testing
- Fixed type errors caused by macros
- Deprecated macros (to be removed in
v7.0.0
) - Improved
<template>
-tag support (allowed importing helpers fromindex
)
Migration guide
Test helpers
Before v6.4.0
, calling setLocale()
and addTranslations()
wouldn't have an effect on the application in tests. You might have had to call await settled()
or use something from @ember/runloop
to trigger an update.
Now, the test helpers handle the update and mean the following in tests:
-
setLocale()
- update the locale as if the user had somehow changed their preferred language -
addTranslations()
- update the translations as if you had somehow added them (e.g. via lazy loading)
You will want to search your test files for setLocale(
, addTranslations(
, and ember-intl/test-support
, then migrate code as follows:
Example: setLocale()
- import { render, settled } from '@ember/test-helpers';
+ import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import { setLocale, setupIntl } from 'ember-intl/test-support';
import { setupRenderingTest } from 'ember-qunit';
import { module, test } from 'qunit';
module('Integration | Component | hello', function (hooks) {
setupRenderingTest(hooks);
setupIntl(hooks);
test('it renders', async function (assert) {
await render(hbs`
<Hello @name="Zoey" />
`);
assert.dom('[data-test-message]').hasText('Hello, Zoey!');
- setLocale('de-de');
- await settled();
+ await setLocale('de-de');
assert.dom('[data-test-message]').hasText('Hallo, Zoey!');
});
});
Example: addTranslations()
- import { render, settled } from '@ember/test-helpers';
+ import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import { addTranslations, setupIntl, t } from 'ember-intl/test-support';
import { setupRenderingTest } from 'ember-qunit';
import { module, test } from 'qunit';
module('Integration | Component | lazy-hello', function (hooks) {
setupRenderingTest(hooks);
setupIntl(hooks);
test('it renders', async function (assert) {
await render(hbs`
<LazyHello @name="Zoey" />
`);
assert
.dom('[data-test-message]')
.doesNotIncludeText(
'Hello, Zoey!',
'Before translations are loaded, we cannot write assertions against a string.',
)
.hasText(
't:lazy-hello.message:("name":"Zoey")',
'Before translations are loaded, we should see the missing-message string.',
)
.hasText(
t('lazy-hello.message', { name: 'Zoey' }),
'Before translations are loaded, we can write assertions against the test helper t().',
);
- addTranslations({
- 'lazy-hello': {
- message: 'Hello, {name}!',
- },
- });
- await settled();
+ await addTranslations({
+ 'lazy-hello': {
+ message: 'Hello, {name}!',
+ },
+ });
assert
.dom('[data-test-message]')
.hasText(
'Hello, Zoey!',
'After translations are loaded, we can write assertions against a string.',
)
.doesNotIncludeText(
't:lazy-hello.message:("name":"Zoey")',
'After translations are loaded, we should not see the missing-message string.',
)
.hasText(
t('lazy-hello.message', { name: 'Zoey' }),
'After translations are loaded, we can write assertions against the test helper t().',
);
});
});
Macros
[!IMPORTANT] The macros, which are a remnant of classic components and
ember-i18n
, will be removed inv7.0.0
. I updated the documentation for macros to warn developers.
[!IMPORTANT] You can no longer import the macros from the
index
file, because thet()
macro would conflict with thet()
helper.Until the macros are removed in
v7.0.0
, you can name-import them from'ember-intl/macros'
or refer to the full path (e.g.import t from 'ember-intl/macros/t';
).
In classic and Glimmer components, inject the intl
service to access its methods. If you want to create a value that depends on other things, you can use the @computed
decorator (i.e. create a computed property) in classic and the native getter in Glimmer components. Alternatively, you can use ember-intl
's helpers in the template.
Before: A classic component with macros
/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging, ember/no-classic-classes, ember/no-classic-components, ember/no-computed-properties-in-native-classes, import/export */
import Component from '@ember/component';
import type { Registry as Services } from '@ember/service';
import { intl, raw, t } from 'ember-intl/macros';
export default class MyComponent extends Component {
tagName = '';
@intl('fruits', function (_intl: Services['intl']) {
// @ts-expect-error: 'this' implicitly has type 'any' because it does not have a type annotation.
return _intl.formatList(this.fruits);
})
declare outputForIntl: string;
@t('hello.message', {
name: 'name',
})
declare outputForT: string;
@t('hello.message', {
name: raw('name'),
})
declare outputForTWithRaw: string;
}
After: A Glimmer component with getters
import { inject as service, type Registry as Services } from '@ember/service';
import Component from '@glimmer/component';
export default class MyComponent extends Component {
@service declare intl: Services['intl'];
get outputForIntl(): string {
return this.intl.formatList(this.args.fruits);
}
get outputForT(): string {
return this.intl.t('hello.message', {
name: this.args.name,
});
}
get outputForTWithRaw(): string {
return this.intl.t('hello.message', {
name: 'name',
});
}
}
Helpers in <template>
-tag components
Before v6.4.0
, you had to remember and write the full path to use one of ember-intl
's helpers in a <template>
-tag component. Now, you can import all helpers from the index
file.
Example: t()
import type { TOC } from '@ember/component/template-only';
- import t from 'ember-intl/helpers/t';
+ import { t } from 'ember-intl';
interface HelloSignature {
Args: {
name: string;
};
}
const HelloComponent: TOC<HelloSignature> =
<template>
<div data-test-message>
{{t "hello.message" name=@name}}
</div>
</template>
export default HelloComponent;