https://github.com/johannschopplich/vue-i18n
🌐 Lightweight internationalization plugin for Vue
https://github.com/johannschopplich/vue-i18n
vue vue-i18n
Last synced: 3 months ago
JSON representation
🌐 Lightweight internationalization plugin for Vue
- Host: GitHub
- URL: https://github.com/johannschopplich/vue-i18n
- Owner: johannschopplich
- License: mit
- Created: 2023-09-08T05:41:04.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2025-06-03T07:53:45.000Z (4 months ago)
- Last Synced: 2025-07-21T17:18:58.231Z (3 months ago)
- Topics: vue, vue-i18n
- Language: TypeScript
- Homepage:
- Size: 783 KB
- Stars: 7
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# @byjohann/vue-i18n
Lightweight internationalization plugin for Vue.
Why bother creating another i18n library if [Vue I18n](https://vue-i18n.intlify.dev) 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.
## Key Features
- 🗜 [`useI18n`](#usei18n) composable
- 🔃 Lazily add translations at runtime
- 📯 Global properties [`$t`](#t--i18n) and [`$i18n`](#t--i18n) accessible in templates
- 🦾 [Strongly typed locales](#strict-locale-and-messages-types) and messages
- 🌬️ Zero dependencies## Setup
```bash
# pnpm
pnpm add @byjohann/vue-i18n# npm
npm i @byjohann/vue-i18n# yarn
yarn add @byjohann/vue-i18n
```## Usage
> [!TIP]
> [📖 Check out the playground](./playground/)Before you can use `@byjohann/vue-i18n`, you need to initialize the `i18n` instance:
```ts
// 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:
```ts
// 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:
```ts
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`
```## Strict Locale and Messages Types
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.
```ts
import type enMessages from './locales/en.json'type Messages = typeof enMessages
type Locale = 'en' | 'de'const { locale, messages } = useI18n()
messages.fr = { // The property "fr" is not assignable to type "LocaleMessages".
// ...
}
```## Message Formatting
### General Formatting
```ts
const messages = {
en: {
intro: 'Hello World'
}
}
```
**Template**
```html
{{ t('intro') }}
```**Output**
```html
Hello World
```### Named Formatting
```ts
const messages = {
en: {
intro: '{msg} World'
}
}
```
**Template**
```html
{{ t('intro', { msg: 'My' }) }}
```**Output**
```html
My World
```### List Formatting
```ts
const messages = {
en: {
intro: '{0} World'
}
}
```
**Template**
```html
{{ t('intro', ['My']) }}
```**Output**
```html
My World
```---
List formatting also accepts array-like objects:
**Template**
```html
{{ t('intro', {'0': 'My'}) }}
```**Output**
```html
My World
```### Auto-Load Translations
To automatically load translations, you can use [the glob import from Vite](https://vitejs.dev/guide/features.html#glob-import) to load all translation files from a directory.
```ts
import type { LocaleMessages } from '@byjohann/vue-i18n'
import { createI18n } from '@byjohann/vue-i18n'// Auto-load translations
const messages = Object.fromEntries(
Object.entries(
import.meta.glob('./locales/*.json', { eager: true })
).map(([key, value]) => [key.slice(10, -5), value])
)const i18n = createI18n({
defaultLocale: 'en',
locales: Object.keys(messages),
messages
})export { i18n }
```## API
### `$t` & `$i18n`
The properties `$t` as well as `$i18n` are available globally in your templates.
Example:
```html
{{ $t('intro') }}
```### `useI18n`
To access the current i18n instance, you can import the `useI18n` composable from `@byjohann/vue-i18n`. The `useI18n` composable is available your `` blocks or the `setup` function of your components.
**Example**
```ts
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**
```ts
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
}
```## 💻 Development
1. Clone this repository
2. Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`
3. Install dependencies using `pnpm install`
4. Start development server using `pnpm run dev` inside `playground`## License
[MIT](./LICENSE) License © 2022-PRESENT [Johann Schopplich](https://github.com/johannschopplich)
[MIT](./LICENSE) License © 2022-2023 [LeanERA GmbH](https://github.com/leanera)
[MIT](./LICENSE) License © 2020 [webkong](https://github.com/webkong)