CluPilotCloud/tests/Feature/TranslationParityTest.php

59 lines
1.8 KiB
PHP

<?php
/**
* German and English carry the same keys.
*
* R16. A key added to one language and forgotten in the other does not fail
* anywhere — Laravel prints the key itself — so it ships, and then surfaces as
* `admin_settings.update_phase.migrate` in the middle of a sentence on whichever
* language nobody was testing in.
*/
/** @return array<int, string> every key in a translation array, dotted. */
function flattenKeys(array $lines, string $prefix = ''): array
{
$keys = [];
foreach ($lines as $key => $value) {
$path = $prefix === '' ? (string) $key : $prefix.'.'.$key;
// Only nested arrays recurse. A list of strings — a bullet list in the
// interface — is one key whose shape is the translator's business.
if (is_array($value) && ! array_is_list($value)) {
$keys = [...$keys, ...flattenKeys($value, $path)];
continue;
}
$keys[] = $path;
}
sort($keys);
return $keys;
}
it('has the same keys in German and English', function () {
$files = array_map(
fn (string $path) => basename($path),
glob(lang_path('de/*.php')) ?: [],
);
expect($files)->not->toBeEmpty();
foreach ($files as $file) {
$de = require lang_path('de/'.$file);
$enPath = lang_path('en/'.$file);
expect(file_exists($enPath))->toBeTrue("lang/en/{$file} is missing");
$en = require $enPath;
$missingInEn = array_diff(flattenKeys($de), flattenKeys($en));
$missingInDe = array_diff(flattenKeys($en), flattenKeys($de));
expect($missingInEn)->toBe([], "missing in lang/en/{$file}: ".implode(', ', $missingInEn));
expect($missingInDe)->toBe([], "missing in lang/de/{$file}: ".implode(', ', $missingInDe));
}
});