trypost/tests/Feature/LocalizationParityTest.php
Paulo Castellano 85120ac8f3 Add UI localization infrastructure and RTL support for 12 new locales
Register the 12 additional languages (fr, de, it, nl, pl, el, ja, ko, zh,
ru, tr, ar) as available UI locales so the language switcher and the API
accept them, keeping the set in lockstep with the ContentLanguage enum.

- config/languages.php lists all 15 UI locales with their native names.
- ContentLanguage::isRtl() drives the document `dir`; SetLocale shares it
  to the Blade root and HandleInertiaRequests shares it to Inertia, and
  app.ts mirrors it on SPA navigations so RTL locales lay out correctly.
- dayjs imports the 12 new locales so dates localize instead of falling
  back to English.
- A LocalizationParityTest guards against key drift: every locale must
  ship every base translation file with exactly the keys of lang/en.
2026-07-03 15:38:40 -03:00

47 lines
1.6 KiB
PHP

<?php
declare(strict_types=1);
use App\Enums\Workspace\ContentLanguage;
use Illuminate\Support\Arr;
test('every UI language in config matches the ContentLanguage enum', function () {
expect(array_keys(config('languages.available')))
->toEqualCanonicalizing(ContentLanguage::values());
});
test('the default UI language is a supported content language', function () {
expect(config('languages.default'))->toBeIn(ContentLanguage::values());
});
test('locale ships every base translation file with identical keys', function (string $locale) {
$missingFiles = [];
$keyDrift = [];
foreach (glob(lang_path('en/*.php')) as $basePath) {
$file = basename($basePath, '.php');
$localePath = lang_path("{$locale}/{$file}.php");
if (! file_exists($localePath)) {
$missingFiles[] = "{$file}.php";
continue;
}
$baseKeys = array_keys(Arr::dot(require $basePath));
$localeKeys = array_keys(Arr::dot(require $localePath));
$missing = array_diff($baseKeys, $localeKeys);
$extra = array_diff($localeKeys, $baseKeys);
if ($missing !== [] || $extra !== []) {
$keyDrift[$file] = [
'missing' => array_values($missing),
'extra' => array_values($extra),
];
}
}
expect($missingFiles)->toBe([], "{$locale} is missing translation files: ".implode(', ', $missingFiles));
expect($keyDrift)->toBe([], "{$locale} has key drift: ".json_encode($keyDrift, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
})->with(ContentLanguage::values());