feat: Apply localization to Track and Children pages (Phase 9 - Batch 2)
**Pages Localized:** - Track main page: Activity selection menu with all tracking options - Children page: Complete localization including age formatting with pluralization **Translation Files:** - Enhanced tracking.json: Added trackActivity, selectActivity, and activities keys - Created children.json for all 5 languages with comprehensive strings - Updated i18n config to include children namespace **Key Features:** - Localized age calculation with proper pluralization (year/years, month/months) - All error messages translated - Gender labels localized - Properly formatted age display for all languages **Languages Supported:** - English, Spanish, French, Portuguese, Chinese (Simplified) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -23,8 +23,10 @@ import { childrenApi, Child, CreateChildData } from '@/lib/api/children';
|
||||
import { ChildDialog } from '@/components/children/ChildDialog';
|
||||
import { DeleteConfirmDialog } from '@/components/children/DeleteConfirmDialog';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
|
||||
export default function ChildrenPage() {
|
||||
const { t } = useTranslation('children');
|
||||
const { user } = useAuth();
|
||||
const [children, setChildren] = useState<Child[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
@@ -43,7 +45,7 @@ export default function ChildrenPage() {
|
||||
fetchChildren();
|
||||
} else {
|
||||
setLoading(false);
|
||||
setError('No family found. Please complete onboarding first.');
|
||||
setError(t('errors.noFamily'));
|
||||
}
|
||||
}, [familyId]);
|
||||
|
||||
@@ -57,7 +59,7 @@ export default function ChildrenPage() {
|
||||
setChildren(data);
|
||||
} catch (err: any) {
|
||||
console.error('Failed to fetch children:', err);
|
||||
setError(err.response?.data?.message || 'Failed to load children');
|
||||
setError(err.response?.data?.message || t('errors.loadFailed'));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -80,7 +82,7 @@ export default function ChildrenPage() {
|
||||
|
||||
const handleSubmit = async (data: CreateChildData) => {
|
||||
if (!familyId) {
|
||||
throw new Error('No family ID found');
|
||||
throw new Error(t('errors.noFamilyId'));
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -94,7 +96,7 @@ export default function ChildrenPage() {
|
||||
setDialogOpen(false);
|
||||
} catch (err: any) {
|
||||
console.error('Failed to save child:', err);
|
||||
throw new Error(err.response?.data?.message || 'Failed to save child');
|
||||
throw new Error(err.response?.data?.message || t('errors.saveFailed'));
|
||||
} finally {
|
||||
setActionLoading(false);
|
||||
}
|
||||
@@ -111,7 +113,7 @@ export default function ChildrenPage() {
|
||||
setChildToDelete(null);
|
||||
} catch (err: any) {
|
||||
console.error('Failed to delete child:', err);
|
||||
setError(err.response?.data?.message || 'Failed to delete child');
|
||||
setError(err.response?.data?.message || t('errors.deleteFailed'));
|
||||
} finally {
|
||||
setActionLoading(false);
|
||||
}
|
||||
@@ -138,11 +140,11 @@ export default function ChildrenPage() {
|
||||
}
|
||||
|
||||
if (years === 0) {
|
||||
return `${months} month${months !== 1 ? 's' : ''}`;
|
||||
return `${months} ${months !== 1 ? t('ageFormat.months') : t('ageFormat.month')}`;
|
||||
} else if (months === 0) {
|
||||
return `${years} year${years !== 1 ? 's' : ''}`;
|
||||
return `${years} ${years !== 1 ? t('ageFormat.years') : t('ageFormat.year')}`;
|
||||
} else {
|
||||
return `${years} year${years !== 1 ? 's' : ''}, ${months} month${months !== 1 ? 's' : ''}`;
|
||||
return `${years} ${years !== 1 ? t('ageFormat.years') : t('ageFormat.year')}, ${months} ${months !== 1 ? t('ageFormat.months') : t('ageFormat.month')}`;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -153,10 +155,10 @@ export default function ChildrenPage() {
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 4 }}>
|
||||
<Box>
|
||||
<Typography variant="h4" component="h1" fontWeight="600" gutterBottom>
|
||||
Children
|
||||
{t('title')}
|
||||
</Typography>
|
||||
<Typography variant="body1" color="text.secondary">
|
||||
Manage your family's children profiles
|
||||
{t('subtitle')}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Button
|
||||
@@ -165,7 +167,7 @@ export default function ChildrenPage() {
|
||||
onClick={handleAddChild}
|
||||
disabled={loading || !familyId}
|
||||
>
|
||||
Add Child
|
||||
{t('addChild')}
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
@@ -186,10 +188,10 @@ export default function ChildrenPage() {
|
||||
<CardContent sx={{ textAlign: 'center', py: 8 }}>
|
||||
<ChildCare sx={{ fontSize: 64, color: 'text.secondary', mb: 2 }} />
|
||||
<Typography variant="h6" component="h2" color="text.secondary" gutterBottom>
|
||||
No children added yet
|
||||
{t('noChildren')}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
|
||||
Add your first child to start tracking their activities
|
||||
{t('noChildrenSubtitle')}
|
||||
</Typography>
|
||||
<Button
|
||||
variant="contained"
|
||||
@@ -197,7 +199,7 @@ export default function ChildrenPage() {
|
||||
onClick={handleAddChild}
|
||||
disabled={!familyId}
|
||||
>
|
||||
Add First Child
|
||||
{t('addFirstChild')}
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -257,7 +259,7 @@ export default function ChildrenPage() {
|
||||
fontWeight="600"
|
||||
sx={{ mt: 1 }}
|
||||
>
|
||||
Age: {calculateAge(child.birthDate)}
|
||||
{t('age')}: {calculateAge(child.birthDate)}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user