Add missing translations for project templates and task details
continuous-integration/drone/push Build is passing

Adds new translation keys for project templates and task details in `en.json` and `de.json`, and updates `ProjectTemplate.tsx` to use these translations.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: ceced2fc-aa46-458d-ba87-ddd4b7bb1518
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/659922a9-0087-461c-90dd-6d9a58b81d4d/ceced2fc-aa46-458d-ba87-ddd4b7bb1518/iGgwDyZ
This commit is contained in:
paul-nothaft
2025-10-24 11:26:17 +00:00
parent 3c39346087
commit d5b045158a
4 changed files with 51 additions and 41 deletions
-4
View File
@@ -30,10 +30,6 @@ externalPort = 3000
localPort = 44261 localPort = 44261
externalPort = 3003 externalPort = 3003
[[ports]]
localPort = 46755
externalPort = 4200
[env] [env]
PORT = "5000" PORT = "5000"
+35 -35
View File
@@ -677,7 +677,7 @@ export default function ProjectTemplate({
{/* Closed Projects Section */} {/* Closed Projects Section */}
<div className="space-y-4 mt-8"> <div className="space-y-4 mt-8">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<h3 className="text-lg font-semibold">Closed Projects</h3> <h3 className="text-lg font-semibold">{t('projectTemplate.closedProjects')}</h3>
<Input <Input
placeholder="Filter closed projects..." placeholder="Filter closed projects..."
value={closedProjectsFilter} value={closedProjectsFilter}
@@ -1124,25 +1124,25 @@ export default function ProjectTemplate({
{/* Project Details */} {/* Project Details */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="space-y-2"> <div className="space-y-2">
<label className="text-sm font-medium">Project Name</label> <label className="text-sm font-medium">{t('projectTemplate.projectName')}</label>
<Input <Input
value={selectedProject.name} value={selectedProject.name}
onChange={(e) => setSelectedProject({ ...selectedProject, name: e.target.value })} onChange={(e) => setSelectedProject({ ...selectedProject, name: e.target.value })}
placeholder="Enter project name" placeholder={t('projectTemplate.projectNamePlaceholder')}
data-testid="input-edit-project-name" data-testid="input-edit-project-name"
/> />
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<label className="text-sm font-medium">Description (Optional)</label> <label className="text-sm font-medium">{t('projectTemplate.projectDescription')}</label>
<Input <Input
value={selectedProject.description || ''} value={selectedProject.description || ''}
onChange={(e) => setSelectedProject({ ...selectedProject, description: e.target.value })} onChange={(e) => setSelectedProject({ ...selectedProject, description: e.target.value })}
placeholder="Enter project description" placeholder={t('projectTemplate.projectDescriptionPlaceholder')}
data-testid="input-edit-project-description" data-testid="input-edit-project-description"
/> />
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<label className="text-sm font-medium">Status</label> <label className="text-sm font-medium">{t('projectTemplate.status')}</label>
<Select <Select
value={selectedProject.status} value={selectedProject.status}
onValueChange={(value: Project['status']) => onValueChange={(value: Project['status']) =>
@@ -1153,9 +1153,9 @@ export default function ProjectTemplate({
<SelectValue /> <SelectValue />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="planning">Planning</SelectItem> <SelectItem value="planning">{t('projectTemplate.planning')}</SelectItem>
<SelectItem value="active">Active</SelectItem> <SelectItem value="active">{t('projectTemplate.active')}</SelectItem>
<SelectItem value="finished">Finished</SelectItem> <SelectItem value="finished">{t('projectTemplate.finished')}</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
@@ -1163,7 +1163,7 @@ export default function ProjectTemplate({
{/* Planned End Date */} {/* Planned End Date */}
<div className="space-y-2"> <div className="space-y-2">
<label className="text-sm font-medium">Planned End Date (Optional)</label> <label className="text-sm font-medium">{t('projectTemplate.plannedEndDate')}</label>
<Popover open={isPlannedEndDateCalendarOpen} onOpenChange={setIsPlannedEndDateCalendarOpen}> <Popover open={isPlannedEndDateCalendarOpen} onOpenChange={setIsPlannedEndDateCalendarOpen}>
<PopoverTrigger asChild> <PopoverTrigger asChild>
<Button <Button
@@ -1174,7 +1174,7 @@ export default function ProjectTemplate({
<CalendarIcon className="mr-2 h-4 w-4" /> <CalendarIcon className="mr-2 h-4 w-4" />
{selectedProject.plannedEndDate {selectedProject.plannedEndDate
? selectedProject.plannedEndDate.toLocaleDateString() ? selectedProject.plannedEndDate.toLocaleDateString()
: "Select planned end date"} : t('projectTemplate.selectPlannedEndDate')}
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start"> <PopoverContent className="w-auto p-0" align="start">
@@ -1198,7 +1198,7 @@ export default function ProjectTemplate({
className="text-xs text-muted-foreground hover:text-destructive" className="text-xs text-muted-foreground hover:text-destructive"
data-testid="button-clear-planned-end-date" data-testid="button-clear-planned-end-date"
> >
Clear date {t('projectTemplate.clearDate')}
</Button> </Button>
)} )}
</div> </div>
@@ -1206,7 +1206,7 @@ export default function ProjectTemplate({
{/* Tasks Section */} {/* Tasks Section */}
<div className="space-y-4"> <div className="space-y-4">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<h3 className="text-lg font-semibold">Project Tasks</h3> <h3 className="text-lg font-semibold">{t('projectTemplate.projectTasks')}</h3>
<Button <Button
variant="outline" variant="outline"
size="sm" size="sm"
@@ -1214,7 +1214,7 @@ export default function ProjectTemplate({
data-testid="button-add-task-edit" data-testid="button-add-task-edit"
> >
<Plus className="w-4 h-4 mr-2" /> <Plus className="w-4 h-4 mr-2" />
Add Task {t('projectTemplate.addTask')}
</Button> </Button>
</div> </div>
@@ -1227,29 +1227,29 @@ export default function ProjectTemplate({
<div className="space-y-3"> <div className="space-y-3">
<div className="grid grid-cols-1 md:grid-cols-2 gap-3"> <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
<div className="space-y-1"> <div className="space-y-1">
<label className="text-xs font-medium text-muted-foreground">Task Title</label> <label className="text-xs font-medium text-muted-foreground">{t('projectTemplate.taskTitle')}</label>
<Input <Input
value={taskForm.title || ''} value={taskForm.title || ''}
onChange={(e) => setTaskForm({...taskForm, title: e.target.value})} onChange={(e) => setTaskForm({...taskForm, title: e.target.value})}
placeholder="Enter task title" placeholder={t('projectTemplate.enterTaskTitle')}
className="text-sm" className="text-sm"
data-testid={`input-inline-task-title-${index}`} data-testid={`input-inline-task-title-${index}`}
/> />
</div> </div>
<div className="space-y-1"> <div className="space-y-1">
<label className="text-xs font-medium text-muted-foreground">Description</label> <label className="text-xs font-medium text-muted-foreground">{t('projectTemplate.description')}</label>
<Input <Input
value={taskForm.description || ''} value={taskForm.description || ''}
onChange={(e) => setTaskForm({...taskForm, description: e.target.value})} onChange={(e) => setTaskForm({...taskForm, description: e.target.value})}
placeholder="Enter task description" placeholder={t('projectTemplate.enterTaskDescription')}
className="text-sm" className="text-sm"
data-testid={`input-inline-task-description-${index}`} data-testid={`input-inline-task-description-${index}`}
/> />
</div> </div>
<div className="space-y-1"> <div className="space-y-1">
<label className="text-xs font-medium text-muted-foreground">Priority</label> <label className="text-xs font-medium text-muted-foreground">{t('projectTemplate.priority')}</label>
<Select <Select
value={taskForm.priority || 'medium'} value={taskForm.priority || 'medium'}
onValueChange={(value: ProjectTask['priority']) => onValueChange={(value: ProjectTask['priority']) =>
@@ -1260,15 +1260,15 @@ export default function ProjectTemplate({
<SelectValue /> <SelectValue />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="low">Low</SelectItem> <SelectItem value="low">{t('priority.low')}</SelectItem>
<SelectItem value="medium">Medium</SelectItem> <SelectItem value="medium">{t('priority.medium')}</SelectItem>
<SelectItem value="high">High</SelectItem> <SelectItem value="high">{t('priority.high')}</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
<div className="space-y-1"> <div className="space-y-1">
<label className="text-xs font-medium text-muted-foreground">Status</label> <label className="text-xs font-medium text-muted-foreground">{t('projectTemplate.status')}</label>
<Select <Select
value={taskForm.status || 'todo'} value={taskForm.status || 'todo'}
onValueChange={(value: ProjectTask['status']) => onValueChange={(value: ProjectTask['status']) =>
@@ -1279,15 +1279,15 @@ export default function ProjectTemplate({
<SelectValue /> <SelectValue />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="todo">To Do</SelectItem> <SelectItem value="todo">{t('status.todo')}</SelectItem>
<SelectItem value="inProgress">In Progress</SelectItem> <SelectItem value="inProgress">{t('status.inProgress')}</SelectItem>
<SelectItem value="done">Done</SelectItem> <SelectItem value="done">{t('status.done')}</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
<div className="space-y-1 md:col-span-2"> <div className="space-y-1 md:col-span-2">
<label className="text-xs font-medium text-muted-foreground">Estimated Hours</label> <label className="text-xs font-medium text-muted-foreground">{t('projectTemplate.estimatedHours')}</label>
<Input <Input
type="number" type="number"
value={taskForm.estimatedHours || ''} value={taskForm.estimatedHours || ''}
@@ -1307,7 +1307,7 @@ export default function ProjectTemplate({
onClick={handleCancelTaskEdit} onClick={handleCancelTaskEdit}
data-testid={`button-cancel-inline-edit-${index}`} data-testid={`button-cancel-inline-edit-${index}`}
> >
Cancel {t('projectTemplate.cancel')}
</Button> </Button>
<Button <Button
size="sm" size="sm"
@@ -1315,7 +1315,7 @@ export default function ProjectTemplate({
disabled={!taskForm.title?.trim()} disabled={!taskForm.title?.trim()}
data-testid={`button-save-inline-edit-${index}`} data-testid={`button-save-inline-edit-${index}`}
> >
Save Changes {t('projectTemplate.save')}
</Button> </Button>
</div> </div>
</div> </div>
@@ -1345,13 +1345,13 @@ export default function ProjectTemplate({
) : null} ) : null}
{task.timeTracked && task.timeTracked > 0 && ( {task.timeTracked && task.timeTracked > 0 && (
<Badge variant="outline" className="text-xs bg-blue-50 text-blue-700 border-blue-200"> <Badge variant="outline" className="text-xs bg-blue-50 text-blue-700 border-blue-200">
{Math.floor(task.timeTracked / 60)}h {task.timeTracked % 60}m tracked {Math.floor(task.timeTracked / 60)}h {task.timeTracked % 60}m {t('projectTemplate.tracked')}
</Badge> </Badge>
)} )}
{task.notes && task.notes.trim() && ( {task.notes && task.notes.trim() && (
<Badge variant="outline" className="text-xs bg-green-50 text-green-700 border-green-200"> <Badge variant="outline" className="text-xs bg-green-50 text-green-700 border-green-200">
<FileText className="w-3 h-3 mr-1" /> <FileText className="w-3 h-3 mr-1" />
Notes {t('projectTemplate.notesLabel')}
</Badge> </Badge>
)} )}
</div> </div>
@@ -1365,7 +1365,7 @@ export default function ProjectTemplate({
handleOpenTaskDetails(task); handleOpenTaskDetails(task);
}} }}
data-testid={`button-details-task-${index}`} data-testid={`button-details-task-${index}`}
title="View task details" title={t('projectTemplate.viewTaskDetails')}
> >
<FileText className="w-3 h-3" /> <FileText className="w-3 h-3" />
</Button> </Button>
@@ -1377,7 +1377,7 @@ export default function ProjectTemplate({
handleEditTask(index); handleEditTask(index);
}} }}
data-testid={`button-edit-task-edit-${index}`} data-testid={`button-edit-task-edit-${index}`}
title="Edit task" title={t('projectTemplate.editTaskTooltip')}
> >
<Edit className="w-3 h-3" /> <Edit className="w-3 h-3" />
</Button> </Button>
@@ -1389,7 +1389,7 @@ export default function ProjectTemplate({
handleRemoveTask(index); handleRemoveTask(index);
}} }}
data-testid={`button-remove-task-edit-${index}`} data-testid={`button-remove-task-edit-${index}`}
title="Remove task" title={t('projectTemplate.removeTask')}
> >
<Trash2 className="w-3 h-3" /> <Trash2 className="w-3 h-3" />
</Button> </Button>
@@ -1401,7 +1401,7 @@ export default function ProjectTemplate({
{projectTasks.length === 0 && ( {projectTasks.length === 0 && (
<div className="text-center text-muted-foreground text-sm py-8 border-2 border-dashed border-muted rounded-lg"> <div className="text-center text-muted-foreground text-sm py-8 border-2 border-dashed border-muted rounded-lg">
No tasks in this project yet. Click "Add Task" to get started. {t('projectTemplate.noTasksInProject')}
</div> </div>
)} )}
</div> </div>
+8 -1
View File
@@ -253,7 +253,14 @@
"projectDescriptionPlaceholder": "Projektbeschreibung eingeben (optional)", "projectDescriptionPlaceholder": "Projektbeschreibung eingeben (optional)",
"plannedEndDate": "Geplantes Enddatum", "plannedEndDate": "Geplantes Enddatum",
"selectPlannedEndDate": "Geplantes Enddatum wählen", "selectPlannedEndDate": "Geplantes Enddatum wählen",
"clearDate": "Datum löschen" "clearDate": "Datum löschen",
"noTasksInProject": "Noch keine Aufgaben in diesem Projekt. Klicken Sie auf \"Aufgabe hinzufügen\", um zu beginnen.",
"closedProjects": "Abgeschlossene Projekte",
"viewTaskDetails": "Aufgabendetails anzeigen",
"editTaskTooltip": "Aufgabe bearbeiten",
"removeTask": "Aufgabe entfernen",
"tracked": "verfolgt",
"notesLabel": "Notizen"
}, },
"timeCompletion": { "timeCompletion": {
"title": "Aufgabe abgeschlossen!", "title": "Aufgabe abgeschlossen!",
+8 -1
View File
@@ -253,7 +253,14 @@
"projectDescriptionPlaceholder": "Enter project description (optional)", "projectDescriptionPlaceholder": "Enter project description (optional)",
"plannedEndDate": "Planned End Date", "plannedEndDate": "Planned End Date",
"selectPlannedEndDate": "Select planned end date", "selectPlannedEndDate": "Select planned end date",
"clearDate": "Clear date" "clearDate": "Clear date",
"noTasksInProject": "No tasks in this project yet. Click \"Add Task\" to get started.",
"closedProjects": "Closed Projects",
"viewTaskDetails": "View task details",
"editTaskTooltip": "Edit task",
"removeTask": "Remove task",
"tracked": "tracked",
"notesLabel": "Notes"
}, },
"timeCompletion": { "timeCompletion": {
"title": "Task Completed!", "title": "Task Completed!",