mirror of
https://gitee.com/devlive-community/datacap.git
synced 2024-11-29 18:48:23 +08:00
feat(i18n): fix the problem of using the default language after language acquisition fails
This commit is contained in:
parent
5583aae80c
commit
97f1ee0bd8
@ -127,18 +127,5 @@
|
||||
<artifactId>datacap-executor-spi</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- Sql Parser -->
|
||||
<dependency>
|
||||
<groupId>io.edurt.datacap</groupId>
|
||||
<artifactId>datacap-parser-trino</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.edurt.datacap</groupId>
|
||||
<artifactId>datacap-parser-mysql</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -15,6 +15,7 @@ public interface Adapter
|
||||
|
||||
default List<Object> handlerFormatter(PluginManager pluginManager, String format, List<String> headers, List<Object> columns)
|
||||
{
|
||||
|
||||
return ConvertFilter.filter(pluginManager, format)
|
||||
.map(file -> {
|
||||
ConvertRequest request = new ConvertRequest();
|
||||
|
@ -2,59 +2,123 @@ import { createI18n } from 'vue-i18n'
|
||||
import { inject, provide, ref } from 'vue'
|
||||
import I18nService from '@/services/i18n'
|
||||
|
||||
// 默认语言配置
|
||||
// Default locale
|
||||
const DEFAULT_LOCALE = 'zh_cn'
|
||||
const DEFAULT_MESSAGES = {
|
||||
zh_cn: {
|
||||
// 基础的回退翻译
|
||||
// Basic fallback translation
|
||||
common: {
|
||||
loading: 'Loading...',
|
||||
networkError: 'Network error',
|
||||
loadingFailed: 'Loading failed'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const language = (navigator.language || 'en').toLocaleLowerCase()
|
||||
|
||||
const i18n = createI18n({
|
||||
fallbackLocale: 'zh_cn',
|
||||
fallbackLocale: DEFAULT_LOCALE,
|
||||
globalInjection: true,
|
||||
legacy: false,
|
||||
silentFallbackWarn: true,
|
||||
fallbackWarn: false,
|
||||
silentTranslationWarn: true,
|
||||
missingWarn: false,
|
||||
locale: localStorage.getItem('locale') || language.split('-')[0] || 'zh_cn',
|
||||
messages: {}
|
||||
locale: localStorage.getItem('locale') || language.split('-')[0] || DEFAULT_LOCALE,
|
||||
messages: DEFAULT_MESSAGES
|
||||
})
|
||||
|
||||
export const I18N_KEY = Symbol('i18n-handler')
|
||||
|
||||
export const loadingState = ref(false)
|
||||
export const loadingText = ref('')
|
||||
export const errorState = ref(false)
|
||||
export const errorMessage = ref('')
|
||||
|
||||
export function provideI18nHandler()
|
||||
{
|
||||
const resetState = () => {
|
||||
loadingState.value = false
|
||||
loadingText.value = ''
|
||||
errorState.value = false
|
||||
errorMessage.value = ''
|
||||
}
|
||||
|
||||
const loadLocale = async (locale: string) => {
|
||||
// 如果请求的语言包已经加载过,直接使用
|
||||
// If the requested language package has been loaded, use it directly
|
||||
// @ts-ignore
|
||||
if (i18n.global.availableLocales.includes(locale) &&
|
||||
Object.keys(i18n.global.getLocaleMessage(locale)).length > 1) {
|
||||
// @ts-ignore
|
||||
i18n.global.locale.value = locale
|
||||
localStorage.setItem('locale', locale)
|
||||
return true
|
||||
}
|
||||
|
||||
resetState()
|
||||
loadingState.value = true
|
||||
loadingText.value = 'Loading language...'
|
||||
loadingText.value = i18n.global.t('common.loading')
|
||||
|
||||
try {
|
||||
const response = await I18nService.getLocale(locale)
|
||||
if (response.status) {
|
||||
i18n.global.setLocaleMessage(locale, response.data)
|
||||
if (response.status && response.data && Object.keys(response.data).length > 0) {
|
||||
i18n.global.setLocaleMessage(locale, {
|
||||
...DEFAULT_MESSAGES[DEFAULT_LOCALE],
|
||||
...response.data
|
||||
})
|
||||
// @ts-ignore
|
||||
i18n.global.locale.value = locale
|
||||
localStorage.setItem('locale', locale)
|
||||
resetState()
|
||||
return true
|
||||
}
|
||||
else {
|
||||
throw new Error('Invalid locale data received')
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
errorState.value = true
|
||||
errorMessage.value = error instanceof Error ? error.message : i18n.global.t('common.loadingFailed')
|
||||
|
||||
// 如果加载失败,确保至少有基础翻译可用
|
||||
// Ensure that at least the basic translation is available
|
||||
// @ts-ignore
|
||||
if (!i18n.global.availableLocales.includes(locale)) {
|
||||
i18n.global.setLocaleMessage(locale, DEFAULT_MESSAGES[DEFAULT_LOCALE])
|
||||
}
|
||||
|
||||
// 如果当前语言加载失败,尝试回退到默认语言
|
||||
// If the current language fails to load, try to fall back to the default language
|
||||
if (locale !== DEFAULT_LOCALE &&
|
||||
!i18n.global.availableLocales.includes(i18n.global.locale.value)) {
|
||||
i18n.global.locale.value = DEFAULT_LOCALE
|
||||
localStorage.setItem('locale', DEFAULT_LOCALE)
|
||||
}
|
||||
|
||||
console.error('Failed to load locale:', error)
|
||||
return false
|
||||
}
|
||||
finally {
|
||||
loadingState.value = false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
provide(I18N_KEY, {
|
||||
const i18nHandler = {
|
||||
loadLocale,
|
||||
loadingState,
|
||||
loadingText
|
||||
})
|
||||
|
||||
return {
|
||||
loadLocale,
|
||||
loadingState,
|
||||
loadingText
|
||||
loadingText,
|
||||
errorState,
|
||||
errorMessage,
|
||||
resetState
|
||||
}
|
||||
|
||||
provide(I18N_KEY, i18nHandler)
|
||||
|
||||
return i18nHandler
|
||||
}
|
||||
|
||||
// Hook
|
||||
|
@ -66,9 +66,27 @@ export class HttpUtils
|
||||
message: error.message,
|
||||
status: false
|
||||
}
|
||||
if (error.code === 'ERR_NETWORK') {
|
||||
router.push('/common/not_network?redirect=' + router.currentRoute.value.fullPath)
|
||||
|
||||
// 检查当前路由,避免重复重定向
|
||||
// Current route path, avoid repeated redirection
|
||||
const currentPath = router.currentRoute.value.path
|
||||
const isAlreadyOnErrorPage = currentPath.startsWith('/common/not_network')
|
||||
|
||||
if (error.code === 'ERR_NETWORK' && !isAlreadyOnErrorPage) {
|
||||
// 记录用户原始请求的页面路径
|
||||
// Record the original page path of the user
|
||||
const originalPath = router.currentRoute.value.fullPath
|
||||
router.push({
|
||||
path: '/common/not_network',
|
||||
query: {
|
||||
redirect: originalPath
|
||||
},
|
||||
// 替换当前的历史记录,这样用户点击后退时不会陷入循环
|
||||
// Replace the current history record, so that the user can not enter a loop
|
||||
replace: true
|
||||
})
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,22 @@
|
||||
<template>
|
||||
<div class="relative">
|
||||
<div class="relative min-h-screen">
|
||||
<!-- Loading State -->
|
||||
<div class="relative" v-if="loadingState" style="height: 100vh;">
|
||||
<ShadcnSpin v-model="loadingState" fixed>
|
||||
{{ loadingText }}
|
||||
</ShadcnSpin>
|
||||
</div>
|
||||
|
||||
<div v-show="!loadingState">
|
||||
<!-- Error State -->
|
||||
<div v-if="errorState && !loadingState" class="fixed inset-0 flex items-center justify-center bg-background/80 backdrop-blur-sm">
|
||||
<div class="flex flex-col items-center space-y-4">
|
||||
<ShadcnText type="h3">{{ errorMessage }}</ShadcnText>
|
||||
<ShadcnButton @click="handleRetry">Retry 重试</ShadcnButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Content -->
|
||||
<div v-show="!loadingState && !errorState">
|
||||
<slot/>
|
||||
</div>
|
||||
</div>
|
||||
@ -16,9 +26,15 @@
|
||||
import { onBeforeMount } from 'vue'
|
||||
import { provideI18nHandler } from '@/i18n/I18n'
|
||||
|
||||
const { loadLocale, loadingState, loadingText } = provideI18nHandler()
|
||||
const {
|
||||
loadLocale,
|
||||
loadingState,
|
||||
loadingText,
|
||||
errorState,
|
||||
errorMessage
|
||||
} = provideI18nHandler()
|
||||
|
||||
onBeforeMount(async () => {
|
||||
const handleRetry = async () => {
|
||||
try {
|
||||
const locale = localStorage.getItem('locale') || 'zh_cn'
|
||||
await loadLocale(locale)
|
||||
@ -26,5 +42,9 @@ onBeforeMount(async () => {
|
||||
catch (error) {
|
||||
console.error('Failed to load locale:', error)
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeMount(async () => {
|
||||
await handleRetry()
|
||||
})
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue
Block a user