feat: Complete comprehensive localization of all tracking and management pages
Some checks failed
CI/CD Pipeline / Build Application (push) Has been cancelled
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled

- Feeding page: 47+ strings localized with validation, success/error messages
- Medicine page: 44 strings localized with unit conversion support
- Sleep page: Already localized (verified)
- Diaper page: Already localized (verified)
- Activity page: Already localized (verified)
- AI Assistant: 51 strings localized including chat interface and suggested questions
- Children page: 38 strings fully localized with gender labels
- Family page: 42 strings localized with role management
- Insights page: 41 strings localized including charts and analytics

Added translation files:
- locales/en/ai.json (44 keys)
- locales/en/family.json (42 keys)
- locales/en/insights.json (41 keys)

Updated translation files:
- locales/en/tracking.json (added feeding, health/medicine sections)
- locales/en/children.json (verified complete)

All pages now use useTranslation hook with proper namespaces.
All user-facing text externalized and ready for multi-language support.
This commit is contained in:
2025-10-03 13:57:47 +00:00
parent 5fea603922
commit 41320638e5
10 changed files with 434 additions and 204 deletions

View File

@@ -114,7 +114,7 @@ function MedicineTrackPage() {
}
} catch (err: any) {
console.error('Failed to load children:', err);
setError(err.response?.data?.message || 'Failed to load children');
setError(err.response?.data?.message || t('common.error.loadChildrenFailed'));
} finally {
setChildrenLoading(false);
}
@@ -140,19 +140,19 @@ function MedicineTrackPage() {
const handleSubmit = async () => {
if (!selectedChild) {
setError('Please select a child');
setError(t('common.selectChild'));
return;
}
// Validation
if (!medicineName) {
setError('Please enter medicine name');
setError(t('health.medicineName.required'));
return;
}
const dosageValue = unit === 'ml' ? dosage : dosageText;
if (!dosageValue || (unit === 'ml' && dosage === 0) || (unit !== 'ml' && !dosageText)) {
setError('Please enter dosage');
setError(t('health.dosage.required'));
return;
}
@@ -175,7 +175,7 @@ function MedicineTrackPage() {
notes: notes || undefined,
});
setSuccessMessage('Medicine logged successfully!');
setSuccessMessage(t('health.success'));
// Reset form
resetForm();
@@ -184,7 +184,7 @@ function MedicineTrackPage() {
await loadRecentMedicines();
} catch (err: any) {
console.error('Failed to save medicine:', err);
setError(err.response?.data?.message || 'Failed to save medicine');
setError(err.response?.data?.message || t('health.error'));
} finally {
setLoading(false);
}
@@ -211,13 +211,13 @@ function MedicineTrackPage() {
try {
setLoading(true);
await trackingApi.deleteActivity(activityToDelete);
setSuccessMessage('Medicine deleted successfully');
setSuccessMessage(t('health.deleted'));
setDeleteDialogOpen(false);
setActivityToDelete(null);
await loadRecentMedicines();
} catch (err: any) {
console.error('Failed to delete medicine:', err);
setError(err.response?.data?.message || 'Failed to delete medicine');
setError(err.response?.data?.message || t('health.deleteError'));
} finally {
setLoading(false);
}
@@ -282,17 +282,17 @@ function MedicineTrackPage() {
<CardContent sx={{ textAlign: 'center', py: 8 }}>
<ChildCare sx={{ fontSize: 64, color: 'text.secondary', mb: 2 }} />
<Typography variant="h6" color="text.secondary" gutterBottom>
No Children Added
{t('common.noChildrenAdded')}
</Typography>
<Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
You need to add a child before you can track medicine activities
{t('common.noChildrenMessage')}
</Typography>
<Button
variant="contained"
startIcon={<Add />}
onClick={() => router.push('/children')}
>
Add Child
{t('common.addChild')}
</Button>
</CardContent>
</Card>
@@ -352,11 +352,11 @@ function MedicineTrackPage() {
{children.length > 1 && (
<Paper sx={{ p: 2, mb: 3 }}>
<FormControl fullWidth>
<InputLabel>Select Child</InputLabel>
<InputLabel>{t('common.selectChild')}</InputLabel>
<Select
value={selectedChild}
onChange={(e) => setSelectedChild(e.target.value)}
label="Select Child"
label={t('common.selectChild')}
>
{children.map((child) => (
<MenuItem key={child.id} value={child.id}>
@@ -373,17 +373,17 @@ function MedicineTrackPage() {
<Box sx={{ display: 'flex', alignItems: 'center', mb: 3 }}>
<MedicalServices sx={{ fontSize: 36, color: 'error.main', mr: 2 }} />
<Typography variant="h6" fontWeight="600">
Medicine Information
{t('health.medicineInfo')}
</Typography>
</Box>
<TextField
fullWidth
label="Medicine Name"
label={t('health.medicineName.label')}
value={medicineName}
onChange={(e) => setMedicineName(e.target.value)}
sx={{ mb: 3 }}
placeholder="e.g., Acetaminophen, Ibuprofen"
placeholder={t('health.medicineName.placeholder')}
required
/>
@@ -391,7 +391,7 @@ function MedicineTrackPage() {
{unit === 'ml' ? (
<UnitInput
fullWidth
label="Dosage"
label={t('health.dosage.label')}
type="volume"
value={dosage}
onChange={(metricValue) => setDosage(metricValue)}
@@ -400,16 +400,16 @@ function MedicineTrackPage() {
) : (
<TextField
fullWidth
label="Dosage"
label={t('health.dosage.label')}
value={dosageText}
onChange={(e) => setDosageText(e.target.value)}
placeholder="e.g., 5, 2.5"
placeholder={t('health.dosage.placeholder')}
required
/>
)}
<FormControl fullWidth>
<InputLabel>Unit</InputLabel>
<InputLabel>{t('health.unit')}</InputLabel>
<Select
value={unit}
onChange={(e) => {
@@ -422,39 +422,39 @@ function MedicineTrackPage() {
setDosage(0);
}
}}
label="Unit"
label={t('health.unit')}
>
<MenuItem value="ml">ml</MenuItem>
<MenuItem value="mg">mg</MenuItem>
<MenuItem value="tsp">tsp</MenuItem>
<MenuItem value="tbsp">tbsp</MenuItem>
<MenuItem value="drops">drops</MenuItem>
<MenuItem value="tablet">tablet(s)</MenuItem>
<MenuItem value="ml">{t('health.units.ml')}</MenuItem>
<MenuItem value="mg">{t('health.units.mg')}</MenuItem>
<MenuItem value="tsp">{t('health.units.tsp')}</MenuItem>
<MenuItem value="tbsp">{t('health.units.tbsp')}</MenuItem>
<MenuItem value="drops">{t('health.units.drops')}</MenuItem>
<MenuItem value="tablet">{t('health.units.tablet')}</MenuItem>
</Select>
</FormControl>
</Box>
<FormControl fullWidth sx={{ mb: 3 }}>
<InputLabel>Route</InputLabel>
<InputLabel>{t('health.route.label')}</InputLabel>
<Select
value={route}
onChange={(e) => setRoute(e.target.value as 'oral' | 'topical' | 'injection' | 'other')}
label="Route"
label={t('health.route.label')}
>
<MenuItem value="oral">Oral</MenuItem>
<MenuItem value="topical">Topical</MenuItem>
<MenuItem value="injection">Injection</MenuItem>
<MenuItem value="other">Other</MenuItem>
<MenuItem value="oral">{t('health.route.oral')}</MenuItem>
<MenuItem value="topical">{t('health.route.topical')}</MenuItem>
<MenuItem value="injection">{t('health.route.injection')}</MenuItem>
<MenuItem value="other">{t('health.route.other')}</MenuItem>
</Select>
</FormControl>
<TextField
fullWidth
label="Reason (optional)"
label={t('health.reason.label')}
value={reason}
onChange={(e) => setReason(e.target.value)}
sx={{ mb: 3 }}
placeholder="e.g., Fever, Pain, Allergy"
placeholder={t('health.reason.placeholder')}
/>
<TextField
@@ -477,7 +477,7 @@ function MedicineTrackPage() {
onClick={handleSubmit}
disabled={loading}
>
{loading ? t('activities.medicine') : t('activities.medicine')}
{loading ? t('common.loading') : t('health.logMedicine')}
</Button>
</Paper>
@@ -485,7 +485,7 @@ function MedicineTrackPage() {
<Paper sx={{ p: 3 }}>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
<Typography variant="h6" fontWeight="600">
{t('activities.medicine')}
{t('health.recentMedicines')}
</Typography>
<IconButton onClick={loadRecentMedicines} disabled={medicinesLoading}>
<Refresh />
@@ -578,10 +578,10 @@ function MedicineTrackPage() {
</DialogContent>
<DialogActions>
<Button onClick={() => setDeleteDialogOpen(false)} disabled={loading}>
Cancel
{t('common.cancel')}
</Button>
<Button onClick={handleDeleteConfirm} color="error" disabled={loading}>
{loading ? t('deleteEntry') : t('deleteEntry')}
{loading ? t('common.loading') : t('common.delete')}
</Button>
</DialogActions>
</Dialog>