From 7377f471e9bbef3811cfd7cda50576106afabc2c Mon Sep 17 00:00:00 2001 From: Mohammad Sajad Pourajam Date: Thu, 19 Feb 2026 18:17:16 +0330 Subject: [PATCH] Enhance farm dashboard localization by adding Persian translations for various UI elements, including subheaders, option menus, labels, and fallback text. Refactor components to utilize the new translations, improving the overall user experience for Persian-speaking users. --- messages/fa.json | 83 +++++++++++++++++++ .../dashboards/farm/AnomalyDetectionCard.tsx | 8 +- .../dashboards/farm/EconomicOverview.tsx | 8 +- .../dashboards/farm/FarmAlertsTimeline.tsx | 4 +- .../dashboards/farm/FarmAlertsTracker.tsx | 8 +- src/views/dashboards/farm/FarmWeatherCard.tsx | 4 +- .../dashboards/farm/HarvestPredictionCard.tsx | 6 +- src/views/dashboards/farm/NDVIHealthCard.tsx | 6 +- .../dashboards/farm/RecommendationsList.tsx | 4 +- .../dashboards/farm/SensorComparisonChart.tsx | 8 +- .../dashboards/farm/SensorRadarChart.tsx | 4 +- .../dashboards/farm/SensorValuesList.tsx | 4 +- .../dashboards/farm/SoilMoistureHeatmap.tsx | 10 +-- .../dashboards/farm/WaterNeedPrediction.tsx | 10 ++- .../dashboards/farm/YieldPredictionChart.tsx | 23 +++-- 15 files changed, 146 insertions(+), 44 deletions(-) diff --git a/messages/fa.json b/messages/fa.json index 861eac2..43d1292 100644 --- a/messages/fa.json +++ b/messages/fa.json @@ -170,6 +170,89 @@ "soilHeatmap": "نقشه حرارتی رطوبت خاک", "ndviRecommendations": "NDVI و توصیه‌ها", "economic": "خلاصه اقتصادی" + }, + "subheaders": { + "requiresAttention": "نیاز به توجه", + "explainableRecommendations": "توصیه‌های قابل توضیح", + "costsAndRoi": "هزینه‌ها و بازگشت سرمایه", + "actionItems": "اقدامات پیشنهادی", + "vegetationIndex": "شاخص پوشش گیاهی", + "fieldZonesByTime": "نواحی مزرعه بر اساس زمان", + "aiForecast": "پیش‌بینی هوش مصنوعی", + "thisYearVsLastYear": "امسال در مقایسه با سال قبل", + "aiEstimatedDate": "تاریخ تخمینی هوش مصنوعی", + "outOfRangeValues": "مقادیر خارج از محدوده", + "todayVsLastWeek": "امروز در مقایسه با هفته گذشته", + "todayVsIdealRanges": "امروز در مقایسه با محدوده ایده‌آل", + "realtimeData": "داده لحظه‌ای" + }, + "optionMenu": { + "refresh": "بروزرسانی", + "sevenDayForecast": "پیش‌بینی ۷ روزه", + "details": "جزئیات", + "viewAll": "مشاهده همه", + "dismiss": "رد کردن", + "configure": "پیکربندی", + "export": "خروجی", + "exportPdf": "خروجی PDF", + "exportExcel": "خروجی اکسل", + "snooze": "تعویق", + "markDone": "علامت تکمیل", + "adjust": "تنظیم", + "compare": "مقایسه", + "today": "امروز", + "thisWeek": "این هفته", + "thisMonth": "این ماه", + "lastHour": "۱ ساعت اخیر", + "last24h": "۲۴ ساعت اخیر", + "last7Days": "۷ روز اخیر", + "settings": "تنظیمات" + }, + "labels": { + "humid": "رطوبت", + "wind": "باد", + "totalAlerts": "کل هشدارها", + "activeAlerts": "هشدارهای فعال", + "ndvi": "NDVI", + "ndviIndex": "شاخص NDVI (۰-۱)", + "totalNext7Days": "مجموع ۷ روز آینده", + "value": "مقدار", + "expected": "انتظاری", + "deviation": "انحراف", + "days": "روز", + "tons": "تن" + }, + "colorScale": { + "low": "کم", + "moderate": "متوسط", + "optimal": "بهینه", + "high": "زیاد" + }, + "empty": { + "noAnomalies": "ناهنجاریی یافت نشد. همه سنسورها در محدوده بهینه هستند." + }, + "fallback": { + "dayN": "روز {n}", + "monthJan": "ژانویه", + "monthFeb": "فوریه", + "monthMar": "مارس", + "monthApr": "آوریل", + "monthMay": "مه", + "monthJun": "ژوئن", + "monthJul": "ژوئیه", + "monthAug": "اوت", + "monthSep": "سپتامبر", + "monthOct": "اکتبر", + "monthNov": "نوامبر", + "monthDec": "دسامبر", + "plusPercentVsLastWeek": "+{val}% نسبت به هفته گذشته", + "mon": "دوشنبه", + "tue": "سه‌شنبه", + "wed": "چهارشنبه", + "thu": "پنج‌شنبه", + "fri": "جمعه", + "sat": "شنبه", + "sun": "یکشنبه" } }, "sensorHub": { diff --git a/src/views/dashboards/farm/AnomalyDetectionCard.tsx b/src/views/dashboards/farm/AnomalyDetectionCard.tsx index f1ebe10..8beaedd 100644 --- a/src/views/dashboards/farm/AnomalyDetectionCard.tsx +++ b/src/views/dashboards/farm/AnomalyDetectionCard.tsx @@ -34,14 +34,14 @@ const AnomalyDetectionCard = ({ data }: AnomalyDetectionCardProps) => { } title={t('cards.anomalyDetectionCard')} - subheader='Out of range values' - action={} + subheader={t('subheaders.outOfRangeValues')} + action={} sx={{ '& .MuiCardHeader-avatar': { mr: 3 } }} /> {anomalies.length === 0 ? ( - No anomalies detected. All sensors within optimal range. + {t('empty.noAnomalies')} ) : ( anomalies.map((item, index) => ( @@ -58,7 +58,7 @@ const AnomalyDetectionCard = ({ data }: AnomalyDetectionCardProps) => { /> - Value: {item.value} (Expected: {item.expected}) · Deviation: {item.deviation} + {t('labels.value')}: {item.value} ({t('labels.expected')}: {item.expected}) · {t('labels.deviation')}: {item.deviation} )) diff --git a/src/views/dashboards/farm/EconomicOverview.tsx b/src/views/dashboards/farm/EconomicOverview.tsx index a4233f1..447037a 100644 --- a/src/views/dashboards/farm/EconomicOverview.tsx +++ b/src/views/dashboards/farm/EconomicOverview.tsx @@ -39,7 +39,9 @@ const EconomicOverview = ({ data }: EconomicOverviewProps) => { const t = useTranslations('farmDashboard') const economicData = (data?.economicData as EconomicItem[] | undefined) ?? [] const chartSeries = (data?.chartSeries as Array<{ name: string; data: number[] }>) ?? [] - const chartCategories = (data?.chartCategories as string[]) ?? ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'] + const chartCategories = + (data?.chartCategories as string[]) ?? + [t('fallback.monthJan'), t('fallback.monthFeb'), t('fallback.monthMar'), t('fallback.monthApr'), t('fallback.monthMay'), t('fallback.monthJun')] const theme = useTheme() const options: ApexOptions = { @@ -77,8 +79,8 @@ const EconomicOverview = ({ data }: EconomicOverviewProps) => { } + subheader={t('subheaders.costsAndRoi')} + action={} /> {economicData.length > 0 && ( diff --git a/src/views/dashboards/farm/FarmAlertsTimeline.tsx b/src/views/dashboards/farm/FarmAlertsTimeline.tsx index abdf67b..25ccab1 100644 --- a/src/views/dashboards/farm/FarmAlertsTimeline.tsx +++ b/src/views/dashboards/farm/FarmAlertsTimeline.tsx @@ -51,8 +51,8 @@ const FarmAlertsTimeline = ({ data }: FarmAlertsTimelineProps) => { avatar={} title={t('cards.farmAlertsTimeline')} titleTypographyProps={{ variant: 'h5' }} - subheader='Explainable recommendations' - action={} + subheader={t('subheaders.explainableRecommendations')} + action={} sx={{ '& .MuiCardHeader-avatar': { mr: 3 } }} /> diff --git a/src/views/dashboards/farm/FarmAlertsTracker.tsx b/src/views/dashboards/farm/FarmAlertsTracker.tsx index 5267647..5195203 100644 --- a/src/views/dashboards/farm/FarmAlertsTracker.tsx +++ b/src/views/dashboards/farm/FarmAlertsTracker.tsx @@ -46,7 +46,7 @@ const FarmAlertsTracker = ({ data }: FarmAlertsTrackerProps) => { const options: ApexOptions = { stroke: { dashArray: 10 }, - labels: ['Active Alerts'], + labels: [t('labels.activeAlerts')], colors: ['var(--mui-palette-warning-main)'], states: { hover: { filter: { type: 'none' } }, @@ -97,14 +97,14 @@ const FarmAlertsTracker = ({ data }: FarmAlertsTrackerProps) => { } + subheader={t('subheaders.requiresAttention')} + action={} />
{totalAlerts} - Total Alerts + {t('labels.totalAlerts')}
{alertStats.map((item, index) => ( diff --git a/src/views/dashboards/farm/FarmWeatherCard.tsx b/src/views/dashboards/farm/FarmWeatherCard.tsx index 651a268..5081edd 100644 --- a/src/views/dashboards/farm/FarmWeatherCard.tsx +++ b/src/views/dashboards/farm/FarmWeatherCard.tsx @@ -91,7 +91,7 @@ const FarmWeatherCard = ({ data }: FarmWeatherCardProps) => { title={t('cards.farmWeatherCard')} subheader={condition ? `${condition}, ${temperature}${unit}` : `${temperature}${unit}`} className='pbe-3' - action={} + action={} />
@@ -101,7 +101,7 @@ const FarmWeatherCard = ({ data }: FarmWeatherCardProps) => { {unit} - Humid: {humidity}% | Wind: {windSpeed} {windUnit} + {t('labels.humid')}: {humidity}% | {t('labels.wind')}: {windSpeed} {windUnit}
diff --git a/src/views/dashboards/farm/HarvestPredictionCard.tsx b/src/views/dashboards/farm/HarvestPredictionCard.tsx index ab61acb..b1531a4 100644 --- a/src/views/dashboards/farm/HarvestPredictionCard.tsx +++ b/src/views/dashboards/farm/HarvestPredictionCard.tsx @@ -22,7 +22,7 @@ const HarvestPredictionCard = ({ data }: HarvestPredictionCardProps) => { const t = useTranslations('farmDashboard') const harvestDate = (data?.dateFormatted as string) ?? '' const daysUntil = (data?.daysUntil as number | undefined) ?? 0 - const daysLeftFormatted = daysUntil > 0 ? `${daysUntil} days` : '' + const daysLeftFormatted = daysUntil > 0 ? `${daysUntil} ${t('labels.days')}` : '' const description = (data?.description as string) ?? '' return ( @@ -34,8 +34,8 @@ const HarvestPredictionCard = ({ data }: HarvestPredictionCardProps) => { } title={t('cards.harvestPredictionCard')} - subheader='AI Estimated Date' - action={} + subheader={t('subheaders.aiEstimatedDate')} + action={} />
diff --git a/src/views/dashboards/farm/NDVIHealthCard.tsx b/src/views/dashboards/farm/NDVIHealthCard.tsx index ae30e2a..f504369 100644 --- a/src/views/dashboards/farm/NDVIHealthCard.tsx +++ b/src/views/dashboards/farm/NDVIHealthCard.tsx @@ -37,7 +37,7 @@ const NDVIHealthCard = ({ data }: NDVIHealthCardProps) => { const options: ApexOptions = { stroke: { dashArray: 10 }, - labels: ['NDVI'], + labels: [t('labels.ndvi')], colors: [successColor], states: { hover: { filter: { type: 'none' } }, @@ -88,13 +88,13 @@ const NDVIHealthCard = ({ data }: NDVIHealthCardProps) => { } title={t('cards.ndviHealthCard')} - subheader='Vegetation Index' + subheader={t('subheaders.vegetationIndex')} sx={{ '& .MuiCardHeader-avatar': { mr: 3 } }} />
{ndviIndex} - NDVI Index (0-1) + {t('labels.ndviIndex')} {healthData.length > 0 && (
{healthData.map((item, index) => ( diff --git a/src/views/dashboards/farm/RecommendationsList.tsx b/src/views/dashboards/farm/RecommendationsList.tsx index fa7d509..dbcebb7 100644 --- a/src/views/dashboards/farm/RecommendationsList.tsx +++ b/src/views/dashboards/farm/RecommendationsList.tsx @@ -36,8 +36,8 @@ const RecommendationsList = ({ data }: RecommendationsListProps) => { } + subheader={t('subheaders.actionItems')} + action={} /> {recommendations.map((item, index) => ( diff --git a/src/views/dashboards/farm/SensorComparisonChart.tsx b/src/views/dashboards/farm/SensorComparisonChart.tsx index 42a0027..ae8b544 100644 --- a/src/views/dashboards/farm/SensorComparisonChart.tsx +++ b/src/views/dashboards/farm/SensorComparisonChart.tsx @@ -24,9 +24,11 @@ interface SensorComparisonChartProps { const SensorComparisonChart = ({ data }: SensorComparisonChartProps) => { const t = useTranslations('farmDashboard') const series = (data?.series as Array<{ name: string; data: number[] }>) ?? [] - const categories = (data?.categories as string[]) ?? ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] + const categories = + (data?.categories as string[]) ?? + [t('fallback.mon'), t('fallback.tue'), t('fallback.wed'), t('fallback.thu'), t('fallback.fri'), t('fallback.sat'), t('fallback.sun')] const currentValue = data?.currentValue ?? 48 - const vsLastWeek = (data?.vsLastWeek as string) ?? '+5% vs last week' + const vsLastWeek = (data?.vsLastWeek as string) ?? t('fallback.plusPercentVsLastWeek', { val: '5' }) const theme = useTheme() if (series.length === 0) return null @@ -78,7 +80,7 @@ const SensorComparisonChart = ({ data }: SensorComparisonChartProps) => {
diff --git a/src/views/dashboards/farm/SensorRadarChart.tsx b/src/views/dashboards/farm/SensorRadarChart.tsx index 4826a1c..f3545c2 100644 --- a/src/views/dashboards/farm/SensorRadarChart.tsx +++ b/src/views/dashboards/farm/SensorRadarChart.tsx @@ -73,8 +73,8 @@ const SensorRadarChart = ({ data }: SensorRadarChartProps) => { } + subheader={t('subheaders.todayVsIdealRanges')} + action={} /> diff --git a/src/views/dashboards/farm/SensorValuesList.tsx b/src/views/dashboards/farm/SensorValuesList.tsx index 36d0609..d708932 100644 --- a/src/views/dashboards/farm/SensorValuesList.tsx +++ b/src/views/dashboards/farm/SensorValuesList.tsx @@ -36,8 +36,8 @@ const SensorValuesList = ({ data }: SensorValuesListProps) => { } + subheader={t('subheaders.realtimeData')} + action={} /> {sensors.map((item, index) => ( diff --git a/src/views/dashboards/farm/SoilMoistureHeatmap.tsx b/src/views/dashboards/farm/SoilMoistureHeatmap.tsx index 80790d5..65662b4 100644 --- a/src/views/dashboards/farm/SoilMoistureHeatmap.tsx +++ b/src/views/dashboards/farm/SoilMoistureHeatmap.tsx @@ -52,10 +52,10 @@ const SoilMoistureHeatmap = ({ data }: SoilMoistureHeatmapProps) => { enableShades: false, colorScale: { ranges: [ - { from: 0, to: 30, name: 'Low', color: '#ff6b6b' }, - { from: 31, to: 50, name: 'Moderate', color: '#ffd93d' }, - { from: 51, to: 70, name: 'Optimal', color: '#6bcb77' }, - { from: 71, to: 100, name: 'High', color: '#4d96ff' } + { from: 0, to: 30, name: t('colorScale.low'), color: '#ff6b6b' }, + { from: 31, to: 50, name: t('colorScale.moderate'), color: '#ffd93d' }, + { from: 51, to: 70, name: t('colorScale.optimal'), color: '#6bcb77' }, + { from: 71, to: 100, name: t('colorScale.high'), color: '#4d96ff' } ] } } @@ -75,7 +75,7 @@ const SoilMoistureHeatmap = ({ data }: SoilMoistureHeatmapProps) => { diff --git a/src/views/dashboards/farm/WaterNeedPrediction.tsx b/src/views/dashboards/farm/WaterNeedPrediction.tsx index 3367c50..8ec718a 100644 --- a/src/views/dashboards/farm/WaterNeedPrediction.tsx +++ b/src/views/dashboards/farm/WaterNeedPrediction.tsx @@ -29,7 +29,9 @@ interface WaterNeedPredictionProps { const WaterNeedPrediction = ({ data }: WaterNeedPredictionProps) => { const t = useTranslations('farmDashboard') const series = (data?.series as Array<{ name: string; data: number[] }>) ?? [] - const categories = (data?.categories as string[]) ?? ['Day 1', 'Day 2', 'Day 3', 'Day 4', 'Day 5', 'Day 6', 'Day 7'] + const categories = + (data?.categories as string[]) ?? + [1, 2, 3, 4, 5, 6, 7].map(n => t('fallback.dayN', { n: String(n) })) const totalNext7Days = data?.totalNext7Days ?? 0 const unit = (data?.unit as string) ?? 'm³' const totalFormatted = typeof totalNext7Days === 'number' ? totalNext7Days.toLocaleString() : String(totalNext7Days) @@ -79,8 +81,8 @@ const WaterNeedPrediction = ({ data }: WaterNeedPredictionProps) => { } + subheader={t('subheaders.aiForecast')} + action={} />
@@ -88,7 +90,7 @@ const WaterNeedPrediction = ({ data }: WaterNeedPredictionProps) => { {totalFormatted} {unit} - Total next 7 days + {t('labels.totalNext7Days')}
diff --git a/src/views/dashboards/farm/YieldPredictionChart.tsx b/src/views/dashboards/farm/YieldPredictionChart.tsx index 7358b31..71be045 100644 --- a/src/views/dashboards/farm/YieldPredictionChart.tsx +++ b/src/views/dashboards/farm/YieldPredictionChart.tsx @@ -39,7 +39,20 @@ const YieldPredictionChart = ({ data }: YieldPredictionChartProps) => { const series = (data?.series as Array<{ name: string; data: number[] }>) ?? [] const categories = (data?.categories as string[]) ?? - ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] + [ + t('fallback.monthJan'), + t('fallback.monthFeb'), + t('fallback.monthMar'), + t('fallback.monthApr'), + t('fallback.monthMay'), + t('fallback.monthJun'), + t('fallback.monthJul'), + t('fallback.monthAug'), + t('fallback.monthSep'), + t('fallback.monthOct'), + t('fallback.monthNov'), + t('fallback.monthDec') + ] const summary = (data?.summary as SummaryItem[]) ?? [] const theme = useTheme() if (series.length === 0) return null @@ -68,11 +81,11 @@ const YieldPredictionChart = ({ data }: YieldPredictionChartProps) => { yaxis: { labels: { style: { colors: 'var(--mui-palette-text-disabled)' }, - formatter: (val: number) => `${val}t` + formatter: (val: number) => `${val} ${t('labels.tons')}` } }, tooltip: { - y: { formatter: (val: number) => `${val} tons` } + y: { formatter: (val: number) => `${val} ${t('labels.tons')}` } } } @@ -80,8 +93,8 @@ const YieldPredictionChart = ({ data }: YieldPredictionChartProps) => { } + subheader={t('subheaders.thisYearVsLastYear')} + action={} />