Lightweight internationalization plugin for Vue.
Why bother creating another i18n library if Vue I18n seems to be the de-facto standard? Well, I was looking for a lightweight solution that solely covers the most basic use cases. I also wanted to learn, what a minimalistic i18n library would look like. So I built it.
- π
useI18n
composable - π Lazily add translations at runtime
- π― Global properties
$t
and$i18n
accessible in templates - π¦Ύ Strongly typed locales and messages
- π¬οΈ Zero dependencies
# pnpm
pnpm add @byjohann/vue-i18n
# npm
npm i @byjohann/vue-i18n
# yarn
yarn add @byjohann/vue-i18n
Before you can use @byjohann/vue-i18n
, you need to initialize the i18n
instance:
// plugins/i18n.ts
import { createI18n } from '@byjohann/vue-i18n'
const i18n = createI18n({
defaultLocale: 'en',
locales: ['en', 'de'],
messages: {
en: {
intro: 'Welcome, {name}',
},
de: {
intro: 'Willkommen, {name}',
},
},
})
export default i18n
Inside your app's entry point, import the i18n
instance and add it you Vue:
// main.ts
import { createApp } from 'vue'
import i18n from './i18n'
const app = createApp(App)
app.use(i18n)
app.mount('#app')
Done! Now you can retrieve translated keys in your components:
const { locale, t, setLocale } = useI18n()
locale.value // `en`
t('intro', { name: 'World' }) // `Welcome, World`
// Set new locale
setLocale('de')
locale.value // `de`
t('intro', { name: 'World' }) // `Willkommen, World`
Typed locales and messages will help you to avoid typos and make your code more robust. To narrow the type of your locales, you can create a Locale
type and pass it to the useI18n
composable.
Properties like locale
, locales
and messages
will be typed accordingly.
import type enMessages from './locales/en.json'
type Messages = typeof enMessages
type Locale = 'en' | 'de'
const { locale, messages } = useI18n<Locale, Messages>()
messages.fr = { // The property "fr" is not assignable to type "LocaleMessages<Locale>".
// ...
}
const messages = {
en: {
intro: 'Hello World'
}
} | Template <p>{{ t('intro') }}</p> Output <p>Hello World</p> |
const messages = {
en: {
intro: '{msg} World'
}
} | Template <p>{{ t('intro', { msg: 'My' }) }}</p> Output <p>My World</p> |
const messages = {
en: {
intro: '{0} World'
}
} | Template <p>{{ t('intro', ['My']) }}</p> Output <p>My World</p> List formatting also accepts array-like objects: Template <p>{{ t('intro', {'0': 'My'}) }}</p> Output <p>My World</p> |
To automatically load translations, you can use the glob import from Vite to load all translation files from a directory.
import { createI18n } from '@byjohann/vue-i18n'
import type { LocaleMessages } from '@byjohann/vue-i18n'
// Auto-load translations
const messages = Object.fromEntries(
Object.entries(
import.meta.glob<LocaleMessages>('./locales/*.json', { eager: true })
).map(([key, value]) => [key.slice(10, -5), value])
)
const i18n = createI18n({
defaultLocale: 'en',
locales: Object.keys(messages),
messages
})
export { i18n }
The properties $t
as well as $i18n
are available globally in your templates.
Example:
<p>{{ $t('intro') }}</p>
To access the current i18n instance, you can import the useI18n
composable from @byjohann/vue-i18n
. The useI18n
composable is available your <script setup>
blocks or the setup
function of your components.
Example
import { useI18n } from '@byjohann/vue-i18n'
const {
defaultLocale,
locale,
locales,
messages,
t,
setLocale,
getLocale
} = useI18n()
console.log(locales) // `['en', 'de']`
console.log(t('foo')) // `bar`
Type Declaration
function useI18n<
Locale extends string = string,
Messages extends Record<string, unknown> = Record<string, unknown>
>(): I18nInstance<Locale>
interface I18nInstance<
Locale extends string = string,
Messages extends Record<string, unknown> = Record<string, unknown>
> {
defaultLocale: Locale
locale: ComputedRef<Locale>
locales: readonly Locale[]
messages: LocaleMessages<Locale, Messages>
t: <const T>(key: T, params?: MessageParameters) => string
setLocale: (locale: Locale) => void
getLocale: () => string
}
- Clone this repository
- Enable Corepack using
corepack enable
- Install dependencies using
pnpm install
- Start development server using
pnpm run dev
insideplayground
MIT License Β© 2022-PRESENT Johann Schopplich
MIT License Β© 2022-2023 LeanERA GmbH