fix: 组件改用 useLocale 直读自身 i18n 实例(修复嵌入时文案回退成 key)

useI18n({ useScope: 'global' }) 在嵌入时解析到宿主已安装的 i18n 实例,
而非本子项目实例 -> mobileGame.* 文案回退成 i18n key(显示 ID)。
改为 useLocale composable 直接读本模块级 i18n.global,无论是否 app.use() 都正确。
This commit is contained in:
root
2026-07-24 08:59:35 +00:00
parent a5d4c05392
commit a91c379096
11 changed files with 34 additions and 20 deletions

View File

@@ -4,7 +4,7 @@
// 语言切换:嵌入时父项目经 :locale prop 传入当前语言watch 同步到本实例; // 语言切换:嵌入时父项目经 :locale prop 传入当前语言watch 同步到本实例;
// 独立运行时由本组件内的语言开关 + loadLocaleAsync 自管。 // 独立运行时由本组件内的语言开关 + loadLocaleAsync 自管。
import { ref, watch, defineAsyncComponent } from 'vue' import { ref, watch, defineAsyncComponent } from 'vue'
import { useI18n } from 'vue-i18n' import { useLocale } from './composables/useLocale.js'
import i18n, { loadLocaleAsync } from './i18n/index.js' import i18n, { loadLocaleAsync } from './i18n/index.js'
import HeroSection from './components/HeroSection.vue' import HeroSection from './components/HeroSection.vue'
import ScreenshotCarousel from './components/ScreenshotCarousel.vue' import ScreenshotCarousel from './components/ScreenshotCarousel.vue'
@@ -28,7 +28,7 @@ watch(
{ immediate: true } { immediate: true }
) )
const { t } = useI18n({ useScope: 'global' }) const { t } = useLocale()
const tabs = subTabs const tabs = subTabs
const activeTab = ref(defaultSubTab) const activeTab = ref(defaultSubTab)

View File

@@ -1,8 +1,8 @@
<script setup> <script setup>
import { useI18n } from 'vue-i18n' import { useLocale } from '../composables/useLocale.js'
import { assets } from '../config.js' import { assets } from '../config.js'
const { t } = useI18n({ useScope: 'global' }) const { t } = useLocale()
</script> </script>
<template> <template>

View File

@@ -1,9 +1,9 @@
<script setup> <script setup>
import { useI18n } from 'vue-i18n' import { useLocale } from '../composables/useLocale.js'
import Tag from './ui/Tag.vue' import Tag from './ui/Tag.vue'
import { heroMeta } from '../config.js' import { heroMeta } from '../config.js'
const { t } = useI18n({ useScope: 'global' }) const { t } = useLocale()
</script> </script>
<template> <template>

View File

@@ -1,8 +1,8 @@
<script setup> <script setup>
import { useI18n } from 'vue-i18n' import { useLocale } from '../composables/useLocale.js'
import VersionTimeline from './VersionTimeline.vue' import VersionTimeline from './VersionTimeline.vue'
const { t } = useI18n({ useScope: 'global' }) const { t } = useLocale()
</script> </script>
<template> <template>

View File

@@ -1,9 +1,9 @@
<script setup> <script setup>
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import { useI18n } from 'vue-i18n' import { useLocale } from '../composables/useLocale.js'
import { leaderboard } from '../config.js' import { leaderboard } from '../config.js'
const { t } = useI18n({ useScope: 'global' }) const { t } = useLocale()
const rows = ref([]) const rows = ref([])
const state = ref('loading') // loading | ok | error const state = ref('loading') // loading | ok | error

View File

@@ -1,9 +1,9 @@
<script setup> <script setup>
import { ref, onMounted, onUnmounted } from 'vue' import { ref, onMounted, onUnmounted } from 'vue'
import { useI18n } from 'vue-i18n' import { useLocale } from '../composables/useLocale.js'
import { assets } from '../config.js' import { assets } from '../config.js'
const { t } = useI18n({ useScope: 'global' }) const { t } = useLocale()
const images = assets.screenshots const images = assets.screenshots
const current = ref(0) const current = ref(0)
let timer = null let timer = null

View File

@@ -1,5 +1,5 @@
<script setup> <script setup>
import { useI18n } from 'vue-i18n' import { useLocale } from '../composables/useLocale.js'
const props = defineProps({ const props = defineProps({
tabs: { type: Array, required: true }, // [{ id, labelKey }] tabs: { type: Array, required: true }, // [{ id, labelKey }]
@@ -7,7 +7,7 @@ const props = defineProps({
}) })
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const { t } = useI18n({ useScope: 'global' }) const { t } = useLocale()
</script> </script>
<template> <template>

View File

@@ -1,9 +1,9 @@
<script setup> <script setup>
import { useI18n } from 'vue-i18n' import { useLocale } from '../composables/useLocale.js'
import TeamCard from './TeamCard.vue' import TeamCard from './TeamCard.vue'
import Leaderboard from './Leaderboard.vue' import Leaderboard from './Leaderboard.vue'
const { t } = useI18n({ useScope: 'global' }) const { t } = useLocale()
</script> </script>
<template> <template>

View File

@@ -1,9 +1,9 @@
<script setup> <script setup>
import { computed } from 'vue' import { computed } from 'vue'
import { useI18n } from 'vue-i18n' import { useLocale } from '../composables/useLocale.js'
import { versions, tracks } from '../data/versions.js' import { versions, tracks } from '../data/versions.js'
const { t } = useI18n({ useScope: 'global' }) const { t } = useLocale()
// 按 tracks 数组顺序分组3D 最终形态在前);同一线内按 order 排序 // 按 tracks 数组顺序分组3D 最终形态在前);同一线内按 order 排序
const grouped = computed(() => { const grouped = computed(() => {

View File

@@ -1,6 +1,6 @@
<script setup> <script setup>
import { computed } from 'vue' import { computed } from 'vue'
import { useI18n } from 'vue-i18n' import { useLocale } from '../../composables/useLocale.js'
// 可复用页面外壳 -- 统一页面的容器宽度、垂直节奏与标题。 // 可复用页面外壳 -- 统一页面的容器宽度、垂直节奏与标题。
// Props: // Props:
@@ -13,7 +13,7 @@ const props = defineProps({
padded: { type: Boolean, default: true } padded: { type: Boolean, default: true }
}) })
const { t } = useI18n({ useScope: 'global' }) const { t } = useLocale()
const title = computed(() => (props.titleKey ? t(props.titleKey) : '')) const title = computed(() => (props.titleKey ? t(props.titleKey) : ''))
</script> </script>

View File

@@ -0,0 +1,14 @@
import { computed } from 'vue'
import i18n from '../i18n/index.js'
// ★ 子项目自有的语言辅助 composable。
// 关键:直接读模块级 i18n 实例的 global composer而非 useI18n() 注入。
// 原因useI18n({ useScope: 'global' }) 解析的是「当前运行 app 已安装的全局 i18n」
// 嵌入 mainPage 时那是父项目的实例(不含本子项目 mobileGame.* 文案)-> 文案回退成 key。
// 改为直接引用本子项目实例的 .global无论是否 app.use() 都拿到本子项目的 t。
export function useLocale() {
const { t, locale } = i18n.global
const isZh = computed(() => locale.value === 'zh-CN')
const pick = (obj) => (isZh.value ? obj.zh : obj.en)
return { t, locale, isZh, pick }
}