feat(i18n): 实现国际化支持并优化 WebSocket 连接

- 移除 App.vue 中的固定语言设置
- 在 i18n.ts 中实现系统语言自动检测和手动设置支持
- 添加语言切换时重新连接 WebSocket 的逻辑
- 在 profile 页面添加语言设置入口
- 优化 WebSocket连接过程,添加 accept-language头
This commit is contained in:
xingyy 2025-02-27 14:38:03 +08:00
parent c524bf34f5
commit 462a2b23a9
4 changed files with 86 additions and 15 deletions

View File

@ -17,7 +17,6 @@ const router = useRouter()
const route = useRoute()
const slideDirection = ref('slide-left')
const { locale } = useI18n()
// locale.value = 'en-US'
//
const routeHistory = ref([])

View File

@ -78,6 +78,13 @@ fetchData()
</div>
</div>
<!-- 设置选项 -->
<div class="px-16px mb-20px">
<van-cell-group inset>
<van-cell :title="$t('settings.language')" is-link @click="router.push('/profile/language')" />
</van-cell-group>
</div>
<!-- 列表内容 -->
<div class="grow-1 flex flex-col">
<div class="border-b-1px border-b-#D3D3D3 px-16px">

View File

@ -15,22 +15,59 @@ export default defineNuxtPlugin(() => {
if (import.meta.client) {
const i18n = useNuxtApp().$i18n
const { setLocale } = i18n
const nuxtApp = useNuxtApp()
// 暂时设置固定语言,用于调试
// 可以根据需要修改这里的语言代码:'zh-CN' | 'en-US' | 'ja-JP' | 'zh-TW'
/* const fixedLang = 'zh-CN'
setLocale(fixedLang)
Locale.use(fixedLang)*/
// 获取系统语言
const getSystemLanguage = () => {
const browserLang = navigator.language
// 原自动检测系统语言的逻辑(暂时注释)
// 将浏览器语言映射到应用支持的语言
if (browserLang.startsWith('zh')) {
return browserLang.includes('TW') || browserLang.includes('HK') ? 'zh-TW' : 'zh-CN'
} else if (browserLang.startsWith('ja')) {
return 'ja-JP'
} else if (browserLang.startsWith('en')) {
return 'en-US'
}
// 默认返回中文
return 'zh-CN'
}
// 获取用户手动设置的语言或系统语言
const lang = localStorage.getItem('lang')
if (lang) {
// 用户手动设置了语言,优先使用
setLocale(lang as TypeLocale)
Locale.use(lang)
} else {
// 用户未手动设置语言,使用系统语言
const systemLang = getSystemLanguage()
setLocale(systemLang as TypeLocale)
Locale.use(systemLang)
// 将系统语言保存到 localStorage以便下次使用
localStorage.setItem('lang', systemLang)
}
else {
setLocale(i18n.locale.value)
Locale.use(i18n.locale.value)
}
// 监听系统语言变化(当用户未手动设置语言时)
window.addEventListener('languagechange', () => {
// 只有当用户未手动设置语言时,才跟随系统语言变化
if (!localStorage.getItem('lang')) {
const systemLang = getSystemLanguage()
setLocale(systemLang as TypeLocale)
Locale.use(systemLang)
}
})
// 监听语言变化,当语言变化时,如果有活跃的 WebSocket 连接,则重新连接
watch(() => i18n.locale.value, (newLocale) => {
// 如果 WebSocket 插件已加载并且有活跃连接
if (nuxtApp.$ws) {
// 使用 refreshConnection 方法刷新 WebSocket 连接
console.log('语言已更改为:', newLocale, '正在更新 WebSocket 连接')
nuxtApp.$ws.refreshConnection()
}
})
}
})

View File

@ -3,22 +3,39 @@ import {authStore} from "@/stores/auth";
export default defineNuxtPlugin(() => {
const config = useRuntimeConfig()
const { token } = authStore()
const i18n = useNuxtApp().$i18n
const ws = reactive({
instance: null as WebSocket | null,
isConnected: false,
currentPath: '', // 保存当前连接的路径
currentData: null as Record<string, any> | null, // 保存当前连接的数据
// 修改 connect 方法接收路径和数据对象
connect(path: string, data?: Record<string, any>) {
// 保存当前连接的路径和数据,以便后续重连使用
this.currentPath = path
this.currentData = data || null
if (this.instance?.readyState === WebSocket.OPEN) {
this.instance.close()
}
// 构建查询字符串
const queryString =data
? '?' + Object.entries({ token: token.value,...data})
? '?' + Object.entries({
token: token.value,
'accept-language': i18n.locale.value, // 添加当前语言作为 accept-language
...data
})
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join('&')
: '?' + Object.entries({
token: token.value,
'accept-language': i18n.locale.value // 即使没有其他数据,也添加语言
})
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join('&')
: ''
// 构建完整的 WebSocket URL
const wsUrl = `${config.public.NUXT_PUBLIC_SOCKET_URL}${path}${queryString}`
@ -50,13 +67,24 @@ export default defineNuxtPlugin(() => {
},
// 更新重连方法以支持数据对象
reconnect(path: string, data?: Record<string, any>) {
reconnect(path?: string, data?: Record<string, any>) {
setTimeout(() => {
console.log('尝试重新连接...')
this.connect(path, data)
// 如果提供了新的路径和数据,则使用新的;否则使用保存的当前路径和数据
this.connect(path || this.currentPath, data || this.currentData || undefined)
}, 3000)
},
// 使用当前保存的路径和数据重新连接
refreshConnection() {
if (this.currentPath) {
console.log('刷新 WebSocket 连接,使用当前语言:', i18n.locale.value)
this.connect(this.currentPath, this.currentData || undefined)
return true
}
return false // 如果没有当前连接信息,返回 false
},
// 发送消息
send(data: any) {
if (this.instance?.readyState === WebSocket.OPEN) {