Last active
June 14, 2024 20:21
-
-
Save Kocal/dd3f99475521dd6525f08b2050c660fe to your computer and use it in GitHub Desktop.
Revisions
-
Kocal revised this gist
Jun 14, 2024 . No changes.There are no files selected for viewing
-
Kocal revised this gist
Jun 14, 2024 . No changes.There are no files selected for viewing
-
Kocal created this gist
Mar 24, 2023 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,124 @@ <?php namespace App\Command\Tools; use App\Core\Entity\Website\Locale; use Psr\Log\LoggerInterface; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\MessageCatalogueInterface; use Symfony\Component\Translation\Reader\TranslationReaderInterface; use Symfony\Component\Translation\Writer\TranslationWriterInterface; #[AsCommand( name: 'app:tools:merge-non-icu-and-icu-translations', description: 'Merge non-ICU and ICU translations', )] class MergeNonICUAndICUTranslations extends Command { private const ICU_COMPATIBILITY_YES = 'yes'; private const ICU_COMPATIBILITY_NO = 'no'; private const ICU_COMPATIBILITY_TO_MIGRATE = 'to_migrate'; /** * @var list<Locale::*> */ private array $locales = []; public function __construct( private TranslationReaderInterface $translationReader, private TranslationWriterInterface $translationWriter, ParameterBagInterface $parameterBag, private LoggerInterface $logger ) { $this->locales = $parameterBag->get('locales'); parent::__construct(); } protected function execute(InputInterface $input, OutputInterface $output): int { foreach ($this->locales as $locale) { $catalogue = new MessageCatalogue($locale); $this->translationReader->read(__DIR__.'/../../../translations.original', $catalogue); $catalogue = $this->reorganizeMessages($catalogue, $locale); $this->translationWriter->write($catalogue, 'xlf', [ 'path' => __DIR__.'/../../../translations', ]); } return self::SUCCESS; } private function reorganizeMessages(MessageCatalogue $oldCatalogue, string $locale): MessageCatalogue { $catalogue = new MessageCatalogue($locale); foreach ($oldCatalogue->getDomains() as $domain) { $messagesIcu = $oldCatalogue->all($domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX); $messages = []; foreach ($oldCatalogue->all($domain) as $id => $message) { if (isset($messagesIcu[$id])) { continue; } $messages[$id] = $message; } foreach ($messages as $key => $message) { $icuCompatibility = $this->getIcuCompatibility($message); if (self::ICU_COMPATIBILITY_NO === $icuCompatibility) { $this->logger->info(sprintf('Message "%s" in domain "%s" is not compatible with ICU.', $key, $domain)); continue; } elseif (self::ICU_COMPATIBILITY_TO_MIGRATE === $icuCompatibility) { $message = $this->migrateToICU($message); $icuCompatibility = $this->getICUCompatibility($message); if (self::ICU_COMPATIBILITY_YES !== $icuCompatibility) { $this->logger->error(sprintf('Unable to migrate message "%s" in domain "%s" to ICU format.', $key, $domain)); } } $messagesIcu[$key] = $message; unset($messages[$key]); } $catalogue->add($messages, $domain); $catalogue->add($messagesIcu, $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX); } return $catalogue; } /** * @return self::ICU_COMPATIBILITY_* */ private function getICUCompatibility(string $message): string { if (false === $placeholderMatches = preg_match('/%\w+%/', $message)) { throw new \Exception(sprintf('Unable to parse message "%s", reason "%s".', $message, preg_last_error_msg())); } if (false === $choiceMatches = preg_match('/\{\d+\}/', $message)) { throw new \Exception(sprintf('Unable to parse message "%s", reason "%s".', $message, preg_last_error_msg())); } return match (true) { 0 === $placeholderMatches + $choiceMatches => self::ICU_COMPATIBILITY_YES, $placeholderMatches + $choiceMatches > 0 => self::ICU_COMPATIBILITY_TO_MIGRATE, default => self::ICU_COMPATIBILITY_NO, }; } private function migrateToICU(string $message): string { // dumb approach return preg_replace('/%(\w+)%/', '{\1}', $message) ?? throw new \Exception(sprintf( 'Unable to replace in message "%s", reason "%s".', $message, preg_last_error_msg() )); } }