i18next / i18next-vue

Internationalization for Vue 2 & 3 using the i18next ecosystem
https://i18next.github.io/i18next-vue/
MIT License
74 stars 8 forks source link

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

Closed YehorPytomets closed 1 year ago

YehorPytomets commented 2 years ago

🚀 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

jamuhl commented 2 years ago

Would be great if this stays somewhat alined to react-i18next implementation so it's easy to switch from react-i18next to vue-i18next:

kkuegler commented 2 years ago

Yes, this sounds good. I'd like to take some time to look into this and experiment, so we get an API that feels right (any ideally is compatible with react-i18next).

kkuegler commented 2 years ago

In the new 2.0.0-beta.2 release i18nOptions will now be taken into account for the t retrieved via useTranslation().

This is a little more verbose than directly supporting it in useTranslation(), but it might work as an interim solution.

EranClientside commented 1 year ago

Is the t function supposed to be limited by the component's i18nOptions? I'm using the function inside a computed property but the ns is not limited until after the onMounted and the computed property is not being updated.

kkuegler commented 1 year ago

Hi @EranClientside,

yes, it should use i18nOptions. I included a working example below. If this does not help/not work in your setup, please open a separate issue so we can look into this.

<template>
  <h1>Issue 7b</h1>
  <p>computed: {{ term }}</p>
  <p>computed2: {{ otherTerm }}</p>
  <p>too early: {{ notLikeThis }}</p>
</template>

<script setup>
import { computed } from "vue";
import { useTranslation } from "i18next-vue";

const { t } = useTranslation();
const term = computed(() => t("some.key"));
// this is too early, because i18nOptions is only taking effect in `beforeCreate`, which runs after `setup`:
const notLikeThis = t("some.key"); 
</script>

<script>
export default {
  computed:{
    otherTerm(){
      return this.t("some.key");
    }
  },
  i18nOptions: {
    namespaces: "namespace1",
  },
  name: "issue-seven",
};
</script>
kkuegler commented 1 year ago

We plan to include this in i18next-vue v3. In fact, you can try it in the alpha version already: https://github.com/i18next/i18next-vue/releases/tag/v3.0.0-alpha.0

The syntax is

  const {t} = useTranslation('namespace1', {
    keyPrefix: 'long.path.to',
  });

See https://github.com/i18next/i18next-vue/issues/16 for other changes planned for version 3.

kkuegler commented 1 year ago

As outlined above, this is implemented in v3.