# i18n
Simple i18n implementation with API inspired by vue-i18n (opens new window)
# Parameters
import { useI18n, buildI18n, setI18n } from "vue-composable";
interface i18nOption {
locale: string; // start locale
fallback?: string; // fallback locale
// override the default resolver
resolve?: (
i18n: i18n, // current locale messages
path: Readonly<RefTyped<string>>,
args: RefTyped<FormatObject> | Array<FormatValue> | undefined
) => RefTyped<string>;
notFoundFallback?: boolean, // fallback message if the key not found in the current locale `default:true`
/*
localized messages, the first level property is the locale name
*/
messages: {
en: {
/*object based messages*/
},
'en-GB': {
/*object based messages*/
},
pt: ()=> import('/locale/pt').default, // also supports lazy loading
},
}
useI18n(options);
// dependency injection i18n
setI18n(options);
// inject i18n if no arguments passed
useI18n(); // retrieves the i18n
// retrieves i18n object without injecting
buildI18n(options);
Parameters | Type | Required | Description |
---|---|---|---|
option | i18nOption | false | i18n options |
# Typescript
You can specify the i18n types in multiple ways
# Options
If options are passed the i18n result will be based on the definition locale and the messages[locale].
const { i18n } = useI18n({
locale: "en",
fallback: "en",
messages: {
en: {
hello: "hello world",
},
pt: {
hello2: "Olá mundo",
},
},
});
i18n.hello; // correct, because is the selected locale
i18n.hello2; // typescript error, it doesn't exist in the type
# Templated
If the i18n definition is injected in the parent component, you can pass the messages using templated overload
// types.d.ts
interface I18nMessages {
hello: string;
}
// component.vue
import { I18nMessages } from "./types.d.ts";
const { i18n } = useI18n<I18nMessages>();
# Global definition
If you don't want to import the type on every component, you can describe it globally
// types.d.ts
import { i18n } from "vue-composable";
declare module "vue-composable" {
interface i18n {
hello: string;
}
}
// component.vue
const { i18n } = useI18n();
i18n.hello; // typescript has the definition
# JSON file
You may have the translations in a json file, you can use the types from that json file.
// tsconfig.json
{
"compilerOptions": {
"resolveJsonModule": true,
}
}
// locales/en.json
{
"hello": "Hello"
}
// types.d.ts
import { i18n } from "vue-composable";
type json = typeof import("@/locales/en.json");
declare module "vue-composable" {
interface i18n extends json {}
}
// App.vue
import {setI18n} from 'vue-composable'
import en from '@/locales/en.json',
setup(){
setI18n({
locale: 'en',
messages: {
en,
es: ()=> import('@/locales/es.json'),
// etc...
}
})
}
// Child.vue
const { i18n } = useI18n();
i18n.hello; // typescript has the definition
i18n.hello2; // type error
# State
The useI18n
function exposes the following reactive state:
import { useI18n } from "vue-composable";
const { locale, locales, i18n } = useI18n();
State | Type | Description |
---|---|---|
locale | Ref<String> | Current locale |
locales | Ref<String> | Array of available locales |
i18n | Ref<i18n> | Object based i18n access |
# Methods
The useI18n
function exposes the following methods:
import { useI18n } from "vue-composable";
const { $t, $ts, addLocale, removeLocale } = useI18n();
Signature | Description |
---|---|
$t(path, args?) | Retrieve localised message |
$ts(path, args?) | Same as $t but returns string instead of ref<string> |
addLocale(locale, messages) | add new locale |
removeLocale(locale) | remove locale |
# Example
Hello
Today is: Sunday
Today is: Sunday
Custom locale
# Code
<template>
<div>
<div>
<select v-model="locale">
<option v-for="l in locales" :key="l" :value="l">
{{ i18n.locales[l] }}
</option>
</select>
<div>
<label for="name">{{ i18n.input.name.label }}</label>
<input
name="name"
v-model="name"
:placeholder="i18n.input.name.placeholder"
/>
</div>
</div>
<h1>{{ i18n.title }}</h1>
<h5>{{ $t("hello", { name }).value }}</h5>
<p>
{{
$t("currentDate", { day: $t(`weekDays[${new Date().getDay()}]`) }).value
}}
</p>
<p>
{{ $t("currentDate", { day: i18n.weekDays[new Date().getDay()] }).value }}
</p>
<hr />
<h3>Custom locale</h3>
<div>
<button v-if="locales.indexOf('custom') < 0" @click="addCustomLocale">
Add custom locale
</button>
<button v-else @click="removeCustomLocale">Remove custom locale</button>
</div>
<textarea v-model="customLocaleJson"></textarea>
</div>
</template>
<script>
import Vue from "vue";
import { useI18n, promisedTimeout } from "vue-composable";
import { ref, computed, watch, i18n } from "@vue/composition-api";
export default {
setup() {
const name = ref("");
const i18n = useI18n({
locale: "en",
fallback: "en",
messages: {
en: {
locales: {
en: "English",
pt: "Portuguese",
es: "Spanish",
custom: "YourLocale"
},
weekDays: [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
],
input: {
name: {
label: "Name",
placeholder: "Your name"
}
},
hello: "Hello {name}",
currentDate: "Today is: {day}"
},
pt: {
locales: {
en: "Inglês",
pt: "Português",
es: "Espanhol"
},
weekDays: [
"Domingo",
"Segunda-feira",
"Terca-feira",
"Quarta-feira",
"Quinta-feira",
"Sexta-feira",
"Sábado"
],
input: {
name: {
label: "Nome",
placeholder: "O teu nome"
}
},
hello: "Olá {name}"
currentDate: "Hoje e': {day}",
},
// promised based
es: () =>
promisedTimeout(10).then(() => ({
locales: {
en: "Ingles",
pt: "Portugués",
es: "Espanol"
},
weekDays: [
"Domingo",
"Lunes",
"Martes",
"Miércoles",
"Jueves",
"Viernes",
"Sábado"
],
input: {
name: {
label: "Nombre",
placeholder: "Tu nombre"
}
},
hello: "Holla {name}"
currentDate: "Hoy es: {day}",
}))
}
});
const customLocale = ref({
locales: {
custom: "Awesome"
},
hello: "H3Y"
});
const customLocaleJson = ref(JSON.stringify(customLocale.value));
const addCustomLocale = () => {
i18n.addLocale("custom", customLocale.value);
i18n.locale.value = "custom";
};
const removeCustomLocale = () => i18n.removeLocale("custom");
watch(
customLocaleJson,
json => {
try {
customLocale.value = JSON.parse(json);
} catch (e) {
// err
}
},
{ lazy: true }
);
return {
...i18n,
name,
customLocaleJson,
addCustomLocale,
removeCustomLocale
};
}
};
</script>
← Validation Title →