/**
  * @param string $langPackDir       language pack dir in temp folder
  * @param string $projectNamespace  e.g. Oro, OroCRM, etc
  * @param string $outputFormat      xml, yml, etc
  * @param string $locale            en, en_US, fr, etc
  */
 public function dump($langPackDir, $projectNamespace, $outputFormat, $locale)
 {
     $this->preloadExistingTranslations($locale);
     foreach ($this->bundles as $bundle) {
         // skip bundles from other projects
         if ($projectNamespace != $this->getBundlePrefix($bundle->getNamespace())) {
             continue;
         }
         $this->logger->log(LogLevel::INFO, '');
         $this->logger->log(LogLevel::INFO, sprintf('Writing files for <info>%s</info>', $bundle->getName()));
         /** @var MessageCatalogue $currentCatalogue */
         $currentCatalogue = $this->getCurrentCatalog($locale, $bundle->getName());
         $extractedCatalogue = $this->extractViewTranslationKeys($locale, $bundle->getPath());
         $operation = new MergeOperation($currentCatalogue, $extractedCatalogue);
         $messageCatalogue = $operation->getResult();
         $isEmptyCatalogue = $this->validateAndFilter($messageCatalogue);
         if (!$isEmptyCatalogue) {
             $translationsDir = $langPackDir . DIRECTORY_SEPARATOR . $bundle->getName() . DIRECTORY_SEPARATOR . 'translations';
             $this->filesystem->mkdir($translationsDir);
             $this->writer->writeTranslations($messageCatalogue, $outputFormat, ['path' => $translationsDir]);
         } else {
             $this->logger->log(LogLevel::INFO, '    - no files generated');
         }
     }
 }
Esempio n. 2
0
 /**
  * @param $transFile
  * @param $resourceDirs
  * @param $locale
  * @param $loader
  * @param $globalCatalogue
  * @return MessageCatalogue
  */
 protected function merge($transFile, &$resourceDirs, Locale $locale, TranslationLoader $loader, $globalCatalogue)
 {
     $transFileDir = dirname($transFile);
     if (!in_array($transFileDir, $resourceDirs) && '.' != $transFileDir) {
         $resourceDirs[] = $transFileDir;
         $currentCatalogue = new MessageCatalogue($locale->getAlias());
         $loader->loadMessages($transFileDir, $currentCatalogue);
         $operation = new MergeOperation($globalCatalogue, $currentCatalogue);
         $globalCatalogue = $operation->getResult();
         return $globalCatalogue;
     }
     return $globalCatalogue;
 }
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $io = new SymfonyStyle($input, $output);
     $locale = $input->getArgument('locale');
     $domain = $input->getOption('domain');
     /** @var TranslationLoader $loader */
     $loader = $this->getContainer()->get('translation.loader');
     /** @var Kernel $kernel */
     $kernel = $this->getContainer()->get('kernel');
     // Define Root Path to App folder
     $transPaths = array($kernel->getRootDir() . '/Resources/');
     // Override with provided Bundle info
     if (null !== $input->getArgument('bundle')) {
         try {
             $bundle = $kernel->getBundle($input->getArgument('bundle'));
             $transPaths = array($bundle->getPath() . '/Resources/', sprintf('%s/Resources/%s/', $kernel->getRootDir(), $bundle->getName()));
         } catch (\InvalidArgumentException $e) {
             // such a bundle does not exist, so treat the argument as path
             $transPaths = array($input->getArgument('bundle') . '/Resources/');
             if (!is_dir($transPaths[0])) {
                 throw new \InvalidArgumentException(sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0]));
             }
         }
     } elseif ($input->getOption('all')) {
         foreach ($kernel->getBundles() as $bundle) {
             $transPaths[] = $bundle->getPath() . '/Resources/';
             $transPaths[] = sprintf('%s/Resources/%s/', $kernel->getRootDir(), $bundle->getName());
         }
     }
     // Extract used messages
     $extractedCatalogue = $this->extractMessages($locale, $transPaths);
     // Load defined messages
     $currentCatalogue = $this->loadCurrentMessages($locale, $transPaths, $loader);
     // Merge defined and extracted messages to get all message ids
     $mergeOperation = new MergeOperation($extractedCatalogue, $currentCatalogue);
     $allMessages = $mergeOperation->getResult()->all($domain);
     if (null !== $domain) {
         $allMessages = array($domain => $allMessages);
     }
     // No defined or extracted messages
     if (empty($allMessages) || null !== $domain && empty($allMessages[$domain])) {
         $outputMessage = sprintf('No defined or extracted messages for locale "%s"', $locale);
         if (null !== $domain) {
             $outputMessage .= sprintf(' and domain "%s"', $domain);
         }
         $io->warning($outputMessage);
         return;
     }
     // Load the fallback catalogues
     $fallbackCatalogues = $this->loadFallbackCatalogues($locale, $transPaths, $loader);
     // Display header line
     $headers = array('State', 'Domain', 'Id', sprintf('Message Preview (%s)', $locale));
     foreach ($fallbackCatalogues as $fallbackCatalogue) {
         $headers[] = sprintf('Fallback Message Preview (%s)', $fallbackCatalogue->getLocale());
     }
     $rows = array();
     // Iterate all message ids and determine their state
     foreach ($allMessages as $domain => $messages) {
         foreach (array_keys($messages) as $messageId) {
             $value = $currentCatalogue->get($messageId, $domain);
             $states = array();
             if ($extractedCatalogue->defines($messageId, $domain)) {
                 if (!$currentCatalogue->defines($messageId, $domain)) {
                     $states[] = self::MESSAGE_MISSING;
                 }
             } elseif ($currentCatalogue->defines($messageId, $domain)) {
                 $states[] = self::MESSAGE_UNUSED;
             }
             if (!in_array(self::MESSAGE_UNUSED, $states) && true === $input->getOption('only-unused') || !in_array(self::MESSAGE_MISSING, $states) && true === $input->getOption('only-missing')) {
                 continue;
             }
             foreach ($fallbackCatalogues as $fallbackCatalogue) {
                 if ($fallbackCatalogue->defines($messageId, $domain) && $value === $fallbackCatalogue->get($messageId, $domain)) {
                     $states[] = self::MESSAGE_EQUALS_FALLBACK;
                     break;
                 }
             }
             $row = array($this->formatStates($states), $domain, $this->formatId($messageId), $this->sanitizeString($value));
             foreach ($fallbackCatalogues as $fallbackCatalogue) {
                 $row[] = $this->sanitizeString($fallbackCatalogue->get($messageId, $domain));
             }
             $rows[] = $row;
         }
     }
     $io->table($headers, $rows);
 }
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $locale = $input->getOption('locale');
     if (empty($locale)) {
         $locale = 'en_US';
     }
     $domain = $input->getOption('domain');
     $bundle = $input->getOption('bundle');
     $log = $input->getOption('logfile');
     $loader = $this->getContainer()->get('mautic.translation.loader');
     $factory = $this->getContainer()->get('mautic.factory');
     $viewsOnly = $input->getOption('only-views');
     $dupsOnly = $input->getOption('only-dups');
     $bundles = $factory->getMauticBundles(true);
     if (!empty($log)) {
         $logfile = fopen($log, 'w+');
         $output = new StreamOutput($logfile, null, false, new OutputFormatter(false));
     }
     if (!empty($bundle)) {
         if (!isset($bundles[$bundle])) {
             $output->writeln('Bundle not found');
             return;
         }
         $bundles = [$bundles[$bundle]];
     }
     // Load defined messages
     $currentCatalogue = new MessageCatalogue($locale);
     // Extract used messages from Views
     $extractedCatalogue = new MessageCatalogue($locale);
     $phpFormExtractor = new PhpFormTranslationExtractor();
     foreach ($bundles as $bundle) {
         if (!$dupsOnly) {
             if (file_exists($bundle['directory'] . '/Views')) {
                 $phpFormExtractor->extract($bundle['directory'] . '/Views', $extractedCatalogue);
                 $this->getContainer()->get('translation.extractor')->extract($bundle['directory'] . '/Views', $extractedCatalogue);
             }
             if (!$viewsOnly) {
                 $directories = ['/Form/Type', '/EventListener', '/Model', '/EventListener', '/Controller'];
                 foreach ($directories as $d) {
                     if (file_exists($bundle['directory'] . $d)) {
                         $phpFormExtractor->extract($bundle['directory'] . $d, $extractedCatalogue);
                         $this->getContainer()->get('translation.extractor')->extract($bundle['directory'] . $d, $extractedCatalogue);
                     }
                 }
             }
         }
         if (is_dir($bundle['directory'] . '/Translations')) {
             $currentCatalogue = $loader->load(null, $locale, $domain);
         }
     }
     // Merge defined and extracted messages to get all message ids
     $mergeOperation = new MergeOperation($extractedCatalogue, $currentCatalogue);
     $allMessages = $mergeOperation->getResult()->all($domain);
     if (null !== $domain) {
         $allMessages = [$domain => $allMessages];
     }
     // No defined or extracted messages
     if (empty($allMessages) || null !== $domain && empty($allMessages[$domain])) {
         $outputMessage = sprintf('<info>No defined or extracted messages for locale "%s"</info>', $locale);
         if (null !== $domain) {
             $outputMessage .= sprintf(' <info>and domain "%s"</info>', $domain);
         }
         $output->writeln($outputMessage);
         return;
     }
     /** @var \Symfony\Component\Console\Helper\Table $table */
     $table = new Table($output);
     // Display header line
     $headers = ['State(s)', 'Id', sprintf('Message Preview (%s)', $locale)];
     $table->setHeaders($headers);
     $duplicateCheck = [];
     // Iterate all message ids and determine their state
     foreach ($allMessages as $domain => $messages) {
         foreach (array_keys($messages) as $messageId) {
             $value = $currentCatalogue->get($messageId, $domain);
             $duplicateKey = strtolower($value);
             if (!isset($duplicateCheck[$duplicateKey])) {
                 $duplicateCheck[$duplicateKey] = [];
             }
             $duplicateCheck[$duplicateKey][] = ['id' => $messageId, 'domain' => $domain];
             $states = [];
             if ($extractedCatalogue->defines($messageId, $domain)) {
                 if (!$currentCatalogue->defines($messageId, $domain)) {
                     $states[] = self::MESSAGE_MISSING;
                 }
             } elseif ($currentCatalogue->defines($messageId, $domain)) {
                 $states[] = self::MESSAGE_UNUSED;
             }
             if (!in_array(self::MESSAGE_UNUSED, $states) && true === $input->getOption('only-unused') || !in_array(self::MESSAGE_MISSING, $states) && true === $input->getOption('only-missing')) {
                 continue;
             }
             $row = [$this->formatStates($states), $this->formatId($messageId), $this->sanitizeString($value)];
             $table->addRow($row);
         }
     }
     if (!$dupsOnly) {
         $table->render();
         $output->writeln('');
         $output->writeln('<info>Legend:</info>');
         $output->writeln(sprintf(' %s Missing message', $this->formatState(self::MESSAGE_MISSING)));
         $output->writeln(sprintf(' %s Unused message', $this->formatState(self::MESSAGE_UNUSED)));
         $output->writeln(sprintf(' %s Same as the fallback message', $this->formatState(self::MESSAGE_EQUALS_FALLBACK)));
     }
     $output->writeln('');
     $output->writeln('<info>Duplicates:</info>');
     /** @var \Symfony\Component\Console\Helper\Table $table */
     $table = new Table($output);
     // Display header line
     $headers = ['Value', 'Domain', 'Message ID'];
     $table->setHeaders($headers);
     //Check for duplicates
     $totalDuplicateCount = 0;
     foreach ($duplicateCheck as $value => $dups) {
         $count = count($dups);
         if ($count > 1) {
             ++$totalDuplicateCount;
             $table->addRow(['', '', '']);
             $table->addRow([$this->sanitizeString($value), $count, '']);
             foreach ($dups as $dup) {
                 $table->addRow(['', $dup['domain'], $dup['id']]);
             }
         }
     }
     $table->render();
     $output->writeln('');
     $output->writeln('<info>Total number of duplicates: ' . $totalDuplicateCount . '</info>');
 }
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $locale = $input->getArgument('locale');
     $domain = $input->getOption('domain');
     $kernel = $this->getContainer()->get('kernel');
     $bundle = $kernel->getBundle($input->getArgument('bundle'));
     $loader = $this->getContainer()->get('translation.loader');
     // Extract used messages
     $extractedCatalogue = new MessageCatalogue($locale);
     $bundlePaths = array($bundle->getPath() . '/Resources/', sprintf('%s/Resources/%s/', $kernel->getRootDir(), $bundle->getName()));
     foreach ($bundlePaths as $path) {
         $path = $path . 'views';
         if (is_dir($path)) {
             $this->getContainer()->get('translation.extractor')->extract($path, $extractedCatalogue);
         }
     }
     // Load defined messages
     $currentCatalogue = new MessageCatalogue($locale);
     foreach ($bundlePaths as $path) {
         $path = $path . 'translations';
         if (is_dir($path)) {
             $loader->loadMessages($path, $currentCatalogue);
         }
     }
     // Merge defined and extracted messages to get all message ids
     $mergeOperation = new MergeOperation($extractedCatalogue, $currentCatalogue);
     $allMessages = $mergeOperation->getResult()->all($domain);
     if (null !== $domain) {
         $allMessages = array($domain => $allMessages);
     }
     // No defined or extracted messages
     if (empty($allMessages) || null !== $domain && empty($allMessages[$domain])) {
         $outputMessage = sprintf('<info>No defined or extracted messages for locale "%s"</info>', $locale);
         if (null !== $domain) {
             $outputMessage .= sprintf(' <info>and domain "%s"</info>', $domain);
         }
         $output->writeln($outputMessage);
         return;
     }
     // Load the fallback catalogues
     $fallbackCatalogues = array();
     $translator = $this->getContainer()->get('translator');
     if ($translator instanceof Translator) {
         foreach ($translator->getFallbackLocales() as $fallbackLocale) {
             if ($fallbackLocale === $locale) {
                 continue;
             }
             $fallbackCatalogue = new MessageCatalogue($fallbackLocale);
             $loader->loadMessages($bundle->getPath() . '/Resources/translations', $fallbackCatalogue);
             $fallbackCatalogues[] = $fallbackCatalogue;
         }
     }
     if (class_exists('Symfony\\Component\\Console\\Helper\\Table')) {
         $table = new Table($output);
     } else {
         $table = $this->getHelperSet()->get('table');
     }
     // Display header line
     $headers = array('State(s)', 'Id', sprintf('Message Preview (%s)', $locale));
     foreach ($fallbackCatalogues as $fallbackCatalogue) {
         $headers[] = sprintf('Fallback Message Preview (%s)', $fallbackCatalogue->getLocale());
     }
     $table->setHeaders($headers);
     // Iterate all message ids and determine their state
     foreach ($allMessages as $domain => $messages) {
         foreach (array_keys($messages) as $messageId) {
             $value = $currentCatalogue->get($messageId, $domain);
             $states = array();
             if ($extractedCatalogue->defines($messageId, $domain)) {
                 if (!$currentCatalogue->defines($messageId, $domain)) {
                     $states[] = self::MESSAGE_MISSING;
                 }
             } elseif ($currentCatalogue->defines($messageId, $domain)) {
                 $states[] = self::MESSAGE_UNUSED;
             }
             if (!in_array(self::MESSAGE_UNUSED, $states) && true === $input->getOption('only-unused') || !in_array(self::MESSAGE_MISSING, $states) && true === $input->getOption('only-missing')) {
                 continue;
             }
             foreach ($fallbackCatalogues as $fallbackCatalogue) {
                 if ($fallbackCatalogue->defines($messageId, $domain) && $value === $fallbackCatalogue->get($messageId, $domain)) {
                     $states[] = self::MESSAGE_EQUALS_FALLBACK;
                     break;
                 }
             }
             $row = array($this->formatStates($states), $this->formatId($messageId), $this->sanitizeString($value));
             foreach ($fallbackCatalogues as $fallbackCatalogue) {
                 $row[] = $this->sanitizeString($fallbackCatalogue->get($messageId, $domain));
             }
             $table->addRow($row);
         }
     }
     if (class_exists('Symfony\\Component\\Console\\Helper\\Table')) {
         $table->render();
     } else {
         $table->render($output);
     }
     $output->writeln('');
     $output->writeln('<info>Legend:</info>');
     $output->writeln(sprintf(' %s Missing message', $this->formatState(self::MESSAGE_MISSING)));
     $output->writeln(sprintf(' %s Unused message', $this->formatState(self::MESSAGE_UNUSED)));
     $output->writeln(sprintf(' %s Same as the fallback message', $this->formatState(self::MESSAGE_EQUALS_FALLBACK)));
 }
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $output = new SymfonyStyle($input, $output);
     if (false !== strpos($input->getFirstArgument(), ':d')) {
         $output->caution('The use of "translation:debug" command is deprecated since version 2.7 and will be removed in 3.0. Use the "debug:translation" instead.');
     }
     $locale = $input->getArgument('locale');
     $domain = $input->getOption('domain');
     $loader = $this->getContainer()->get('translation.loader');
     $kernel = $this->getContainer()->get('kernel');
     // Define Root Path to App folder
     $rootPath = $kernel->getRootDir();
     // Override with provided Bundle info
     if (null !== $input->getArgument('bundle')) {
         try {
             $rootPath = $kernel->getBundle($input->getArgument('bundle'))->getPath();
         } catch (\InvalidArgumentException $e) {
             // such a bundle does not exist, so treat the argument as path
             $rootPath = $input->getArgument('bundle');
             if (!is_dir($rootPath)) {
                 throw new \InvalidArgumentException(sprintf('"%s" is neither an enabled bundle nor a directory.', $rootPath));
             }
         }
     }
     // get bundle directory
     $translationsPath = $rootPath . '/Resources/translations';
     // Extract used messages
     $extractedCatalogue = new MessageCatalogue($locale);
     if (is_dir($rootPath . '/Resources/views')) {
         $this->getContainer()->get('translation.extractor')->extract($rootPath . '/Resources/views', $extractedCatalogue);
     }
     // Load defined messages
     $currentCatalogue = new MessageCatalogue($locale);
     if (is_dir($translationsPath)) {
         $loader->loadMessages($translationsPath, $currentCatalogue);
     }
     // Merge defined and extracted messages to get all message ids
     $mergeOperation = new MergeOperation($extractedCatalogue, $currentCatalogue);
     $allMessages = $mergeOperation->getResult()->all($domain);
     if (null !== $domain) {
         $allMessages = array($domain => $allMessages);
     }
     // No defined or extracted messages
     if (empty($allMessages) || null !== $domain && empty($allMessages[$domain])) {
         $outputMessage = sprintf('No defined or extracted messages for locale "%s"', $locale);
         if (null !== $domain) {
             $outputMessage .= sprintf(' and domain "%s"', $domain);
         }
         $output->warning($outputMessage);
         return;
     }
     // Load the fallback catalogues
     $fallbackCatalogues = array();
     $translator = $this->getContainer()->get('translator');
     if ($translator instanceof Translator) {
         foreach ($translator->getFallbackLocales() as $fallbackLocale) {
             if ($fallbackLocale === $locale) {
                 continue;
             }
             $fallbackCatalogue = new MessageCatalogue($fallbackLocale);
             $loader->loadMessages($translationsPath, $fallbackCatalogue);
             $fallbackCatalogues[] = $fallbackCatalogue;
         }
     }
     // Display header line
     $headers = array('State', 'Domain', 'Id', sprintf('Message Preview (%s)', $locale));
     foreach ($fallbackCatalogues as $fallbackCatalogue) {
         $headers[] = sprintf('Fallback Message Preview (%s)', $fallbackCatalogue->getLocale());
     }
     $rows = array();
     // Iterate all message ids and determine their state
     foreach ($allMessages as $domain => $messages) {
         foreach (array_keys($messages) as $messageId) {
             $value = $currentCatalogue->get($messageId, $domain);
             $states = array();
             if ($extractedCatalogue->defines($messageId, $domain)) {
                 if (!$currentCatalogue->defines($messageId, $domain)) {
                     $states[] = self::MESSAGE_MISSING;
                 }
             } elseif ($currentCatalogue->defines($messageId, $domain)) {
                 $states[] = self::MESSAGE_UNUSED;
             }
             if (!in_array(self::MESSAGE_UNUSED, $states) && true === $input->getOption('only-unused') || !in_array(self::MESSAGE_MISSING, $states) && true === $input->getOption('only-missing')) {
                 continue;
             }
             foreach ($fallbackCatalogues as $fallbackCatalogue) {
                 if ($fallbackCatalogue->defines($messageId, $domain) && $value === $fallbackCatalogue->get($messageId, $domain)) {
                     $states[] = self::MESSAGE_EQUALS_FALLBACK;
                     break;
                 }
             }
             $row = array($this->formatStates($states), $domain, $this->formatId($messageId), $this->sanitizeString($value));
             foreach ($fallbackCatalogues as $fallbackCatalogue) {
                 $row[] = $this->sanitizeString($fallbackCatalogue->get($messageId, $domain));
             }
             $rows[] = $row;
         }
     }
     $output->table($headers, $rows);
 }
Esempio n. 7
0
 public function execute()
 {
     $locales = $this->getLocaleManager()->getActiveList();
     $errors = [];
     foreach ($locales as $locale) {
         if (!in_array($locale->getAlias(), ['ru', 'en'])) {
             continue;
         }
         $globalCatalogue = new MessageCatalogue($locale->getAlias());
         $resourceDirs = [];
         foreach ($this->getTranslator()->getResources() as $resources) {
             foreach ($resources as $transFile) {
                 if ($transFile[0] == DIRECTORY_SEPARATOR) {
                     $transFileDir = dirname($transFile);
                     if (!in_array($transFileDir, $resourceDirs)) {
                         $resourceDirs[] = $transFileDir;
                         $currentCatalogue = new MessageCatalogue($locale->getAlias());
                         $this->getTranslationLoader()->loadMessages($transFileDir, $currentCatalogue);
                         $operation = new MergeOperation($globalCatalogue, $currentCatalogue);
                         $globalCatalogue = $operation->getResult();
                     }
                 }
             }
         }
         $localeErrors = $this->compareDbWithFiles($globalCatalogue);
         $errors[$locale->getAlias()] = $localeErrors;
     }
     foreach ($errors as $localeAlias => $errorLocaleData) {
         if (count($errorLocaleData) > 0) {
             $this->getLogger()->info('<info>' . strtoupper($localeAlias) . ' update:</info>');
             $this->getLogger()->info('use OctavaTranslationDbMigrateTrait;');
             foreach ($errorLocaleData as $domain => $errorData) {
                 $this->getLogger()->error('$this->deleteTranslations(\'' . $domain . '\', [\'' . implode("', '", $errorData) . '\']);');
             }
         }
     }
     $count = 0;
     foreach ($errors as $locale => $errorLocaleData) {
         foreach ($errorLocaleData as $domain => $errorData) {
             $count += count($errorData);
         }
         $this->getLogger()->info('<info>' . strtoupper($locale) . '</info> - found errors: ' . $count);
     }
     return $count ? 1 : 0;
 }