readProjectFile('i18n/default_de.json'); $enContent = $this->readProjectFile('i18n/default_en.json'); $this->assertIsArray(json_decode($deContent, true), 'i18n/default_de.json is not valid JSON'); $this->assertIsArray(json_decode($enContent, true), 'i18n/default_en.json is not valid JSON'); } public function testAllGermanKeysExistInEnglish(): void { $de = $this->loadTranslationKeys('i18n/default_de.json'); $en = $this->loadTranslationKeys('i18n/default_en.json'); $missingInEn = array_values(array_diff($de, $en)); $this->assertSame( [], $missingInEn, "Keys in default_de.json missing from default_en.json (GR-UI-015):\n" . implode("\n", $missingInEn) ); } public function testAllEnglishKeysExistInGerman(): void { $de = $this->loadTranslationKeys('i18n/default_de.json'); $en = $this->loadTranslationKeys('i18n/default_en.json'); $missingInDe = array_values(array_diff($en, $de)); $this->assertSame( [], $missingInDe, "Keys in default_en.json missing from default_de.json (GR-UI-015):\n" . implode("\n", $missingInDe) ); } public function testTranslationValuesAreNonEmpty(): void { $deContent = $this->readProjectFile('i18n/default_de.json'); $enContent = $this->readProjectFile('i18n/default_en.json'); $de = json_decode($deContent, true); $en = json_decode($enContent, true); $this->assertIsArray($de); $this->assertIsArray($en); $emptyDe = array_keys(array_filter($de, static fn ($v): bool => trim((string) $v) === '')); $emptyEn = array_keys(array_filter($en, static fn ($v): bool => trim((string) $v) === '')); $this->assertSame([], $emptyDe, "Empty values in default_de.json:\n" . implode("\n", $emptyDe)); $this->assertSame([], $emptyEn, "Empty values in default_en.json:\n" . implode("\n", $emptyEn)); } /** * @return list */ private function loadTranslationKeys(string $path): array { $content = $this->readProjectFile($path); $data = json_decode($content, true); $this->assertIsArray($data, $path . ' is not valid JSON'); $keys = array_keys($data); sort($keys, SORT_STRING); return $keys; } }