feat(i18n): 实现用户语言偏好服务器同步功能

- 添加 UserLanguage 类型定义 ('zh-CN' | 'en-US')
- 在 UpdateUserDto 中新增 language 字段
- 实现语言切换时自动同步到服务器
- 为已登录用户保存语言偏好设置
- 服务器同步失败时降级处理,不影响本地语言切换
This commit is contained in:
richarjiang
2025-11-27 11:17:21 +08:00
parent 18d83091a9
commit 08adf0f20d
2 changed files with 26 additions and 1 deletions

View File

@@ -9,6 +9,7 @@ import { useAppDispatch, useAppSelector } from '@/hooks/redux';
import { useAuthGuard } from '@/hooks/useAuthGuard'; import { useAuthGuard } from '@/hooks/useAuthGuard';
import type { BadgeDto } from '@/services/badges'; import type { BadgeDto } from '@/services/badges';
import { reportBadgeShowcaseDisplayed } from '@/services/badges'; import { reportBadgeShowcaseDisplayed } from '@/services/badges';
import { updateUser, type UserLanguage } from '@/services/users';
import { fetchAvailableBadges, selectBadgeCounts, selectBadgePreview, selectSortedBadges } from '@/store/badgesSlice'; import { fetchAvailableBadges, selectBadgeCounts, selectBadgePreview, selectSortedBadges } from '@/store/badgesSlice';
import { selectActiveMembershipPlanName } from '@/store/membershipSlice'; import { selectActiveMembershipPlanName } from '@/store/membershipSlice';
import { DEFAULT_MEMBER_NAME, fetchActivityHistory, fetchMyProfile } from '@/store/userSlice'; import { DEFAULT_MEMBER_NAME, fetchActivityHistory, fetchMyProfile } from '@/store/userSlice';
@@ -89,13 +90,33 @@ export default function PersonalScreen() {
} }
try { try {
setIsSwitchingLanguage(true); setIsSwitchingLanguage(true);
// 将 AppLanguage ('zh' | 'en') 映射到 UserLanguage ('zh-CN' | 'en-US')
const languageMap: Record<AppLanguage, UserLanguage> = {
'zh': 'zh-CN',
'en': 'en-US',
};
const userLanguage = languageMap[language];
// 先切换本地语言
await changeAppLanguage(language); await changeAppLanguage(language);
// 如果用户已登录,同步更新服务器语言设置
if (isLoggedIn) {
try {
await updateUser({ language: userLanguage });
log.info('语言设置已同步到服务器', { language: userLanguage });
} catch (error) {
log.warn('同步语言设置到服务器失败', error);
// 服务器更新失败不影响本地语言切换,静默处理
}
}
} catch (error) { } catch (error) {
log.warn('语言切换失败', error); log.warn('语言切换失败', error);
} finally { } finally {
setIsSwitchingLanguage(false); setIsSwitchingLanguage(false);
} }
}, [activeLanguageCode, isSwitchingLanguage]); }, [activeLanguageCode, isSwitchingLanguage, isLoggedIn]);
// 推送通知设置仅在独立页面管理 // 推送通知设置仅在独立页面管理

View File

@@ -2,6 +2,9 @@ import { api } from '@/services/api';
export type Gender = 'male' | 'female'; export type Gender = 'male' | 'female';
// 用户语言设置
export type UserLanguage = 'zh-CN' | 'en-US';
export type UpdateUserDto = { export type UpdateUserDto = {
name?: string; name?: string;
avatar?: string; // base64 字符串 avatar?: string; // base64 字符串
@@ -21,6 +24,7 @@ export type UpdateUserDto = {
armCircumference?: number; // 臂围 armCircumference?: number; // 臂围
thighCircumference?: number; // 大腿围 thighCircumference?: number; // 大腿围
calfCircumference?: number; // 小腿围 calfCircumference?: number; // 小腿围
language?: UserLanguage; // 用户语言偏好
}; };
export async function updateUser(dto: UpdateUserDto): Promise<Record<string, any>> { export async function updateUser(dto: UpdateUserDto): Promise<Record<string, any>> {