xiCO2k / laravel-vue-i18n

Allows to connect your `Laravel` Framework translation files with `Vue`.
MIT License
621 stars 51 forks source link

Refactor to class instance, allowing multiple instances #59

Closed ragulka closed 2 years ago

ragulka commented 2 years ago

This PR is a follow-up to https://github.com/xiCO2k/laravel-vue-i18n/issues/56 and refactors the library to use a class-based approach. There are no breaking changes - existing usages should continue to work just fine. Tests have been provided.

The goal is to allow creating multiple translator instances, which allows translating different parts of the UI in different languages. This is useful in certain scenarios, such as for a translation tool, or some app that displays a preview of some document or component in a different language than the rest of the UI.

Implementation details

All language loading and translation logic remains the same - it has merely been moved inside the I18n class. It is possible to create multiple instances of this class, each with different options (language, resolver). These different instances can be created directly in a Vue component, or installed as a Vue app plugin.

import { I18n } from 'laravel-vue-i18n'

const resolver = lang => import(`./fixtures/lang/${lang}.json`)

const i18nEn = new I18n({
    lang: 'en',
    resolve: resolver
})
const i18nPt = new I18n({
    lang: 'pt',
    resolve: resolver
})

i18nEn.trans('Welcome!') // will output "Welcome!"
i18nPt.trans('Welcome!') // will output "Bem-vindo!"

By default, installing the the i18nVue plugin will create a shared instance. This instance is accessed when importing the translation functions, such as trans, directly. When using multiple Vue app instances, it's possible to either share the I18n instance between them, or have each app create its own instance.

shared usage (default - also the current behavior)

import { i18nVue } from 'laravel-vue-i18n'

createApp()
    .use(i18nVue, { lang: 'pt' })
    .mount('#app');

// elsewhere
import { trans } from 'laravel-vue-i18n'

trans('Welcome!') // will output "Bem-vindo!"

non-shared usage - makes sense only if creating multiple Vue app instances

import { i18nVue } from 'laravel-vue-i18n'

createApp()
    .use(i18nVue, {
        lang: 'es'
        shared: false, // don't use the shared instance
    })
    .mount('#app');

Accessing the shared instance

It's possible to access the shared instance via code as well:

import { I18n } from 'laravel-vue-i18n'

I18n.getSharedInstance()

Caveats

It is possible to import a translation function before installing the i18nVue plugin (this is alos the current behavior, nothing new here). When calling the translation function, ie trans(), and the plugin has not been installed, the shared instance will be created with default options. This ensures that it's possible to import and call these functions without any fatal errors (also current behavior). When installing the plugin, and a shared instance exists, the options for this instance will be updated with the ones provided by the installer (assuming the shared: false flag was not used).

xiCO2k commented 2 years ago

Thanks for the PR, will dig in during next week. 🤘

xiCO2k commented 2 years ago

Hey @ragulka just tested and looks great to me.

Can you just add some of this example on the README.md file?

Thanks again, Francisco

ragulka commented 2 years ago

@xiCO2k done in https://github.com/xiCO2k/laravel-vue-i18n/pull/59/commits/e7d772ce33f79c999850a1f0e6080ecbc18b265e - let me know what you think?

xiCO2k commented 2 years ago

Thanks @ragulka will ship it later today or tomorrow. thanks for the contribution. ❤️