Git Product home page Git Product logo

i18next-vue's Introduction

i18next-vue

Introduction

This library is a simple wrapper for i18next, simplifying its use in Vue 3.

There is also a Vue 2 version of this package.

Upgrade

In the documentation, you can find information on how to upgrade from @panter/vue-i18next, from i18next-vue 3.x or earlier versions.

Installation

npm install i18next-vue

Initialisation

import Vue from "vue";
import i18next from "i18next";
import I18NextVue from "i18next-vue";
import App from "./App.vue";

/*const i18nInitialized = */i18next.init({ ... });
createApp(App).use(I18NextVue, { i18next }).mount('#app');

// to wait for loading the translations first, do this instead:
// i18nInitialized.then(() => createApp(App).use(I18NextVue, { i18next }).mount('#app'));

Usage

Use the $t translation function, which works like (and uses) the versatile t function from i18next.

There is a full tutorial for setting up i18next-vue. You can check out the live demo version version of it, too.

To learn about more options, check out the full documentation.

Simple example

Given the i18next translations

i18next.init({
	// ...
	resources: {
		en: {
			// language
			translation: {
				// the default namespace
				insurance: "Insurance",
			},
		},
		de: {
			// language
			translation: {
				// the default namespace
				insurance: "Versicherung",
			},
		},
	},
});

You can use

<template>
	<h1>A test in {{ $i18next.language }}</h1>
	<p>{{ $t("insurance") }}</p>
</template>

$t() works both in Options API and Composition API components.

Using the useTranslation() composition function you can access the i18next instance and t() in the setup part, and e.g. get a t() functions for a specific namespace.

<script setup>
import { computed } from "vue";
import { useTranslation } from "i18next-vue";
const { i18next, t } = useTranslation();
const term = computed(() => t("insurance"));
</script>

<template>
	<h1>A test in {{ i18next.language }}</h1>
	<p>inline: {{ t("insurance") }}</p>
	<p>inline with $t: {{ $t("insurance") }}</p>
	<p>computed: {{ term }}</p>
</template>

Translation component

i18next-vue provides a <i18next> translation component, so you can use markup (including Vue components) in translations.

In this example {faq-link} will be replaced by the faq-link slot, i.e. by the router link. You can move {faq-link} around in the translation, so it makes sense for the target language.

i18next.init({
  // ...
  resources: {
    en: {
      translation: {
        "message": "Open the {faq-link} page."
        "faq": "Frequently Asked Questions"
      }
    },
    fr: {
      // ...
    }
  }
})
<template>
	<i18next :translation="$t('message')">
		<template #faq-link>
			<router-link :to="FAQ_ROUTE">
				{{ $t("faq") }}
			</router-link>
		</template>
	</i18next>
</template>

Custom slot values

Custom slot values may be useful when the default braces ({ and }) are wrongly treated by the Locize service or don't satisfy other needs.

Use custom values for recognizing start and end of the insertion points of the <i18next>/TranslationComponent inside the localization term:

// main.js
i18next.init({
  // ...
  resources: {
    en: {
      translation: {
        "message": "Open the <slot>faq-link</slot> page."
        "faq": "FAQ"
      }
    },
    de: {
      // ...
    }
  }
})

app.use(I18NextVue, {
    i18next,
    slotStart: '<slot>',
    slotEnd: '</slot>',
});
<!-- Component.vue -->
<template>
	<i18next :translation="$t('message')">
		<template #faq-link>
			<router-link :to="FAQ_ROUTE">
				{{ $t("faq") }}
			</router-link>
		</template>
	</i18next>
</template>

Contributing

Requirements

  • Node.js >= v20

i18next-vue's People

Contributors

adrai avatar anc95 avatar claudiocro avatar dlw93 avatar friedow avatar henriquebremenkanp avatar joelpintoribeiro avatar kkuegler avatar lexxor avatar menthol avatar mtorromeo avatar pioniro avatar saraedum avatar smitt04 avatar yehorpytomets avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

i18next-vue's Issues

support v-t directive

πŸš€ Feature Proposal

Is it able to support v-t directive

Motivation

I think v-t directive can make code more flexible, since we can provide a default transaction from the code

Example

<p v-t="helloworld">Hello world</p>

The `i18next` object returned from the `useTranslation()` is not reactive.

πŸ› Bug Report

Hello!

When using i18next object returned from the useTranslation() in computed properties to get the current language, for example in a language switcher component, we expect it to be reactive as docs in the index.ts specify. But it it isn't.

To Reproduce

For example, in the following component, neither of the computed properties will be updated after the language change:

<template>
    <p>firstLanguage: {{firstLanguage}}</p>
    <p>resolvedLanguage: {{resolvedLanguage}}</p>
    <p>language: {{language}}</p>
    <button @click="translateToChinese">Zh</button>
    <button @click="translateToEnglish">En</button>
</template>
<script setup>
    import {computed} from 'vue';
    import {useTranslation} from 'i18next-vue';

    const {i18next} = useTranslation();
    const firstLanguage = computed(() => i18next.languages[0]);
    const resolvedLanguage = computed(() => i18next.resolvedLanguage);
    const language = computed(() => i18next.language);

    function translateToChinese() {
        i18next.changeLanguage('zh');
    }

    function translateToEnglish() {
        i18next.changeLanguage('en');
    }
</script>

But the t() function updates as expected. To temporary work around this issue we've created our local composable that makes the i18next reactive by subscribing to common i18next events:

import {readonly, shallowRef, triggerRef} from "vue";
import {useTranslation} from "i18next-vue";

/**
 * Composable that makes the `i18next` object reactive, allowing to trigger language updates.
 *
 * <p>Exposes the `t()` function and `i18next` object from the `useTranslation()` composable,
 * but with reactive `i18next`.
 */
export default function useI18next() {

    const {i18next: i18nextOriginal, t} = useTranslation();
    const i18next = shallowRef(i18nextOriginal);

    // watch for common i18next events: https://www.i18next.com/overview/api#events
    i18nextOriginal.on("languageChanged", update);
    i18nextOriginal.on("loaded", update);
    i18nextOriginal.store.on("added", update);
    i18nextOriginal.store.on("removed", update);

    function update() {
        triggerRef(i18next); // trigger update
    }

    return {
        i18next: readonly(i18next), // prohibits changing `i18next` value in components
        t,
    }
}

Could you please fix that and make the i18next returned from useTranslation() reactive, or clarify why it is not reactive if it is so by design and describe this in the documentation explicitly. Because the composable name makes us believe that the returned values are reactive, if not stated the opposite. Hope our solution helps in some way.

I would be grateful to get any feedback on that.

Expected behavior

It is expected that the i18next is reactive and can be used in computed properties to get the current language.

Your Environment

  • i18next: ^21.8.10
  • i18next-vue: 2.0.0-beta.0
  • vue: ^3.2.37
  • npm: 8.5.5
  • node: v16.15.0
  • browsers: Firefox, Chrome
  • os: Mac
  • run command: npm run serve

Implement <i18next> component.

πŸš€ Feature Proposal

We propose to implement the <i18next> that was available in @panter/vue-i18next and and made it much easier to insert HTML and components as interpolation values.

Motivation and Example

Now we have to write HTML snippets outside of a template in a <script> and cannot use components as interpolation values.
For example, the following case with <i18next> component was rewritten into a composable that encapsulates translation and interpolation details:

<!--
  - Vue 2
  - @panter/vue-i18next
  -->
<template>
    <!-- ...some other template code... -->
    <i18next tag="p" class="value" path="license.goToTermsOfUse">
        <router-link :to="{ name: 'LICENSE' }"
                     class="link"
                     place="termsOfUse">
            {{ $t('license.termsOfUse') }}
        </router-link>
    </i18next>
</template>
<!--
  - Vue 3
  - i18next/i18next-vue
  -->
<template>
    <!-- ...some other template code... -->
    <p class="value" v-html="goToTermsOfUse"/>
</template>

<script setup>
// imports and other code...

const {t} = useTranslation();
const {goToTermsOfUse} = useTermsOfUse(t);

/** Creates and exposes localized message of Terms of use. */
function useTermsOfUse(t) {

    const router = useRouter();
    const termsOfUseLink = router.resolve({ name: 'LICENSE' }).href;
    const termsOfUse = computed(() => t('somenamespace:license.termsOfUse'));

    const goToTermsOfUse = computed(() => t('somenamespace:license.goToTermsOfUse', {
        termsOfUse: `<a class="link" href="${termsOfUseLink}">${termsOfUse.value}</a>`,
        interpolation: {escapeValue: false},
    }));

    return {
        goToTermsOfUse,
    };
}
</script>

Both of the snippets render the following message:

Screenshot 2022-06-29 at 13 05 34

I would be grateful to hear any response on the possibility of implementing that component.

Your Environment

  • i18next: ^21.8.10
  • i18next-vue: 2.0.0-beta.0
  • vue: ^3.2.37
  • npm: 8.5.5
  • node: v16.15.0
  • browsers: Firefox, Chrome
  • os: Mac
  • run command: npm run serve

Vue 2 compatible TranslationComponent not working as expected

πŸ› Bug Report

Thank you so much for the clear migration documentation it has mostly been a beeze to migrate from @panter/vue-i18next.

I've discovered a couple of slightly unexpected behaviors.

  1. I think the migration docs may need to be updated. According to the docs the <i18next> component is deprecated. However, it seems it was added in V1 here
  2. The TranslationComponent doesn't seem to be working as expected -- the child value isn't interpolated. This seemingly is because the translation prop enters the component's render function with the template values stripped (see screenshot)
Screenshot 2023-10-19 at 7 06 08 PM

To Reproduce

This is a private repository so I unfortunately cannot provide a reproduction but below is my i18next config:

import i18next from 'i18next';
import I18NextVue from 'i18next-vue';
import Vue from 'vue';

import english from '../locales/en/translation.json';
import spanish from '../locales/es/translation.json';

i18next.init({
  lng: 'en',
  nsSeparator: false,
  keySeparator: false,
  fallbackLng: false,
  resources: {
    en: { translation: english },
    es: { translation: spanish },
  },
  interpolation: {
    prefix: '{',
    suffix: '}',
  },
});

Vue.use(I18NextVue, { i18next });

export function setDefaultInterpolationVariables(variables: { [key: string]: string }) {
  i18next.options.interpolation!.defaultVariables = variables;
}

Expected behavior

The following snippet

<i18next :translation="$t('Need help with {processor}?')">
     <template #processor>{{ processor }}</template>
</i18next>

with the follow es translation file key/value pair
"Need help with {processor}?": "ΒΏNecesita ayuda con {processor}?",

Should render as
Screenshot 2023-10-19 at 7 08 58 PM

Instead it renders as
Screenshot 2023-10-19 at 7 08 48 PM

Your Environment

  • runtime version: node v16.14.2
  • i18next version: 19.0.0
  • os: Mac
  • any other relevant information
    "vue": "2.7.14",
    "i18next-vue": "^1.1.0",
    "vite": "^2.5.4",

dont work lazy loading file

When i want used i18next-resources-to-backend , lang loaded after render component. How change it. I need lang load before render

i18n.use(resourcesToBackend((language: string) => import(`./locales/${language}.json`))).init({
  detection: {
    order: ['cookie', 'localStorage'],
    lookupCookie: 'slang',
    lookupLocalStorage: 'last_language',
  },
  fallbackLng: getDefaultLanguage(),
  debug: true,
});

debug info

render App
i18next.js:13 i18next::backendConnector: loaded namespace translation for language uk {qwe: 'uk', order: {…}, basicSkeleton: {…}, cardForm: {…}, form: {…}, …}
i18next.js:13 i18next: languageChanged uk
i18next.js:13 i18next: initialized {debug: true, initImmediate: true, ns: Array(1), defaultNS: Array(1), fallbackLng: Array(1), …}

how fix it?

[Typescript Error] useTranslation - Type instantiation is excessively deep and possibly infinite

Hi, thank you for the awesome framework, it's so amazing!

πŸ› Bug Report

I have two question:

  • The first one is related to the type error
    I get the typescript error Type instantiation is excessively deep and possibly infinite while using useTranslation composable function in a Vue component. I've searched some similar issues but did not find the solution.
  • I follow the youtube video to setup typescript for i18next: https://www.youtube.com/watch?v=GLIas4DH3Ww
    It seems doesn't work properly.

To Reproduce

https://stackblitz.com/edit/github-lup5wg?file=src%2Fcomponents%2FComponentTypeError.ts

Screenshot:
image

Both useTranslation() and t() has the type error:

import { h, computed } from 'vue';
import { useTranslation } from 'i18next-vue';

export default {
  name: 'ComponentTypeError',
  setup() {
    // Here is the type error
    const { t } = useTranslation();

    // Here is the type error
    const insurance = computed(() => t('insurance'));

    return () => {
      return h('div', `inline => ${insurance.value}`);
    };
  },
};

Expected behavior

  • Should not cause typescript issues
  • The autocompletion should work properly

Your Environment

  • runtime version: node v18(locally), stackbliz(node v18.8)
  • i18next version: 23.5.1
  • i18next-vue: 3.0.0
  • typescript: 5.2.2
  • os: Mac

Support TypeScript

πŸš€ Feature Proposal

Ref:
When I use i18next react, it supports TypeScript. Could this vue version also add TypeScript support for the $t interface?

https://react.i18next.com/latest/typescript

Motivation

Add translation key validation/auto-completion support during dev.

Example

//similar usage as react version.
const { t } = useTranslation('settings')//namespace support, load namespace if it's not loaded

t('TranslationKey')//can be validated by TypeScript

test

πŸ› Bug Report

A clear and concise description of what the bug is.

To Reproduce

A minimal reproducible example.
A codesandbox example or similar
or at least steps to reproduce the behavior:

// Paste your code here

Expected behavior

A clear and concise description of what you expected to happen.

// Paste the expected results here

Your Environment

  • runtime version: i.e. node v14, deno, browser xy
  • i18next version: i.e. 19.5.3
  • os: Mac, Windows, Linux
  • any other relevant information

Changes for `i18next-vue` v3

πŸš€ Proposed changes for i18next-vue v3

For version 3, we'd like to streamline the API of i18next-vue and lean more on the Composition API. Please leave your feedback below.

[Update 2023-08-10] Release 3.0.0 available

We have released version 3.0.0 and a migration guide with the (breaking) changes.

You are still welcome to leave a comment below.

Proposed (breaking) changes

  • [update 2023-07-23] This list is now superseded by https://i18next.github.io/i18next-vue/migration-v3.html
  • require i18next >=23
  • make this package ESM-only
    • this would make it hard for CommonJS users to consume the library
    • this would make the package smaller and easier to maintain
  • extend useTranslation() with parameters to specify a fixed language, namespace(s) and a keyprefix (all optional)
    • having this available via the Composition API feels like a clean API
  • remove support for i18nOptions in the Options API
    • you could instead use useTranslation() for most of these use-cases
    • update 2023-07-12: we'll probably continue to support everything but messages behind a legacy flag until v4.
  • remove support for <i18n> blocks in SFCs
    • apparently there is no compatible Vue 3 loader for this and nobody complained so far
    • Vue 3 loaders like @intlify/unplugin-vue-i18n produce a different, function-based format now, which is not what we want
  • remove support for per-component translations
    • that would be the result of removing i18nOptions and <i18n>
    • if there is demand for this, we could re-add per-component messages via useTranslation()
  • update 2023-07-12: the translation functions will return an empty string while i18next is not yet initialized
    • before they returned the untranslated translation key, which is usually uglier than an empty string

Your feedback is welcome!

These are all quite big changes if you are relying on them in an existing application. That's why we are looking for your user feedback in this issue as a comment below.

Let us know, which feature you would like to keep, or where you would like some backward compatibility to ease the upgrade process to v3. All of the changes are still up for debate.

Thank you!

importing i18next-vue breaks type checking a basic nuxt app

πŸ› Bug Report

In a fresh nuxt 3 app, if you add a util function, and import i18next-vue in a component, then type checking breaks for the util function.

It's possible this is more of a nuxt issue, but i thought i would report it here first since adding/removing this specific import causes/fixes the issue.

To Reproduce

Here's a minimal reproduction: https://stackblitz.com/edit/github-zn8swb?file=package.json&terminal=typecheck

If you run npm run typecheck in the stackblitz console, you will get errors. If you comment out the import of i18next-vue then typechecking passes.

Expected behavior

Should not cause typescript issues

Your Environment

  • runtime version: node 19 (locally), node 16 (stackblitz)
  • i18next version: 22.4.9
  • i18next-vue version: 2.1.1
  • os: Mac
  • typescript 4.9.5

Limit the scope of a SFC component to some namespace and key prefix.

πŸš€ Feature Proposal

Hello!

We propose to implement the possibility of narrowing down the scope of a t() function returned from the useTranslation() to a certain namespace and/or key prefix as this is possible with $t() function in a template.

Motivation

This will allow restricting the component to a certain subtree of localization terms that we defined specifically for this component and produce less code. As of now, we have to write similar full keys in each t() call:

<script setup>
    // imports...
    
    const {t} = useTranslation();
    const term1 = computed(() => t('namespace1:long.path.to.term1'));
    const term2 = computed(() => t('namespace1:long.path.to.term2'));
    // ...
    const termN = computed(() => t('namespace1:long.path.to.termN'));
</script>

Example

We propose reimplementing the useTranslation() to accept the i18nOptions that limit the returned t() function to the provided namespace and/or key prefix:

<script setup>
    // imports...
    
    const {t} = useTranslation({
        namepsaces: 'namespace1',
        keyPrefix: 'long.path.to',
    });
    const term1 = computed(() => t('term1'));
    const term2 = computed(() => t('term2'));
    // ...
    const termN = computed(() => t('termN'));
</script>

By the way, when applying i18nOptions to a component with Options API, the options apply only to the $t() function in a template:

<template>
<!-- Works as expected:  -->
<p>{{$t('term1')}}</p>
<!-- Still have to specify the full path:  -->
<p>{{term2}}</p>
<p>{{t('namespace1:long.path.to.term3')}}</p>
</template>

<script>
export default {
    i18nOptions: {
        namepsaces: 'namespace1',
        keyPrefix: 'long.path.to',
    },
};
</script>

<script setup>
    // imports...
    
    const {t} = useTranslation();
    const term2 = computed(() => t('namespace1:long.path.to.term2'));
</script>

Would be grateful to hear any feedback on that.

Your Environment

  • i18next: ^21.8.10
  • i18next-vue: 2.0.0-beta.0
  • vue: ^3.2.37
  • npm: 8.5.5
  • node: v16.15.0
  • browsers: Firefox, Chrome
  • os: Mac
  • run command: npm run serve

Unable to install via npm?

πŸ› Bug Report

Unable to install using npm and install from zip / folder creates unexpected errors

To Reproduce

  • Have node.js v15 or higher
  • Try "npm install i18next-vue"

Expected behavior

For the module to be installed

Actual behavior

NPM throws a 404 error message

Your Environment

  • runtime version: node v16.15.0
  • i18next version: i.e. 21.8.0
  • os: Mac

support esm export

πŸš€ Feature Proposal

A clear and concise description of what the feature is.

Motivation

Please outline the motivation for the proposal.

Example

Please provide an example for how this feature would be used.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.