https://github.com/padcom/vue-i18n
https://github.com/padcom/vue-i18n
Last synced: about 1 year ago
JSON representation
- Host: GitHub
- URL: https://github.com/padcom/vue-i18n
- Owner: padcom
- Created: 2023-10-26T08:44:30.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2024-10-04T07:50:23.000Z (over 1 year ago)
- Last Synced: 2025-04-20T13:36:07.531Z (about 1 year ago)
- Language: TypeScript
- Size: 110 KB
- Stars: 4
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Simplified and unified Vue.js i18n
This package implements simplified mechanism for internationalization (i18n) of components in Vue.js.
## TLDR;
If you want to see all the bits and pieces in action check out the [example](https://github.com/padcom/vue-i18n-example-vue3)
## Installation
There are 2 parts to making this system work:
1. Vite plugin
2. Vue.js plugin or context creation (for webcomponents)
### Installing Vite plugin
To install the Vite plugin first install the package:
```
npm install --save-dev @padcom/vite-plugin-vue-i18n
```
and then add it to your `vite.config.js`:
```typescript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import i18n from '@padcom/vite-plugin-vue-i18n'
export default defineConfig({
plugins: [
vue(),
i18n(),
]
})
```
Nothing really fancy, but needs to be done so that Vite understands how to process the `` blocks in `.vue` files.
### Installing the Vue.js part
First things first, you need to install the part that provides the actual i18n capabilities:
```
npm install --save-dev @padcom/vue-i18n
```
### Providing messages context
In contrast to the original `vue-i18n` plugin this one does not provide a global function that can inject messages from the global scope. Instead, everything is done using composition functions and Vue's native `provide`/`inject`.
#### For applications
For applications the easiest way to do it is to install the provided Vue.js plugin when creating the application:
```typescript
import { createApp } from 'vue'
import { createI18n } from '@padcom/vue-i18n'
import App from './App.vue'
const messages = {
en: {
hello: 'Hello, world!',
},
}
createI18n({ messages })
createApp(App)
.mount('#app')
```
#### For anything else
In the case of for example webcomponents, where the application instance is just not available there is no way to use a plugin approach like that. But no worries - this package has you covered! Instead of using a Vue.js plugin you can create the necessary context yourself:
`Host.ce.vue` - a file acting as the webcomponent host for your application:
```vue
import { createI18Context } from '@padcom/vue-i18n'
import SomeComponentThatWantsToUseTranslations from '...'
const messages = {
en: {
hello: 'Hello, world!',
},
}
createI18Context({ messages })
```
### Messages structure in real life
You can get the `messages` from anywhere - here we just provide them in the same file to make it easier for presentation but in real life you might want to extract them to a folder structure like the original [vue-i18n](https://kazupon.github.io/vue-i18n/) plugin suggests:
```
src
+ i18n
+ index.ts
+ locale
+ en.ts
+ de.ts
...
```
where `src/i18n/index.ts` contains re-exports of all the different messages for languages:
```typescript
export { default as en } from './locale/en'
export { default as de } from './locale/de'
```
and the individual message files just export the messages as follows:
```typescript
export default {
hello: 'Hello, world!',
}
```
With that kind of structure, this is how you would import the messages when you want to import your messages in `./src/i18n.js` or when you create the injection context manually:
```typescript
import * as messages from './locale'
export const i18n = createI18n({
messages,
})
```
and then in the `main.ts` of your application you simply import the module:
```typescript
import './i18n'
```
Of course this is the most extensive version of the configuration. You can do it all in `main.ts` if your application is small enough:
```typescript
import { createApp } from 'vue'
import { createI18n } from '@padcom/vue-i18n'
createI18n({
messages: {
en: {
hello: 'Hello, world!',
},
},
})
createApp(App).mount('#app')
```
## Usage
Once you've installed and configured everything using this system is very simple:
```vue
{{ t('message') }}
import { useI18n } from '@padcom/vue-i18n'
const { t } = useI18n()
{
"en": {
"message": "Hello, world!",
},
"de": {
"message": "Hallo Welt!",
}
}
```
### Forcing resolution to use global messages only
Sometimes you might have duplicated message ids. In general you should try to avoid it as it makes reasoning about the code more difficult. Nevertheless, real world sometimes makes us do things we will regret later on and this system is not going to stand in your way.
You can enforce the `t` to use global messages by specifying the `useScope` key when calling `useI18n()`:
```typescript
const { t } = useI18n({ useScope: 'global' })
```
### Disabling global messages resolution
Sometimes you might want your component to only use local translations. This system has you covered:
```typescript
const { t } = useI18n({ useScope: 'local' })
```
The default value for `useScope` is `'local-first'`, which means you'll get the the local value if defined or else the system will default to global scope.
### Language selection
The system implements a simplistic, but powerful resolution system to get the message.
There are 2 locales that you can choose from:
1. `locale`
2. `fallbackLocale`
Both are initialized to the country code of the client's browser (e.g. `'en'`). But you can change them however you'd like either when installing the application plugin:
```typescript
createApp(App)
.use(i18n, {
messages,
locale: 'xy',
fallbackLocale: 'au'
})
.mount('#app')
```
or when creating the context:
```typescript
const { locale, fallbackLocale } = createI18Context({
messages,
locale: 'xy',
fallbackLocale: 'au',
})
```
The message resolution is as follows:
1. Try to resolve the given key using `locale` from `` provided keys
2. Try to resolve the given key using `fallbackLocale` from `` provided keys
3. Try to resolve the given key using global scope messages using `locale`
4. Try to resolve the given key using global scope messages using `fallbackLocale`
### Reacting to changes in selected locale
When you want to react to when the locale is changed you'd use a Vue.js' watch to do so:
```typescript
import { watch } from 'vue'
import { useI18n } from '@padcom/vue-i18n'
const { locale } = useI18n()
watch(locale, newLocale => {
console.log('Locale changed to', newLocale)
})
```
## Closing thoughts
This internationalization system was created specifically because the original [vue-i18n](https://kazupon.github.io/vue-i18n) plugin makes it impossible to use it in the context of webcomponents. It's a design choice they have made and that's not going to change any time soon.
However, if you don't need webcomponents interoperability and you're happy with how the original plugin works or if you need some of the advanced features (like pluralization or message arguments) then you should definitely go with the original one. It's much more robust and this system will probably never grow to be as complete as the original one is.