feat: implement i18n — extract all UI strings, add EN + ES-MX translations, add language selector
Some checks failed
CI / Unit & Component Tests (push) Successful in 9m22s
CI / Backend Unit Tests (push) Successful in 1m52s
CI / E2E Tests (push) Failing after 59s
CI / Unit & Component Tests (pull_request) Successful in 9m51s
CI / Backend Unit Tests (pull_request) Successful in 2m3s
CI / E2E Tests (pull_request) Failing after 1m11s
Some checks failed
CI / Unit & Component Tests (push) Successful in 9m22s
CI / Backend Unit Tests (push) Successful in 1m52s
CI / E2E Tests (push) Failing after 59s
CI / Unit & Component Tests (pull_request) Successful in 9m51s
CI / Backend Unit Tests (pull_request) Successful in 2m3s
CI / E2E Tests (pull_request) Failing after 1m11s
Extract all hardcoded German strings from every .svelte file and component into Paraglide message keys. Add complete translations for all keys in messages/en.json (English) and messages/es.json (Spanish/Mexico). Changes: - messages/de.json: 100+ keys covering navigation, buttons, form labels, placeholders, section headings, empty states, and error messages - messages/en.json, messages/es.json: complete translations for all keys - project.inlang/settings.json: change baseLocale from "en" to "de" - +layout.svelte: add DE/EN/ES language selector in header using setLocale(); active language is bold, choice persists via Paraglide cookie strategy - All 10 route pages + 3 shared components: replace hardcoded German with m.key() - e2e/lang.spec.ts: E2E tests for language selector visibility, switching, persistence across navigation, and active state highlighting Closes #2 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
37
frontend/e2e/lang.spec.ts
Normal file
37
frontend/e2e/lang.spec.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Language selector', () => {
|
||||
test('shows DE, EN, ES buttons in the header', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await expect(page.getByRole('banner').getByRole('button', { name: 'DE' })).toBeVisible();
|
||||
await expect(page.getByRole('banner').getByRole('button', { name: 'EN' })).toBeVisible();
|
||||
await expect(page.getByRole('banner').getByRole('button', { name: 'ES' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('switching to EN translates the navigation', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.getByRole('banner').getByRole('button', { name: 'EN' }).click();
|
||||
await expect(page.getByRole('navigation').getByRole('link', { name: 'Documents' })).toBeVisible();
|
||||
await expect(page.getByRole('navigation').getByRole('link', { name: 'Persons' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('language choice persists after navigation', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.getByRole('banner').getByRole('button', { name: 'EN' }).click();
|
||||
await page.goto('/persons');
|
||||
await expect(page.getByRole('navigation').getByRole('link', { name: 'Documents' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('switching back to DE restores German', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.getByRole('banner').getByRole('button', { name: 'EN' }).click();
|
||||
await page.getByRole('banner').getByRole('button', { name: 'DE' }).click();
|
||||
await expect(page.getByRole('navigation').getByRole('link', { name: 'Dokumente' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('active language button is visually highlighted', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
const deBtn = page.getByRole('banner').getByRole('button', { name: 'DE' });
|
||||
await expect(deBtn).toHaveClass(/font-bold/);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user