Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Locale property of useI18n seems as it is not Reactive #132

Closed
yusuf-io opened this issue Oct 1, 2020 · 13 comments
Closed

Locale property of useI18n seems as it is not Reactive #132

yusuf-io opened this issue Oct 1, 2020 · 13 comments
Labels
Status: Need More Info Lacks enough info to make progress

Comments

@yusuf-io
Copy link

yusuf-io commented Oct 1, 2020

Hi vue-i18n authors,
I am working on Vue 3 project and trying to switch locale via URL i18n.locale=to.params.lang. In the components where I am using ...useI18n() inside the return of setup() to retrievelocale , but locale property does not change dynamically as expected.
Thanks!

@kazupon
Copy link
Member

kazupon commented Oct 2, 2020

setup with object spread (...useI18n({ ... })), it's merged into the render context.
So you need to use locale on the template side.

@yusuf-io
Copy link
Author

yusuf-io commented Oct 2, 2020

There is no problem with using locale on the template side, the problem is with its value which is static as set inside createI18n and does not update on the template side when switching locale in URL.

@ux-engineer
Copy link

ux-engineer commented Oct 2, 2020

@YusufISMAILOGLU can you use {{ $i18n.locale }} in template?

I'm using Script Setup syntax, and this export seems to work as reactive in the template:

export const { locale } = useI18n();

@yusuf-io
Copy link
Author

yusuf-io commented Oct 3, 2020

@ux-engineer thank you for your feedback, but useI18n can be used just inside setup. when
return { ...useI18n() }
locale should be exposed to template and it is true but it is NOT reactive .

@kazupon kazupon added the Status: Need More Info Lacks enough info to make progress label Oct 3, 2020
@kazupon
Copy link
Member

kazupon commented Oct 3, 2020

@YusufISMAILOGLU
Could you provide minimum repro codes please?

@yusuf-io
Copy link
Author

yusuf-io commented Oct 3, 2020

i18n.js

import { createI18n } from "vue-i18n";
const i18n = createI18n({
  legacy: true,
  locale: process.env.VUE_APP_I18N_LOCALE || "en",
  fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || "en",
  messages: {
    en: {
      msg: "Hello",
    },
    tr: {
      msg: "Merhaba",
    },
  },
});
export default i18n;

main.js

import { createApp } from "vue";
import App from "./App.vue";
import router from "./router/router";
import i18n from "./i18n";
import "./index.css";
// use beforeEach route guard to set the language
router.beforeEach((to, form, next) => {
  // use the language form the routing params or default language
  let language = to.params.lang;
  if (!["en", "tr"].includes(language)) {
    return next("en");
  }
  if (i18n.locale !== language) {
    i18n.locale = language; // update the locale
  }
  return next();
});

createApp(App).use(router).use(i18n).mount("#app");

HelloWorld.vue

<template>
  <h1>{{ t("msg") }} Vue 3.0 + Vite</h1>
  <button @click="count++">count is: {{ count }}</button>
</template>

<script>
import { reactive, toRefs } from "vue";
import { useI18n } from "vue-i18n";

export default {
  name: "HelloWorld",

  setup() {
    const state = reactive({
      count: 0,
    });
    console.log(useI18n().locale.value); //should console the updated value which set in main.js file,
// but it does not and console the default locale which defined in i18n.js
    return {
      ...toRefs(state),
      ...useI18n(),
    };
  },
};
</script>

@yusuf-io yusuf-io changed the title Local property of useI18n seems as it is not Reactive Locale property of useI18n seems as it is not Reactive Oct 3, 2020
@kazupon
Copy link
Member

kazupon commented Oct 4, 2020

Thanks!
and, could you provide vue & vue-i18n version, vue & vue-i18n version please ?

@kazupon
Copy link
Member

kazupon commented Oct 4, 2020

i18n.js:
if (i18n.locale !== language) {
    i18n.locale = language; // update the locale
  }

You need to use global property i18n instance.
(i18n.global return composer object: https://github.com/intlify/vue-i18n-next/blob/master/docs/vue-i18n.i18n.md)

i18n.js:
if (i18n.global.locale.value !== language) {
    i18n.global.locale.value = language; // update the locale
  }

@kazupon
Copy link
Member

kazupon commented Oct 4, 2020

i18n.js:
const i18n = createI18n({
  legacy: true,

If set legacy: true, useI18n cannot be used with the composition API.

@yusuf-io
Copy link
Author

yusuf-io commented Oct 4, 2020

Thanks!
and, could you provide vue & vue-i18n version, vue & vue-i18n version please ?

vue & vue-i18n version

  • vue: 3.0.0
  • vite-plugin-vue-i18n: 1.0.0-alpha.2

@yusuf-io
Copy link
Author

yusuf-io commented Oct 4, 2020

By using global property i18n instance, it woks fine.
@kazupon appreciate your help.

@yusuf-io yusuf-io closed this as completed Oct 4, 2020
@ux-engineer
Copy link

@YusufISMAILOGLU I'd advise against using this syntax:

return {
  ...useI18n(),
};

This way you are exposing everything to the template when actually needing just one property. Instead consider using object-desctructed properties:

const { locale } = useI18n();

return {
  locale,
};

Also in some cases, you might need to wrap the returned property as ref, but I'm not yet sure when this is needed to be more specific...perhaps not helpful here:

const { locale } = useI18n();

return {
  locale: ref(locale),
};

@yusuf-io
Copy link
Author

yusuf-io commented Oct 4, 2020

Actually in my app I use object destructuring, but for purpose of clarity I used ...useI18n() in my aforementioned example.
@ux-engineer Thank you for your advice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Need More Info Lacks enough info to make progress
Projects
None yet
Development

No branches or pull requests

3 participants