feat(i18n): 实现应用国际化支持,添加中英文翻译

- 为所有UI组件添加国际化支持,替换硬编码文本
- 新增useI18n钩子函数统一管理翻译
- 完善中英文翻译资源,覆盖统计、用药、通知设置等模块
- 优化Tab布局使用翻译键值替代静态文本
- 更新药品管理、个人资料编辑等页面的多语言支持
This commit is contained in:
richarjiang
2025-11-13 11:09:55 +08:00
parent 416d144387
commit 2dca3253e6
21 changed files with 1669 additions and 366 deletions

View File

@@ -7,6 +7,7 @@ import dayjs from 'dayjs';
import { Image } from 'expo-image';
import { router } from 'expo-router';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
@@ -19,6 +20,7 @@ const SleepCard: React.FC<SleepCardProps> = ({
selectedDate,
style,
}) => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const challenges = useAppSelector(selectChallengeList);
const [sleepDuration, setSleepDuration] = useState<number | null>(null);
@@ -39,7 +41,7 @@ const SleepCard: React.FC<SleepCardProps> = ({
const data = await fetchCompleteSleepData(selectedDate);
setSleepDuration(data?.totalSleepTime || null);
} catch (error) {
console.error('SleepCard: 获取睡眠数据失败:', error);
console.error('SleepCard: Failed to get sleep data:', error);
setSleepDuration(null);
} finally {
setLoading(false);
@@ -75,7 +77,7 @@ const SleepCard: React.FC<SleepCardProps> = ({
try {
await dispatch(reportChallengeProgress({ id: sleepChallenge.id, value: sleepDuration })).unwrap();
} catch (error) {
logger.warn('SleepCard: 挑战进度上报失败', { error, challengeId: sleepChallenge.id });
logger.warn('SleepCard: Challenge progress report failed', { error, challengeId: sleepChallenge.id });
}
lastReportedRef.current = { date: dateKey, value: sleepDuration };
@@ -91,10 +93,10 @@ const SleepCard: React.FC<SleepCardProps> = ({
source={require('@/assets/images/icons/icon-sleep.png')}
style={styles.titleIcon}
/>
<Text style={styles.cardTitle}></Text>
<Text style={styles.cardTitle}>{t('statistics.components.sleep.title')}</Text>
</View>
<Text style={styles.sleepValue}>
{loading ? '加载中...' : (sleepDuration != null ? formatSleepTime(sleepDuration) : '--')}
{loading ? t('statistics.components.sleep.loading') : (sleepDuration != null ? formatSleepTime(sleepDuration) : '--')}
</Text>
</View>
);