diff --git a/src/screens/AnalyseScreen.tsx b/src/screens/AnalyseScreen.tsx index ebe97df..ffab6df 100644 --- a/src/screens/AnalyseScreen.tsx +++ b/src/screens/AnalyseScreen.tsx @@ -72,6 +72,11 @@ export function AnalyseScreen({ navigation, route }: Props) { const checkliste = cache?.checkliste ?? analyse.checkliste; const fachbegriffe = cache?.fachbegriffe ?? analyse.fachbegriffe; + // Arabisch, Farsi, Urdu, Paschtu laufen von rechts nach links. Ohne das + // steht der übersetzte Text linksbündig und liest sich falsch. + const rtl = !!sprache.rtl; + const rtlText = rtl ? ({ writingDirection: 'rtl', textAlign: 'right' } as const) : null; + const sprscheWaehlen = async (neu: Sprache) => { setSprachwahlOffen(false); setSprache(neu); @@ -221,8 +226,8 @@ export function AnalyseScreen({ navigation, route }: Props) { {/* ── Das ist passiert ── */} Das ist passiert - {kernaussage} - {erklaerung} + {kernaussage} + {erklaerung} {/* ── Das müssen Sie tun ── */} {checkliste.length > 0 && ( @@ -235,7 +240,7 @@ export function AnalyseScreen({ navigation, route }: Props) { return ( setErledigt((e) => ({ ...e, [i]: !e[i] }))} accessibilityRole="checkbox" accessibilityState={{ checked: fertig }} @@ -247,7 +252,7 @@ export function AnalyseScreen({ navigation, route }: Props) { {i + 1} )} - {punkt} + {punkt} ); })} @@ -264,7 +269,7 @@ export function AnalyseScreen({ navigation, route }: Props) { {fachbegriffe.map((f, i) => ( {f.begriff} - {f.erklaerung} + {f.erklaerung} ))} diff --git a/src/types.ts b/src/types.ts index c594248..df1dcb5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -90,18 +90,43 @@ export interface Sprache { name: string; /** Name in der Sprache selbst (damit Nutzer ihre Sprache erkennen). */ eigenname: string; + /** Schrift läuft von rechts nach links (Arabisch, Farsi, Urdu, Paschtu). */ + rtl?: boolean; } +/** + * Zielsprachen für die Übersetzung — grob nach Größe der jeweiligen + * Sprachgemeinschaft in Deutschland sortiert, damit die häufigsten oben + * stehen und man nicht lange scrollen muss. + */ export const SPRACHEN: Sprache[] = [ { code: 'tr', name: 'Türkisch', eigenname: 'Türkçe' }, - { code: 'ar', name: 'Arabisch', eigenname: 'العربية' }, - { code: 'en', name: 'Englisch', eigenname: 'English' }, + { code: 'ar', name: 'Arabisch', eigenname: 'العربية', rtl: true }, { code: 'ru', name: 'Russisch', eigenname: 'Русский' }, { code: 'uk', name: 'Ukrainisch', eigenname: 'Українська' }, - { code: 'fr', name: 'Französisch', eigenname: 'Français' }, - { code: 'fa', name: 'Farsi', eigenname: 'فارسی' }, - { code: 'ro', name: 'Rumänisch', eigenname: 'Română' }, { code: 'pl', name: 'Polnisch', eigenname: 'Polski' }, + { code: 'ro', name: 'Rumänisch', eigenname: 'Română' }, + { code: 'en', name: 'Englisch', eigenname: 'English' }, + { code: 'fa', name: 'Farsi / Dari', eigenname: 'فارسی', rtl: true }, + { code: 'ku', name: 'Kurdisch (Kurmancî)', eigenname: 'Kurdî' }, + { code: 'bg', name: 'Bulgarisch', eigenname: 'Български' }, + { code: 'hr', name: 'Kroatisch', eigenname: 'Hrvatski' }, + { code: 'sr', name: 'Serbisch', eigenname: 'Српски' }, + { code: 'bs', name: 'Bosnisch', eigenname: 'Bosanski' }, + { code: 'sq', name: 'Albanisch', eigenname: 'Shqip' }, + { code: 'it', name: 'Italienisch', eigenname: 'Italiano' }, + { code: 'el', name: 'Griechisch', eigenname: 'Ελληνικά' }, + { code: 'es', name: 'Spanisch', eigenname: 'Español' }, + { code: 'pt', name: 'Portugiesisch', eigenname: 'Português' }, + { code: 'fr', name: 'Französisch', eigenname: 'Français' }, + { code: 'hu', name: 'Ungarisch', eigenname: 'Magyar' }, + { code: 'vi', name: 'Vietnamesisch', eigenname: 'Tiếng Việt' }, + { code: 'hi', name: 'Hindi', eigenname: 'हिन्दी' }, + { code: 'ur', name: 'Urdu', eigenname: 'اردو', rtl: true }, + { code: 'ps', name: 'Paschtu', eigenname: 'پښتو', rtl: true }, + { code: 'ti', name: 'Tigrinya', eigenname: 'ትግርኛ' }, + { code: 'so', name: 'Somali', eigenname: 'Soomaali' }, + { code: 'zh', name: 'Chinesisch', eigenname: '中文' }, ]; /** Untere Tab-Leiste: Fristen-Übersicht · Scannen · Archiv. */ diff --git a/src/utils/__tests__/sprachen.test.ts b/src/utils/__tests__/sprachen.test.ts new file mode 100644 index 0000000..25dac58 --- /dev/null +++ b/src/utils/__tests__/sprachen.test.ts @@ -0,0 +1,37 @@ +/** + * Schützt die Sprachliste vor stillen Fehlern. Besonders wichtig: doppelte + * Codes — Übersetzungen werden pro Code gecacht (brief.uebersetzungen[code]), + * zwei gleiche Codes würden sich gegenseitig überschreiben. + */ +import { SPRACHEN } from '../../types'; + +describe('SPRACHEN', () => { + it('hat keine doppelten Sprachcodes', () => { + const codes = SPRACHEN.map((s) => s.code); + expect(new Set(codes).size).toBe(codes.length); + }); + + it('enthält kein Deutsch (das ist die Ausgangssprache, nicht Zielsprache)', () => { + expect(SPRACHEN.some((s) => s.code === 'de')).toBe(false); + }); + + it('hat für jede Sprache Code, Name und Eigenname', () => { + for (const s of SPRACHEN) { + expect(s.code).toMatch(/^[a-z]{2,3}$/); + expect(s.name.trim().length).toBeGreaterThan(0); + expect(s.eigenname.trim().length).toBeGreaterThan(0); + } + }); + + it('markiert genau die Rechts-nach-links-Sprachen', () => { + const rtl = SPRACHEN.filter((s) => s.rtl).map((s) => s.code).sort(); + expect(rtl).toEqual(['ar', 'fa', 'ps', 'ur']); + }); + + it('bietet die für Deutschland wichtigsten Sprachen an', () => { + const codes = SPRACHEN.map((s) => s.code); + for (const pflicht of ['tr', 'ar', 'ru', 'uk', 'pl', 'ro', 'en', 'fa']) { + expect(codes).toContain(pflicht); + } + }); +});