You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

InertiaJS(Laravel9+Vue3)应用JS中无法设置i18n.locale问题

问题描述

在Laravel9 + Vue3技术栈的InertiaJS应用中集成9.1版本vue-i18n实现国际化功能时,需要在JavaScript逻辑中切换i18n语言环境并同步执行自定义逻辑,但调用$i18n.locale、this.$i18n.locale两种写法均运行失败,错误提示为this.$i18n / $i18n is not defined,无法正常完成语言设置。

原有配置代码

app.js i18n配置段

require('./bootstrap');

import { createApp, h } from 'vue';
import { createI18n } from 'vue-i18n'
import { createInertiaApp } from '@inertiajs/inertia-vue3';
import { InertiaProgress } from '@inertiajs/progress';

const appName = window.document.getElementsByTagName('title')[0]?.innerText || 'Laravel';

createInertiaApp({
    title: (title) => `${title} - ${appName}`,
    resolve: (name) => require(`./Pages/${name}.vue`),
    setup({ el, app, props, plugin }) {
        const i18n = createI18n({
            locale: "de",
            // locale: props.initialPage.props.locale, // 从props读取用户默认语言
            fallbackLocale: "en", // 设置兜底语言
            messages: loadLocaleMessages(),
        });

        return createApp({ render: () => h(app, props) })
            .use(plugin)
            .use(i18n)
            .mixin({ methods: { route } })
            .mount(el);
    },
});

Authenticated.vue 语言切换段

<script setup>
import {ref, onMounted} from 'vue';
import BreezeDropdown from '@/Components/Dropdown.vue';
import BreezeNavLink from '@/Components/NavLink.vue';
import BreezeResponsiveNavLink from '@/Components/ResponsiveNavLink.vue';
import ProjectVersion from '@/Components/ProjectVersion.vue';
import {Link} from '@inertiajs/inertia-vue3';
import { usePage } from '@inertiajs/inertia-vue3';
import { computed } from 'vue';

function switchLanguage(key){
    console.log('switchLanguage to ' + key);
    this.$i18n.locale = key; // 此处运行报错
}
</script>

<template>
<div v-if="$i18n.locale == 'en'">
  <a @click.prevent="switchLanguage('de')" href="#">
     Deutsch
  </a>
</div>
<div v-if="$i18n.locale == 'de'">
  <a @click.prevent="switchLanguage('en')" href="#">
     English
  </a>
</div>
</template>
报错原因
  • 代码使用Vue3的<script setup>语法,该语法块内不存在组件实例的this上下文,因此this.$i18n无法找到对应对象
  • 模板中可以直接使用$i18n是Vue全局属性的模板透传规则,<script setup>块内不会自动注入该全局变量,直接写$i18n也会触发未定义错误
  • 原有i18n实例初始化在createInertiaApp的setup回调内部,作用域无法被外部组件访问,且未开启vue-i18n 9.x的组合式API支持配置
修复方案
  1. 调整i18n实例初始化位置,补充必要配置,修改app.js:
require('./bootstrap');

import { createApp, h } from 'vue';
import { createI18n } from 'vue-i18n'
import { createInertiaApp } from '@inertiajs/inertia-vue3';
import { InertiaProgress } from '@inertiajs/progress';

const appName = window.document.getElementsByTagName('title')[0]?.innerText || 'Laravel';
// 将i18n实例提升到外层初始化,方便全局导入调用
const i18n = createI18n({
    legacy: false, // vue-i18n 9.x 组合式API模式必须开启该配置
    locale: "de",
    fallbackLocale: "en",
    globalInjection: true, // 开启全局注入,保证模板内原有$i18n、$t写法正常可用
    messages: loadLocaleMessages(),
});

createInertiaApp({
    title: (title) => `${title} - ${appName}`,
    resolve: (name) => require(`./Pages/${name}.vue`),
    setup({ el, app, props, plugin }) {
        // 初始化时优先用后端返回的用户语言配置覆盖默认值
        i18n.global.locale.value = props.initialPage.props.locale || 'de';

        return createApp({ render: () => h(app, props) })
            .use(plugin)
            .use(i18n)
            .mixin({ methods: { route } })
            .mount(el);
    },
});

export default i18n; // 导出i18n实例供组件导入使用

提示:更规范的实践是把i18n初始化逻辑单独抽离到/resources/js/i18n/index.js文件中导出实例,避免从app.js导入时产生循环依赖问题。

  1. 修改Authenticated.vue中的语言切换逻辑,直接导入i18n实例修改全局语言配置,无需依赖this:
<script setup>
import {ref, onMounted, computed} from 'vue';
import BreezeDropdown from '@/Components/Dropdown.vue';
import BreezeNavLink from '@/Components/NavLink.vue';
import BreezeResponsiveNavLink from '@/Components/ResponsiveNavLink.vue';
import ProjectVersion from '@/Components/ProjectVersion.vue';
import {Link} from '@inertiajs/inertia-vue3';
import { usePage } from '@inertiajs/inertia-vue3';
// 导入初始化完成的i18n实例,路径按项目实际目录结构调整
import i18n from '@/app.js';

// 响应式获取当前语言,供模板渲染使用
const currentLocale = computed(() => i18n.global.locale.value);

function switchLanguage(key){
    console.log('switchLanguage to ' + key);
    // 直接修改全局语言配置,legacy:false模式下locale为ref类型,需要修改.value属性
    i18n.global.locale.value = key;
    // 此处可追加需要同步执行的自定义逻辑,比如缓存语言配置到本地、请求后端保存用户语言偏好等
    localStorage.setItem('user_locale', key);
}
</script>

<template>
<div v-if="currentLocale == 'en'">
  <a @click.prevent="switchLanguage('de')" href="#">
     Deutsch
  </a>
</div>
<div v-if="currentLocale == 'de'">
  <a @click.prevent="switchLanguage('en')" href="#">
     English
  </a>
</div>
</template>

额外优化建议

  • 语言持久化:切换语言时将配置存入localStorage,i18n初始化时优先读取本地缓存值,其次读取后端返回的用户偏好,最后使用默认兜底语言,保证刷新页面后语言状态不丢失
  • 路由同步:如果需要URL携带语言前缀,可以在切换语言时同步调用Inertia路由跳转方法,把语言参数拼到URL上,更利于SEO

内容的提问来源于stack exchange,提问作者Konrad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 23:45:36