fix(i18n): translate remaining German hardcoded strings in PhotoUpload

Replace 6 hardcoded German strings in PhotoUpload.tsx with t() calls:
- 'Tag verknüpfen' → t('photos.linkDay')
- 'Kein Tag' / 'Tag N' → t('photos.noDay') / t('photos.dayLabel')
- '{N} Foto(s) ausgewählt' → t('photos.photoSelected/photosSelected')
- 'bis zu 30 Fotos' hint → t('photos.fileTypeHint')
- 'Wird hochgeladen...' → t('common.uploading')

Add all 6 new keys to all 14 language files and update test
assertions from German strings to English equivalents.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Isaias Tavares
2026-04-12 16:53:50 -03:00
parent ecbb1de8de
commit 0fe1c443e9
16 changed files with 96 additions and 12 deletions
@@ -50,7 +50,7 @@ describe('PhotoUpload', () => {
it('FE-COMP-PHOTOUPLOAD-002: options section hidden before files are selected', () => {
render(<PhotoUpload {...defaultProps} />)
expect(screen.queryByText('Tag verknüpfen')).not.toBeInTheDocument()
expect(screen.queryByText('Link Day')).not.toBeInTheDocument()
expect(screen.queryByPlaceholderText('Optional caption...')).not.toBeInTheDocument()
})
@@ -65,27 +65,27 @@ describe('PhotoUpload', () => {
render(<PhotoUpload {...defaultProps} />)
await uploadFiles([makeFile()])
expect(screen.getByAltText('photo.jpg')).toBeInTheDocument()
expect(screen.getByText('Tag verknüpfen')).toBeInTheDocument()
expect(screen.getByText('Link Day')).toBeInTheDocument()
expect(screen.getByPlaceholderText('Optional caption...')).toBeInTheDocument()
})
it('FE-COMP-PHOTOUPLOAD-005: file count label updates correctly', async () => {
render(<PhotoUpload {...defaultProps} />)
await uploadFiles([makeFile('photo1.jpg'), makeFile('photo2.jpg')])
expect(screen.getByText('2 Fotos ausgewählt')).toBeInTheDocument()
expect(screen.getByText('2 Photos selected')).toBeInTheDocument()
})
it('FE-COMP-PHOTOUPLOAD-006: remove button removes a file from preview', async () => {
render(<PhotoUpload {...defaultProps} />)
await uploadFiles([makeFile('photo1.jpg'), makeFile('photo2.jpg')])
expect(screen.getByText('2 Fotos ausgewählt')).toBeInTheDocument()
expect(screen.getByText('2 Photos selected')).toBeInTheDocument()
// Remove buttons are inside `.relative.aspect-square` wrappers in the preview grid
const removeButtons = document.querySelectorAll('.relative.aspect-square button')
expect(removeButtons.length).toBe(2)
await userEvent.click(removeButtons[0])
expect(screen.getByText('1 Foto ausgewählt')).toBeInTheDocument()
expect(screen.getByText('1 Photo selected')).toBeInTheDocument()
expect(screen.getAllByRole('img').length).toBe(1)
})
@@ -146,7 +146,7 @@ describe('PhotoUpload', () => {
await userEvent.click(getSubmitButton())
await waitFor(() => {
expect(screen.getByText(/wird hochgeladen/i)).toBeInTheDocument()
expect(screen.getAllByText(/uploading/i).length).toBeGreaterThan(0)
})
expect(getSubmitButton()).toBeDisabled()
+6 -6
View File
@@ -90,7 +90,7 @@ export function PhotoUpload({ tripId, days, places, onUpload, onClose }: PhotoUp
<>
<p className="text-gray-600 font-medium">{t('photos.dropHereActive')}</p>
<p className="text-gray-400 text-sm mt-1">{t('photos.clickToSelect')}</p>
<p className="text-gray-400 text-xs mt-2">JPG, PNG, WebP · max. 10 MB · bis zu 30 Fotos</p>
<p className="text-gray-400 text-xs mt-2">{t('photos.fileTypeHint')}</p>
</>
)}
</div>
@@ -98,7 +98,7 @@ export function PhotoUpload({ tripId, days, places, onUpload, onClose }: PhotoUp
{/* Preview grid */}
{files.length > 0 && (
<div>
<p className="text-sm font-medium text-gray-700 mb-2">{files.length} Foto{files.length !== 1 ? 's' : ''} ausgewählt</p>
<p className="text-sm font-medium text-gray-700 mb-2">{files.length} {t(files.length !== 1 ? 'photos.photosSelected' : 'photos.photoSelected')}</p>
<div className="grid grid-cols-4 sm:grid-cols-6 gap-2 max-h-48 overflow-y-auto">
{files.map((file, idx) => (
<div key={idx} className="relative aspect-square group">
@@ -126,15 +126,15 @@ export function PhotoUpload({ tripId, days, places, onUpload, onClose }: PhotoUp
{files.length > 0 && (
<div className="grid grid-cols-2 gap-3">
<div>
<label className="block text-xs font-medium text-gray-700 mb-1">Tag verknüpfen</label>
<label className="block text-xs font-medium text-gray-700 mb-1">{t('photos.linkDay')}</label>
<select
value={dayId}
onChange={e => setDayId(e.target.value)}
className="w-full border border-gray-200 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-slate-900"
>
<option value="">Kein Tag</option>
<option value="">{t('photos.noDay')}</option>
{(days || []).map(day => (
<option key={day.id} value={day.id}>Tag {day.day_number}</option>
<option key={day.id} value={day.id}>{t('photos.dayLabel', { number: day.day_number })}</option>
))}
</select>
</div>
@@ -169,7 +169,7 @@ export function PhotoUpload({ tripId, days, places, onUpload, onClose }: PhotoUp
<div className="bg-slate-50 rounded-lg p-3">
<div className="flex items-center gap-2 mb-2">
<div className="w-4 h-4 border-2 border-slate-900 border-t-transparent rounded-full animate-spin" />
<span className="text-sm text-slate-900">Wird hochgeladen...</span>
<span className="text-sm text-slate-900">{t('common.uploading')}</span>
</div>
<div className="w-full bg-slate-200 rounded-full h-1.5">
<div