feat(i18n): 添加 HTTP 错误的国际化支持

- 在 en-US、ja-JP、zh-CN 和 zh-TW 语言文件中添加了 HTTP 错误相关翻译
- 更新了 http.js 文件,使用国际化消息替换硬编码的错误提示
- 优化了错误处理逻辑,提高了代码的可维护性和用户体验
This commit is contained in:
xingyy 2025-02-26 14:08:04 +08:00
parent 589e02c5fe
commit 44703705f9
7 changed files with 120 additions and 47 deletions

View File

@ -6,25 +6,26 @@ import {codeAuthStore} from "@/stores-collect-code/auth/index.js"
let httpStatusErrorHandler let httpStatusErrorHandler
let http let http
// HTTP 状态码映射 // HTTP 状态码映射 - 使用i18n国际化
const HTTP_STATUS_MAP = {
400: '请求参数错误',
401: '未授权或登录过期',
403: '访问被禁止',
404: '请求的资源不存在',
500: '服务器内部错误',
502: '网关错误',
503: '服务暂时不可用',
504: '网关超时'
}
export function setupHttp() { export function setupHttp() {
if (http) return http if (http) return http
const {token}= codeAuthStore() const {token}= codeAuthStore()
const config = useRuntimeConfig() const config = useRuntimeConfig()
const baseURL = config.public.NUXT_PUBLIC_API_COLLECT_CODE const baseURL = config.public.NUXT_PUBLIC_API_COLLECT_CODE
const router = useRouter() const router = useRouter()
const i18n = useNuxtApp().$i18n
// 国际化的HTTP状态码映射
const HTTP_STATUS_MAP = {
400: i18n.t('http.error.badRequest'),
401: i18n.t('http.error.unauthorized'),
403: i18n.t('http.error.forbidden'),
404: i18n.t('http.error.notFound'),
500: i18n.t('http.error.serverError'),
502: i18n.t('http.error.badGateway'),
503: i18n.t('http.error.serviceUnavailable'),
504: i18n.t('http.error.gatewayTimeout')
}
const defaultOptions = { const defaultOptions = {
baseURL, baseURL,
@ -42,7 +43,8 @@ export function setupHttp() {
// 添加 token // 添加 token
options.headers = { options.headers = {
...options.headers, ...options.headers,
Authorization: token.value Authorization: token.value,
'accept-language': i18n.locale.value
} }
// GET 请求添加时间戳防止缓存 // GET 请求添加时间戳防止缓存
@ -60,12 +62,12 @@ export function setupHttp() {
// 处理业务错误 // 处理业务错误
if (data.status === 1) { if (data.status === 1) {
message.error(data.msg || '操作失败') message.error(data.msg || i18n.t('http.error.operationFailed'))
} }
// 处理登录失效 // 处理登录失效
if (data.status === 401) { if (data.status === 401) {
message.error('登录已过期,请重新登录') message.error(i18n.t('http.error.loginExpired'))
token.value = '' // 清除 token token.value = '' // 清除 token
router.replace('/collectCode/login') router.replace('/collectCode/login')
} }
@ -77,14 +79,14 @@ export function setupHttp() {
async onResponseError({ response, request }) { async onResponseError({ response, request }) {
// 网络错误 // 网络错误
if (!response) { if (!response) {
message.error('网络连接失败,请检查网络设置') message.error(i18n.t('http.error.networkError'))
return Promise.reject(new Error('网络错误')) return Promise.reject(new Error(i18n.t('http.error.networkError')))
} }
const status = response.status const status = response.status
const data = response._data const data = response._data
// 处理 HTTP 状态错误 // 处理 HTTP 状态错误
const errorMessage = data.msg || HTTP_STATUS_MAP[status] || '请求失败' const errorMessage = data.msg || HTTP_STATUS_MAP[status] || i18n.t('http.error.requestFailed')
if (Array.isArray(data.msg)) { if (Array.isArray(data.msg)) {
data.msg.forEach(item => { data.msg.forEach(item => {
@ -112,7 +114,7 @@ export function injectHttpStatusErrorHandler(handler) {
export function getHttp() { export function getHttp() {
if (!http) { if (!http) {
throw new Error('HTTP client not initialized. Call setupHttp first.') throw new Error(useNuxtApp().$i18n.t('http.error.httpNotInitialized'))
} }
return http return http
} }

View File

@ -6,26 +6,27 @@ import {authStore} from "@/stores/auth/index.js"
let httpStatusErrorHandler let httpStatusErrorHandler
let http let http
// HTTP 状态码映射 // HTTP 状态码映射 - 使用i18n国际化
const HTTP_STATUS_MAP = {
400: '请求参数错误',
401: '未授权或登录过期',
403: '访问被禁止',
404: '请求的资源不存在',
500: '服务器内部错误',
502: '网关错误',
503: '服务暂时不可用',
504: '网关超时'
}
export function setupHttp() { export function setupHttp() {
if (http) return http if (http) return http
const config = useRuntimeConfig() const config = useRuntimeConfig()
const baseURL = config.public.NUXT_PUBLIC_API_BASE const baseURL = config.public.NUXT_PUBLIC_API_BASE
const { token } = authStore() const { token } = authStore()
const router = useRouter() const router = useRouter()
const i18n = useNuxtApp().$i18n
// 国际化的HTTP状态码映射
const HTTP_STATUS_MAP = {
400: i18n.t('http.error.badRequest'),
401: i18n.t('http.error.unauthorized'),
403: i18n.t('http.error.forbidden'),
404: i18n.t('http.error.notFound'),
500: i18n.t('http.error.serverError'),
502: i18n.t('http.error.badGateway'),
503: i18n.t('http.error.serviceUnavailable'),
504: i18n.t('http.error.gatewayTimeout')
}
const defaultOptions = { const defaultOptions = {
baseURL, baseURL,
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
@ -33,7 +34,6 @@ export function setupHttp() {
retry: 3, retry: 3,
retryDelay: 1000, retryDelay: 1000,
} }
http = ofetch.create({ http = ofetch.create({
...defaultOptions, ...defaultOptions,
@ -42,8 +42,10 @@ export function setupHttp() {
// 添加 token // 添加 token
options.headers = { options.headers = {
...options.headers, ...options.headers,
Authorization: token.value Authorization: token.value,
} 'accept-language':i18n.locale.value
}
// GET 请求添加时间戳防止缓存 // GET 请求添加时间戳防止缓存
if (request.toLowerCase().includes('get')) { if (request.toLowerCase().includes('get')) {
@ -60,12 +62,12 @@ export function setupHttp() {
// 处理业务错误 // 处理业务错误
if (data.status === 1) { if (data.status === 1) {
message.error(data.msg || '操作失败') message.error(data.msg || i18n.t('http.error.operationFailed'))
} }
// 处理登录失效 // 处理登录失效
if (data.status === 401) { if (data.status === 401) {
message.error('登录已过期,请重新登录') message.error(i18n.t('http.error.loginExpired'))
token.value = '' // 清除 token token.value = '' // 清除 token
router.replace('/login') router.replace('/login')
} }
@ -77,14 +79,14 @@ export function setupHttp() {
async onResponseError({ response, request }) { async onResponseError({ response, request }) {
// 网络错误 // 网络错误
if (!response) { if (!response) {
message.error('网络连接失败,请检查网络设置') message.error(i18n.t('http.error.networkError'))
return Promise.reject(new Error('网络错误')) return Promise.reject(new Error(i18n.t('http.error.networkError')))
} }
const status = response.status const status = response.status
const data = response._data const data = response._data
// 处理 HTTP 状态错误 // 处理 HTTP 状态错误
const errorMessage = data.msg || HTTP_STATUS_MAP[status] || '请求失败' const errorMessage = data.msg || HTTP_STATUS_MAP[status] || i18n.t('http.error.requestFailed')
if (Array.isArray(data.msg)) { if (Array.isArray(data.msg)) {
data.msg.forEach(item => { data.msg.forEach(item => {
@ -112,7 +114,7 @@ export function injectHttpStatusErrorHandler(handler) {
export function getHttp() { export function getHttp() {
if (!http) { if (!http) {
throw new Error('HTTP client not initialized. Call setupHttp first.') throw new Error(useNuxtApp().$i18n.t('http.error.httpNotInitialized'))
} }
return http return http
} }

View File

@ -18,12 +18,11 @@ export default defineNuxtPlugin(() => {
// 暂时设置固定语言,用于调试 // 暂时设置固定语言,用于调试
// 可以根据需要修改这里的语言代码:'zh-CN' | 'en-US' | 'ja-JP' | 'zh-TW' // 可以根据需要修改这里的语言代码:'zh-CN' | 'en-US' | 'ja-JP' | 'zh-TW'
const fixedLang = 'en-US' /* const fixedLang = 'ja-JP'
setLocale(fixedLang) setLocale(fixedLang)
Locale.use(fixedLang) Locale.use(fixedLang)*/
// 原自动检测系统语言的逻辑(暂时注释) // 原自动检测系统语言的逻辑(暂时注释)
/*
const lang = localStorage.getItem('lang') const lang = localStorage.getItem('lang')
if (lang) { if (lang) {
setLocale(lang as TypeLocale) setLocale(lang as TypeLocale)
@ -33,6 +32,5 @@ export default defineNuxtPlugin(() => {
setLocale(i18n.locale.value) setLocale(i18n.locale.value)
Locale.use(i18n.locale.value) Locale.use(i18n.locale.value)
} }
*/
} }
}) })

View File

@ -641,5 +641,22 @@
}, },
"floatingBubble": { "floatingBubble": {
"backToLive": "Back to Live" "backToLive": "Back to Live"
},
"http": {
"error": {
"badRequest": "Invalid request parameters",
"unauthorized": "Unauthorized or login expired",
"forbidden": "Access forbidden",
"notFound": "Requested resource not found",
"serverError": "Server internal error",
"badGateway": "Gateway error",
"serviceUnavailable": "Service temporarily unavailable",
"gatewayTimeout": "Gateway timeout",
"operationFailed": "Operation failed",
"loginExpired": "Login has expired, please login again",
"networkError": "Network connection failed, please check your network settings",
"requestFailed": "Request failed",
"httpNotInitialized": "HTTP client not initialized. Call setupHttp first."
}
} }
} }

View File

@ -641,5 +641,22 @@
}, },
"floatingBubble": { "floatingBubble": {
"backToLive": "ライブに戻る" "backToLive": "ライブに戻る"
},
"http": {
"error": {
"badRequest": "リクエストパラメータが無効です",
"unauthorized": "認証されていないか、ログインが期限切れです",
"forbidden": "アクセスが禁止されています",
"notFound": "要求されたリソースが見つかりません",
"serverError": "サーバー内部エラー",
"badGateway": "ゲートウェイエラー",
"serviceUnavailable": "サービスが一時的に利用できません",
"gatewayTimeout": "ゲートウェイタイムアウト",
"operationFailed": "操作に失敗しました",
"loginExpired": "ログインの有効期限が切れました。再度ログインしてください",
"networkError": "ネットワーク接続に失敗しました。ネットワーク設定を確認してください",
"requestFailed": "リクエストに失敗しました",
"httpNotInitialized": "HTTPクライアントが初期化されていません。先にsetupHttpを呼び出してください"
}
} }
} }

View File

@ -638,5 +638,25 @@
"uploadSuccess": "上传成功", "uploadSuccess": "上传成功",
"uploadFail": "上传失败" "uploadFail": "上传失败"
} }
},
"floatingBubble": {
"backToLive": "回到直播"
},
"http": {
"error": {
"badRequest": "请求参数错误",
"unauthorized": "未授权或登录过期",
"forbidden": "访问被禁止",
"notFound": "请求的资源不存在",
"serverError": "服务器内部错误",
"badGateway": "网关错误",
"serviceUnavailable": "服务暂时不可用",
"gatewayTimeout": "网关超时",
"operationFailed": "操作失败",
"loginExpired": "登录已过期,请重新登录",
"networkError": "网络连接失败,请检查网络设置",
"requestFailed": "请求失败",
"httpNotInitialized": "HTTP客户端未初始化请先调用setupHttp"
}
} }
} }

View File

@ -641,6 +641,23 @@
}, },
"floatingBubble": { "floatingBubble": {
"backToLive": "回到直播" "backToLive": "回到直播"
},
"http": {
"error": {
"badRequest": "請求參數錯誤",
"unauthorized": "未授權或登錄過期",
"forbidden": "訪問被禁止",
"notFound": "請求的資源不存在",
"serverError": "伺服器內部錯誤",
"badGateway": "閘道錯誤",
"serviceUnavailable": "服務暫時不可用",
"gatewayTimeout": "閘道超時",
"operationFailed": "操作失敗",
"loginExpired": "登錄已過期,請重新登錄",
"networkError": "網絡連接失敗,請檢查網絡設置",
"requestFailed": "請求失敗",
"httpNotInitialized": "HTTP客戶端未初始化請先調用setupHttp"
}
} }
} }