feat(i18n): 增强生理周期模块的国际化支持,添加多语言格式和翻译

This commit is contained in:
richarjiang
2025-12-18 09:36:08 +08:00
parent 4836058d56
commit feb5052fcd
11 changed files with 192 additions and 52 deletions

View File

@@ -1,10 +1,12 @@
import { Colors } from '@/constants/Colors';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { STATUS_COLORS } from './constants';
import { DayCellProps } from './types';
export const DayCell: React.FC<DayCellProps> = ({ cell, isSelected, onPress }) => {
const { t } = useTranslation();
const status = cell.info?.status;
const colors = status ? STATUS_COLORS[status] : undefined;
@@ -32,7 +34,7 @@ export const DayCell: React.FC<DayCellProps> = ({ cell, isSelected, onPress }) =
{cell.label}
</Text>
</View>
{cell.isToday && <Text style={styles.todayText}></Text>}
{cell.isToday && <Text style={styles.todayText}>{t('menstrual.today')}</Text>}
</TouchableOpacity>
);
};

View File

@@ -1,7 +1,10 @@
import { Colors } from '@/constants/Colors';
import { Ionicons } from '@expo/vector-icons';
import dayjs from 'dayjs';
import 'dayjs/locale/en';
import 'dayjs/locale/zh-cn';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { DimensionValue, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { InlineTipProps } from './types';
@@ -12,9 +15,12 @@ export const InlineTip: React.FC<InlineTipProps> = ({
onMarkStart,
onCancelMark,
}) => {
const { t, i18n } = useTranslation();
// 14.28% per cell. Center is 7.14%.
const pointerLeft = `${columnIndex * 14.2857 + 7.1428}%` as DimensionValue;
const isFuture = selectedDate.isAfter(dayjs(), 'day');
const localeKey = i18n.language.startsWith('en') ? 'en' : 'zh-cn';
const dateFormat = t('menstrual.dateFormatShort', { defaultValue: 'M月D日' });
return (
<View style={styles.inlineTipCard}>
@@ -22,17 +28,19 @@ export const InlineTip: React.FC<InlineTipProps> = ({
<View style={styles.inlineTipRow}>
<View style={styles.inlineTipDate}>
<Ionicons name="calendar-outline" size={16} color="#111827" />
<Text style={styles.inlineTipDateText}>{selectedDate.format('M月D日')}</Text>
<Text style={styles.inlineTipDateText}>
{selectedDate.locale(localeKey).format(dateFormat)}
</Text>
</View>
{!isFuture && (!selectedInfo || !selectedInfo.confirmed) && (
<TouchableOpacity style={styles.inlinePrimaryBtn} onPress={onMarkStart}>
<Ionicons name="add" size={14} color="#fff" />
<Text style={styles.inlinePrimaryText}></Text>
<Text style={styles.inlinePrimaryText}>{t('menstrual.actions.markPeriod')}</Text>
</TouchableOpacity>
)}
{!isFuture && selectedInfo?.confirmed && selectedInfo.status === 'period' && (
<TouchableOpacity style={styles.inlineSecondaryBtn} onPress={onCancelMark}>
<Text style={styles.inlineSecondaryText}></Text>
<Text style={styles.inlineSecondaryText}>{t('menstrual.actions.cancelMark')}</Text>
</TouchableOpacity>
)}
</View>

View File

@@ -1,19 +1,21 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { StyleSheet, Text, View } from 'react-native';
import { STATUS_COLORS } from './constants';
import { LegendItem } from './types';
const LEGEND_ITEMS: LegendItem[] = [
{ label: '经期', key: 'period' },
{ label: '预测经期', key: 'predicted-period' },
{ label: '排卵期', key: 'fertile' },
{ label: '排卵日', key: 'ovulation-day' },
];
export const Legend: React.FC = () => {
const { t } = useTranslation();
const legendItems: LegendItem[] = [
{ label: t('menstrual.legend.period'), key: 'period' },
{ label: t('menstrual.legend.predictedPeriod'), key: 'predicted-period' },
{ label: t('menstrual.legend.fertile'), key: 'fertile' },
{ label: t('menstrual.legend.ovulation'), key: 'ovulation-day' },
];
return (
<View style={styles.legendRow}>
{LEGEND_ITEMS.map((item) => (
{legendItems.map((item) => (
<View key={item.key} style={styles.legendItem}>
<View
style={[

View File

@@ -17,6 +17,7 @@ interface MonthBlockProps {
selectedDateKey: string;
onSelect: (dateKey: string) => void;
renderTip: (colIndex: number) => React.ReactNode;
weekLabels?: string[];
}
export const MonthBlock: React.FC<MonthBlockProps> = ({
@@ -24,8 +25,10 @@ export const MonthBlock: React.FC<MonthBlockProps> = ({
selectedDateKey,
onSelect,
renderTip,
weekLabels,
}) => {
const weeks = useMemo(() => chunkArray(month.cells, 7), [month.cells]);
const labels = weekLabels?.length === 7 ? weekLabels : WEEK_LABELS;
return (
<View style={styles.monthCard}>
@@ -34,7 +37,7 @@ export const MonthBlock: React.FC<MonthBlockProps> = ({
<Text style={styles.monthSubtitle}>{month.subtitle}</Text>
</View>
<View style={styles.weekRow}>
{WEEK_LABELS.map((label) => (
{labels.map((label) => (
<Text key={label} style={styles.weekLabel}>
{label}
</Text>