首页 > 解决方案 > Vue i18n 语言环境切换器不适用于已翻译的 url,它可以自行翻译

问题描述

构建一个局部工作的语言环境切换器(欢迎提示和改进),它将在语言之间切换(延迟加载),但是当尝试将 url 更改为翻译部分时,它将不起作用(不会加载正确的组件)。

对于我所看到的是插件初始化语言环境值没有更新,或者当我手动将其更改为不同的语言环境时,它将加载组件。

将下面的代码添加到区域设置开关时,它将起作用,但仅在刷新页面后才起作用。

this.$root.$i18n.locale = 'nl-NL'

例子

example.com/en/user // works
example.com/nl/gebruikers // not loading component

/locales/en-US.json

{
    "routes":{
        "users" : {
            "index" : "en/users",
            "create" : "en/users/create"
        }
        ...
        ...
    }
}

/locales/nl-NL.json

{
    "routes":{
        "users" : {
            "index" : "nl/gebruikers",
            "create" : "nl/gebruikers/aanmaken"
        }
        ...
        ...
    }
}

插件/i18n.js

import { nextTick } from 'vue'
import { createI18n } from 'vue-i18n'

export function setI18nLanguage(i18n, locale) {
    if (i18n.mode === 'legacy') {
      i18n.global.locale = locale
    } else {
      i18n.global.locale.value = locale
    }
    document.querySelector('html').setAttribute('lang', locale)
}

export async function loadLocaleMessages(i18n, locale) {
    const messages = await import(
      /* webpackChunkName: "locale-[request]" */ `../locales/${locale}.json`
    )
    i18n.global.setLocaleMessage(locale, messages.default)
    return nextTick();
}

function initI18nTranslations () {
    return { 
        "en-US": require(`./../locales/en-US.json`)
    }
}

const i18n = createI18n({
    formatFallbackMessages: true,
    silentFallbackWarn: true,
    silentTranslationWarn: true,
    locale: 'en-US', // this seems to be the issue
    fallbackLocale: 'en-US',
    messages: initI18nTranslations()    
});
  
export default i18n

路由器/router.js

import { createWebHistory, createRouter} from "vue-router";
import routes from './routes.js';
import i18n, {loadLocaleMessages, setI18nLanguage, i18nValues} from '../plugins/i18n.js';

const router = createRouter({
    history: createWebHistory(),
    routes: [
        {
            path: "/",
            redirect: `/${redirectLocale}`
        },
        {
            path: `/:locale(${redirectLocale})?`,
            component: () => import('../Pages/Page.vue'),
            children: routes
        }
    ] 
});

const { t } = i18n.global;

router.beforeEach(async (to, from, next) => {

    const paramsLocale = i18nValues(i18n).locale

    to.params.locale = paramsLocale;

    if (!i18n.global.availableLocales.includes(paramsLocale)) {
      await loadLocaleMessages(i18n, paramsLocale)
    }

    setI18nLanguage(i18n, paramsLocale)

    if(from.params.locale && from.params.locale != to.params.locale && to.name != undefined){
       from.name = to.name;
       next('/'+t('routes.'+to.name))
    }else{
       next()
    }

});
  
export default router;

语言环境.vue

<template>
    <el-dropdown class="language">
        <template #trigger>             
            <img :src="imgPath(localeFlag)" alt=""/>
        </template>
        <template #content>
            <ul>
                <template v-for="locale in locales">
                    <li v-if="selectedLocale != locale.code" :key="locale.code">
                        <a href="#" @click="switchLocale(locale.code)">
                            <img :src="imgPath(locale.flag)" :alt="locale.name"/>
                        </a>
                    </li>
                </template>
            </ul>
        </template>
    </el-dropdown>
</template>

<script>
import { SUPPORTED_LOCALES, SUPPORTED_LOCALES_DEFAULT } from '../../plugins/locales.js'
import {LS_LOCALE_KEY} from '../../plugins/localstorage.js';
import i18n from '../../plugins/i18n.js'
import { useRouter } from 'vue-router';

export default {
    name: 'el-locale',
    props:{
        img: String,
        alt: String
    },
    data () {
        return {
            path: '/',
            localeFlag: SUPPORTED_LOCALES_DEFAULT.flag,
            locales: SUPPORTED_LOCALES,
            selectedLocale : '',
        }
    },
    methods:{
        imgPath (src) {
          return '/storage/img/lang/24/'+src+'.png';
        },
        switchLocale (locale) {

           console.log(this.currentRouteName)
            if (this.selectedLocale !== locale) {
                this.selectedLocale = locale;
                this.$store.commit('updatedLocale', locale);
                this.setActiveLocaleIcon();
            }
        },
        setActiveLocaleIcon () {
            var findMatch = this.locales.find(obj => {             
                return obj.code === this.selectedLocale;
            });
            this.localeFlag = findMatch.flag;
        },
        getSavedLocale () {
            this.selectedLocale = window.localStorage.getItem(LS_LOCALE_KEY) || 'en-US';
        }
    },     
    mounted () {
        this.getSavedLocale();
        this.setActiveLocaleIcon();
    }
}
</script>

标签: vue.jsvue-routervue-i18n

解决方案


推荐阅读