diff --git a/src/Symfony/Component/Translation/Command/XliffLintCommand.php b/src/Symfony/Component/Translation/Command/XliffLintCommand.php
index 2caa6abefbcf7..751971616ea5e 100644
--- a/src/Symfony/Component/Translation/Command/XliffLintCommand.php
+++ b/src/Symfony/Component/Translation/Command/XliffLintCommand.php
@@ -33,13 +33,15 @@ class XliffLintCommand extends Command
private $displayCorrectFiles;
private $directoryIteratorProvider;
private $isReadableProvider;
+ private $requireStrictFileNames;
- public function __construct(string $name = null, callable $directoryIteratorProvider = null, callable $isReadableProvider = null)
+ public function __construct(string $name = null, callable $directoryIteratorProvider = null, callable $isReadableProvider = null, bool $requireStrictFileNames = true)
{
parent::__construct($name);
$this->directoryIteratorProvider = $directoryIteratorProvider;
$this->isReadableProvider = $isReadableProvider;
+ $this->requireStrictFileNames = $requireStrictFileNames;
}
/**
@@ -115,14 +117,16 @@ private function validate($content, $file = null)
$document->loadXML($content);
if (null !== $targetLanguage = $this->getTargetLanguageFromFile($document)) {
- $expectedFileExtension = sprintf('%s.xlf', str_replace('-', '_', $targetLanguage));
- $realFileExtension = explode('.', basename($file), 2)[1] ?? '';
+ $normalizedLocale = preg_quote(str_replace('-', '_', $targetLanguage), '/');
+ // strict file names require translation files to be named '____.locale.xlf'
+ // otherwise, both '____.locale.xlf' and 'locale.____.xlf' are allowed
+ $expectedFilenamePattern = $this->requireStrictFileNames ? sprintf('/^.*\.%s\.xlf/', $normalizedLocale) : sprintf('/^(.*\.%s\.xlf|%s\..*\.xlf)/', $normalizedLocale, $normalizedLocale);
- if ($expectedFileExtension !== $realFileExtension) {
+ if (0 === preg_match($expectedFilenamePattern, basename($file))) {
$errors[] = array(
'line' => -1,
'column' => -1,
- 'message' => sprintf('There is a mismatch between the file extension ("%s") and the "%s" value used in the "target-language" attribute of the file.', $realFileExtension, $targetLanguage),
+ 'message' => sprintf('There is a mismatch between the language included in the file name ("%s") and the "%s" value used in the "target-language" attribute of the file.', basename($file), $targetLanguage),
);
}
}
diff --git a/src/Symfony/Component/Translation/Tests/Command/XliffLintCommandTest.php b/src/Symfony/Component/Translation/Tests/Command/XliffLintCommandTest.php
index e37600c3ebb87..8b1187ae26e00 100644
--- a/src/Symfony/Component/Translation/Tests/Command/XliffLintCommandTest.php
+++ b/src/Symfony/Component/Translation/Tests/Command/XliffLintCommandTest.php
@@ -40,6 +40,23 @@ public function testLintCorrectFile()
$this->assertContains('OK', trim($tester->getDisplay()));
}
+ /**
+ * @dataProvider provideStrictFilenames
+ */
+ public function testStrictFilenames($requireStrictFileNames, $fileNamePattern, $targetLanguage, $mustFail)
+ {
+ $tester = $this->createCommandTester($requireStrictFileNames);
+ $filename = $this->createFile('note', $targetLanguage, $fileNamePattern);
+
+ $tester->execute(
+ array('filename' => $filename),
+ array('verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false)
+ );
+
+ $this->assertEquals($mustFail ? 1 : 0, $tester->getStatusCode());
+ $this->assertContains($mustFail ? '[WARNING] 0 XLIFF files have valid syntax and 1 contain errors.' : '[OK] All 1 XLIFF files contain valid syntax.', $tester->getDisplay());
+ }
+
public function testLintIncorrectXmlSyntax()
{
$tester = $this->createCommandTester();
@@ -59,7 +76,7 @@ public function testLintIncorrectTargetLanguage()
$tester->execute(array('filename' => $filename), array('decorated' => false));
$this->assertEquals(1, $tester->getStatusCode(), 'Returns 1 in case of error');
- $this->assertContains('There is a mismatch between the file extension ("en.xlf") and the "es" value used in the "target-language" attribute of the file.', trim($tester->getDisplay()));
+ $this->assertContains('There is a mismatch between the language included in the file name ("messages.en.xlf") and the "es" value used in the "target-language" attribute of the file.', trim($tester->getDisplay()));
}
/**
@@ -102,7 +119,7 @@ public function testGetHelp()
/**
* @return string Path to the new file
*/
- private function createFile($sourceContent = 'note', $targetLanguage = 'en')
+ private function createFile($sourceContent = 'note', $targetLanguage = 'en', $fileNamePattern = 'messages.%locale%.xlf')
{
$xliffContent = <<
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: