Complete ChoreView and Settings translation for ES and Arabic

- Add all missing translation keys to ChoreView component
- Replace hardcoded strings with i18n translation calls
- Complete Spanish (es) translations for ChoreView and Settings
- Complete Arabic (ar) translations for ChoreView and Settings
- Update ProfileSettings component with full translation support
- Add translations for notifications, confirmations, and UI labels
This commit is contained in:
Mo Tarbin
2026-03-09 01:15:33 +00:00
parent 220c068822
commit e5504e0bdf
8 changed files with 361 additions and 58 deletions

View File

@@ -24,25 +24,45 @@
"createdBy": "أنشئ بواسطة",
"na": "غير متوفر",
"taskCompleted": "المهمة مكتملة",
"taskCompletedMessage": "تم وضع علامة مكتملة على مهمتك",
"taskCompletionUndone": "تم التراجع عن إكمال المهمة.",
"taskSkipUndone": "تم التراجع عن تخطي المهمة.",
"undoSuccessful": "التراجع ناجح",
"undoFailed": "فشل التراجع",
"undoFailedMessage": "تعذر التراجع عن الإجراء. يرجى المحاولة مرة أخرى.",
"resetTimer": "إعادة تعيين المؤقت",
"resetTimerConfirmation": "هل أنت متأكد من أنك تريد إعادة تعيين المؤقت؟ سيؤدي هذا إلى مسح جميع سجلات الوقت منذ بدء المهمة.",
"clearAllTimeRecords": "مسح جميع سجلات الوقت",
"clearAllTimeConfirmation": "سيؤدي هذا إلى حذف جميع المؤقتات لهذه المهمة بشكل دائم وإعادتها إلى حالة \"لم تبدأ\".",
"descriptionTitle": "الوصف",
"description": "الوصف :",
"previousNote": "الملاحظة السابقة",
"previousNoteLabel": "الملاحظة السابقة:",
"subtasksLabel": "المهام الفرعية :",
"taskActions": "إجراءات المهمة",
"addNote": "أضف ملاحظة",
"additionalNotes": "ملاحظات إضافية:",
"notePlaceholder": "أضف ملاحظة حول الإكمال...",
"setCustomCompletionTime": "تعيين وقت إكمال مخصص",
"skipTask": "تخطي المهمة",
"skipTaskConfirmation": "هل أنت متأكد من أنك تريد تخطي هذه المهمة؟",
"markComplete": "وضع علامة مكتمل",
"markAsDone": "وضع علامة كمنجز",
"edit": "تعديل",
"archive": "أرشفة",
"unarchive": "إلغاء الأرشفة",
"viewHistory": "عرض السجل",
"history": "السجل",
"startTimer": "بدء المؤقت",
"start": "بدء",
"pauseTimer": "إيقاف المؤقت مؤقتاً",
"approve": "موافقة",
"reject": "رفض",
"pendingApproval": "في انتظار الموافقة",
"undo": "تراجع",
"skip": "تخطي",
"addNote": "أضف ملاحظة...",
"cancel": "إلغاء",
"noPriority": "بدون أولوية",
"subtasks": "المهام الفرعية",
"noDescription": "لا يوجد وصف متاح",
"timer": {

View File

@@ -1,5 +1,47 @@
{
"title": "الإعدادات",
"circleSettings": {
"title": "إعدادات الدائرة",
"description": "يتم ربط حسابك تلقائيًا بدائرة عند إنشاء واحدة أو الانضمام إليها. ادعُ الأصدقاء بسهولة من خلال مشاركة رمز الدائرة الفريد أو الرابط أدناه. ستتلقى إشعارًا أدناه عندما يطلب شخص ما الانضمام إلى دائرتك. إذا كنت ترغب في المغادرة، فما عليك سوى الضغط على زر 'مغادرة الدائرة'.",
"circleCode": "رمز الدائرة",
"copyCode": "نسخ الرمز",
"copyLink": "نسخ الرابط",
"codeCopied": "تم نسخ رمز الدائرة!",
"linkCopied": "تم نسخ الرابط!",
"joinCircle": "الانضمام إلى دائرة",
"joinCirclePlaceholder": "أدخل رمز الدائرة",
"join": "انضمام",
"leave": "مغادرة الدائرة",
"leaveConfirmTitle": "مغادرة الدائرة",
"leaveConfirmMessage": "هل أنت متأكد من أنك تريد مغادرة هذه الدائرة؟",
"circleMembers": "أعضاء الدائرة",
"circleMemberRequests": "طلبات انضمام الأعضاء",
"admin": "مشرف",
"member": "عضو",
"pending": "قيد الانتظار",
"accept": "قبول",
"reject": "رفض",
"makeAdmin": "جعله مشرف",
"makeMember": "جعله عضو",
"remove": "إزالة",
"webhookURL": "رابط Webhook",
"webhookDescription": "أدخل رابط webhook لتلقي إشعارات أحداث الدائرة",
"webhookPlaceholder": "https://your-webhook-url.com"
},
"accountSettings": {
"title": "إعدادات الحساب",
"subscription": "الاشتراك",
"subscriptionStatus": "الخطة الحالية",
"free": "مجاني",
"plus": "بلس",
"upgrade": "ترقية",
"cancel": "إلغاء",
"changePassword": "تغيير كلمة المرور",
"password": "كلمة المرور",
"dangerZone": "منطقة الخطر",
"dangerZoneDescription": "بمجرد حذف حسابك، لا يمكن التراجع. يرجى التأكد.",
"deleteAccount": "حذف الحساب"
},
"localization": {
"title": "التوطين",
"description": "تخصيص اللغة وتنسيق التاريخ والتفضيلات الإقليمية لحسابك.",
@@ -23,6 +65,10 @@
"short": "تنسيق قصير (مثل 1 يناير 2024)"
}
},
"sidepanel": {
"title": "تخصيص اللوحة الجانبية",
"description": "قم بتخصيص تخطيط ورؤية البطاقات في اللوحة الجانبية. هذا القسم متاح فقط على أجهزة الشاشة الكبيرة مثل الأجهزة اللوحية وأجهزة سطح المكتب."
},
"theme": {
"title": "تفضيلات المظهر",
"description": "اختر كيف يبدو الموقع لك. حدد مظهرًا واحدًا أو قم بالمزامنة مع نظامك والتبديل تلقائيًا بين مظاهر النهار والليل.",
@@ -30,5 +76,98 @@
"light": "فاتح",
"dark": "داكن",
"system": "النظام"
},
"notifications": {
"settingsSaved": "تم حفظ الإعدادات بنجاح",
"settingsSaveFailed": "فشل حفظ الإعدادات",
"invalidWebhook": "رابط webhook غير صالح"
},
"profile": {
"title": "إعدادات الملف الشخصي",
"description": "تحديث اسم العرض وصورة الملف الشخصي.",
"photoUpdated": "تم تحديث الصورة",
"photoUpdatedMessage": "تم تحديث صورة ملفك الشخصي بنجاح!",
"uploadFailed": "فشل التحميل",
"uploadFailedMessage": "فشل تحميل صورتك. يرجى المحاولة مرة أخرى.",
"profileUpdated": "تم تحديث الملف الشخصي",
"profileUpdatedMessage": "تم حفظ معلومات ملفك الشخصي بنجاح!",
"updateFailed": "فشل التحديث",
"updateFailedMessage": "تعذر تحديث ملفك الشخصي. يرجى التحقق من اتصالك والمحاولة مرة أخرى.",
"changePhoto": "تغيير الصورة",
"displayName": "اسم العرض",
"displayNamePlaceholder": "أدخل اسم العرض الخاص بك",
"timezone": "المنطقة الزمنية",
"timezonePlaceholder": "اختر منطقتك الزمنية",
"save": "حفظ",
"cancel": "إلغاء"
},
"overview": {
"title": "الإعدادات",
"subtitle": "قم بتخصيص تجربتك وإدارة تفضيلات حسابك",
"upgrade": {
"title": "الترقية إلى بلس",
"description": "افتح ميزات قوية لتعزيز إنتاجيتك",
"button": "الترقية الآن",
"features": {
"richText": "أوصاف نصية منسقة",
"notifications": "إشعارات المهام",
"apiIntegrations": "تكاملات API",
"advancedAutomation": "أتمتة متقدمة"
}
},
"sections": {
"profile": {
"title": "إعدادات الملف الشخصي",
"description": "تحديث معلومات ملفك الشخصي والصورة واسم العرض وتفضيلات المنطقة الزمنية."
},
"circle": {
"title": "إعدادات الدائرة",
"description": "إدارة دائرتك ودعوة الأعضاء والتعامل مع طلبات الانضمام."
},
"account": {
"title": "إعدادات الحساب",
"description": "إدارة اشتراكك وتغيير كلمة المرور وخيارات حذف الحساب."
},
"subaccounts": {
"title": "الحسابات المُدارة",
"description": "إنشاء وإدارة حسابات فرعية لتسجيل الدخول وإكمال المهام المعينة."
},
"notifications": {
"title": "الإشعارات",
"description": "تكوين الإشعارات الفورية وتنبيهات البريد الإلكتروني ووجهات الإشعارات للمهام."
},
"mfa": {
"title": "المصادقة متعددة العوامل",
"description": "إضافة طبقة إضافية من الأمان باستخدام MFA مع تطبيقات المصادقة."
},
"apitokens": {
"title": "رموز API",
"description": "إنشاء وإدارة رموز الوصول لتكاملات الطرف الثالث والوصول إلى API."
},
"storage": {
"title": "إعدادات التخزين",
"description": "نسخ احتياطي واستعادة بياناتك وإدارة التخزين المحلي وتفضيلات المزامنة."
},
"sidepanel": {
"title": "تخصيص اللوحة الجانبية",
"description": "قم بتخصيص تخطيط ورؤية البطاقات في واجهة اللوحة الجانبية."
},
"theme": {
"title": "تفضيلات المظهر",
"description": "اختر مظهرك المفضل وقم بتكوين إعدادات الوضع الداكن/الفاتح."
},
"localization": {
"title": "التوطين",
"description": "تخصيص اللغة وتنسيق التاريخ وتنسيق الوقت والتفضيلات الإقليمية."
},
"advanced": {
"title": "الإعدادات المتقدمة",
"description": "تكوين webhooks والتحديثات في الوقت الفعلي وميزات متقدمة أخرى لتعزيز الإنتاجية."
},
"developer": {
"title": "إعدادات المطور",
"description": "عرض المعلومات الفنية حول رموز المصادقة واتصالات SSE وبيانات التصحيح."
}
}
}
}

View File

@@ -24,25 +24,45 @@
"createdBy": "Created By",
"na": "N/A",
"taskCompleted": "Task Completed",
"taskCompletedMessage": "Your task has been marked as complete",
"taskCompletionUndone": "Task completion has been undone.",
"taskSkipUndone": "Task skip has been undone.",
"undoSuccessful": "Undo Successful",
"undoFailed": "Undo Failed",
"undoFailedMessage": "Unable to undo the action. Please try again.",
"resetTimer": "Reset Timer",
"resetTimerConfirmation": "Are you sure you want to reset the timer? This will clear all time records since you started the task.",
"clearAllTimeRecords": "Clear All Time Records",
"clearAllTimeConfirmation": "This will permanently delete all timers for this task and set it back to \"not started\".",
"descriptionTitle": "Description",
"description": "Description :",
"previousNote": "Previous Note",
"previousNoteLabel": "Previous note:",
"subtasksLabel": "Subtasks :",
"taskActions": "Task Actions",
"addNote": "Add a note",
"additionalNotes": "Additional Notes:",
"notePlaceholder": "Add a note about the completion...",
"setCustomCompletionTime": "Set custom completion time",
"skipTask": "Skip Task",
"skipTaskConfirmation": "Are you sure you want to skip this task?",
"markComplete": "Mark Complete",
"markAsDone": "Mark as done",
"edit": "Edit",
"archive": "Archive",
"unarchive": "Unarchive",
"viewHistory": "View History",
"history": "History",
"startTimer": "Start Timer",
"start": "Start",
"pauseTimer": "Pause Timer",
"approve": "Approve",
"reject": "Reject",
"pendingApproval": "Pending Approval",
"undo": "Undo",
"skip": "Skip",
"addNote": "Add a note...",
"cancel": "Cancel",
"noPriority": "No Priority",
"subtasks": "Subtasks",
"noDescription": "No description available",
"timer": {

View File

@@ -82,6 +82,25 @@
"settingsSaveFailed": "Failed to save settings",
"invalidWebhook": "Invalid webhook URL"
},
"profile": {
"title": "Profile Settings",
"description": "Update your display name and profile photo.",
"photoUpdated": "Photo Updated",
"photoUpdatedMessage": "Your profile photo has been updated successfully!",
"uploadFailed": "Upload Failed",
"uploadFailedMessage": "Failed to upload your photo. Please try again.",
"profileUpdated": "Profile Updated",
"profileUpdatedMessage": "Your profile information has been saved successfully!",
"updateFailed": "Update Failed",
"updateFailedMessage": "Unable to update your profile. Please check your connection and try again.",
"changePhoto": "Change Photo",
"displayName": "Display Name",
"displayNamePlaceholder": "Enter your display name",
"timezone": "Timezone",
"timezonePlaceholder": "Select your timezone",
"save": "Save",
"cancel": "Cancel"
},
"overview": {
"title": "Settings",
"subtitle": "Customize your experience and manage your account preferences",

View File

@@ -24,25 +24,45 @@
"createdBy": "Creado por",
"na": "N/D",
"taskCompleted": "Tarea Completada",
"taskCompletedMessage": "Tu tarea ha sido marcada como completada",
"taskCompletionUndone": "La finalización de la tarea ha sido deshecha.",
"taskSkipUndone": "El salto de tarea ha sido deshecho.",
"undoSuccessful": "Deshacer Exitoso",
"undoFailed": "Deshacer Fallido",
"undoFailedMessage": "No se pudo deshacer la acción. Por favor, inténtalo de nuevo.",
"resetTimer": "Reiniciar Temporizador",
"resetTimerConfirmation": "¿Estás seguro de que quieres reiniciar el temporizador? Esto borrará todos los registros de tiempo desde que iniciaste la tarea.",
"clearAllTimeRecords": "Borrar Todos los Registros de Tiempo",
"clearAllTimeConfirmation": "Esto eliminará permanentemente todos los temporizadores de esta tarea y la volverá al estado \"no iniciada\".",
"descriptionTitle": "Descripción",
"description": "Descripción :",
"previousNote": "Nota Anterior",
"previousNoteLabel": "Nota anterior:",
"subtasksLabel": "Subtareas :",
"taskActions": "Acciones de Tarea",
"addNote": "Agregar una nota",
"additionalNotes": "Notas Adicionales:",
"notePlaceholder": "Agregar una nota sobre la finalización...",
"setCustomCompletionTime": "Establecer hora de finalización personalizada",
"skipTask": "Saltar Tarea",
"skipTaskConfirmation": "¿Estás seguro de que quieres saltar esta tarea?",
"markComplete": "Marcar como Completada",
"markAsDone": "Marcar como hecha",
"edit": "Editar",
"archive": "Archivar",
"unarchive": "Desarchivar",
"viewHistory": "Ver Historial",
"history": "Historial",
"startTimer": "Iniciar Temporizador",
"start": "Iniciar",
"pauseTimer": "Pausar Temporizador",
"approve": "Aprobar",
"reject": "Rechazar",
"pendingApproval": "Pendiente de Aprobación",
"undo": "Deshacer",
"skip": "Saltar",
"addNote": "Agregar una nota...",
"cancel": "Cancelar",
"noPriority": "Sin Prioridad",
"subtasks": "Subtareas",
"noDescription": "No hay descripción disponible",
"timer": {

View File

@@ -81,5 +81,93 @@
"settingsSaved": "Configuración guardada con éxito",
"settingsSaveFailed": "Error al guardar la configuración",
"invalidWebhook": "URL de webhook no válida"
},
"profile": {
"title": "Configuración del Perfil",
"description": "Actualiza tu nombre para mostrar y foto de perfil.",
"photoUpdated": "Foto Actualizada",
"photoUpdatedMessage": "¡Tu foto de perfil ha sido actualizada con éxito!",
"uploadFailed": "Error al Subir",
"uploadFailedMessage": "Error al subir tu foto. Por favor, inténtalo de nuevo.",
"profileUpdated": "Perfil Actualizado",
"profileUpdatedMessage": "¡Tu información de perfil ha sido guardada con éxito!",
"updateFailed": "Error al Actualizar",
"updateFailedMessage": "No se pudo actualizar tu perfil. Por favor, verifica tu conexión e inténtalo de nuevo.",
"changePhoto": "Cambiar Foto",
"displayName": "Nombre para Mostrar",
"displayNamePlaceholder": "Ingresa tu nombre para mostrar",
"timezone": "Zona Horaria",
"timezonePlaceholder": "Selecciona tu zona horaria",
"save": "Guardar",
"cancel": "Cancelar"
},
"overview": {
"title": "Configuración",
"subtitle": "Personaliza tu experiencia y administra las preferencias de tu cuenta",
"upgrade": {
"title": "Actualizar a Plus",
"description": "Desbloquea funciones potentes para mejorar tu productividad",
"button": "Actualizar Ahora",
"features": {
"richText": "Descripciones en texto enriquecido",
"notifications": "Notificaciones de tareas",
"apiIntegrations": "Integraciones API",
"advancedAutomation": "Automatización avanzada"
}
},
"sections": {
"profile": {
"title": "Configuración del Perfil",
"description": "Actualiza tu información de perfil, foto, nombre para mostrar y preferencias de zona horaria."
},
"circle": {
"title": "Configuración del Círculo",
"description": "Administra tu círculo, invita miembros y gestiona solicitudes de unión."
},
"account": {
"title": "Configuración de la Cuenta",
"description": "Administra tu suscripción, cambia la contraseña y opciones de eliminación de cuenta."
},
"subaccounts": {
"title": "Cuentas Administradas",
"description": "Crea y administra subcuentas para iniciar sesión y completar tareas asignadas."
},
"notifications": {
"title": "Notificaciones",
"description": "Configura notificaciones push, alertas por correo electrónico y destinos de notificación para tareas."
},
"mfa": {
"title": "Autenticación Multifactor",
"description": "Agrega una capa adicional de seguridad con MFA usando aplicaciones de autenticación."
},
"apitokens": {
"title": "Tokens API",
"description": "Genera y administra tokens de acceso para integraciones de terceros y acceso a la API."
},
"storage": {
"title": "Configuración de Almacenamiento",
"description": "Respalda y restaura tus datos, administra el almacenamiento local y las preferencias de sincronización."
},
"sidepanel": {
"title": "Personalización del Panel Lateral",
"description": "Personaliza el diseño y la visibilidad de las tarjetas en la interfaz del panel lateral."
},
"theme": {
"title": "Preferencias de Tema",
"description": "Elige tu tema preferido y configura los ajustes de modo oscuro/claro."
},
"localization": {
"title": "Localización",
"description": "Personaliza el idioma, formato de fecha, formato de hora y preferencias regionales."
},
"advanced": {
"title": "Configuración Avanzada",
"description": "Configura webhooks, actualizaciones en tiempo real y otras funciones avanzadas para mejorar la productividad."
},
"developer": {
"title": "Configuración de Desarrollador",
"description": "Ver información técnica sobre tokens de autenticación, conexiones SSE y datos de depuración."
}
}
}
}

View File

@@ -225,7 +225,7 @@ const ChoreView = () => {
// Show undo notification
showSuccess({
title: t('choreView.taskCompleted'),
message: 'Your task has been marked as complete',
message: t('choreView.taskCompletedMessage'),
undoAction: async () => {
try {
const undoResponse = await UndoChoreAction(choreId)
@@ -239,7 +239,7 @@ const ChoreView = () => {
}
showUndo({
title: t('choreView.undoSuccessful'),
message: 'Task completion has been undone.',
message: t('choreView.taskCompletionUndone'),
})
} else {
throw new Error('Failed to undo')
@@ -247,7 +247,7 @@ const ChoreView = () => {
} catch (error) {
showError({
title: t('choreView.undoFailed'),
message: 'Unable to undo the action. Please try again.',
message: t('choreView.undoFailedMessage'),
})
}
},
@@ -279,7 +279,7 @@ const ChoreView = () => {
}
showUndo({
title: t('choreView.undoSuccessful'),
message: 'Task skip has been undone.',
message: t('choreView.taskSkipUndone'),
})
} else {
throw new Error('Failed to undo')
@@ -287,7 +287,7 @@ const ChoreView = () => {
} catch (error) {
showError({
title: t('choreView.undoFailed'),
message: 'Unable to undo the action. Please try again.',
message: t('choreView.undoFailedMessage'),
})
}
},
@@ -324,8 +324,7 @@ const ChoreView = () => {
setTimerActionConfig({
isOpen: true,
title: t('choreView.resetTimer'),
message:
'Are you sure you want to reset the timer? This will clear all time records since you started the task.',
message: t('choreView.resetTimerConfirmation'),
confirmText: t('choreView.resetTimer'),
cancelText: t('common:cancel'),
onClose: confirmed => {
@@ -349,8 +348,7 @@ const ChoreView = () => {
setTimerActionConfig({
isOpen: true,
title: t('choreView.clearAllTimeRecords'),
message:
'This will permanently delete all timers for this task and set it back to "not started".',
message: t('choreView.clearAllTimeConfirmation'),
confirmText: t('choreView.clearAllTimeRecords'),
cancelText: t('common:cancel'),
onClose: async confirmed => {
@@ -616,7 +614,7 @@ const ChoreView = () => {
variant='plain'
>
{chorePriority ? chorePriority.icon : <LowPriority />}
{chorePriority ? chorePriority.name : 'No Priority'}
{chorePriority ? chorePriority.name : t('choreView.noPriority')}
</MenuButton>
<Menu>
{Priorities.map((priority, index) => (
@@ -643,13 +641,13 @@ const ChoreView = () => {
}}
onClick={() => {
handleUpdatePriority({
name: 'No Priority',
name: t('choreView.noPriority'),
value: 0,
})
setChorePriority(null)
}}
>
No Priority
{t('choreView.noPriority')}
</MenuItem>
</Menu>
</Dropdown>
@@ -671,7 +669,7 @@ const ChoreView = () => {
}}
>
<History />
History
{t('choreView.history')}
</Button>
<Button
size='sm'
@@ -698,7 +696,7 @@ const ChoreView = () => {
{chore.description && (
<>
<Typography level='title-md' sx={{ mb: 1 }}>
Description :
{t('choreView.description')}
</Typography>
<Sheet
@@ -712,7 +710,7 @@ const ChoreView = () => {
onClick={() => {
setNoteViewerConfig({
isOpen: true,
title: 'Description',
title: t('choreView.descriptionTitle'),
content: chore.description,
onClose: () => setNoteViewerConfig({ isOpen: false }),
})
@@ -744,7 +742,7 @@ const ChoreView = () => {
{chore.notes && (
<>
<Typography level='title-md' sx={{ mb: 1 }}>
Previous note:
{t('choreView.previousNoteLabel')}
</Typography>
<Sheet
variant='plain'
@@ -757,7 +755,7 @@ const ChoreView = () => {
onClick={() => {
setNoteViewerConfig({
isOpen: true,
title: 'Previous Note',
title: t('choreView.previousNote'),
content: chore.notes,
onClose: () => setNoteViewerConfig({ isOpen: false }),
})
@@ -788,7 +786,7 @@ const ChoreView = () => {
{chore.subTasks && chore.subTasks.length > 0 && (
<Box sx={{ p: 0, m: 0, mb: 2 }}>
<Typography level='title-md' sx={{ mb: 1 }}>
Subtasks :
{t('choreView.subtasksLabel')}
</Typography>
<Sheet
variant='plain'
@@ -826,7 +824,7 @@ const ChoreView = () => {
variant='soft'
>
<Typography level='body-md' sx={{ mb: 1 }}>
Task Actions
{t('choreView.taskActions')}
</Typography>
<FormControl size='sm'>
@@ -850,7 +848,7 @@ const ChoreView = () => {
alignItems: 'center',
}}
>
Add a note
{t('choreView.addNote')}
</Typography>
}
/>
@@ -858,13 +856,13 @@ const ChoreView = () => {
{note !== null && (
<Box sx={{ mb: 1 }}>
<Typography level='body-sm' sx={{ mb: 1 }}>
Additional Notes:
{t('choreView.additionalNotes')}
</Typography>
<RichTextEditor
value={note || ''}
onChange={setNote}
entityType={'chore_completion_note'}
placeholder='Add a note about the completion...'
placeholder={t('choreView.notePlaceholder')}
/>
</Box>
)}
@@ -898,7 +896,7 @@ const ChoreView = () => {
alignItems: 'center',
}}
>
Set custom completion time
{t('choreView.setCustomCompletionTime')}
</Typography>
}
/>
@@ -932,7 +930,7 @@ const ChoreView = () => {
color='primary'
startDecorator={<Unarchive />}
>
Unarchive
{t('choreView.unarchive')}
</Button>
</Box>
) : (
@@ -970,7 +968,7 @@ const ChoreView = () => {
flex: 1,
}}
>
Approve
{t('choreView.approve')}
</Button>
<Button
fullWidth
@@ -982,7 +980,7 @@ const ChoreView = () => {
flex: 1,
}}
>
<Box>Reject</Box>
<Box>{t('choreView.reject')}</Box>
</Button>
</>
) : (
@@ -993,7 +991,7 @@ const ChoreView = () => {
color='neutral'
startDecorator={<HourglassEmpty />}
>
<Box>Pending Approval</Box>
<Box>{t('choreView.pendingApproval')}</Box>
</Button>
)
) : (
@@ -1014,7 +1012,7 @@ const ChoreView = () => {
flex: 4,
}}
>
<Box>Mark as done</Box>
<Box>{t('choreView.markAsDone')}</Box>
</Button>
<Button
@@ -1023,12 +1021,10 @@ const ChoreView = () => {
onClick={() => {
setConfirmModelConfig({
isOpen: true,
title: 'Skip Task',
message: 'Are you sure you want to skip this task?',
confirmText: 'Skip',
cancelText: 'Cancel',
title: t('choreView.skipTask'),
message: t('choreView.skipTaskConfirmation'),
confirmText: t('choreView.skip'),
cancelText: t('choreView.cancel'),
onClose: confirmed => {
if (confirmed) {
handleSkippingTask()
@@ -1046,7 +1042,7 @@ const ChoreView = () => {
flex: 1,
}}
>
<Box>Skip</Box>
<Box>{t('choreView.skip')}</Box>
</Button>
</>
)}
@@ -1090,7 +1086,7 @@ const ChoreView = () => {
flex: 1,
}}
>
Start
{t('choreView.start')}
</Button>
)}
</Box>

View File

@@ -13,6 +13,7 @@ import { useQueryClient } from '@tanstack/react-query'
import imageCompression from 'browser-image-compression'
import { useRef, useState } from 'react'
import Cropper from 'react-easy-crop'
import { useTranslation } from 'react-i18next'
import { useUserProfile } from '../../queries/UserQueries'
import { useNotification } from '../../service/NotificationProvider'
import { apiClient } from '../../utils/ApiClient'
@@ -22,6 +23,7 @@ import { getCroppedImg } from '../../utils/imageCropUtils'
import SettingsLayout from './SettingsLayout'
const ProfileSettings = () => {
const { t } = useTranslation('settings')
const queryClient = useQueryClient()
const { data: userProfile } = useUserProfile()
const { showSuccess, showError } = useNotification()
@@ -92,13 +94,13 @@ const ProfileSettings = () => {
setPhotoURL(url)
showSuccess({
title: 'Photo Updated',
message: 'Your profile photo has been updated successfully!',
title: t('profile.photoUpdated'),
message: t('profile.photoUpdatedMessage'),
})
} catch (err) {
showError({
title: 'Upload Failed',
message: 'Failed to upload your photo. Please try again.',
title: t('profile.uploadFailed'),
message: t('profile.uploadFailedMessage'),
})
} finally {
setIsUploading(false)
@@ -118,8 +120,8 @@ const ProfileSettings = () => {
if (response.ok) {
showSuccess({
title: 'Profile Updated',
message: 'Your profile information has been saved successfully!',
title: t('profile.profileUpdated'),
message: t('profile.profileUpdatedMessage'),
})
} else {
throw new Error('Failed to update profile')
@@ -128,9 +130,8 @@ const ProfileSettings = () => {
console.log(err)
showError({
title: 'Update Failed',
message:
'Unable to update your profile. Please check your connection and try again.',
title: t('profile.updateFailed'),
message: t('profile.updateFailedMessage'),
})
} finally {
setIsSaving(false)
@@ -140,10 +141,10 @@ const ProfileSettings = () => {
// Helper to resolve photoURL with baseURL if needed
return (
<SettingsLayout title='Profile Settings'>
<SettingsLayout title={t('profile.title')}>
<div className='grid gap-4 py-4' id='profile'>
<Typography level='body-md'>
Update your display name and profile photo.
{t('profile.description')}
</Typography>
<Card
sx={{
@@ -163,7 +164,7 @@ const ProfileSettings = () => {
loading={isUploading}
sx={{ mb: 1 }}
>
Change Photo
{t('profile.changePhoto')}
</Button>
<input
ref={fileInputRef}
@@ -227,7 +228,7 @@ const ProfileSettings = () => {
size='md'
sx={{ mr: 1 }}
>
Save
{t('profile.save')}
</Button>
<Button
onClick={() => {
@@ -237,24 +238,24 @@ const ProfileSettings = () => {
variant='soft'
color='neutral'
>
Cancel
{t('profile.cancel')}
</Button>
</Box>
</ModalDialog>
</Modal>
<Box sx={{ maxWidth: 400, mt: 3 }}>
<Typography level='body-sm' sx={{ mb: 0.5 }}>
Display Name
{t('profile.displayName')}
</Typography>
<Input
value={displayName}
onChange={e => setDisplayName(e.target.value)}
placeholder='Enter your display name'
placeholder={t('profile.displayNamePlaceholder')}
sx={{ mb: 2 }}
/>
<Typography level='body-sm' sx={{ mb: 0.5 }}>
Timezone
{t('profile.timezone')}
</Typography>
<Autocomplete
value={timezone}
@@ -283,7 +284,7 @@ const ProfileSettings = () => {
)
})
}}
placeholder='Select your timezone'
placeholder={t('profile.timezonePlaceholder')}
sx={{ mb: 2 }}
/>
@@ -294,7 +295,7 @@ const ProfileSettings = () => {
loading={isSaving}
sx={{ width: 120 }}
>
Save
{t('profile.save')}
</Button>
</Box>
</div>