Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions tests/TranslationCatalogueTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

declare(strict_types=1);

namespace AssoConnect\ValidatorBundle\Tests;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use SimpleXMLElement;

/**
* Nothing fails at runtime when a catalogue is missing or incomplete: the violation message simply falls
* back to its English default, so the gap only shows up in front of an end user.
*/
class TranslationCatalogueTest extends TestCase
{
private const string TRANSLATIONS_DIR = __DIR__ . '/../translations';
private const string REFERENCE_LOCALE = 'en';

/** Every locale the catalogues are expected to cover. */
private const array EXPECTED_LOCALES = ['en', 'fr', 'es'];

/** @return iterable<string, array{locale: string}> */
public static function provideLocales(): iterable
{
foreach (self::EXPECTED_LOCALES as $locale) {
yield $locale => ['locale' => $locale];
}
}

#[DataProvider('provideLocales')]
public function testCatalogueExists(string $locale): void
{
self::assertFileExists(self::catalogPath($locale));
}

#[DataProvider('provideLocales')]
public function testCatalogueCoversEveryReferenceMessage(string $locale): void
{
self::assertSame(
$this->sources(self::REFERENCE_LOCALE),
$this->sources($locale),
sprintf('The %s catalogue does not cover the same messages as the %s one.', $locale, self::REFERENCE_LOCALE)
);
}

#[DataProvider('provideLocales')]
public function testEveryMessageIsTranslated(string $locale): void
{
foreach ($this->units($locale) as $unit) {
self::assertNotSame(
'',
trim((string) $unit->children()->target),
sprintf('Message "%s" has no %s translation.', $unit->children()->source, $locale)
);
}
}

private static function catalogPath(string $locale): string
{
return sprintf('%s/validators.%s.xlf', self::TRANSLATIONS_DIR, $locale);
}

/** @return list<string> */
private function sources(string $locale): array
{
$sources = [];
foreach ($this->units($locale) as $unit) {
$sources[] = (string) $unit->children()->source;
}
sort($sources);

return $sources;
}

/** @return list<SimpleXMLElement> */
private function units(string $locale): array
{
$catalog = simplexml_load_file(self::catalogPath($locale));
self::assertInstanceOf(
SimpleXMLElement::class,
$catalog,
sprintf('The %s catalogue is not valid XML.', $locale)
);

// local-name() keeps the query independent from the XLIFF namespace declared on the root element
$units = $catalog->xpath('//*[local-name()="trans-unit"]');
self::assertIsArray($units, sprintf('The %s catalogue holds no translation unit.', $locale));

return array_values($units);
}
}
67 changes: 67 additions & 0 deletions translations/validators.es.xlf
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="file.ext">
<body>
<trans-unit id="1">
<source>The value {{ domain }} is not a valid domain name.</source>
<target>El valor {{ domain }} no es un nombre de dominio válido.</target>
</trans-unit>
<trans-unit id="2">
<source>The domain {{ domain }} is not setup to received emails.</source>
<target>El dominio {{ domain }} no está configurado para recibir correos electrónicos.</target>
</trans-unit>
<trans-unit id="3">
<source>The value {{ value }} is not a valid phone number.</source>
<target>El valor {{ value }} no es un número de teléfono válido.</target>
</trans-unit>
<trans-unit id="4">
<source>The value {{ value }} is not formatted as an international phone number.</source>
<target>El valor {{ value }} no tiene el formato de un número de teléfono internacional.</target>
</trans-unit>
<trans-unit id="5">
<source>The phone number {{ value }} is too short.</source>
<target>El número de teléfono {{ value }} es demasiado corto.</target>
</trans-unit>
<trans-unit id="6">
<source>The phone number {{ value }} is too long.</source>
<target>El número de teléfono {{ value }} es demasiado largo.</target>
</trans-unit>
<trans-unit id="7">
<source>The phone number {{ value }} does not exist.</source>
<target>El número de teléfono {{ value }} no existe.</target>
</trans-unit>
<trans-unit id="8">
<source>The value {{ value }} is not an accepted phone number type.</source>
<target>El valor {{ value }} no es un tipo de número de teléfono aceptado.</target>
</trans-unit>
<trans-unit id="9">
<source>The value {{ value }} is not a valid landline phone number.</source>
<target>El valor {{ value }} no es un número de teléfono fijo válido.</target>
</trans-unit>
<trans-unit id="10">
<source>The value {{ value }} is not a valid mobile phone number.</source>
<target>El valor {{ value }} no es un número de teléfono móvil válido.</target>
</trans-unit>
<trans-unit id="11">
<source>The float precision is limited to {{ precision }} numbers.</source>
<target>La precisión está limitada a {{ precision }} decimales.</target>
</trans-unit>
<trans-unit id="12">
<source>The value {{ value }} is not a valid timezone.</source>
<target>El valor {{ value }} no es una zona horaria válida.</target>
</trans-unit>
<trans-unit id="13">
<source>The value {{ value }} is not a valid SIREN number.</source>
<target>El valor {{ value }} no es un número SIREN válido.</target>
</trans-unit>
<trans-unit id="14">
<source>The value {{ value }} is not a valid RNA identifier.</source>
<target>El valor {{ value }} no es un identificador RNA válido.</target>
</trans-unit>
<trans-unit id="15">
<source>The intra-EU VAT number {{ value }} is not valid.</source>
<target>El número de IVA intracomunitario {{ value }} no es válido.</target>
</trans-unit>
</body>
</file>
</xliff>
Loading