From ad694992410c8b745e2e1166ee991d67a630e7a9 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 7 Dec 2023 17:53:55 +0100 Subject: [PATCH 1/4] [Translation] Allow translation:extract to sort messages with --force --- .../Command/TranslationUpdateCommand.php | 9 +++++- .../Translation/Dumper/CsvFileDumper.php | 2 +- .../Translation/Dumper/FileDumper.php | 4 +-- .../Translation/Dumper/IcuResFileDumper.php | 6 ++-- .../Translation/Dumper/IniFileDumper.php | 2 +- .../Translation/Dumper/JsonFileDumper.php | 2 +- .../Translation/Dumper/MoFileDumper.php | 2 +- .../Translation/Dumper/PhpFileDumper.php | 2 +- .../Translation/Dumper/PoFileDumper.php | 2 +- .../Translation/Dumper/QtFileDumper.php | 2 +- .../Translation/Dumper/XliffFileDumper.php | 4 +-- .../Translation/Dumper/YamlFileDumper.php | 2 +- .../Translation/MessageCatalogue.php | 28 +++++++++++++++---- 13 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index bf2c0ec8fd179..504c91df8d2ff 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -277,7 +277,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int $bundleTransPath = end($transPaths); } - $this->writer->write($operation->getResult(), $format, ['path' => $bundleTransPath, 'default_locale' => $this->defaultLocale, 'xliff_version' => $xliffVersion, 'as_tree' => $input->getOption('as-tree'), 'inline' => $input->getOption('as-tree') ?? 0]); + $this->writer->write($operation->getResult(), $format, [ + 'path' => $bundleTransPath, + 'default_locale' => $this->defaultLocale, + 'xliff_version' => $xliffVersion, + 'as_tree' => $input->getOption('as-tree'), + 'inline' => $input->getOption('as-tree') ?? 0, + 'sort' => $input->getOption('sort'), + ]); if (true === $input->getOption('dump-messages')) { $resultMessage .= ' and translation files were updated'; diff --git a/src/Symfony/Component/Translation/Dumper/CsvFileDumper.php b/src/Symfony/Component/Translation/Dumper/CsvFileDumper.php index 60b7441133770..b680018f65258 100644 --- a/src/Symfony/Component/Translation/Dumper/CsvFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/CsvFileDumper.php @@ -27,7 +27,7 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra { $handle = fopen('php://memory', 'r+'); - foreach ($messages->all($domain) as $source => $target) { + foreach ($messages->all($domain, $options['sort']) as $source => $target) { fputcsv($handle, [$source, $target], $this->delimiter, $this->enclosure); } diff --git a/src/Symfony/Component/Translation/Dumper/FileDumper.php b/src/Symfony/Component/Translation/Dumper/FileDumper.php index 3846e7380da5f..e8e5b82578497 100644 --- a/src/Symfony/Component/Translation/Dumper/FileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/FileDumper.php @@ -55,7 +55,7 @@ public function dump(MessageCatalogue $messages, array $options = []): void } $intlDomain = $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX; - $intlMessages = $messages->all($intlDomain); + $intlMessages = $messages->all($intlDomain, $options['sort']); if ($intlMessages) { $intlPath = $options['path'].'/'.$this->getRelativePath($intlDomain, $messages->getLocale()); @@ -64,7 +64,7 @@ public function dump(MessageCatalogue $messages, array $options = []): void $messages->replace([], $intlDomain); try { - if ($messages->all($domain)) { + if ($messages->all($domain, $options['sort'])) { file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options)); } continue; diff --git a/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php b/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php index e603ee8c48c99..28561cd4c0d9c 100644 --- a/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php @@ -26,7 +26,7 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra { $data = $indexes = $resources = ''; - foreach ($messages->all($domain) as $source => $target) { + foreach ($messages->all($domain, $options['sort']) as $source => $target) { $indexes .= pack('v', \strlen($data) + 28); $data .= $source."\0"; } @@ -35,7 +35,7 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra $keyTop = $this->getPosition($data); - foreach ($messages->all($domain) as $source => $target) { + foreach ($messages->all($domain, $options['sort']) as $source => $target) { $resources .= pack('V', $this->getPosition($data)); $data .= pack('V', \strlen($target)) @@ -46,7 +46,7 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra $resOffset = $this->getPosition($data); - $data .= pack('v', \count($messages->all($domain))) + $data .= pack('v', \count($messages->all($domain, $options['sort']))) .$indexes .$this->writePadding($data) .$resources diff --git a/src/Symfony/Component/Translation/Dumper/IniFileDumper.php b/src/Symfony/Component/Translation/Dumper/IniFileDumper.php index 6cbdef606761a..38ba7dcda4685 100644 --- a/src/Symfony/Component/Translation/Dumper/IniFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/IniFileDumper.php @@ -24,7 +24,7 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra { $output = ''; - foreach ($messages->all($domain) as $source => $target) { + foreach ($messages->all($domain, $options['sort']) as $source => $target) { $escapeTarget = str_replace('"', '\"', $target); $output .= $source.'="'.$escapeTarget."\"\n"; } diff --git a/src/Symfony/Component/Translation/Dumper/JsonFileDumper.php b/src/Symfony/Component/Translation/Dumper/JsonFileDumper.php index e5035397f7c6c..e2f4cf4ddb371 100644 --- a/src/Symfony/Component/Translation/Dumper/JsonFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/JsonFileDumper.php @@ -24,7 +24,7 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra { $flags = $options['json_encoding'] ?? \JSON_PRETTY_PRINT; - return json_encode($messages->all($domain), $flags); + return json_encode($messages->all($domain, $options['sort']), $flags); } protected function getExtension(): string diff --git a/src/Symfony/Component/Translation/Dumper/MoFileDumper.php b/src/Symfony/Component/Translation/Dumper/MoFileDumper.php index 9ded5f4ef3855..8b31b49545ead 100644 --- a/src/Symfony/Component/Translation/Dumper/MoFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/MoFileDumper.php @@ -27,7 +27,7 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra $offsets = []; $size = 0; - foreach ($messages->all($domain) as $source => $target) { + foreach ($messages->all($domain, $options['sort']) as $source => $target) { $offsets[] = array_map('strlen', [$sources, $source, $targets, $target]); $sources .= "\0".$source; $targets .= "\0".$target; diff --git a/src/Symfony/Component/Translation/Dumper/PhpFileDumper.php b/src/Symfony/Component/Translation/Dumper/PhpFileDumper.php index 51e90665d75fa..b2f2cbc599c8e 100644 --- a/src/Symfony/Component/Translation/Dumper/PhpFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/PhpFileDumper.php @@ -22,7 +22,7 @@ class PhpFileDumper extends FileDumper { public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string { - return "all($domain), true).";\n"; + return "all($domain, $options['sort']), true).";\n"; } protected function getExtension(): string diff --git a/src/Symfony/Component/Translation/Dumper/PoFileDumper.php b/src/Symfony/Component/Translation/Dumper/PoFileDumper.php index a2d0deb78153a..c2a445131d446 100644 --- a/src/Symfony/Component/Translation/Dumper/PoFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/PoFileDumper.php @@ -30,7 +30,7 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra $output .= "\n"; $newLine = false; - foreach ($messages->all($domain) as $source => $target) { + foreach ($messages->all($domain, $options['sort']) as $source => $target) { if ($newLine) { $output .= "\n"; } else { diff --git a/src/Symfony/Component/Translation/Dumper/QtFileDumper.php b/src/Symfony/Component/Translation/Dumper/QtFileDumper.php index 0373e9c109542..784a403369401 100644 --- a/src/Symfony/Component/Translation/Dumper/QtFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/QtFileDumper.php @@ -28,7 +28,7 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra $context = $ts->appendChild($dom->createElement('context')); $context->appendChild($dom->createElement('name', $domain)); - foreach ($messages->all($domain) as $source => $target) { + foreach ($messages->all($domain, $options['sort']) as $source => $target) { $message = $context->appendChild($dom->createElement('message')); $metadata = $messages->getMetadata($source, $domain); if (isset($metadata['sources'])) { diff --git a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php index 22f0227b9d52f..d2aa354845500 100644 --- a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php @@ -90,7 +90,7 @@ private function dumpXliff1(string $defaultLocale, MessageCatalogue $messages, ? } $xliffBody = $xliffFile->appendChild($dom->createElement('body')); - foreach ($messages->all($domain) as $source => $target) { + foreach ($messages->all($domain, $options['sort']) as $source => $target) { $translation = $dom->createElement('trans-unit'); $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._')); @@ -165,7 +165,7 @@ private function dumpXliff2(string $defaultLocale, MessageCatalogue $messages, ? } } - foreach ($messages->all($domain) as $source => $target) { + foreach ($messages->all($domain, $options['sort']) as $source => $target) { $translation = $dom->createElement('unit'); $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._')); diff --git a/src/Symfony/Component/Translation/Dumper/YamlFileDumper.php b/src/Symfony/Component/Translation/Dumper/YamlFileDumper.php index d2670331e6602..064f290f3d0e9 100644 --- a/src/Symfony/Component/Translation/Dumper/YamlFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/YamlFileDumper.php @@ -36,7 +36,7 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra throw new LogicException('Dumping translations in the YAML format requires the Symfony Yaml component.'); } - $data = $messages->all($domain); + $data = $messages->all($domain, $options['sort']); if (isset($options['as_tree']) && $options['as_tree']) { $data = ArrayConverter::expandToTree($data); diff --git a/src/Symfony/Component/Translation/MessageCatalogue.php b/src/Symfony/Component/Translation/MessageCatalogue.php index 1ae29ff5d9113..69e1e5a49e383 100644 --- a/src/Symfony/Component/Translation/MessageCatalogue.php +++ b/src/Symfony/Component/Translation/MessageCatalogue.php @@ -55,15 +55,25 @@ public function getDomains(): array return array_values($domains); } - public function all(string $domain = null): array + public function all(string $domain = null, ?string $sort = null): array { + $sort = $sort ? strtolower($sort) : null; + if (null !== $domain) { // skip messages merge if intl-icu requested explicitly if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) { - return $this->messages[$domain] ?? []; + $messages = $this->messages[$domain] ?? []; + } else { + $messages = ($this->messages[$domain.self::INTL_DOMAIN_SUFFIX] ?? []) + ($this->messages[$domain] ?? []); + } + + if ('desc' === $sort) { + krsort($messages); + } elseif ('asc' === $sort) { + ksort($messages); } - return ($this->messages[$domain.self::INTL_DOMAIN_SUFFIX] ?? []) + ($this->messages[$domain] ?? []); + return $messages; } $allMessages = []; @@ -71,10 +81,18 @@ public function all(string $domain = null): array foreach ($this->messages as $domain => $messages) { if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) { $domain = substr($domain, 0, -\strlen(self::INTL_DOMAIN_SUFFIX)); - $allMessages[$domain] = $messages + ($allMessages[$domain] ?? []); + $messages = $messages + ($allMessages[$domain] ?? []); } else { - $allMessages[$domain] = ($allMessages[$domain] ?? []) + $messages; + $messages = ($allMessages[$domain] ?? []) + $messages; } + + if ('desc' === $sort) { + krsort($messages); + } elseif ('asc' === $sort) { + ksort($messages); + } + + $allMessages[$domain] = $messages; } return $allMessages; From b2de1a1f01cf853ba81a77ab41bd9f59aa1128fa Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Mon, 18 Dec 2023 14:27:46 +0100 Subject: [PATCH 2/4] Update the documentation of translation:extract This commit reverts the change made in PR #49189 as the command accepts the argument `--sort` with `--force`. Reference: https://github.com/symfony/symfony/pull/49189 --- .../FrameworkBundle/Command/TranslationUpdateCommand.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index 504c91df8d2ff..4f4e2809dcfb2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -87,7 +87,7 @@ protected function configure(): void new InputOption('force', null, InputOption::VALUE_NONE, 'Should the extract be done'), new InputOption('clean', null, InputOption::VALUE_NONE, 'Should clean not found messages'), new InputOption('domain', null, InputOption::VALUE_OPTIONAL, 'Specify the domain to extract'), - new InputOption('sort', null, InputOption::VALUE_OPTIONAL, 'Return list of messages sorted alphabetically (only works with --dump-messages)', 'asc'), + new InputOption('sort', null, InputOption::VALUE_OPTIONAL, 'Return list of messages sorted alphabetically', 'asc'), new InputOption('as-tree', null, InputOption::VALUE_OPTIONAL, 'Dump the messages as a tree-like structure: The given value defines the level where to switch to inline YAML'), ]) ->setHelp(<<<'EOF' @@ -116,6 +116,7 @@ protected function configure(): void You can dump a tree-like structure using the yaml format with --as-tree flag: php %command.full_name% --force --format=yaml --as-tree=3 en AcmeBundle + php %command.full_name% --force --format=yaml --sort=asc --as-tree=3 fr EOF ) From f7b5715cd09b4044b9e68d12d52536177f227555 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Mon, 18 Dec 2023 14:38:39 +0100 Subject: [PATCH 3/4] Fix access to the optional 'sort' option --- .../Component/Translation/Dumper/CsvFileDumper.php | 4 +++- .../Component/Translation/Dumper/FileDumper.php | 6 ++++-- .../Translation/Dumper/IcuResFileDumper.php | 7 ++++--- .../Component/Translation/Dumper/IniFileDumper.php | 4 +++- .../Component/Translation/Dumper/JsonFileDumper.php | 3 ++- .../Component/Translation/Dumper/MoFileDumper.php | 4 +++- .../Component/Translation/Dumper/PhpFileDumper.php | 4 +++- .../Component/Translation/Dumper/PoFileDumper.php | 4 +++- .../Component/Translation/Dumper/QtFileDumper.php | 4 +++- .../Component/Translation/Dumper/XliffFileDumper.php | 12 ++++++++---- .../Component/Translation/Dumper/YamlFileDumper.php | 4 +++- 11 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Component/Translation/Dumper/CsvFileDumper.php b/src/Symfony/Component/Translation/Dumper/CsvFileDumper.php index b680018f65258..dc8e04d35df67 100644 --- a/src/Symfony/Component/Translation/Dumper/CsvFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/CsvFileDumper.php @@ -27,7 +27,9 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra { $handle = fopen('php://memory', 'r+'); - foreach ($messages->all($domain, $options['sort']) as $source => $target) { + $sort = $options['sort'] ?? null; + + foreach ($messages->all($domain, $sort) as $source => $target) { fputcsv($handle, [$source, $target], $this->delimiter, $this->enclosure); } diff --git a/src/Symfony/Component/Translation/Dumper/FileDumper.php b/src/Symfony/Component/Translation/Dumper/FileDumper.php index e8e5b82578497..b6b9b29a0a7ad 100644 --- a/src/Symfony/Component/Translation/Dumper/FileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/FileDumper.php @@ -44,6 +44,8 @@ public function dump(MessageCatalogue $messages, array $options = []): void throw new InvalidArgumentException('The file dumper needs a path option.'); } + $sort = $options['sort'] ?? null; + // save a file for each domain foreach ($messages->getDomains() as $domain) { $fullpath = $options['path'].'/'.$this->getRelativePath($domain, $messages->getLocale()); @@ -55,7 +57,7 @@ public function dump(MessageCatalogue $messages, array $options = []): void } $intlDomain = $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX; - $intlMessages = $messages->all($intlDomain, $options['sort']); + $intlMessages = $messages->all($intlDomain, $sort); if ($intlMessages) { $intlPath = $options['path'].'/'.$this->getRelativePath($intlDomain, $messages->getLocale()); @@ -64,7 +66,7 @@ public function dump(MessageCatalogue $messages, array $options = []): void $messages->replace([], $intlDomain); try { - if ($messages->all($domain, $options['sort'])) { + if ($messages->all($domain, $sort)) { file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options)); } continue; diff --git a/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php b/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php index 28561cd4c0d9c..9e4a78cae5325 100644 --- a/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php @@ -25,8 +25,9 @@ class IcuResFileDumper extends FileDumper public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string { $data = $indexes = $resources = ''; + $sort = $options['sort'] ?? null; - foreach ($messages->all($domain, $options['sort']) as $source => $target) { + foreach ($messages->all($domain, $sort) as $source => $target) { $indexes .= pack('v', \strlen($data) + 28); $data .= $source."\0"; } @@ -35,7 +36,7 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra $keyTop = $this->getPosition($data); - foreach ($messages->all($domain, $options['sort']) as $source => $target) { + foreach ($messages->all($domain, $sort) as $source => $target) { $resources .= pack('V', $this->getPosition($data)); $data .= pack('V', \strlen($target)) @@ -46,7 +47,7 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra $resOffset = $this->getPosition($data); - $data .= pack('v', \count($messages->all($domain, $options['sort']))) + $data .= pack('v', \count($messages->all($domain, $sort))) .$indexes .$this->writePadding($data) .$resources diff --git a/src/Symfony/Component/Translation/Dumper/IniFileDumper.php b/src/Symfony/Component/Translation/Dumper/IniFileDumper.php index 38ba7dcda4685..d44227a2d34db 100644 --- a/src/Symfony/Component/Translation/Dumper/IniFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/IniFileDumper.php @@ -24,7 +24,9 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra { $output = ''; - foreach ($messages->all($domain, $options['sort']) as $source => $target) { + $sort = $options['sort'] ?? null; + + foreach ($messages->all($domain, $sort) as $source => $target) { $escapeTarget = str_replace('"', '\"', $target); $output .= $source.'="'.$escapeTarget."\"\n"; } diff --git a/src/Symfony/Component/Translation/Dumper/JsonFileDumper.php b/src/Symfony/Component/Translation/Dumper/JsonFileDumper.php index e2f4cf4ddb371..9ce20322ccf90 100644 --- a/src/Symfony/Component/Translation/Dumper/JsonFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/JsonFileDumper.php @@ -23,8 +23,9 @@ class JsonFileDumper extends FileDumper public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string { $flags = $options['json_encoding'] ?? \JSON_PRETTY_PRINT; + $sort = $options['sort'] ?? null; - return json_encode($messages->all($domain, $options['sort']), $flags); + return json_encode($messages->all($domain, $sort), $flags); } protected function getExtension(): string diff --git a/src/Symfony/Component/Translation/Dumper/MoFileDumper.php b/src/Symfony/Component/Translation/Dumper/MoFileDumper.php index 8b31b49545ead..f65e1eb4ec750 100644 --- a/src/Symfony/Component/Translation/Dumper/MoFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/MoFileDumper.php @@ -27,7 +27,9 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra $offsets = []; $size = 0; - foreach ($messages->all($domain, $options['sort']) as $source => $target) { + $sort = $options['sort'] ?? null; + + foreach ($messages->all($domain, $sort) as $source => $target) { $offsets[] = array_map('strlen', [$sources, $source, $targets, $target]); $sources .= "\0".$source; $targets .= "\0".$target; diff --git a/src/Symfony/Component/Translation/Dumper/PhpFileDumper.php b/src/Symfony/Component/Translation/Dumper/PhpFileDumper.php index b2f2cbc599c8e..72b367a1e01f7 100644 --- a/src/Symfony/Component/Translation/Dumper/PhpFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/PhpFileDumper.php @@ -22,7 +22,9 @@ class PhpFileDumper extends FileDumper { public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string { - return "all($domain, $options['sort']), true).";\n"; + $sort = $options['sort'] ?? null; + + return "all($domain, $sort), true).";\n"; } protected function getExtension(): string diff --git a/src/Symfony/Component/Translation/Dumper/PoFileDumper.php b/src/Symfony/Component/Translation/Dumper/PoFileDumper.php index c2a445131d446..dfdb1d24728cb 100644 --- a/src/Symfony/Component/Translation/Dumper/PoFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/PoFileDumper.php @@ -29,8 +29,10 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra $output .= '"Language: '.$messages->getLocale().'\n"'."\n"; $output .= "\n"; + $sort = $options['sort'] ?? null; + $newLine = false; - foreach ($messages->all($domain, $options['sort']) as $source => $target) { + foreach ($messages->all($domain, $sort) as $source => $target) { if ($newLine) { $output .= "\n"; } else { diff --git a/src/Symfony/Component/Translation/Dumper/QtFileDumper.php b/src/Symfony/Component/Translation/Dumper/QtFileDumper.php index 784a403369401..b145c447d9b1a 100644 --- a/src/Symfony/Component/Translation/Dumper/QtFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/QtFileDumper.php @@ -28,7 +28,9 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra $context = $ts->appendChild($dom->createElement('context')); $context->appendChild($dom->createElement('name', $domain)); - foreach ($messages->all($domain, $options['sort']) as $source => $target) { + $sort = $options['sort'] ?? null; + + foreach ($messages->all($domain, $sort) as $source => $target) { $message = $context->appendChild($dom->createElement('message')); $metadata = $messages->getMetadata($source, $domain); if (isset($metadata['sources'])) { diff --git a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php index d2aa354845500..90b8540a14fa6 100644 --- a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php @@ -43,7 +43,7 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra return $this->dumpXliff1($defaultLocale, $messages, $domain, $options); } if ('2.0' === $xliffVersion) { - return $this->dumpXliff2($defaultLocale, $messages, $domain); + return $this->dumpXliff2($defaultLocale, $messages, $domain, $options); } throw new InvalidArgumentException(sprintf('No support implemented for dumping XLIFF version "%s".', $xliffVersion)); @@ -56,6 +56,8 @@ protected function getExtension(): string private function dumpXliff1(string $defaultLocale, MessageCatalogue $messages, ?string $domain, array $options = []): string { + $sort = $options['sort'] ?? null; + $toolInfo = ['tool-id' => 'symfony', 'tool-name' => 'Symfony']; if (\array_key_exists('tool_info', $options)) { $toolInfo = array_merge($toolInfo, $options['tool_info']); @@ -90,7 +92,7 @@ private function dumpXliff1(string $defaultLocale, MessageCatalogue $messages, ? } $xliffBody = $xliffFile->appendChild($dom->createElement('body')); - foreach ($messages->all($domain, $options['sort']) as $source => $target) { + foreach ($messages->all($domain, $sort) as $source => $target) { $translation = $dom->createElement('trans-unit'); $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._')); @@ -137,8 +139,10 @@ private function dumpXliff1(string $defaultLocale, MessageCatalogue $messages, ? return $dom->saveXML(); } - private function dumpXliff2(string $defaultLocale, MessageCatalogue $messages, ?string $domain): string + private function dumpXliff2(string $defaultLocale, MessageCatalogue $messages, ?string $domain, array $options = []): string { + $sort = $options['sort'] ?? null; + $dom = new \DOMDocument('1.0', 'utf-8'); $dom->formatOutput = true; @@ -165,7 +169,7 @@ private function dumpXliff2(string $defaultLocale, MessageCatalogue $messages, ? } } - foreach ($messages->all($domain, $options['sort']) as $source => $target) { + foreach ($messages->all($domain, $sort) as $source => $target) { $translation = $dom->createElement('unit'); $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._')); diff --git a/src/Symfony/Component/Translation/Dumper/YamlFileDumper.php b/src/Symfony/Component/Translation/Dumper/YamlFileDumper.php index 064f290f3d0e9..fd942514b3934 100644 --- a/src/Symfony/Component/Translation/Dumper/YamlFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/YamlFileDumper.php @@ -36,7 +36,9 @@ public function formatCatalogue(MessageCatalogue $messages, string $domain, arra throw new LogicException('Dumping translations in the YAML format requires the Symfony Yaml component.'); } - $data = $messages->all($domain, $options['sort']); + $sort = $options['sort'] ?? null; + + $data = $messages->all($domain, $sort); if (isset($options['as_tree']) && $options['as_tree']) { $data = ArrayConverter::expandToTree($data); From e540efe69b7373592679b1b131daee8d5493c101 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Mon, 18 Dec 2023 14:45:01 +0100 Subject: [PATCH 4/4] Accept null value for the sort option To not introduce a breaking change in the API of the translation:extract command, I need to accept the "null" value for the `--sort` option when `--force` is passed to the command. Meaning that I had to remove the default value of the `InputOption`. In the mean time, I didn't want to break the previous behaviour when using `--dump-messages`. So in this case, when the option is not passed, I fallback to the value "asc". --- .../Command/TranslationUpdateCommand.php | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index 4f4e2809dcfb2..028bc8778758c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -87,7 +87,7 @@ protected function configure(): void new InputOption('force', null, InputOption::VALUE_NONE, 'Should the extract be done'), new InputOption('clean', null, InputOption::VALUE_NONE, 'Should clean not found messages'), new InputOption('domain', null, InputOption::VALUE_OPTIONAL, 'Specify the domain to extract'), - new InputOption('sort', null, InputOption::VALUE_OPTIONAL, 'Return list of messages sorted alphabetically', 'asc'), + new InputOption('sort', null, InputOption::VALUE_OPTIONAL, 'Return list of messages sorted alphabetically'), new InputOption('as-tree', null, InputOption::VALUE_OPTIONAL, 'Dump the messages as a tree-like structure: The given value defines the level where to switch to inline YAML'), ]) ->setHelp(<<<'EOF' @@ -235,19 +235,22 @@ protected function execute(InputInterface $input, OutputInterface $output): int $domainMessagesCount = \count($list); - if ($sort = $input->getOption('sort')) { - $sort = strtolower($sort); - if (!\in_array($sort, self::SORT_ORDERS, true)) { - $errorIo->error(['Wrong sort order', 'Supported formats are: '.implode(', ', self::SORT_ORDERS).'.']); + $sort = $input->getOption('sort'); + if (null === $sort) { + $sort = 'asc'; + } + + $sort = strtolower($sort); + if (!\in_array($sort, self::SORT_ORDERS, true)) { + $errorIo->error(['Wrong sort order', 'Supported formats are: '.implode(', ', self::SORT_ORDERS).'.']); - return 1; - } + return 1; + } - if (self::DESC === $sort) { - rsort($list); - } else { - sort($list); - } + if (self::DESC === $sort) { + rsort($list); + } else { + sort($list); } $io->section(sprintf('Messages extracted for domain "%s" (%d message%s)', $domain, $domainMessagesCount, $domainMessagesCount > 1 ? 's' : ''));