Мне нужно создать приложение на английском, французском и польском языках, поэтому я хочу установить и настроить эти три языка в моем приложении Svelte.
Я создал свое приложение и установил тесты.
Я буду использовать svelte-i18n
npm i svelte-i18n
Пришло время сконфигурировать этот пакет. Файл main.js перед конфигурацией выглядит следующим образом:
import './app.css'
import App from './App.svelte'
const app = new App({
target: document.getElementById('app')
})
export default app
Теперь я добавляю импорт svelte-i18n:
import './app.css'
import App from './App.svelte'
import { addMessages, init } from 'svelte-i18n'
addMessages('en', {
hello: 'Hello word!'
}) // this is my key that I will use after in my App page.
init({
initialLocale: 'en',
fallbackLocale: 'en'
}); // here I inicialise and configure a local language
const app = new App({
target: document.getElementById('app')
})
export default app
Теперь я импортирую i18n в App.svelte следующим образом:
<script>
import { _ } from 'svelte-i18n'
</script>
<main>
<h1>{$_('hello')}</h1>
</main>
В браузере это работает очень хорошо, но тесты не удались. Я разберусь с этим позже. На данный момент я добавляю еще один язык в main.js:
import './app.css'
import App from './App.svelte'
import { addMessages, init } from 'svelte-i18n'
addMessages('en', {
hello: 'Hello word!'
})
addMessages('fr', {
hello: 'Salut tout le monde!'
})
addMessages('pl', {
hello: 'Witajcie w naszej bajce!'
})
init({
initialLocale: 'fr',
fallbackLocale: 'en'
});
const app = new App({
target: document.getElementById('app')
})
export default app
Таким образом, когда вы меняете локальный язык, ваш текст в браузере также изменится.
Как я уже говорил, тесты не работают, поэтому я их исправлю.
Прежде всего, я создаю папку locale в папке src
mkdir locale
cd locale
touch i18n.js
Из main.js я вырезал эту часть кода:
import { addMessages, init } from 'svelte-i18n'
addMessages('en', {
hello: 'Hello word!'
})
addMessages('fr', {
hello: 'Salut tout le monde!'
})
addMessages('pl', {
hello: 'Witajcie w naszej bajce!'
})
init({
initialLocale: 'fr',
fallbackLocale: 'en'
});
вставляю его в i18n.js и импортирую этот файл в main.js:
import './locale/i18n'
Перевод работает в браузере.
Я импортирую этот файл также в файл App.spec.js:
import '../src/locale/i18n'
и тесты становятся зелеными, когда локальным языком является английский.
Чтобы иметь все языки в одном файле, я создаю JSON файл для каждого языка:
, а в i18n.js импортирую все эти файлы:
import { addMessages, init } from 'svelte-i18n';
import en from './en.json';
import fr from './fr.json';
import pl from './pl.json';
addMessages('en', en)
addMessages('fr', fr)
addMessages('pl', pl)
init({
initialLocale: 'en',
fallbackLocale: 'en'
});
Теперь я проверяю, хорошо ли отображается перевод
App.spec.js:
/**
* @jest-environment jsdom
*/
import App from "../src/App.svelte";
import { render, screen } from "@testing-library/svelte";
import '../src/locale/i18n'
import en from '../src/locale/en.json' //here I import a json files
import fr from '../src/locale/fr.json'
import pl from '../src/locale/pl.json'
// I modify a little bit a teste by adding description tag
describe("App Page", () =>{
describe("Layout", () =>{
it("has Hello header", () =>{
render(App);
const header = screen.getAllByText("Hello word!");
expect(header).toBeTruthy()
});
});
describe("i18n", () =>{
it("displays text in English", () =>{
render(App);
expect(screen.queryByRole('heading', {level: 1, name: en.hello})).toBeInDocument; /here I use from json file key and its value
});
it("displays text in French", () =>{
render(App);
expect(screen.queryByRole('heading', {level: 1, name: fr.hello})).toBeInDocument;
});
it("displays text in Polish", () =>{
render(App);
expect(screen.queryByRole('heading', {level: 1, name: pl.hello})).toBeInDocument;
});
})
})
На данный момент все работает по умолчанию, но я хочу сменить язык, поэтому мне нужно создать маленькую кнопку для переключения между языками.
В тестах я добавляю эти 2 теста:
it("displays text in French after clic a FR btn", async () =>{
render(App);
const frBtn = screen.getByText('FR');
await userEvent.click(frBtn);
expect(screen.queryByRole('heading', {level: 1, name: fr.hello})).toBeInDocument;
});
it("displays text in Polish after clic a PL btn", async () =>{
render(App);
const plBtn = screen.getByText('PL');
await userEvent.click(plBtn);
expect(screen.queryByRole('heading', {level: 1, name: pl.hello})).toBeInDocument;
});
Эти тесты корректны, но это не работает, потому что мне нужно импортировать пользовательское событие из библиотеки, которую я установил ранее.
import userEvent from '@testing-library/user-event'
Теперь тесты не работают, потому что в App.svelte у меня нет ни одного элемента, на который можно было бы нажать. Поэтому я создаю 3 языковых элемента и добавляю к ним on:click. Мне также нужно импортировать локаль из i18n. Теперь App.svelte выглядит следующим образом:
<script>
import { _, locale } from 'svelte-i18n'
</script>
<main>
<h1>{$_('hello')}</h1>
<span on:click = {() => locale.set("en")}>EN</span>
<span on:click = {() => locale.set("fr")}>FR</span>
<span on:click = {() => locale.set("pl")} >PL</span>
</main>
Теперь все работает, но мне нужно знать, работает ли кнопка EN также хорошо, как и другие, поэтому я создал еще один тест:
it("displays text in English after click from PL btn", async() =>{
render(App);
const plBtn = screen.getByText('PL');
await userEvent.click(plBtn);
const enBtn = screen.getByText('EN');
await userEvent.click(enBtn);
expect(screen.queryByRole('heading', {level: 1, name: en.hello})).toBeInDocument;
});
Так что весь App.spec.js выглядит следующим образом:
/**
* @jest-environment jsdom
*/
import App from "../src/App.svelte";
import { render, screen } from "@testing-library/svelte";
import userEvent from '@testing-library/user-event'
import '../src/locale/i18n'
import en from '../src/locale/en.json'
import fr from '../src/locale/fr.json'
import pl from '../src/locale/pl.json'
describe("App Page", () =>{
describe("Layout", () =>{
it("has Hello header", () =>{
render(App);
const header = screen.getAllByText("Hello word!");
expect(header).toBeTruthy()
});
});
describe("i18n", () =>{
it("displays text in English by default", () =>{
render(App);
expect(screen.queryByRole('heading', {level: 1, name: en.hello})).toBeInDocument;
});
it("displays text in French after clic a FR btn", async () =>{
render(App);
const frBtn = screen.getByText('FR');
await userEvent.click(frBtn);
expect(screen.queryByRole('heading', {level: 1, name: fr.hello})).toBeInDocument;
});
it("displays text in Polish after clic a PL btn", async () =>{
render(App);
const plBtn = screen.getByText('PL');
await userEvent.click(plBtn);
expect(screen.queryByRole('heading', {level: 1, name: pl.hello})).toBeInDocument;
});
it("displays text in English after click from PL btn", async() =>{
render(App);
const plBtn = screen.getByText('PL');
await userEvent.click(plBtn);
const enBtn = screen.getByText('EN');
await userEvent.click(enBtn);
expect(screen.queryByRole('heading', {level: 1, name: en.hello})).toBeInDocument;
});
})
})
Когда я запускаю тесты, все зеленые.