Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…ndle into DECK36-master
  • Loading branch information
Cédric Girard committed Jun 12, 2015
2 parents 40e2268 + d743ac3 commit 8f15e0a
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 22 deletions.
35 changes: 26 additions & 9 deletions Command/ExportTranslationsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Lexik\Bundle\TranslationBundle\Manager\FileInterface;
use Symfony\Component\Filesystem\Filesystem;

/**
* Export translations from the database in to files.
Expand All @@ -16,12 +17,12 @@
class ExportTranslationsCommand extends ContainerAwareCommand
{
/**
* @var Symfony\Component\Console\Input\InputInterface
* @var \Symfony\Component\Console\Input\InputInterface
*/
private $input;

/**
* @var Symfony\Component\Console\Output\OutputInterface
* @var \Symfony\Component\Console\Output\OutputInterface
*/
private $output;

Expand All @@ -36,7 +37,8 @@ protected function configure()
$this->addOption('locales', 'l', InputOption::VALUE_OPTIONAL, 'Only export files for given locales. e.g. "--locales=en,de"', null);
$this->addOption('domains', 'd', InputOption::VALUE_OPTIONAL, 'Only export files for given domains. e.g. "--domains=messages,validators"', null);
$this->addOption('format', 'f', InputOption::VALUE_OPTIONAL, 'Force the output format.', null);
$this->addOption('override', 'o', InputOption::VALUE_NONE, 'Only export modified phrases (app/Resources/translations are imported fully anyway)');
$this->addOption('override', 'o', InputOption::VALUE_NONE, 'Only export modified phrases (app/Resources/translations are exported fully anyway)');
$this->addOption('export-path', 'p', InputOption::VALUE_REQUIRED, 'Export files to given path.');
}

/**
Expand Down Expand Up @@ -80,17 +82,20 @@ protected function getFilesToExport()
*/
protected function exportFile(FileInterface $file)
{
$rootDir = $this->getContainer()->getParameter('kernel.root_dir');
$rootDir = $this->input->getOption('export-path') ? $this->input->getOption('export-path') . '/' : $this->getContainer()->getParameter('kernel.root_dir');

$this->output->writeln(sprintf('<info># Exporting "%s/%s":</info>', $file->getPath(), $file->getName()));

$override = $this->input->getOption('override');

// we only export updated translations in case of the file is located in vendor/
if ($override) {
$onlyUpdated = ('Resources/translations' !== $file->getPath());
if (!$this->input->getOption('export-path')) {
// we only export updated translations in case of the file is located in vendor/
if ($override) {
$onlyUpdated = ('Resources/translations' !== $file->getPath());
} else {
$onlyUpdated = (false !== strpos($file->getPath(), 'vendor/'));
}
} else {
$onlyUpdated = (false !== strpos($file->getPath(), 'vendor/'));
$onlyUpdated = !$override;
}

$translations = $this->getContainer()
Expand All @@ -107,7 +112,19 @@ protected function exportFile(FileInterface $file)
$outputPath = sprintf('%s/%s', $rootDir, $file->getPath());
}

$this->output->writeln(sprintf('<info># OutputPath "%s":</info>', $outputPath));

// ensure the path exists
if ($this->input->getOption('export-path')) {
/** @var Filesystem $fs */
$fs = $this->getContainer()->get('filesystem');
if (!$fs->exists($outputPath)) {
$fs->mkdir($outputPath);
}
}

$outputFile = sprintf('%s/%s.%s.%s', $outputPath, $file->getDomain(), $file->getLocale(), $format);
$this->output->writeln(sprintf('<info># OutputFile "%s":</info>', $outputFile));

$translations = $this->mergeExistingTranslations($file, $outputFile, $translations);
$this->doExport($outputFile, $translations, $format);
Expand Down
68 changes: 56 additions & 12 deletions Command/ImportTranslationsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@
class ImportTranslationsCommand extends ContainerAwareCommand
{
/**
* @var Symfony\Component\Console\Input\InputInterface
* @var \Symfony\Component\Console\Input\InputInterface
*/
private $input;

/**
* @var Symfony\Component\Console\Output\OutputInterface
* @var \Symfony\Component\Console\Output\OutputInterface
*/
private $output;

Expand All @@ -44,6 +44,8 @@ protected function configure()
$this->addOption('domains', 'd', InputOption::VALUE_OPTIONAL, 'Only imports files for given domains (comma separated).');
$this->addOption('case-insensitive', 'i', InputOption::VALUE_NONE, 'Process translation as lower case to avoid duplicate entry errors.');
$this->addOption('merge', 'm', InputOption::VALUE_NONE, 'Merge translation (use ones with latest updatedAt date).');
$this->addOption('import-path', 'p', InputOption::VALUE_REQUIRED, 'Search for translations at given path');
$this->addOption('only-vendors', 'o', InputOption::VALUE_NONE, 'Import from vendors only');

$this->addArgument('bundle', InputArgument::OPTIONAL, 'Import translations for this specific bundle.', null);
}
Expand All @@ -61,18 +63,42 @@ protected function execute(InputInterface $input, OutputInterface $output)
$locales = $this->getContainer()->getParameter('lexik_translation.managed_locales');
}

if ($this->input->getOption('import-path')
&& ($this->input->getOption('globals')
|| $this->input->getOption('merge')
|| $this->input->getOption('only-vendors'))) {
throw new \LogicException('You cannot use "globals", "merge" or "only-vendors" and "import-path" at the same time.');
}

if ($this->input->getOption('only-vendors') && $this->input->getOption('globals')) {
throw new \LogicException('You cannot use "globals" and "only-vendors" at the same time.');
}

$domains = $input->getOption('domains') ? explode(',', $input->getOption('domains')) : array();

$bundleName = $this->input->getArgument('bundle');
if ($bundleName) {
$bundle = $this->getApplication()->getKernel()->getBundle($bundleName);
$this->importBundleTranslationFiles($bundle, $locales, $domains);
} else {
if (!$this->input->getOption('merge')) {

if (null !== $bundle->getParent()) {
// due to symfony's bundle inheritance if a bundle has a parent it is fetched first.
// so we tell getBundle to NOT fetch the first if a parent is present
$bundle = $this->getApplication()->getKernel()->getBundle($bundle->getParent(), false)[1];
$this->output->writeln('<info>Using: ' . $bundle->getName() . ' as bundle to lookup translations files for.');
}

$this->importBundleTranslationFiles($bundle, $locales, $domains, (bool) $this->input->getOption('globals'));
} else if(!$this->input->getOption('import-path')) {

if (!$this->input->getOption('merge') && !$this->input->getOption('only-vendors')) {
$this->output->writeln('<info>*** Importing application translation files ***</info>');
$this->importAppTranslationFiles($locales, $domains);
}

if ($this->input->getOption('globals')) {
$this->importBundlesTranslationFiles($locales, $domains, true);
}

if (!$this->input->getOption('globals')) {
$this->output->writeln('<info>*** Importing bundles translation files ***</info>');
$this->importBundlesTranslationFiles($locales, $domains);
Expand All @@ -87,12 +113,21 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
}

if ($this->input->getOption('import-path')) {
$this->importTranslationFilesFromPath($this->input->getOption('import-path'), $locales, $domains);
}

if ($this->input->getOption('cache-clear')) {
$this->output->writeln('<info>Removing translations cache files ...</info>');
$this->removeTranslationCache();
}
}

protected function importTranslationFilesFromPath($path, array $locales, array $domains) {
$finder = $this->findTranslationsFiles($path, $locales, $domains, false);
$this->importTranslationFiles($finder);
}

/**
* Imports Symfony's components translation files.
*
Expand Down Expand Up @@ -138,13 +173,14 @@ protected function importAppTranslationFiles(array $locales, array $domains)
*
* @param array $locales
* @param array $domains
* @param boolean $global
*/
protected function importBundlesTranslationFiles(array $locales, array $domains)
protected function importBundlesTranslationFiles(array $locales, array $domains, $global = false)
{
$bundles = $this->getApplication()->getKernel()->getBundles();

foreach ($bundles as $bundle) {
$this->importBundleTranslationFiles($bundle, $locales, $domains);
$this->importBundleTranslationFiles($bundle, $locales, $domains, $global);
}
}

Expand All @@ -154,11 +190,18 @@ protected function importBundlesTranslationFiles(array $locales, array $domains)
* @param BundleInterface $bundle
* @param array $locales
* @param array $domains
* @param boolean $global
*/
protected function importBundleTranslationFiles(BundleInterface $bundle, $locales, $domains)
protected function importBundleTranslationFiles(BundleInterface $bundle, $locales, $domains, $global = false)
{
$path = $bundle->getPath();
if ($global) {
$path = $this->getApplication()->getKernel()->getRootDir() . '/Resources/' . $bundle->getName() . '/translations';
$this->output->writeln('<info>*** Importing ' . $bundle->getName() . '`s translation files from ' . $path . ' ***</info>');
}

$this->output->writeln(sprintf('<info># %s:</info>', $bundle->getName()));
$finder = $this->findTranslationsFiles($bundle->getPath(), $locales, $domains);
$finder = $this->findTranslationsFiles($path, $locales, $domains);
$this->importTranslationFiles($finder);
}

Expand Down Expand Up @@ -194,17 +237,18 @@ protected function importTranslationFiles($finder)
* @param string $path
* @param array $locales
* @param array $domains
* @return Symfony\Component\Finder\Finder
* @return \Symfony\Component\Finder\Finder
*/
protected function findTranslationsFiles($path, array $locales, array $domains)
protected function findTranslationsFiles($path, array $locales, array $domains, $autocompletePath = true)
{
$finder = null;

if (preg_match('#^win#i', PHP_OS)) {
$path = preg_replace('#'. preg_quote(DIRECTORY_SEPARATOR, '#') .'#', '/', $path);
}

$dir = $path.'/Resources/translations';
$dir = true == $autocompletePath ? (0 === strpos($path, $this->getApplication()->getKernel()->getRootDir() . '/Resources') ? $path : $path . '/Resources/translations') : $path;
$this->output->writeln('<info>*** Using dir ' . $dir . ' to lookup translation files. ***</info>');

if (is_dir($dir)) {
$finder = new Finder();
Expand Down
2 changes: 2 additions & 0 deletions Manager/FileInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Lexik\Bundle\TranslationBundle\Manager;

use Symfony\Component\HttpFoundation\File\File;

/**
* File interface.
*
Expand Down
4 changes: 3 additions & 1 deletion Resources/doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,10 @@ Command options:
* `--force` (or `-f`): update the translations even if the element already exist in the database.
* `--globals` (or `-g`): import only from the `app/Resources/translations`. It will ignore the option if you provide a BundleName to import.
* `--locales` (or `-l`): import only for these locales, instead of using the managed locales from the config. eg: `--locales=fr --locales=en`
* `--domains` (or `-d`): Only export files for given domains (comma separated). eg `--domains=messages,validators`
* `--domains` (or `-d`): Only import files for given domains (comma separated). eg `--domains=messages,validators`
* `--case-insensitive` (or `-i`): Convert keys as lower case to check if a key has already been imported.
* `--import-path` (or `-p`): Search for translations at given path. Cannot be used with globals, merge or only-vendors option. eg `--import-path=\tmp`
* `--only-vendors` (or `-o`): Only import files from vendor-bundles. eg `--only-vendors`

Export translations
===================
Expand Down

0 comments on commit 8f15e0a

Please sign in to comment.