feat(i18n): 全面实现应用核心功能模块的国际化支持
- 新增 i18n 翻译资源,覆盖睡眠、饮水、体重、锻炼、用药 AI 识别、步数、健身圆环、基础代谢及设置等核心模块 - 重构相关页面及组件(如 SleepDetail, WaterDetail, WorkoutHistory 等)使用 `useI18n` 钩子替换硬编码文本 - 升级 `utils/date` 工具库与 `DateSelector` 组件,支持基于语言环境的日期格式化与显示 - 完善登录页、注销流程及权限申请弹窗的双语提示信息 - 优化部分页面的 UI 细节与字体样式以适配多语言显示
This commit is contained in:
@@ -22,9 +22,11 @@ import {
|
||||
} from 'react-native';
|
||||
|
||||
import { HeaderBar } from '@/components/ui/HeaderBar';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { useSafeAreaTop } from '@/hooks/useSafeAreaWithPadding';
|
||||
|
||||
const WaterReminderSettings: React.FC = () => {
|
||||
const { t } = useI18n();
|
||||
const safeAreaTop = useSafeAreaTop()
|
||||
const theme = (useColorScheme() ?? 'light') as 'light' | 'dark';
|
||||
const colorTokens = Colors[theme];
|
||||
@@ -71,9 +73,9 @@ const WaterReminderSettings: React.FC = () => {
|
||||
setStartTimePickerVisible(false);
|
||||
} else {
|
||||
Alert.alert(
|
||||
'时间设置提示',
|
||||
'开始时间不能晚于或等于结束时间,请重新选择',
|
||||
[{ text: '确定' }]
|
||||
t('waterReminderSettings.alerts.timeValidation.title'),
|
||||
t('waterReminderSettings.alerts.timeValidation.startTimeInvalid'),
|
||||
[{ text: t('waterReminderSettings.buttons.confirm') }]
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -91,9 +93,9 @@ const WaterReminderSettings: React.FC = () => {
|
||||
setEndTimePickerVisible(false);
|
||||
} else {
|
||||
Alert.alert(
|
||||
'时间设置提示',
|
||||
'结束时间不能早于或等于开始时间,请重新选择',
|
||||
[{ text: '确定' }]
|
||||
t('waterReminderSettings.alerts.timeValidation.title'),
|
||||
t('waterReminderSettings.alerts.timeValidation.endTimeInvalid'),
|
||||
[{ text: t('waterReminderSettings.buttons.confirm') }]
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -125,18 +127,28 @@ const WaterReminderSettings: React.FC = () => {
|
||||
|
||||
if (waterReminderSettings.enabled) {
|
||||
const timeInfo = `${waterReminderSettings.startTime}-${waterReminderSettings.endTime}`;
|
||||
const intervalInfo = `每${waterReminderSettings.interval}分钟`;
|
||||
const intervalInfo = `${waterReminderSettings.interval}${t('waterReminderSettings.labels.minutes')}`;
|
||||
Alert.alert(
|
||||
'设置成功',
|
||||
`喝水提醒已开启\n\n时间段:${timeInfo}\n提醒间隔:${intervalInfo}\n\n我们将在指定时间段内定期提醒您喝水`,
|
||||
[{ text: '确定', onPress: () => router.back() }]
|
||||
t('waterReminderSettings.alerts.success.enabled'),
|
||||
t('waterReminderSettings.alerts.success.enabledMessage', {
|
||||
timeRange: timeInfo,
|
||||
interval: intervalInfo
|
||||
}),
|
||||
[{ text: t('waterReminderSettings.buttons.confirm'), onPress: () => router.back() }]
|
||||
);
|
||||
} else {
|
||||
Alert.alert('设置成功', '喝水提醒已关闭', [{ text: '确定', onPress: () => router.back() }]);
|
||||
Alert.alert(
|
||||
t('waterReminderSettings.alerts.success.disabled'),
|
||||
t('waterReminderSettings.alerts.success.disabledMessage'),
|
||||
[{ text: t('waterReminderSettings.buttons.confirm'), onPress: () => router.back() }]
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('保存喝水提醒设置失败:', error);
|
||||
Alert.alert('保存失败', '无法保存喝水提醒设置,请重试');
|
||||
Alert.alert(
|
||||
t('waterReminderSettings.alerts.error.title'),
|
||||
t('waterReminderSettings.alerts.error.message')
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -176,7 +188,7 @@ const WaterReminderSettings: React.FC = () => {
|
||||
<View style={styles.decorativeCircle2} />
|
||||
|
||||
<HeaderBar
|
||||
title="喝水提醒"
|
||||
title={t('waterReminderSettings.title')}
|
||||
onBack={() => {
|
||||
router.back();
|
||||
}}
|
||||
@@ -198,7 +210,7 @@ const WaterReminderSettings: React.FC = () => {
|
||||
<View style={styles.waterReminderSectionHeader}>
|
||||
<View style={styles.waterReminderSectionTitleContainer}>
|
||||
<Ionicons name="notifications-outline" size={20} color={colorTokens.text} />
|
||||
<Text style={[styles.waterReminderSectionTitle, { color: colorTokens.text }]}>推送提醒</Text>
|
||||
<Text style={[styles.waterReminderSectionTitle, { color: colorTokens.text }]}>{t('waterReminderSettings.sections.notifications')}</Text>
|
||||
</View>
|
||||
<Switch
|
||||
value={waterReminderSettings.enabled}
|
||||
@@ -208,7 +220,7 @@ const WaterReminderSettings: React.FC = () => {
|
||||
/>
|
||||
</View>
|
||||
<Text style={[styles.waterReminderSectionDesc, { color: colorTokens.textSecondary }]}>
|
||||
开启后将在指定时间段内定期推送喝水提醒
|
||||
{t('waterReminderSettings.descriptions.notifications')}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
@@ -216,15 +228,15 @@ const WaterReminderSettings: React.FC = () => {
|
||||
{waterReminderSettings.enabled && (
|
||||
<>
|
||||
<View style={styles.waterReminderSection}>
|
||||
<Text style={[styles.waterReminderSectionTitle, { color: colorTokens.text }]}>提醒时间段</Text>
|
||||
<Text style={[styles.waterReminderSectionTitle, { color: colorTokens.text }]}>{t('waterReminderSettings.sections.timeRange')}</Text>
|
||||
<Text style={[styles.waterReminderSectionDesc, { color: colorTokens.textSecondary }]}>
|
||||
只在指定时间段内发送提醒,避免打扰您的休息
|
||||
{t('waterReminderSettings.descriptions.timeRange')}
|
||||
</Text>
|
||||
|
||||
<View style={styles.timeRangeContainer}>
|
||||
{/* 开始时间 */}
|
||||
<View style={styles.timePickerContainer}>
|
||||
<Text style={[styles.timeLabel, { color: colorTokens.text }]}>开始时间</Text>
|
||||
<Text style={[styles.timeLabel, { color: colorTokens.text }]}>{t('waterReminderSettings.labels.startTime')}</Text>
|
||||
<Pressable
|
||||
style={[styles.timePicker, { backgroundColor: 'white' }]}
|
||||
onPress={openStartTimePicker}
|
||||
@@ -236,7 +248,7 @@ const WaterReminderSettings: React.FC = () => {
|
||||
|
||||
{/* 结束时间 */}
|
||||
<View style={styles.timePickerContainer}>
|
||||
<Text style={[styles.timeLabel, { color: colorTokens.text }]}>结束时间</Text>
|
||||
<Text style={[styles.timeLabel, { color: colorTokens.text }]}>{t('waterReminderSettings.labels.endTime')}</Text>
|
||||
<Pressable
|
||||
style={[styles.timePicker, { backgroundColor: 'white' }]}
|
||||
onPress={openEndTimePicker}
|
||||
@@ -250,9 +262,9 @@ const WaterReminderSettings: React.FC = () => {
|
||||
|
||||
{/* 提醒间隔设置 */}
|
||||
<View style={styles.waterReminderSection}>
|
||||
<Text style={[styles.waterReminderSectionTitle, { color: colorTokens.text }]}>提醒间隔</Text>
|
||||
<Text style={[styles.waterReminderSectionTitle, { color: colorTokens.text }]}>{t('waterReminderSettings.sections.interval')}</Text>
|
||||
<Text style={[styles.waterReminderSectionDesc, { color: colorTokens.textSecondary }]}>
|
||||
选择提醒的频率,建议30-120分钟为宜
|
||||
{t('waterReminderSettings.descriptions.interval')}
|
||||
</Text>
|
||||
|
||||
<View style={styles.intervalContainer}>
|
||||
@@ -263,7 +275,7 @@ const WaterReminderSettings: React.FC = () => {
|
||||
style={styles.intervalPicker}
|
||||
>
|
||||
{[30, 45, 60, 90, 120, 150, 180].map(interval => (
|
||||
<Picker.Item key={interval} label={`${interval}分钟`} value={interval} />
|
||||
<Picker.Item key={interval} label={`${interval}${t('waterReminderSettings.labels.minutes')}`} value={interval} />
|
||||
))}
|
||||
</Picker>
|
||||
</View>
|
||||
@@ -279,7 +291,7 @@ const WaterReminderSettings: React.FC = () => {
|
||||
onPress={handleWaterReminderSave}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
<Text style={[styles.saveButtonText, { color: colorTokens.onPrimary }]}>保存设置</Text>
|
||||
<Text style={[styles.saveButtonText, { color: colorTokens.onPrimary }]}>{t('waterReminderSettings.labels.saveSettings')}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</ScrollView>
|
||||
@@ -295,11 +307,11 @@ const WaterReminderSettings: React.FC = () => {
|
||||
<Pressable style={styles.modalBackdrop} onPress={() => setStartTimePickerVisible(false)} />
|
||||
<View style={styles.timePickerModalSheet}>
|
||||
<View style={styles.modalHandle} />
|
||||
<Text style={[styles.modalTitle, { color: colorTokens.text }]}>选择开始时间</Text>
|
||||
<Text style={[styles.modalTitle, { color: colorTokens.text }]}>{t('waterReminderSettings.labels.startTime')}</Text>
|
||||
|
||||
<View style={styles.timePickerContent}>
|
||||
<View style={styles.timePickerSection}>
|
||||
<Text style={[styles.timePickerLabel, { color: colorTokens.text }]}>小时</Text>
|
||||
<Text style={[styles.timePickerLabel, { color: colorTokens.text }]}>{t('waterReminderSettings.labels.hours')}</Text>
|
||||
<View style={styles.hourPickerContainer}>
|
||||
<Picker
|
||||
selectedValue={tempStartHour}
|
||||
@@ -314,12 +326,12 @@ const WaterReminderSettings: React.FC = () => {
|
||||
</View>
|
||||
|
||||
<View style={styles.timeRangePreview}>
|
||||
<Text style={[styles.timeRangePreviewLabel, { color: colorTokens.textSecondary }]}>时间段预览</Text>
|
||||
<Text style={[styles.timeRangePreviewLabel, { color: colorTokens.textSecondary }]}>{t('waterReminderSettings.labels.timeRangePreview')}</Text>
|
||||
<Text style={[styles.timeRangePreviewText, { color: colorTokens.text }]}>
|
||||
{String(tempStartHour).padStart(2, '0')}:00 - {waterReminderSettings.endTime}
|
||||
</Text>
|
||||
{!isValidTimeRange(`${String(tempStartHour).padStart(2, '0')}:00`, waterReminderSettings.endTime) && (
|
||||
<Text style={styles.timeRangeWarning}>⚠️ 开始时间不能晚于或等于结束时间</Text>
|
||||
<Text style={styles.timeRangeWarning}>⚠️ {t('waterReminderSettings.alerts.timeValidation.startTimeInvalid')}</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
@@ -329,13 +341,13 @@ const WaterReminderSettings: React.FC = () => {
|
||||
onPress={() => setStartTimePickerVisible(false)}
|
||||
style={[styles.modalBtn, { backgroundColor: 'white' }]}
|
||||
>
|
||||
<Text style={[styles.modalBtnText, { color: colorTokens.text }]}>取消</Text>
|
||||
<Text style={[styles.modalBtnText, { color: colorTokens.text }]}>{t('waterReminderSettings.buttons.cancel')}</Text>
|
||||
</Pressable>
|
||||
<Pressable
|
||||
onPress={confirmStartTime}
|
||||
style={[styles.modalBtn, styles.modalBtnPrimary, { backgroundColor: colorTokens.primary }]}
|
||||
>
|
||||
<Text style={[styles.modalBtnText, styles.modalBtnTextPrimary, { color: colorTokens.onPrimary }]}>确定</Text>
|
||||
<Text style={[styles.modalBtnText, styles.modalBtnTextPrimary, { color: colorTokens.onPrimary }]}>{t('waterReminderSettings.buttons.confirm')}</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
</View>
|
||||
@@ -351,11 +363,11 @@ const WaterReminderSettings: React.FC = () => {
|
||||
<Pressable style={styles.modalBackdrop} onPress={() => setEndTimePickerVisible(false)} />
|
||||
<View style={styles.timePickerModalSheet}>
|
||||
<View style={styles.modalHandle} />
|
||||
<Text style={[styles.modalTitle, { color: colorTokens.text }]}>选择结束时间</Text>
|
||||
<Text style={[styles.modalTitle, { color: colorTokens.text }]}>{t('waterReminderSettings.labels.endTime')}</Text>
|
||||
|
||||
<View style={styles.timePickerContent}>
|
||||
<View style={styles.timePickerSection}>
|
||||
<Text style={[styles.timePickerLabel, { color: colorTokens.text }]}>小时</Text>
|
||||
<Text style={[styles.timePickerLabel, { color: colorTokens.text }]}>{t('waterReminderSettings.labels.hours')}</Text>
|
||||
<View style={styles.hourPickerContainer}>
|
||||
<Picker
|
||||
selectedValue={tempEndHour}
|
||||
@@ -370,12 +382,12 @@ const WaterReminderSettings: React.FC = () => {
|
||||
</View>
|
||||
|
||||
<View style={styles.timeRangePreview}>
|
||||
<Text style={[styles.timeRangePreviewLabel, { color: colorTokens.textSecondary }]}>时间段预览</Text>
|
||||
<Text style={[styles.timeRangePreviewLabel, { color: colorTokens.textSecondary }]}>{t('waterReminderSettings.labels.timeRangePreview')}</Text>
|
||||
<Text style={[styles.timeRangePreviewText, { color: colorTokens.text }]}>
|
||||
{waterReminderSettings.startTime} - {String(tempEndHour).padStart(2, '0')}:00
|
||||
</Text>
|
||||
{!isValidTimeRange(waterReminderSettings.startTime, `${String(tempEndHour).padStart(2, '0')}:00`) && (
|
||||
<Text style={styles.timeRangeWarning}>⚠️ 结束时间不能早于或等于开始时间</Text>
|
||||
<Text style={styles.timeRangeWarning}>⚠️ {t('waterReminderSettings.alerts.timeValidation.endTimeInvalid')}</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
@@ -385,13 +397,13 @@ const WaterReminderSettings: React.FC = () => {
|
||||
onPress={() => setEndTimePickerVisible(false)}
|
||||
style={[styles.modalBtn, { backgroundColor: 'white' }]}
|
||||
>
|
||||
<Text style={[styles.modalBtnText, { color: colorTokens.text }]}>取消</Text>
|
||||
<Text style={[styles.modalBtnText, { color: colorTokens.text }]}>{t('waterReminderSettings.buttons.cancel')}</Text>
|
||||
</Pressable>
|
||||
<Pressable
|
||||
onPress={confirmEndTime}
|
||||
style={[styles.modalBtn, styles.modalBtnPrimary, { backgroundColor: colorTokens.primary }]}
|
||||
>
|
||||
<Text style={[styles.modalBtnText, styles.modalBtnTextPrimary, { color: colorTokens.onPrimary }]}>确定</Text>
|
||||
<Text style={[styles.modalBtnText, styles.modalBtnTextPrimary, { color: colorTokens.onPrimary }]}>{t('waterReminderSettings.buttons.confirm')}</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user