- Sprache je Benutzer (users.locale), Middleware SetLocale, Auswahl unter Einstellungen → Darstellung; angebotene Sprachen in config/app.php - Übersetzungen über Laravel Lang (lang/de.json, lang/de/*.php), Seitentitel aus #[Title] werden übersetzt - Eigene Texte und Korrekturen in lang/project/de.json, übernommen mit `artisan lang:apply-project` (überstehen `lang:update`) - Tests: jede im Code verwendete Übersetzung ist vorhanden, eigene Übersetzungen sind übernommen, Sprachwahl und Standardsprache; SecurityTest prüft Texte sprachunabhängig über __() - lang/ von Pint ausgenommen (erzeugte Dateien) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
77 lines
2.5 KiB
PHP
77 lines
2.5 KiB
PHP
<?php
|
||
|
||
namespace Tests\Unit;
|
||
|
||
use Illuminate\Support\Facades\File;
|
||
use Tests\TestCase;
|
||
|
||
/**
|
||
* Jeder Text, der im Code über __() bzw. #[Title(...)] verwendet wird, braucht für jede
|
||
* angebotene Sprache außer der Quellsprache Englisch eine Übersetzung in lang/{code}.json.
|
||
*/
|
||
class TranslationCoverageTest extends TestCase
|
||
{
|
||
public function test_every_translation_key_used_in_the_code_is_translated(): void
|
||
{
|
||
$keys = $this->translationKeysUsedInCode();
|
||
$this->assertNotEmpty($keys);
|
||
|
||
foreach (array_keys(config('app.available_locales')) as $locale) {
|
||
if ($locale === 'en') {
|
||
continue;
|
||
}
|
||
|
||
$translations = json_decode(File::get(lang_path("{$locale}.json")), true, flags: JSON_THROW_ON_ERROR);
|
||
$missing = array_values(array_diff($keys, array_keys($translations)));
|
||
|
||
$this->assertSame([], $missing, "Fehlende Übersetzungen in lang/{$locale}.json");
|
||
}
|
||
}
|
||
|
||
public function test_project_translations_are_applied(): void
|
||
{
|
||
foreach (File::glob(lang_path('project/*.json')) as $projectFile) {
|
||
$locale = pathinfo($projectFile, PATHINFO_FILENAME);
|
||
|
||
$project = json_decode(File::get($projectFile), true, flags: JSON_THROW_ON_ERROR);
|
||
$translations = json_decode(File::get(lang_path("{$locale}.json")), true, flags: JSON_THROW_ON_ERROR);
|
||
|
||
$notApplied = array_keys(array_diff_assoc($project, array_intersect_key($translations, $project)));
|
||
|
||
$this->assertSame([], $notApplied, "lang/project/{$locale}.json nicht übernommen – `sail artisan lang:apply-project` ausführen");
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @return list<string>
|
||
*/
|
||
private function translationKeysUsedInCode(): array
|
||
{
|
||
$patterns = [
|
||
'/__\(\s*\'((?:[^\'\\\\]|\\\\.)*)\'/',
|
||
'/__\(\s*"((?:[^"\\\\]|\\\\.)*)"/',
|
||
'/#\[Title\(\s*\'((?:[^\'\\\\]|\\\\.)*)\'/',
|
||
];
|
||
|
||
$keys = [];
|
||
|
||
foreach ([resource_path('views'), app_path()] as $directory) {
|
||
foreach (File::allFiles($directory) as $file) {
|
||
if ($file->getExtension() !== 'php') {
|
||
continue;
|
||
}
|
||
|
||
foreach ($patterns as $pattern) {
|
||
preg_match_all($pattern, $file->getContents(), $matches);
|
||
|
||
foreach ($matches[1] as $key) {
|
||
$keys[] = stripslashes($key);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return array_values(array_unique($keys));
|
||
}
|
||
}
|