task(H4): i18n foundation - strings.ts de/en maps, t() with key fallback, language persistence, useT hook, LayoutBar + Topbar texts switched
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Task H4 – i18n-Grundlage: zentrale strings.ts Maps de/en.
|
||||
*
|
||||
* strings-Modul: t(key) mit de/en-Maps, getLanguage/setLanguage
|
||||
* (localStorage-persistiert, Default de), subscribe + useT-Hook.
|
||||
* Kern-UI-Texte (LayoutBar, Modus-Umschaltung) laufen ueber die
|
||||
* Maps; vollstaendige mechanische Ersetzung aller Komponenten ist
|
||||
* teilautomatisierbares Follow-up (Roadmap-Vermerk).
|
||||
*/
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import { render, screen, cleanup, fireEvent, act } from '@testing-library/react';
|
||||
import {
|
||||
t, getLanguage, setLanguage, subscribeLanguage, useT, LANGUAGES,
|
||||
} from '../src/i18n/strings';
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
// ––– strings-Modul ––––––––––––––––––––––––
|
||||
|
||||
describe('H4: i18n strings', () => {
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
setLanguage('de');
|
||||
});
|
||||
|
||||
it('Default-Sprache ist de', () => {
|
||||
expect(getLanguage()).toBe('de');
|
||||
});
|
||||
|
||||
it('t liefert deutsche Kern-UI-Texte', () => {
|
||||
expect(t('layouts.title')).toBe('Layouts');
|
||||
expect(t('layouts.add')).toBe('Layout hinzufügen');
|
||||
expect(t('layouts.empty')).toBe('Keine Layouts');
|
||||
});
|
||||
|
||||
it('setLanguage(en) wechselt auf englische Texte', () => {
|
||||
setLanguage('en');
|
||||
expect(t('layouts.title')).toBe('Layouts');
|
||||
expect(t('layouts.add')).toBe('Add layout');
|
||||
expect(t('layouts.empty')).toBe('No layouts');
|
||||
});
|
||||
|
||||
it('Sprache persistiert in localStorage und ueberlebt Reload-Semantik', () => {
|
||||
setLanguage('en');
|
||||
expect(localStorage.getItem('webcad.language')).toBe('en');
|
||||
// erneutes Lesen startet aus persistiertem Zustand
|
||||
expect(getLanguage()).toBe('en');
|
||||
});
|
||||
|
||||
it('LANGUAGES enthaelt genau de und en', () => {
|
||||
expect(LANGUAGES).toEqual(['de', 'en']);
|
||||
});
|
||||
|
||||
it('t mit unbekanntem Key liefert den Key zurueck (Fallback, lint-bar)', () => {
|
||||
setLanguage('de');
|
||||
expect(t('gibts.nicht')).toBe('gibts.nicht');
|
||||
});
|
||||
|
||||
it('subscribeLanguage feuert bei Wechsel und unsubscribed', () => {
|
||||
const cb = vi.fn();
|
||||
const off = subscribeLanguage(cb);
|
||||
setLanguage('en');
|
||||
expect(cb).toHaveBeenCalledWith('en');
|
||||
off();
|
||||
cb.mockClear();
|
||||
setLanguage('de');
|
||||
expect(cb).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
// ––– useT-Hook + Komponente ––––––––––––––––––
|
||||
|
||||
describe('H4: useT-Hook rendert LayoutBar zweisprachig', () => {
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
setLanguage('de');
|
||||
});
|
||||
|
||||
it('LayoutBar zeigt deutsche Texte und wechselt live auf englisch', async () => {
|
||||
const LayoutBar = (await import('../src/components/LayoutBar')).default;
|
||||
render(<LayoutBar doc={null} bridge={null} />);
|
||||
expect(screen.getByText('Layouts')).toBeTruthy();
|
||||
expect(screen.getByText('Keine Layouts')).toBeTruthy();
|
||||
expect(screen.getByTitle('Layout hinzufügen')).toBeTruthy();
|
||||
|
||||
act(() => {
|
||||
setLanguage('en');
|
||||
});
|
||||
// Live-Update via subscribe (nach act flush)
|
||||
expect(screen.getByText('No layouts')).toBeTruthy();
|
||||
expect(screen.getByTitle('Add layout')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user