-
-
Notifications
You must be signed in to change notification settings - Fork 377
Description
Reporting a bug?
In fact I guess this is not a bug, though I didn't find a workable way to solve this currently, after searching lots of docs, issues and pages. However I guess maybe the official reference of vue-i18n could describe the solution about this issue.
In some scenario, I want to create some reactive object containing translated i18n strings (via some reusable util functions) in setup()
.
The official documentation of vue-i18n says If t(key) is used in a reactive context, it will re-evaluate once the locale changes.
, however, I just cannot find a way to make the value reactive via steup()
.
Module versions (please complete the following information):
vue
: 3.xvue-i18n
: 9.x
Reproduction Link
https://codesandbox.io/s/vue-i18n-reactive-in-setup-t9j3e
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Vue I18n v9 Starter Template</title>
</head>
<body>
<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/vue-i18n@next"></script>
<div id="app">
<form>
<label>{{ $t('message.language') }}</label>
<select v-model="curLang">
<option value="en">en</option>
<option value="ja">ja</option>
</select>
</form>
<button v-on:click="showChild = !showChild">Toggle Child v-if</button>
<p>{{ $t("message.directMsg") }}</p>
<Child v-if="showChild"></Child>
</div>
<script>
const { createApp, defineComponent, reactive, ref } = Vue;
const { createI18n } = VueI18n;
const i18n = createI18n({ // step 1
legacy: false,
globalInjection: true,
locale: "en",
messages: {
en: {
message: {
language: "Language",
directMsg: "Direct i18n.t()",
msgInObj: "i18n.t() in Object"
}
},
ja: {
message: {
language: "言語",
directMsg: "直接の i18n.t()",
msgInObj: "オブジェクト内の i18n.t()"
}
}
}
});
const Child = defineComponent({
template: `<p><b>Child Component, in setup():</b>
<div>{{ directVal }}</div> // step 5
<div>{{ obj.indirectVal }}</div>
</p>`,
setup() {
let directVal = i18n.global.t("message.directMsg");
let obj = reactive({ // step 4
indirectVal: i18n.global.t("message.msgInObj")
});
return {
directVal,
obj
};
}
});
const app = createApp({ // step 2
components: {
Child
},
data() {
return {
showChild: true
};
},
computed: {
curLang: {
get() {
return i18n.global.locale.value;
},
set(nv) {
i18n.global.locale.value = nv;
}
}
}
});
app.use(i18n);
app.mount("#app");
i18n.global.locale.value = "ja"; // step 3
</script>
</body>
</html>
To Reproduce
Steps to reproduce the behavior:
- Initialize an i18n instance (composition API, no
legacy
), with defaultlocale: 'en'
- Initialize Vue app instance and
use()
the i18n instance. - Change language with
i18n.global.locale.value
toja
- Create a reactive object
tmpObj
in<Child>
component'ssetup()
function, and add a propertytest
into the object with the return value ofi18n.global.t()
- Access
{{ tmpObj.test }}
in the template of<Child>
. Now it's translation is still inen
. - Reload (please click the button
Toggle Child v-if
) the<Child>
, Now it's translation will becomeja
. (because<Child>
'ssetup()
is run again afteri18n.global.locale.value
changed.)
Expected behavior
The <Child>
should show ja
string as soon as i18n.global.locale.value
changed.
Screenshots
Additional context
No.