feat(localization): enhance task drawer translations and UI consistency

- Updated translations for task drawer components in Albanian, German, Spanish, Portuguese, Chinese, and English to improve clarity and consistency.
- Added new keys for task progress, activity log, and time log forms to support enhanced user interactions.
- Improved placeholder texts, error messages, and button labels for better user experience across multiple languages.
- Refactored activity log component to utilize translation keys for dynamic content rendering.
This commit is contained in:
chamikaJ
2025-07-08 15:51:47 +05:30
parent f06851fa37
commit 8fb33e311d
10 changed files with 394 additions and 171 deletions

View File

@@ -1,28 +1,37 @@
{
"taskHeader": {
"taskNamePlaceholder": "Shkruani detyrën tuaj",
"taskNamePlaceholder": "Shkruani Detyrën tuaj",
"deleteTask": "Fshi Detyrën"
},
"taskInfoTab": {
"title": "Info",
"title": "Informacioni",
"details": {
"title": "Detajet",
"task-key": "Çelësi i Detyrës",
"phase": "Faza",
"assignees": "Përgjegjësit",
"due-date": "Afati i Përfundimit",
"assignees": "Të Caktuar",
"due-date": "Data e Përfundimit",
"time-estimation": "Vlerësimi i Kohës",
"priority": "Prioriteti",
"labels": "Etiketa",
"billable": "Fakturueshme",
"labels": "Etiketat",
"billable": "E Faturueshme",
"notify": "Njofto",
"when-done-notify": "Kur përfundo, njofto",
"when-done-notify": "Kur përfundon, njofto",
"start-date": "Data e Fillimit",
"end-date": "Data e Përfundimit",
"hide-start-date": "Fshih Datën e Fillimit",
"show-start-date": "Shfaq Datën e Fillimit",
"hours": "Orë",
"minutes": "Minuta"
"minutes": "Minuta",
"progressValue": "Vlera e Progresit",
"progressValueTooltip": "Vendosni përqindjen e progresit (0-100%)",
"progressValueRequired": "Ju lutemi vendosni një vlerë progresi",
"progressValueRange": "Progresi duhet të jetë midis 0 dhe 100",
"taskWeight": "Pesha e Detyrës",
"taskWeightTooltip": "Vendosni peshën e kësaj nëndetyre (përqindje)",
"taskWeightRequired": "Ju lutemi vendosni një peshë detyre",
"taskWeightRange": "Pesha duhet të jetë midis 0 dhe 100",
"recurring": "E Përsëritur"
},
"labels": {
"labelInputPlaceholder": "Kërko ose krijo",
@@ -30,37 +39,48 @@
},
"description": {
"title": "Përshkrimi",
"placeholder": "Shtoni një përshkrim më të detajuar..."
"placeholder": "Shto një përshkrim më të detajuar..."
},
"subTasks": {
"title": "Nën-Detyrat",
"addSubTask": "+ Shto Nën-Detyrë",
"addSubTaskInputPlaceholder": "Shkruani detyrën dhe shtypni Enter",
"refreshSubTasks": "Rifresko Nën-Detyrat",
"title": "Nëndetyrat",
"addSubTask": "Shto Nëndetyrë",
"addSubTaskInputPlaceholder": "Shkruani detyrën tuaj dhe shtypni enter",
"refreshSubTasks": "Rifresko Nëndetyrat",
"edit": "Modifiko",
"delete": "Fshi",
"confirmDeleteSubTask": "Jeni i sigurt që doni të fshini këtë nën-detyrë?",
"deleteSubTask": "Fshi Nën-Detyrën"
"confirmDeleteSubTask": "Jeni i sigurt që doni të fshini këtë nëndetyrë?",
"deleteSubTask": "Fshi Nëndetyrën"
},
"dependencies": {
"title": "Varësitë",
"addDependency": "+ Shto varësi të re",
"blockedBy": "I bllokuar nga",
"searchTask": "Shkruani për të kërkuar detyra",
"noTasksFound": "Asnjë detyrë nuk u gjet",
"blockedBy": "Bllokuar nga",
"searchTask": "Shkruani për të kërkuar detyrë",
"noTasksFound": "Nuk u gjetën detyra",
"confirmDeleteDependency": "Jeni i sigurt që doni të fshini?"
},
"attachments": {
"title": "Bashkëngjitjet",
"chooseOrDropFileToUpload": "Zgjidhni ose lëshoni skedar për ngarkim",
"uploading": "Po ngarkohet..."
"chooseOrDropFileToUpload": "Zgjidhni ose hidhni skedar për ngarkuar",
"uploading": "Duke ngarkuar..."
},
"comments": {
"title": "Komentet",
"addComment": "+ Shto koment të ri",
"noComments": "Asnjë koment ende. Bëhu i pari që komenton!",
"noComments": "Ende pa komente. Bëhu i pari që komenton!",
"delete": "Fshi",
"confirmDeleteComment": "Jeni i sigurt që doni të fshini këtë koment?"
"confirmDeleteComment": "Jeni i sigurt që doni të fshini këtë koment?",
"addCommentPlaceholder": "Shto një koment...",
"cancel": "Anulo",
"commentButton": "Komento",
"attachFiles": "Bashkëngjit skedarë",
"addMoreFiles": "Shto më shumë skedarë",
"selectedFiles": "Skedarët e Zgjedhur (Deri në 25MB, Maksimumi {count})",
"maxFilesError": "Mund të ngarkoni maksimum {count} skedarë",
"processFilesError": "Dështoi përpunimi i skedarëve",
"addCommentError": "Ju lutemi shtoni një koment ose bashkëngjitni skedarë",
"createdBy": "Krijuar {time} nga {user}",
"updatedTime": "Përditësuar {time}"
},
"searchInputPlaceholder": "Kërko sipas emrit",
"pendingInvitation": "Ftesë në Pritje"
@@ -68,11 +88,36 @@
"taskTimeLogTab": {
"title": "Regjistri i Kohës",
"addTimeLog": "Shto regjistrim të ri kohe",
"totalLogged": "Koha totale e regjistruar",
"totalLogged": "Totali i Regjistruar",
"exportToExcel": "Eksporto në Excel",
"noTimeLogsFound": "Asnjë regjistrim kohe nuk u gjet"
"noTimeLogsFound": "Nuk u gjetën regjistra kohe",
"timeLogForm": {
"date": "Data",
"startTime": "Koha e Fillimit",
"endTime": "Koha e Përfundimit",
"workDescription": "Përshkrimi i Punës",
"descriptionPlaceholder": "Shto një përshkrim",
"logTime": "Regjistro kohën",
"updateTime": "Përditëso kohën",
"cancel": "Anulo",
"selectDateError": "Ju lutemi zgjidhni një datë",
"selectStartTimeError": "Ju lutemi zgjidhni kohën e fillimit",
"selectEndTimeError": "Ju lutemi zgjidhni kohën e përfundimit",
"endTimeAfterStartError": "Koha e përfundimit duhet të jetë pas kohës së fillimit"
}
},
"taskActivityLogTab": {
"title": "Regjistri i Aktivitetit"
"title": "Regjistri i Aktivitetit",
"add": "SHTO",
"remove": "HIQE",
"none": "Asnjë",
"weight": "Pesha",
"createdTask": "krijoi detyrën."
},
"taskProgress": {
"markAsDoneTitle": "Shëno Detyrën si të Kryer?",
"confirmMarkAsDone": "Po, shëno si të kryer",
"cancelMarkAsDone": "Jo, mbaj statusin aktual",
"markAsDoneDescription": "Keni vendosur progresin në 100%. Doni të përditësoni statusin e detyrës në \"Kryer\"?"
}
}

View File

@@ -1,6 +1,6 @@
{
"taskHeader": {
"taskNamePlaceholder": "Aufgabe eingeben",
"taskNamePlaceholder": "Geben Sie Ihre Aufgabe ein",
"deleteTask": "Aufgabe löschen"
},
"taskInfoTab": {
@@ -9,20 +9,29 @@
"title": "Details",
"task-key": "Aufgaben-Schlüssel",
"phase": "Phase",
"assignees": "Zugewiesene",
"assignees": "Beauftragte",
"due-date": "Fälligkeitsdatum",
"time-estimation": "Zeitschätzung",
"priority": "Priorität",
"labels": "Labels",
"billable": "Abrechenbar",
"notify": "Benachrichtigen",
"when-done-notify": "Bei Fertigstellung benachrichtigen",
"when-done-notify": "Bei Abschluss benachrichtigen",
"start-date": "Startdatum",
"end-date": "Enddatum",
"hide-start-date": "Startdatum ausblenden",
"show-start-date": "Startdatum anzeigen",
"hours": "Stunden",
"minutes": "Minuten"
"minutes": "Minuten",
"progressValue": "Fortschrittswert",
"progressValueTooltip": "Fortschritt in Prozent einstellen (0-100%)",
"progressValueRequired": "Bitte geben Sie einen Fortschrittswert ein",
"progressValueRange": "Fortschritt muss zwischen 0 und 100 liegen",
"taskWeight": "Aufgabengewicht",
"taskWeightTooltip": "Gewicht dieser Teilaufgabe festlegen (Prozent)",
"taskWeightRequired": "Bitte geben Sie ein Aufgabengewicht ein",
"taskWeightRange": "Gewicht muss zwischen 0 und 100 liegen",
"recurring": "Wiederkehrend"
},
"labels": {
"labelInputPlaceholder": "Suchen oder erstellen",
@@ -30,29 +39,29 @@
},
"description": {
"title": "Beschreibung",
"placeholder": "Detaillierte Beschreibung hinzufügen..."
"placeholder": "Detailliertere Beschreibung hinzufügen..."
},
"subTasks": {
"title": "Unteraufgaben",
"addSubTask": "+ Unteraufgabe hinzufügen",
"addSubTaskInputPlaceholder": "Aufgabe eingeben und Enter drücken",
"refreshSubTasks": "Unteraufgaben aktualisieren",
"title": "Teilaufgaben",
"addSubTask": "Teilaufgabe hinzufügen",
"addSubTaskInputPlaceholder": "Geben Sie Ihre Aufgabe ein und drücken Sie Enter",
"refreshSubTasks": "Teilaufgaben aktualisieren",
"edit": "Bearbeiten",
"delete": "Löschen",
"confirmDeleteSubTask": "Sind Sie sicher, dass Sie diese Unteraufgabe löschen möchten?",
"deleteSubTask": "Unteraufgabe löschen"
"confirmDeleteSubTask": "Sind Sie sicher, dass Sie diese Teilaufgabe löschen möchten?",
"deleteSubTask": "Teilaufgabe löschen"
},
"dependencies": {
"title": "Abhängigkeiten",
"addDependency": "+ Neue Abhängigkeit hinzufügen",
"blockedBy": "Blockiert durch",
"blockedBy": "Blockiert von",
"searchTask": "Aufgabe suchen",
"noTasksFound": "Keine Aufgaben gefunden",
"confirmDeleteDependency": "Sind Sie sicher, dass Sie dies löschen möchten?"
"confirmDeleteDependency": "Sind Sie sicher, dass Sie löschen möchten?"
},
"attachments": {
"title": "Anhänge",
"chooseOrDropFileToUpload": "Datei auswählen oder zum Hochladen ablegen",
"chooseOrDropFileToUpload": "Datei zum Hochladen wählen oder ablegen",
"uploading": "Wird hochgeladen..."
},
"comments": {
@@ -60,19 +69,55 @@
"addComment": "+ Neuen Kommentar hinzufügen",
"noComments": "Noch keine Kommentare. Seien Sie der Erste!",
"delete": "Löschen",
"confirmDeleteComment": "Sind Sie sicher, dass Sie diesen Kommentar löschen möchten?"
"confirmDeleteComment": "Sind Sie sicher, dass Sie diesen Kommentar löschen möchten?",
"addCommentPlaceholder": "Kommentar hinzufügen...",
"cancel": "Abbrechen",
"commentButton": "Kommentieren",
"attachFiles": "Dateien anhängen",
"addMoreFiles": "Weitere Dateien hinzufügen",
"selectedFiles": "Ausgewählte Dateien (Bis zu 25MB, Maximum {count})",
"maxFilesError": "Sie können maximal {count} Dateien hochladen",
"processFilesError": "Fehler beim Verarbeiten der Dateien",
"addCommentError": "Bitte fügen Sie einen Kommentar hinzu oder hängen Sie Dateien an",
"createdBy": "Erstellt {time} von {user}",
"updatedTime": "Aktualisiert {time}"
},
"searchInputPlaceholder": "Nach Namen suchen",
"pendingInvitation": "Einladung ausstehend"
"searchInputPlaceholder": "Nach Name suchen",
"pendingInvitation": "Ausstehende Einladung"
},
"taskTimeLogTab": {
"title": "Zeiterfassung",
"addTimeLog": "Neuen Zeiteintrag hinzufügen",
"totalLogged": "Gesamt erfasst",
"exportToExcel": "Nach Excel exportieren",
"noTimeLogsFound": "Keine Zeiterfassungen gefunden"
"noTimeLogsFound": "Keine Zeiteinträge gefunden",
"timeLogForm": {
"date": "Datum",
"startTime": "Startzeit",
"endTime": "Endzeit",
"workDescription": "Arbeitsbeschreibung",
"descriptionPlaceholder": "Beschreibung hinzufügen",
"logTime": "Zeit erfassen",
"updateTime": "Zeit aktualisieren",
"cancel": "Abbrechen",
"selectDateError": "Bitte wählen Sie ein Datum",
"selectStartTimeError": "Bitte wählen Sie eine Startzeit",
"selectEndTimeError": "Bitte wählen Sie eine Endzeit",
"endTimeAfterStartError": "Endzeit muss nach der Startzeit liegen"
}
},
"taskActivityLogTab": {
"title": "Aktivitätsprotokoll"
"title": "Aktivitätsprotokoll",
"add": "HINZUFÜGEN",
"remove": "ENTFERNEN",
"none": "Keine",
"weight": "Gewicht",
"createdTask": "hat die Aufgabe erstellt."
},
"taskProgress": {
"markAsDoneTitle": "Aufgabe als erledigt markieren?",
"confirmMarkAsDone": "Ja, als erledigt markieren",
"cancelMarkAsDone": "Nein, aktuellen Status beibehalten",
"markAsDoneDescription": "Sie haben den Fortschritt auf 100% gesetzt. Möchten Sie den Aufgabenstatus auf \"Erledigt\" aktualisieren?"
}
}

View File

@@ -69,7 +69,18 @@
"addComment": "+ Add new comment",
"noComments": "No comments yet. Be the first to comment!",
"delete": "Delete",
"confirmDeleteComment": "Are you sure you want to delete this comment?"
"confirmDeleteComment": "Are you sure you want to delete this comment?",
"addCommentPlaceholder": "Add a comment...",
"cancel": "Cancel",
"commentButton": "Comment",
"attachFiles": "Attach files",
"addMoreFiles": "Add more files",
"selectedFiles": "Selected Files (Up to 25MB, Maximum of {count})",
"maxFilesError": "You can only upload a maximum of {count} files",
"processFilesError": "Failed to process files",
"addCommentError": "Please add a comment or attach files",
"createdBy": "Created {time} by {user}",
"updatedTime": "Updated {time}"
},
"searchInputPlaceholder": "Search by name",
"pendingInvitation": "Pending Invitation"
@@ -79,10 +90,29 @@
"addTimeLog": "Add new time log",
"totalLogged": "Total Logged",
"exportToExcel": "Export to Excel",
"noTimeLogsFound": "No time logs found"
"noTimeLogsFound": "No time logs found",
"timeLogForm": {
"date": "Date",
"startTime": "Start Time",
"endTime": "End Time",
"workDescription": "Work Description",
"descriptionPlaceholder": "Add a description",
"logTime": "Log time",
"updateTime": "Update time",
"cancel": "Cancel",
"selectDateError": "Please select a date",
"selectStartTimeError": "Please select start time",
"selectEndTimeError": "Please select end time",
"endTimeAfterStartError": "End time must be after start time"
}
},
"taskActivityLogTab": {
"title": "Activity Log"
"title": "Activity Log",
"add": "ADD",
"remove": "REMOVE",
"none": "None",
"weight": "Weight",
"createdTask": "created the task."
},
"taskProgress": {
"markAsDoneTitle": "Mark Task as Done?",

View File

@@ -1,93 +1,123 @@
{
"taskHeader": {
"taskNamePlaceholder": "Escribe tu tarea",
"deleteTask": "Eliminar tarea"
"taskNamePlaceholder": "Escriba su Tarea",
"deleteTask": "Eliminar Tarea"
},
"taskInfoTab": {
"title": "Información",
"details": {
"title": "Detalles",
"task-key": "Clave de tarea",
"task-key": "Clave de Tarea",
"phase": "Fase",
"assignees": "Asignados",
"due-date": "Fecha de vencimiento",
"time-estimation": "Estimación de tiempo",
"due-date": "Fecha de Vencimiento",
"time-estimation": "Estimación de Tiempo",
"priority": "Prioridad",
"labels": "Etiquetas",
"billable": "Facturable",
"notify": "Notificar",
"when-done-notify": "Al terminar, notificar",
"start-date": "Fecha de inicio",
"end-date": "Fecha de finalización",
"hide-start-date": "Ocultar fecha de inicio",
"show-start-date": "Mostrar fecha de inicio",
"start-date": "Fecha de Inicio",
"end-date": "Fecha de Fin",
"hide-start-date": "Ocultar Fecha de Inicio",
"show-start-date": "Mostrar Fecha de Inicio",
"hours": "Horas",
"minutes": "Minutos",
"progressValue": "Valor de Progreso",
"progressValueTooltip": "Establecer el porcentaje de progreso (0-100%)",
"progressValueRequired": "Por favor, introduce un valor de progreso",
"progressValueRequired": "Por favor, introduzca un valor de progreso",
"progressValueRange": "El progreso debe estar entre 0 y 100",
"taskWeight": "Peso de la Tarea",
"taskWeightTooltip": "Establecer el peso de esta subtarea (porcentaje)",
"taskWeightRequired": "Por favor, introduce un peso para la tarea",
"taskWeightRequired": "Por favor, introduzca un peso de tarea",
"taskWeightRange": "El peso debe estar entre 0 y 100",
"recurring": "Recurrente"
},
"labels": {
"labelInputPlaceholder": "Buscar o crear",
"labelsSelectorInputTip": "Pulse Enter para crear"
"labelsSelectorInputTip": "Presiona Enter para crear"
},
"description": {
"title": "Descripción",
"placeholder": "Añadir una descripción más detallada..."
},
"subTasks": {
"title": "Subtareas",
"addSubTask": "+ Añadir subtarea",
"addSubTaskInputPlaceholder": "Escribe tu tarea y pulsa enter",
"refreshSubTasks": "Actualizar subtareas",
"title": "Sub Tareas",
"addSubTask": "Agregar Sub Tarea",
"addSubTaskInputPlaceholder": "Escriba su tarea y presione enter",
"refreshSubTasks": "Actualizar Sub Tareas",
"edit": "Editar",
"delete": "Eliminar",
"confirmDeleteSubTask": "¿Estás seguro de que quieres eliminar esta subtarea?",
"deleteSubTask": "Eliminar subtarea"
"confirmDeleteSubTask": "¿Está seguro de que desea eliminar esta subtarea?",
"deleteSubTask": "Eliminar Sub Tarea"
},
"dependencies": {
"title": "Dependencias",
"addDependency": "+ Añadir nueva dependencia",
"addDependency": "+ Agregar nueva dependencia",
"blockedBy": "Bloqueado por",
"searchTask": "Escribe para buscar tarea",
"searchTask": "Escribir para buscar tarea",
"noTasksFound": "No se encontraron tareas",
"confirmDeleteDependency": "¿Estás seguro de que quieres eliminar?"
"confirmDeleteDependency": "¿Está seguro de que desea eliminar?"
},
"attachments": {
"title": "Adjuntos",
"chooseOrDropFileToUpload": "Elige o arrastra un archivo para subir",
"chooseOrDropFileToUpload": "Elija o arrastre un archivo para subir",
"uploading": "Subiendo..."
},
"comments": {
"title": "Comentarios",
"addComment": "+ Añadir nuevo comentario",
"noComments": "No hay comentarios todavía. ¡Sé el primero en comentar!",
"addComment": "+ Agregar nuevo comentario",
"noComments": "Aún no hay comentarios. ¡Sé el primero en comentar!",
"delete": "Eliminar",
"confirmDeleteComment": "¿Estás seguro de que quieres eliminar este comentario?"
"confirmDeleteComment": "¿Está seguro de que desea eliminar este comentario?",
"addCommentPlaceholder": "Agregar un comentario...",
"cancel": "Cancelar",
"commentButton": "Comentar",
"attachFiles": "Adjuntar archivos",
"addMoreFiles": "Agregar más archivos",
"selectedFiles": "Archivos Seleccionados (Hasta 25MB, Máximo {count})",
"maxFilesError": "Solo puede subir un máximo de {count} archivos",
"processFilesError": "Error al procesar archivos",
"addCommentError": "Por favor agregue un comentario o adjunte archivos",
"createdBy": "Creado {time} por {user}",
"updatedTime": "Actualizado {time}"
},
"searchInputPlaceholder": "Buscar por nombre",
"pendingInvitation": "Invitación pendiente"
"pendingInvitation": "Invitación Pendiente"
},
"taskTimeLogTab": {
"title": "Registro de tiempo",
"title": "Registro de Tiempo",
"addTimeLog": "Añadir nuevo registro de tiempo",
"totalLogged": "Total registrado",
"totalLogged": "Total Registrado",
"exportToExcel": "Exportar a Excel",
"noTimeLogsFound": "No se encontraron registros de tiempo"
"noTimeLogsFound": "No se encontraron registros de tiempo",
"timeLogForm": {
"date": "Fecha",
"startTime": "Hora de Inicio",
"endTime": "Hora de Fin",
"workDescription": "Descripción del Trabajo",
"descriptionPlaceholder": "Agregar una descripción",
"logTime": "Registrar tiempo",
"updateTime": "Actualizar tiempo",
"cancel": "Cancelar",
"selectDateError": "Por favor seleccione una fecha",
"selectStartTimeError": "Por favor seleccione la hora de inicio",
"selectEndTimeError": "Por favor seleccione la hora de fin",
"endTimeAfterStartError": "La hora de fin debe ser posterior a la hora de inicio"
}
},
"taskActivityLogTab": {
"title": "Registro de actividad"
"title": "Registro de Actividad",
"add": "AGREGAR",
"remove": "QUITAR",
"none": "Ninguno",
"weight": "Peso",
"createdTask": "creó la tarea."
},
"taskProgress": {
"markAsDoneTitle": "¿Marcar Tarea como Completada?",
"confirmMarkAsDone": "Sí, marcar como completada",
"cancelMarkAsDone": "No, mantener estado actual",
"markAsDoneDescription": "Has establecido el progreso al 100%. ¿Quieres actualizar el estado de la tarea a \"Completada\"?"
"markAsDoneDescription": "Ha establecido el progreso al 100%. ¿Le gustaría actualizar el estado de la tarea a \"Completada\"?"
}
}

View File

@@ -1,35 +1,35 @@
{
"taskHeader": {
"taskNamePlaceholder": "Digite sua tarefa",
"deleteTask": "Excluir tarefa"
"taskNamePlaceholder": "Digite sua Tarefa",
"deleteTask": "Deletar Tarefa"
},
"taskInfoTab": {
"title": "Informações",
"details": {
"title": "Detalhes",
"task-key": "Chave da tarefa",
"task-key": "Chave da Tarefa",
"phase": "Fase",
"assignees": "Responsáveis",
"due-date": "Data de vencimento",
"time-estimation": "Estimativa de tempo",
"due-date": "Data de Vencimento",
"time-estimation": "Estimativa de Tempo",
"priority": "Prioridade",
"labels": "Etiquetas",
"billable": "Faturável",
"notify": "Notificar",
"when-done-notify": "Quando concluída, notificar",
"start-date": "Data de início",
"end-date": "Data de término",
"hide-start-date": "Ocultar data de início",
"show-start-date": "Mostrar data de início",
"when-done-notify": "Quando concluído, notificar",
"start-date": "Data de Início",
"end-date": "Data de Fim",
"hide-start-date": "Ocultar Data de Início",
"show-start-date": "Mostrar Data de Início",
"hours": "Horas",
"minutes": "Minutos",
"progressValue": "Valor de Progresso",
"progressValue": "Valor do Progresso",
"progressValueTooltip": "Definir a porcentagem de progresso (0-100%)",
"progressValueRequired": "Por favor, insira um valor de progresso",
"progressValueRange": "O progresso deve estar entre 0 e 100",
"taskWeight": "Peso da Tarefa",
"taskWeightTooltip": "Definir o peso desta subtarefa (porcentagem)",
"taskWeightRequired": "Por favor, insira um peso para a tarefa",
"taskWeightRequired": "Por favor, insira um peso da tarefa",
"taskWeightRange": "O peso deve estar entre 0 e 100",
"recurring": "Recorrente"
},
@@ -42,14 +42,14 @@
"placeholder": "Adicionar uma descrição mais detalhada..."
},
"subTasks": {
"title": "Subtarefas",
"addSubTask": "+ Adicionar subtarefa",
"title": "Sub Tarefas",
"addSubTask": "Adicionar Sub Tarefa",
"addSubTaskInputPlaceholder": "Digite sua tarefa e pressione enter",
"refreshSubTasks": "Atualizar subtarefas",
"refreshSubTasks": "Atualizar Sub Tarefas",
"edit": "Editar",
"delete": "Excluir",
"confirmDeleteSubTask": "Tem certeza de que deseja excluir esta subtarefa?",
"deleteSubTask": "Excluir subtarefa"
"delete": "Deletar",
"confirmDeleteSubTask": "Tem certeza de que deseja deletar esta subtarefa?",
"deleteSubTask": "Deletar Sub Tarefa"
},
"dependencies": {
"title": "Dependências",
@@ -57,37 +57,67 @@
"blockedBy": "Bloqueado por",
"searchTask": "Digite para pesquisar tarefa",
"noTasksFound": "Nenhuma tarefa encontrada",
"confirmDeleteDependency": "Tem certeza de que deseja excluir?"
"confirmDeleteDependency": "Tem certeza de que deseja deletar?"
},
"attachments": {
"title": "Anexos",
"chooseOrDropFileToUpload": "Escolha ou arraste um arquivo para carregar",
"uploading": "Carregando..."
"chooseOrDropFileToUpload": "Escolha ou arraste um arquivo para upload",
"uploading": "Enviando..."
},
"comments": {
"title": "Comentários",
"addComment": "+ Adicionar novo comentário",
"noComments": "Nenhum comentário ainda. Seja o primeiro a comentar!",
"delete": "Excluir",
"confirmDeleteComment": "Tem certeza de que deseja excluir este comentário?"
"noComments": "Ainda não há comentários. Seja o primeiro a comentar!",
"delete": "Deletar",
"confirmDeleteComment": "Tem certeza de que deseja deletar este comentário?",
"addCommentPlaceholder": "Adicionar um comentário...",
"cancel": "Cancelar",
"commentButton": "Comentar",
"attachFiles": "Anexar arquivos",
"addMoreFiles": "Adicionar mais arquivos",
"selectedFiles": "Arquivos Selecionados (Até 25MB, Máximo {count})",
"maxFilesError": "Você pode fazer upload de no máximo {count} arquivos",
"processFilesError": "Falha ao processar arquivos",
"addCommentError": "Por favor adicione um comentário ou anexe arquivos",
"createdBy": "Criado {time} por {user}",
"updatedTime": "Atualizado {time}"
},
"searchInputPlaceholder": "Pesquisar por nome",
"pendingInvitation": "Convite pendente"
"pendingInvitation": "Convite Pendente"
},
"taskTimeLogTab": {
"title": "Registro de tempo",
"title": "Registro de Tempo",
"addTimeLog": "Adicionar novo registro de tempo",
"totalLogged": "Total registrado",
"totalLogged": "Total Registrado",
"exportToExcel": "Exportar para Excel",
"noTimeLogsFound": "Nenhum registro de tempo encontrado"
"noTimeLogsFound": "Nenhum registro de tempo encontrado",
"timeLogForm": {
"date": "Data",
"startTime": "Hora de Início",
"endTime": "Hora de Fim",
"workDescription": "Descrição do Trabalho",
"descriptionPlaceholder": "Adicionar uma descrição",
"logTime": "Registrar tempo",
"updateTime": "Atualizar tempo",
"cancel": "Cancelar",
"selectDateError": "Por favor selecione uma data",
"selectStartTimeError": "Por favor selecione a hora de início",
"selectEndTimeError": "Por favor selecione a hora de fim",
"endTimeAfterStartError": "A hora de fim deve ser posterior à hora de início"
}
},
"taskActivityLogTab": {
"title": "Registro de atividade"
"title": "Registro de Atividade",
"add": "ADICIONAR",
"remove": "REMOVER",
"none": "Nenhum",
"weight": "Peso",
"createdTask": "criou a tarefa."
},
"taskProgress": {
"markAsDoneTitle": "Marcar Tarefa como Concluída?",
"confirmMarkAsDone": "Sim, marcar como concluída",
"cancelMarkAsDone": "Não, manter status atual",
"markAsDoneDescription": "Você definiu o progresso como 100%. Deseja atualizar o status da tarefa para \"Concluída\"?"
"markAsDoneDescription": "Você definiu o progresso para 100%. Gostaria de atualizar o status da tarefa para \"Concluída\"?"
}
}

View File

@@ -7,26 +7,35 @@
"title": "信息",
"details": {
"title": "详情",
"task-key": "任务ID",
"task-key": "任务",
"phase": "阶段",
"assignees": "受人",
"assignees": "受人",
"due-date": "截止日期",
"time-estimation": "估计时间",
"time-estimation": "时间估算",
"priority": "优先级",
"labels": "标签",
"billable": "可计费",
"notify": "通知",
"when-done-notify": "完成时通知",
"when-done-notify": "完成时通知",
"start-date": "开始日期",
"end-date": "结束日期",
"hide-start-date": "隐藏开始日期",
"show-start-date": "显示开始日期",
"hours": "小时",
"minutes": "分钟"
"minutes": "分钟",
"progressValue": "进度值",
"progressValueTooltip": "设置进度百分比0-100%",
"progressValueRequired": "请输入进度值",
"progressValueRange": "进度必须在0到100之间",
"taskWeight": "任务权重",
"taskWeightTooltip": "设置此子任务的权重(百分比)",
"taskWeightRequired": "请输入任务权重",
"taskWeightRange": "权重必须在0到100之间",
"recurring": "重复"
},
"labels": {
"labelInputPlaceholder": "搜索或创建",
"labelsSelectorInputTip": "按回车创建"
"labelsSelectorInputTip": "按回车创建"
},
"description": {
"title": "描述",
@@ -34,8 +43,8 @@
},
"subTasks": {
"title": "子任务",
"addSubTask": "+ 添加子任务",
"addSubTaskInputPlaceholder": "输入您的任务并按回车",
"addSubTask": "添加子任务",
"addSubTaskInputPlaceholder": "输入您的任务并按回车",
"refreshSubTasks": "刷新子任务",
"edit": "编辑",
"delete": "删除",
@@ -45,8 +54,8 @@
"dependencies": {
"title": "依赖关系",
"addDependency": "+ 添加新依赖",
"blockedBy": "被阻",
"searchTask": "输入搜索任务",
"blockedBy": "被阻",
"searchTask": "输入搜索任务",
"noTasksFound": "未找到任务",
"confirmDeleteDependency": "您确定要删除吗?"
},
@@ -58,9 +67,20 @@
"comments": {
"title": "评论",
"addComment": "+ 添加新评论",
"noComments": "尚无评论。成为第一个评论的人!",
"noComments": "还没有评论。成为第一个评论的人!",
"delete": "删除",
"confirmDeleteComment": "您确定要删除此评论吗?"
"confirmDeleteComment": "您确定要删除此评论吗?",
"addCommentPlaceholder": "添加评论...",
"cancel": "取消",
"commentButton": "评论",
"attachFiles": "附加文件",
"addMoreFiles": "添加更多文件",
"selectedFiles": "已选择的文件最多25MB最大{count}个)",
"maxFilesError": "您最多只能上传{count}个文件",
"processFilesError": "处理文件失败",
"addCommentError": "请添加评论或附加文件",
"createdBy": "{time}由{user}创建",
"updatedTime": "更新于{time}"
},
"searchInputPlaceholder": "按名称搜索",
"pendingInvitation": "待处理邀请"
@@ -68,11 +88,36 @@
"taskTimeLogTab": {
"title": "时间日志",
"addTimeLog": "添加新时间日志",
"totalLogged": "总记录",
"totalLogged": "总记录时间",
"exportToExcel": "导出到Excel",
"noTimeLogsFound": "未找到时间日志"
"noTimeLogsFound": "未找到时间日志",
"timeLogForm": {
"date": "日期",
"startTime": "开始时间",
"endTime": "结束时间",
"workDescription": "工作描述",
"descriptionPlaceholder": "添加描述",
"logTime": "记录时间",
"updateTime": "更新时间",
"cancel": "取消",
"selectDateError": "请选择日期",
"selectStartTimeError": "请选择开始时间",
"selectEndTimeError": "请选择结束时间",
"endTimeAfterStartError": "结束时间必须在开始时间之后"
}
},
"taskActivityLogTab": {
"title": "活动日志"
"title": "活动日志",
"add": "添加",
"remove": "移除",
"none": "无",
"weight": "权重",
"createdTask": "创建了任务。"
},
"taskProgress": {
"markAsDoneTitle": "将任务标记为完成?",
"confirmMarkAsDone": "是的,标记为完成",
"cancelMarkAsDone": "不,保持当前状态",
"markAsDoneDescription": "您已将进度设置为100%。您想将任务状态更新为\"完成\"吗?"
}
}

View File

@@ -20,7 +20,7 @@ const TaskDrawerActivityLog = () => {
const [loading, setLoading] = useState<boolean>(false);
const { selectedTaskId, taskFormViewModel } = useAppSelector(state => state.taskDrawerReducer);
const { mode: themeMode } = useAppSelector(state => state.themeReducer);
const { t } = useTranslation();
const { t } = useTranslation('task-drawer/task-drawer');
useEffect(() => {
fetchActivityLogs();
@@ -73,7 +73,7 @@ const TaskDrawerActivityLog = () => {
</Tag>
<ArrowRightOutlined />
&nbsp;
<Tag color={'default'}>{activity.log_type === 'create' ? 'ADD' : 'REMOVE'}</Tag>
<Tag color={'default'}>{activity.log_type === 'create' ? t('taskActivityLogTab.add') : t('taskActivityLogTab.remove')}</Tag>
</Flex>
);
@@ -87,7 +87,7 @@ const TaskDrawerActivityLog = () => {
: activity.previous_status?.color_code
}
>
{truncateText(activity.previous_status?.name) || 'None'}
{truncateText(activity.previous_status?.name) || t('taskActivityLogTab.none')}
</Tag>
<ArrowRightOutlined />
&nbsp;
@@ -98,7 +98,7 @@ const TaskDrawerActivityLog = () => {
: activity.next_status?.color_code
}
>
{truncateText(activity.next_status?.name) || 'None'}
{truncateText(activity.next_status?.name) || t('taskActivityLogTab.none')}
</Tag>
</Flex>
);
@@ -113,7 +113,7 @@ const TaskDrawerActivityLog = () => {
: activity.previous_priority?.color_code
}
>
{truncateText(activity.previous_priority?.name) || 'None'}
{truncateText(activity.previous_priority?.name) || t('taskActivityLogTab.none')}
</Tag>
<ArrowRightOutlined />
&nbsp;
@@ -124,7 +124,7 @@ const TaskDrawerActivityLog = () => {
: activity.next_priority?.color_code
}
>
{truncateText(activity.next_priority?.name) || 'None'}
{truncateText(activity.next_priority?.name) || t('taskActivityLogTab.none')}
</Tag>
</Flex>
);
@@ -133,12 +133,12 @@ const TaskDrawerActivityLog = () => {
return (
<Flex gap={4} align="center">
<Tag color={activity.previous_phase?.color_code}>
{truncateText(activity.previous_phase?.name) || 'None'}
{truncateText(activity.previous_phase?.name) || t('taskActivityLogTab.none')}
</Tag>
<ArrowRightOutlined />
&nbsp;
<Tag color={activity.next_phase?.color_code}>
{truncateText(activity.next_phase?.name) || 'None'}
{truncateText(activity.next_phase?.name) || t('taskActivityLogTab.none')}
</Tag>
</Flex>
);
@@ -156,20 +156,20 @@ const TaskDrawerActivityLog = () => {
case IActivityLogAttributeTypes.WEIGHT:
return (
<Flex gap={4} align="center">
<Tag color="purple">Weight: {activity.previous || '100'}</Tag>
<Tag color="purple">{t('taskActivityLogTab.weight')}: {activity.previous || '100'}</Tag>
<ArrowRightOutlined />
&nbsp;
<Tag color="purple">Weight: {activity.current || '100'}</Tag>
<Tag color="purple">{t('taskActivityLogTab.weight')}: {activity.current || '100'}</Tag>
</Flex>
);
default:
return (
<Flex gap={4} align="center">
<Tag color={'default'}>{truncateText(activity.previous) || 'None'}</Tag>
<Tag color={'default'}>{truncateText(activity.previous) || t('taskActivityLogTab.none')}</Tag>
<ArrowRightOutlined />
&nbsp;
<Tag color={'default'}>{truncateText(activity.current) || 'None'}</Tag>
<Tag color={'default'}>{truncateText(activity.current) || t('taskActivityLogTab.none')}</Tag>
</Flex>
);
}
@@ -222,7 +222,7 @@ const TaskDrawerActivityLog = () => {
<Flex vertical gap={4}>
<Flex gap={4} align="center">
<Typography.Text strong>{activityLogs.name}</Typography.Text>
<Typography.Text>created the task.</Typography.Text>
<Typography.Text>{t('taskActivityLogTab.createdTask')}</Typography.Text>
<Tooltip
title={
activityLogs.created_at

View File

@@ -1,18 +1,14 @@
import { Button, Flex, Form, Mentions, Space, Tooltip, Typography, message } from 'antd';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { PaperClipOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons';
import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { updateTaskCounts } from '@/features/task-management/task-management.slice';
import { colors } from '@/styles/colors';
import { themeWiseColor } from '@/utils/themeWiseColor';
import { formatDateTimeWithLocale } from '@/utils/format-date-time-with-locale';
import { calculateTimeDifference } from '@/utils/calculate-time-difference';
import {
IMentionMemberSelectOption,
IMentionMemberViewModel,
} from '@/types/project/projectComments.types';
import { projectCommentsApiService } from '@/api/projects/comments/project-comments.api.service';
import { ITaskCommentsCreateRequest } from '@/types/tasks/task-comments.types';
import { ITaskAttachment } from '@/types/tasks/task-attachment-view-model';
import logger from '@/utils/errorLogger';
@@ -40,6 +36,7 @@ const formatFileSize = (bytes: number): string => {
};
const InfoTabFooter = () => {
const { t } = useTranslation('task-drawer/task-drawer');
const MAXIMUM_FILE_COUNT = 5;
const [characterLength, setCharacterLength] = useState<number>(0);
@@ -136,7 +133,7 @@ const InfoTabFooter = () => {
if (!selectedTaskId || !projectId) return;
if (!isCommentValid()) {
message.error('Please add a comment or attach files');
message.error(t('taskInfoTab.comments.addCommentError'));
return;
}
@@ -188,7 +185,7 @@ const InfoTabFooter = () => {
const files = Array.from(event.target.files);
if (selectedFiles.length + files.length > MAXIMUM_FILE_COUNT) {
message.error(`You can only upload a maximum of ${MAXIMUM_FILE_COUNT} files`);
message.error(t('taskInfoTab.comments.maxFilesError', { count: MAXIMUM_FILE_COUNT }));
return;
}
@@ -219,7 +216,7 @@ const InfoTabFooter = () => {
}
} catch (error) {
console.error('Failed to process files:', error);
message.error('Failed to process files');
message.error(t('taskInfoTab.comments.processFilesError'));
} finally {
setUploading(false);
@@ -279,7 +276,7 @@ const InfoTabFooter = () => {
}}
>
<Mentions
placeholder={'Add a comment...'}
placeholder={t('taskInfoTab.comments.addCommentPlaceholder')}
options={mentionsOptions}
autoSize
maxLength={5000}
@@ -312,7 +309,7 @@ const InfoTabFooter = () => {
{selectedFiles.length > 0 && (
<Flex vertical gap={8} style={{ marginTop: 12 }}>
<Typography.Title level={5} style={{ margin: 0 }}>
Selected Files (Up to 25MB, Maximum of {MAXIMUM_FILE_COUNT})
{t('taskInfoTab.comments.selectedFiles', { count: MAXIMUM_FILE_COUNT })}
</Typography.Title>
<Flex
vertical
@@ -368,7 +365,7 @@ const InfoTabFooter = () => {
icon={<PlusOutlined />}
disabled={selectedFiles.length >= MAXIMUM_FILE_COUNT || uploading}
>
Add more files
{t('taskInfoTab.comments.addMoreFiles')}
</Button>
</Flex>
</Flex>
@@ -378,7 +375,7 @@ const InfoTabFooter = () => {
<Form.Item name={'comment'} style={{ marginBlock: 12 }}>
<div>
<Mentions
placeholder={'Add a comment...'}
placeholder={t('taskInfoTab.comments.addCommentPlaceholder')}
options={mentionsOptions}
autoSize
autoFocus
@@ -427,8 +424,8 @@ const InfoTabFooter = () => {
<Tooltip
title={
selectedFiles.length >= MAXIMUM_FILE_COUNT
? `Maximum ${MAXIMUM_FILE_COUNT} files allowed`
: 'Attach files'
? t('taskInfoTab.comments.maxFilesError', { count: MAXIMUM_FILE_COUNT })
: t('taskInfoTab.comments.attachFiles')
}
>
<Button
@@ -439,14 +436,14 @@ const InfoTabFooter = () => {
</Tooltip>
<Space>
<Button onClick={handleCancel}>Cancel</Button>
<Button onClick={handleCancel}>{t('taskInfoTab.comments.cancel')}</Button>
<Button
type="primary"
disabled={!isCommentValid()}
onClick={handleSubmit}
loading={uploading}
>
Comment
{t('taskInfoTab.comments.commentButton')}
</Button>
</Space>
</Flex>
@@ -463,9 +460,10 @@ const InfoTabFooter = () => {
}
>
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
Created{' '}
{taskFormViewModel?.task?.created_from_now || 'N/A'}{' '}
by {taskFormViewModel?.task?.reporter}
{t('taskInfoTab.comments.createdBy', {
time: taskFormViewModel?.task?.created_from_now || 'N/A',
user: taskFormViewModel?.task?.reporter || ''
})}
</Typography.Text>
</Tooltip>
<Tooltip
@@ -476,8 +474,9 @@ const InfoTabFooter = () => {
}
>
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
Updated{' '}
{taskFormViewModel?.task?.updated_from_now || 'N/A'}
{t('taskInfoTab.comments.updatedTime', {
time: taskFormViewModel?.task?.updated_from_now || 'N/A'
})}
</Typography.Text>
</Tooltip>
</Flex>

View File

@@ -1,6 +1,7 @@
import React from 'react';
import { Button, DatePicker, Form, Input, TimePicker, Flex } from 'antd';
import { ClockCircleOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next';
import dayjs from 'dayjs';
import { useAppSelector } from '@/hooks/useAppSelector';
@@ -25,6 +26,7 @@ const TimeLogForm = ({
initialValues,
mode = 'create',
}: TimeLogFormProps) => {
const { t } = useTranslation('task-drawer/task-drawer');
const currentSession = useAuthService().getCurrentSession();
const { socket, connected } = useSocket();
const [form] = Form.useForm();
@@ -140,7 +142,7 @@ const TimeLogForm = ({
form.setFields([
{
name: 'endTime',
errors: ['End time must be after start time'],
errors: [t('taskTimeLogTab.timeLogForm.endTimeAfterStartError')],
},
]);
return;
@@ -219,44 +221,44 @@ const TimeLogForm = ({
<Flex gap={8} wrap="wrap" style={{ width: '100%' }}>
<Form.Item
name="date"
label="Date"
rules={[{ required: true, message: 'Please select a date' }]}
label={t('taskTimeLogTab.timeLogForm.date')}
rules={[{ required: true, message: t('taskTimeLogTab.timeLogForm.selectDateError') }]}
>
<DatePicker disabledDate={current => current && current.toDate() > new Date()} />
</Form.Item>
<Form.Item
name="startTime"
label="Start Time"
rules={[{ required: true, message: 'Please select start time' }]}
label={t('taskTimeLogTab.timeLogForm.startTime')}
rules={[{ required: true, message: t('taskTimeLogTab.timeLogForm.selectStartTimeError') }]}
>
<TimePicker format="HH:mm" />
</Form.Item>
<Form.Item
name="endTime"
label="End Time"
rules={[{ required: true, message: 'Please select end time' }]}
label={t('taskTimeLogTab.timeLogForm.endTime')}
rules={[{ required: true, message: t('taskTimeLogTab.timeLogForm.selectEndTimeError') }]}
>
<TimePicker format="HH:mm" />
</Form.Item>
</Flex>
</Form.Item>
<Form.Item name="description" label="Work Description" style={{ marginBlockEnd: 12 }}>
<Input.TextArea placeholder="Add a description" />
<Form.Item name="description" label={t('taskTimeLogTab.timeLogForm.workDescription')} style={{ marginBlockEnd: 12 }}>
<Input.TextArea placeholder={t('taskTimeLogTab.timeLogForm.descriptionPlaceholder')} />
</Form.Item>
<Form.Item style={{ marginBlockEnd: 0 }}>
<Flex gap={8}>
<Button onClick={onCancel}>Cancel</Button>
<Button onClick={onCancel}>{t('taskTimeLogTab.timeLogForm.cancel')}</Button>
<Button
type="primary"
icon={<ClockCircleOutlined />}
disabled={!isFormValid()}
htmlType="submit"
>
{mode === 'edit' ? 'Update time' : 'Log time'}
{mode === 'edit' ? t('taskTimeLogTab.timeLogForm.updateTime') : t('taskTimeLogTab.timeLogForm.logTime')}
</Button>
</Flex>
</Form.Item>

View File

@@ -4,11 +4,9 @@ import {
Card,
Flex,
Form,
GetProp,
Input,
Tooltip,
Typography,
UploadProps,
Spin,
Skeleton,
} from 'antd';
@@ -20,7 +18,6 @@ import { useDocumentTitle } from '@/hooks/useDoumentTItle';
import { useMixpanelTracking } from '@/hooks/useMixpanelTracking';
import {
evt_settings_profile_visit,
evt_settings_profile_avatar_upload,
evt_settings_profile_name_change,
evt_settings_profile_picture_update,
} from '@/shared/worklenz-analytics-events';