Jak zaimplementować i18n w Vue 3 Composition API
i18n to skrót oznaczający internationalization, czyli internacjonalizację. Jest to termin określający procesy i techniki służące do dostosowania oprogramowania do różnych języków i kultur, bez konieczności zmiany kodu źródłowego. i18n umożliwia nie tylko tłumaczenie tekstów, ale też formatowanie dat, czasu, walut i liczb.
Istnieje wiele narzędzi i bibliotek, ułatwiających implementację założeń i18n. W przypadku środowiska Vue 3 najpopularniejszą biblioteką jest vue-i18n. W tym artykule pokażę Ci, jak w prosty sposób zacząć swoją przygodę z i18n.
Instalacja
NPM:
npm install vue-i18n@9
Yarn:
yarn add vue-i18n@9
Pełną dokumentację znajdziesz tutaj.
Przygotowanie plików
W katalogu src załóż nowy folder o nazwie locales. To tutaj będziesz przechowywał wszystkie pliki z tłumaczeniami. Stwórz nowy plik - en.json. Możesz wybrać inny format (np. YAML), ale ze względu na to, że json jest w tym wypadku bardziej popularny, to on posłuży nam za wzorzec.
"common": {
"next": "Next",
"cancel": "Cancel"
},
"home": {
"logOut": {
"logIn": "Log in",
"register": "Register"
},
"logIn": {
"welcome": "Welcome!",
}
}
Klucze muszą być jednakowe we wszystkich plikach z tłumaczeniami. Jeśli chcesz dodać kolejny język musisz stworzyć nowy plik i dla istniejących kluczy przypisać odpowiednie wartości. Np. dla języka polskiego byłby to plik pl.json.
"common": {
"next": "Dalej",
"cancel": "Anuluj"
},
"home": {
"logOut": {
"logIn": "Zaloguj się",
"register": "Załóż konto"
},
"logIn": {
"welcome": "Witaj!",
}
}
Konfiguracja
Przejdź do pliku main.ts. Zaimportuj utworzone przed chwilą pliki z tłumaczeniami. Następnie musisz skonfigurować i18n.
import pl from "./locales/pl.json"
import en from "./locales/en.json"
const i18n = createI18n({
locale: navigator.language,
fallbackLocale: "en",
messages: { pl, en },
legacy: false
})
Locale umożliwia określenie jaki ma być język startowy aplikacji. Możesz podać tu konkretny plik, np. “en” albo użyć właściwości navigator.language, który odpowiada językowi przeglądarki użytkownika.
FallbackLocale wskazuje na plik z tłumaczeniami, który zostanie użyty w sytuacji, gdy przeglądarka użytkownika jest w języku, którego Twoja aplikacja nie wspiera lub gdy zabrakło odpowiedniego klucza w innym pliku json.
We właściwości messages deklarujesz pliki z tłumaczeniami. Pole legacy musisz ustawić na false, jeśli używasz Composition API.
Po utworzeniu instancji aplikacji konieczne jest zarejestrowanie pluginu i18n.
const app = createApp(App)
app.use(i18n)
app.mount('#app')
Użycie w komponencie
Aby użyć i18n w danym komponencie musisz go zaimportować, a następnie dokonać destrukturyzacji, żeby uzyskać dostęp do funkcji t. Posłuży ona do wykonywania tłumaczeń.
<script setup lang='ts'>
import {useI18n} from 'vue-i18n'
const {t} = useI18n();
</script>
W części HTML zamiast stringów, używaj odpowiednich kluczy, z pomocą funkcji t.
<span>{{t('home.logIn.welcome')}</span>
Language switcher
Warto dać użytkownikowi możliwość dopasowania języka do swoich preferencji. W tym celu możesz użyć właściwości locale.
<script setup lang="ts">
import {useI18n} from 'vue-i18n'
const {locale} = useI18n();
const currentLanguage = locale.value;
</script>
Aby zmienić aktywny język wystarczy przypisać do locale.value nową wartość, np. “pl”.
Poniżej zaprezentuję moją implementację language switcher’a.
Najpierw dodałam interfejs SelectOption. Label będzie odpowiadał tekstowi wyświetlanemu w Select, a value będzie wskazywał na nazwę pliku z odpowiednim tłumaczeniem.
export interface SelectOption {
label: string,
value: string
}
Następnie stworzyłam komponent LanguageSwitcher. Przechowuje on informacje o dostępnych językach, obsługuje ich zmianę oraz komunikuje się z komponentem-dzieckiem BaseSelect. Przyjmuje on właściwość options typu tablica SecetOption oraz obsługuje modelValue typu string.
<script setup lang="ts">
import {useI18n} from 'vue-i18n'
import BaseSelect from "@/components/common/baseSelect/BaseSelect.vue";
import type {SelectOption} from "@/components/common/baseSelect/selectOption";
import {ref, watchEffect} from "vue";
const {locale} = useI18n();
const options: SelectOption[] = [
{
label: 'English',
value: 'en'
},
{
label: 'Polski',
value: 'pl'
}
];
const currentLanguage = options.find((x) => x.value === locale.value)?.label ?? "English";
const selectedOption = ref(currentLanguage);
watchEffect(() => {
locale.value = options.find((x) => x.label === selectedOption.value)!.value;
})
</script>
<template>
<BaseSelect v-model="selectedOption" :options="options"/>
</template>
CurrentLanguage sprawdza jaki język jest obecnie ustawiony jako wiodący. Jeśli użytkownik używa języka nieobsługiwanego przez aplikację, zostanie wybrany angielski.
WatchEffect na podstawie zmiany wartości w BaseSelect wyszukuje odpowiednie value i przypisuje do locale.value.
Dalsze kroki
Vue-i18n daje ogromne możliwości. Warto zapoznać się z kompletną dokumentacją.