我目前正在尝试实现一个功能,用户可以在设置页面(SettingsDialog.vue)中从下拉菜单中选择一种语言,更新所有文本以匹配新语言。这个应用程序有多个Vue文件,比如一个MenuBar.vue,HelpDialog.vue,每个文件都是从translation.ts提取的,用于他们的英文翻译。但是,我注意到从下拉菜单中选择一种语言只会改变我的SettingsDialog.vue文件中的元素,而不是我拥有的所有其他Vue文件。
我尝试使用Vue-I18n文档实现,在文件中全局地更改地区。在选择SettingsDialog.vue中的语言、将translation.ts中的英文翻译应用于菜单栏、帮助页等之后,我期望整个应用程序的语言环境会发生变化。发生的情况是,来自translation.ts的翻译只适用于SettingsDialog.vue页面,而不适用于其他地方。
我想这是一个电子应用程序,项目中的Vue文件使用类星体,这将是有帮助的。每个文件都有正确的导入语句。
main.ts:
// ...
window.datalayer = [];
const i18n = createI18n({
legacy: false,
locale: "",
messages,
});
createApp(App)
.use(store, storeKey)
.use(router)
.use(
createGtm({
id: process.env.VUE_APP_GTM_CONTAINER_ID ?? "GTM-DUMMY",
vueRouter: router,
enabled: false,
})
)
.use(Quasar, {
config: {
brand: {
primary: "#a5d4ad",
secondary: "#212121",
},
},
iconSet,
plugins: {
Dialog,
Loading,
},
})
.use(ipcMessageReceiver, { store })
.use(markdownItPlugin)
.use(i18n)
.mount("#app");SettingsDialog.vue
// ...
<!-- Language Setting Card -->
<q-card flat class="setting-card">
<q-card-actions>
<div id="app" class="text-h5">{{ $t("言語") }}</div>
</q-card-actions>
<q-card-actions class="q-px-md q-py-sm bg-setting-item">
<div id="app">{{ $t("言語を選択する") }}</div>
<q-space />
<q-select
filled
v-model="locale"
dense
emit-value
map-options
options-dense
:options="[
{ value: 'ja', label: '日本語 (Japanese)' },
{ value: 'en', label: '英語 (English)' },
]"
label="Language"
>
<q-tooltip
:delay="500"
anchor="center left"
self="center right"
transition-show="jump-left"
transition-hide="jump-right"
>
Test
</q-tooltip>
</q-select>
</q-card-actions>
</q-card>
// ...
<script lang="ts">
import { useI18n } from "vue-i18n";
// ...
setup(props, { emit }) {
const { t, locale } = useI18n({ useScope: "global" });
// ...
return {
t,
locale,
// ...
};MenuBar.vue
<template>
<q-bar class="bg-background q-pa-none relative-position">
<div
v-if="$q.platform.is.mac && !isFullscreen"
class="mac-traffic-light-space"
></div>
<img v-else src="icon.png" class="window-logo" alt="application logo" />
<menu-button
v-for="(root, index) of menudata"
:key="index"
:menudata="root"
v-model:selected="subMenuOpenFlags[index]"
:disable="menubarLocked"
@mouseover="reassignSubMenuOpen(index)"
@mouseleave="
root.type === 'button' ? (subMenuOpenFlags[index] = false) :
undefined
"
/>
// ...
<script lang="ts">
import { defineComponent, ref, computed, ComputedRef, watch } from "vue";
import { useStore } from "@/store";
import MenuButton from "@/components/MenuButton.vue";
import TitleBarButtons from "@/components/TitleBarButtons.vue";
import { useQuasar } from "quasar";
import { HotkeyAction, HotkeyReturnType } from "@/type/preload";
import { setHotkeyFunctions } from "@/store/setting";
import {
generateAndConnectAndSaveAudioWithDialog,
generateAndSaveAllAudioWithDialog,
generateAndSaveOneAudioWithDialog,
} from "@/components/Dialog";
import { useI18n } from "vue-i18n";
import messages from "../translation";
type MenuItemBase<T extends string> = {
type: T;
label?: string;
};
export type MenuItemSeparator = MenuItemBase<"separator">;
export type MenuItemRoot = MenuItemBase<"root"> & {
onClick: () => void;
subMenu: MenuItemData[];
};
export type MenuItemButton = MenuItemBase<"button"> & {
onClick: () => void;
};
export type MenuItemCheckbox = MenuItemBase<"checkbox"> & {
checked: ComputedRef<boolean>;
onClick: () => void;
};
export type MenuItemData =
| MenuItemSeparator
| MenuItemRoot
| MenuItemButton
| MenuItemCheckbox;
export type MenuItemType = MenuItemData["type"];
export default defineComponent({
name: "MenuBar",
components: {
MenuButton,
TitleBarButtons,
},
setup() {
const { t } = useI18n({
messages,
});
// ...
};
const menudata = ref<MenuItemData[]>([
{
type: "root",
label: t("ファイル"),
onClick: () => {
closeAllDialog();
},
// ...
]);translation.ts
const messages = {
en: {
// MenuBar.vue
ファイル: "File",
エンジン: "Engine",
ヘルプ: "Help",
// SettingDialog.vue
言語: 'Language',
言語を選択する: 'Select Language',
オフ: 'OFF',
エンジンモード: 'Engine Mode',
// HelpDialog.vue
ソフトウェアの利用規約: 'test',
}
};
export default messages;发布于 2022-04-05 15:59:45
也许还有更多的问题,但现在我看到了两个:
menudata应该是computed,而不是ref。现在,您正在创建一个JS对象,并将其label属性设置为t()调用的结果。当全局区域设置更改时,不会再次创建此对象。它仍然持有t()函数唯一执行时返回的值--当setup()运行时。//更正
const menudata = computed<MenuItemData[]>(() => [
{
type: "root",
label: t("ファイル"),
onClick: () => {
closeAllDialog();
},
// ...
]);这样,每当i18n.global.locale更改时,就会再次使用新的翻译创建menudata。
作为另一种选择,将label设置为key并在模板中使用t(label)。然而,computed是更有效的解决方案。
messages传递给useI18n()。只适用于全局实例。通过将配置对象传递到组件中的useI18n()中,您将创建局部范围,如果您将所有翻译都存储在一个全局位置中,这是没有意义的。https://stackoverflow.com/questions/71746549
复制相似问题