Author: david
Date: Thu Dec 8 09:28:49 2011
New Revision: 10378
Log:
Move i18n tasks to their own directory
Added:
trunk/lib/task/i18n/
trunk/lib/task/i18n/i18nConsolidateTask.class.php
- copied unchanged from r10377,
trunk/lib/task/i18nConsolidateTask.class.php
trunk/lib/task/i18n/i18nDiffTask.class.php
- copied unchanged from r10377, trunk/lib/task/i18nDiffTask.class.php
trunk/lib/task/i18n/i18nRectifyTask.class.php
- copied unchanged from r10377, trunk/lib/task/i18nRectifyTask.class.php
trunk/lib/task/i18n/i18nRemoveDuplicatesTask.class.php
- copied unchanged from r10377,
trunk/lib/task/i18nRemoveDuplicatesTask.class.php
trunk/lib/task/i18n/i18nUpdateFixturesTask.class.php
- copied unchanged from r10377,
trunk/lib/task/i18nUpdateFixturesTask.class.php
Deleted:
trunk/lib/task/i18nConsolidateTask.class.php
trunk/lib/task/i18nDiffTask.class.php
trunk/lib/task/i18nRectifyTask.class.php
trunk/lib/task/i18nRemoveDuplicatesTask.class.php
trunk/lib/task/i18nUpdateFixturesTask.class.php
Copied: trunk/lib/task/i18n/i18nConsolidateTask.class.php (from r10377,
trunk/lib/task/i18nConsolidateTask.class.php)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/lib/task/i18n/i18nConsolidateTask.class.php Thu Dec 8 09:28:49
2011 (r10378, copy of r10377,
trunk/lib/task/i18nConsolidateTask.class.php)
@@ -0,0 +1,203 @@
+<?php
+
+/*
+ * This file is part of Qubit Toolkit.
+ *
+ * Qubit Toolkit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Qubit Toolkit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Qubit Toolkit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Restore i18n strings lost when XLIFF files were broken into plugin-specific
+ * directories
+ *
+ * @package symfony
+ * @subpackage task
+ * @author David Juhasz <[email protected]>
+ * @version SVN: $Id$
+ */
+class i18nConsolidateTask extends sfBaseTask
+{
+ /**
+ * @see sfTask
+ */
+ protected function configure()
+ {
+ $this->addArguments(array(
+ new sfCommandArgument('culture', sfCommandArgument::REQUIRED, 'The
target culture'),
+ ));
+
+ $this->addOptions(array(
+ // http://trac.symfony-project.org/ticket/8352
+ new sfCommandOption('application', null,
sfCommandOption::PARAMETER_REQUIRED, 'The application name', true),
+ ));
+
+ $this->namespace = 'i18n';
+ $this->name = 'consolidate';
+ $this->briefDescription = 'Combine all application messages into a single
output (XLIFF) file for ease of use by translators';
+
+ $this->detailedDescription = <<<EOF
+Combine all application messages into a single output (XLIFF) file for ease of
use by translators.
+EOF;
+ }
+
+ /**
+ * @see sfTask
+ */
+ public function execute($arguments = array(), $options = array())
+ {
+ $this->logSection('i18n', sprintf('Consolidating *%s* i18n messages',
$arguments['culture']));
+
+ // get i18n configuration from factories.yml
+ $config =
sfFactoryConfigHandler::getConfiguration($this->configuration->getConfigPaths('config/factories.yml'));
+
+ $class = $config['i18n']['class'];
+ $params = $config['i18n']['param'];
+ unset($params['cache']);
+
+ // Extract i18n messages from php files (including plugins)
+ $i18n = new $class($this->configuration, new sfNoCache(), $params);
+ $extract = new sfI18nConsolidatedExtract($i18n, $arguments['culture']);
+ $extract->extract();
+
+ // Save to app/qubit/i18n/consolidated
+ $consolidated = new $class($this->configuration, new sfNoCache(), $params);
+
$consolidated->setMessageSource(array(sfConfig::get('sf_web_dir').'/i18n/consolidated'),
$arguments['culture']);
+ $consolidated->getMessageSource()->setCulture($arguments['culture']);
+ $extract->save($consolidated);
+ }
+}
+
+class sfI18nConsolidatedExtract extends sfI18nApplicationExtract
+{
+ protected $messageSource = array();
+
+ public function configure()
+ {
+ // Override sfI18nAcpplicationExtract::configure() so we extract from
+ // plugin XLIFF files
+ }
+
+ public function save($consolidated)
+ {
+ $messages = array();
+ $translates = array();
+
+ foreach ($this->i18n->getMessageSource()->read() as $catalogue =>
$translations)
+ {
+ foreach ($translations as $key => $values)
+ {
+ $messages[] = $key;
+
+ // build associative array containing translated values
+ if (!isset($translates[$key]) || 0 == strlen($translates[$key][0]))
+ {
+ $translates[$key] = $values;
+ }
+ }
+ }
+
+ // Sort and remove duplicates
+ $messages = array_unique($messages);
+ sort($messages);
+
+ // Add sources to XLIFF file
+ foreach ($messages as $message)
+ {
+ $consolidated->getMessageSource()->append($message);
+ }
+
+ // Save all sources to consolidated i18n file
+ $consolidated->getMessageSource()->save();
+
+ // Now save translated strings
+ foreach ($translates as $key => $item)
+ {
+ // Track source file for message in comments
+ $comment = $item[2];
+ if (isset($this->sourceFile[$key]))
+ {
+ $comment = $this->sourceFile[$key];
+ }
+
+ $consolidated->getMessageSource()->update($key, $item[0], $comment);
+ }
+ }
+
+ public function extract()
+ {
+ // Add global templates
+ $this->extractFromPhpFiles(sfConfig::get('sf_app_template_dir'));
+
+ // Add global librairies
+ $this->extractFromPhpFiles(sfConfig::get('sf_app_lib_dir'));
+
+ // Add forms
+ $this->extractFromPhpFiles(sfConfig::get('sf_lib_dir').'/form');
+
+ // Extract from modules
+ $modules =
sfFinder::type('dir')->maxdepth(0)->in(sfConfig::get('sf_app_module_dir'));
+ foreach ($modules as $module)
+ {
+ $this->extractFromPhpFiles(array(
+ $module.'/actions',
+ $module.'/lib',
+ $module.'/templates',
+ ));
+ }
+
+ // Extract plugin strings
+ $plugins =
sfFinder::type('dir')->maxdepth(0)->not_name('.')->in(sfConfig::get('sf_plugins_dir'));
+ foreach ($plugins as $plugin)
+ {
+ foreach (sfFinder::type('dir')->maxdepth(0)->in($plugin.'/modules') as
$piModule)
+ {
+ $this->extractFromPhpFiles(array(
+ $piModule.'/actions',
+ $piModule.'/lib',
+ $piModule.'/templates',
+ ));
+ }
+ }
+ }
+
+ /**
+ * Extracts i18n strings from PHP files.
+ *
+ * @param string $dir The PHP full path name
+ */
+ protected function extractFromPhpFiles($dir)
+ {
+ $phpExtractor = new sfI18nPhpExtractor();
+
+ $files = sfFinder::type('file')->name('*.php');
+ $messages = array();
+ foreach ($files->in($dir) as $file)
+ {
+ $extracted = $phpExtractor->extract(file_get_contents($file));
+ $messages = array_merge($messages, $extracted);
+
+ // Track source file for all messages
+ foreach ($extracted as $message)
+ {
+ if (!isset($this->sourceFile[$message]))
+ {
+ // Link to file in googlecode repository
+ $this->sourceFile[$message] =
str_replace(sfConfig::get('sf_web_dir'),
'http://code.google.com/p/qubit-toolkit/source/browse/trunk', $file);
+ }
+ }
+ }
+
+ $this->updateMessages($messages);
+ }
+}
Copied: trunk/lib/task/i18n/i18nDiffTask.class.php (from r10377,
trunk/lib/task/i18nDiffTask.class.php)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/lib/task/i18n/i18nDiffTask.class.php Thu Dec 8 09:28:49 2011
(r10378, copy of r10377, trunk/lib/task/i18nDiffTask.class.php)
@@ -0,0 +1,178 @@
+<?php
+
+/*
+ * This file is part of Qubit Toolkit.
+ *
+ * Qubit Toolkit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Qubit Toolkit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Qubit Toolkit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Output a list of removed and added i18n messages to allow auditing of
+ * changes, and preservation of translations data that may still be valid.
+ * Output formats currrently include csv and tab to allow easy import into a
+ * spreadsheet application.
+ *
+ * @package symfony
+ * @subpackage task
+ * @author David Juhasz <[email protected]>
+ * @version SVN: $Id$
+ */
+class i18nDiffTask extends sfBaseTask
+{
+ const FORMAT_CSV = 'csv';
+ const FORMAT_TAB = 'tab';
+
+ /**
+ * @see sfTask
+ */
+ protected function configure()
+ {
+ $this->addArguments(array(
+ new sfCommandArgument('application', sfCommandArgument::REQUIRED, 'The
application name'),
+ new sfCommandArgument('culture', sfCommandArgument::REQUIRED, 'The
target culture'),
+ ));
+
+ $this->addOptions(array(
+ new sfCommandOption('file', 'f', sfCommandOption::PARAMETER_OPTIONAL,
'Specify a destination filename for writing output', 'stdout'),
+ new sfCommandOption('format', 'o', sfCommandOption::PARAMETER_OPTIONAL,
'Specify an output format (currently only supports csv & tab-delimited)',
self::FORMAT_CSV)
+ ));
+
+ $this->namespace = 'i18n';
+ $this->name = 'diff';
+ $this->briefDescription = 'Compares existing XLIFF strings to new i18n
strings extracted from PHP files as per the i18n:extract task.';
+
+ $this->detailedDescription = <<<EOF
+The [i18n:diff|INFO] task compares existing XLIFF strings to new i18n strings
+extracted from PHP files for the given application and target culture:
+
+ [./symfony i18n:diff frontend fr|INFO]
+
+By default, the task outputs to STDOUT. To specify an destination file
+use the [--file|COMMENT] or [-f|COMMENT] options:
+
+ [./symfony i18n:diff --file="french_diff.csv" frontend fr|INFO]
+ [./symfony i18n:diff -f="french_diff.csv" frontend fr|INFO]
+
+By defulat, the task outputs the differences in CSV format. To specify an
+alternate file format use the [--format|COMMENT] or [-t|COMMENT] options:
+
+ [./symfony i18n:diff --format="tab" frontend fr|INFO]
+ [./symfony i18n:diff -o="tab" frontend fr|INFO]
+
+Possible [--format|COMMENT] values are "csv" and "tab".
+EOF;
+ }
+
+ /**
+ * @see sfTask
+ * @see sfI18nExtract
+ */
+ public function execute($arguments = array(), $options = array())
+ {
+ $output = "";
+
+ if (strtolower($options['file']) != 'stdout')
+ {
+ $this->logSection('i18n', sprintf('Diff i18n strings for the "%s"
application', $arguments['application']));
+ }
+
+ // get i18n configuration from factories.yml
+ $config =
sfFactoryConfigHandler::getConfiguration($this->configuration->getConfigPaths('config/factories.yml'));
+
+ $class = $config['i18n']['class'];
+ $params = $config['i18n']['param'];
+ unset($params['cache']);
+
+ $this->i18n = new $class($this->configuration, new sfNoCache(), $params);
+ $extract = new sfI18nApplicationExtract($this->i18n,
$arguments['culture']);
+ $extract->extract();
+
+ if (strtolower($options['file']) != 'stdout')
+ {
+ $this->logSection('i18n', sprintf('found "%d" new i18n strings',
count($extract->getNewMessages())));
+ $this->logSection('i18n', sprintf('found "%d" old i18n strings',
count($extract->getOldMessages())));
+ }
+
+ // Column headers
+ $rows[0] = array('Action', 'Source', 'Target');
+
+ // Old messages
+ foreach ($this->getOldTranslations($extract) as $source=>$target)
+ {
+ $rows[] = array('Removed', $source, $target);
+ }
+
+ // New messages
+ foreach ($extract->getNewMessages() as $message)
+ {
+ $rows[] = array('Added', $message);
+ }
+
+ // Choose output format
+ switch (strtolower($options['format']))
+ {
+ case 'csv':
+ foreach ($rows as $row)
+ {
+ $output .= '"'.implode('","', array_map('addslashes', $row))."\"\n";
+ }
+ break;
+ case 'tab':
+ foreach ($rows as $row)
+ {
+ $output .= implode("\t", $row)."\n";
+ }
+ break;
+ }
+
+ // Output file
+ if (strtolower($options['file']) != 'stdout')
+ {
+ echo "\n".$options['file'];
+ // Remove '=' if using -f="file.csv" notation
+ $filename = (substr($options['file'], 0, 1) == '=') ?
substr($options['file'], 1) : $options['file'];
+ file_put_contents($filename, $output);
+ }
+ else
+ {
+ echo $output;
+ }
+ }
+
+ /**
+ * Loads old translations currently saved in the message sources.
+ *
+ * @param sfI18nApplicationExtract $extract
+ * @return array of source and target translations
+ */
+ public function getOldTranslations($extract)
+ {
+ $oldMessages = array_diff($extract->getCurrentMessages(),
$extract->getAllSeenMessages());
+
+ foreach ($this->i18n->getMessageSource()->read() as $catalogue =>
$translations)
+ {
+ foreach ($translations as $key => $value)
+ {
+ $allTranslations[$key] = $value[0];
+ }
+ }
+
+ foreach ($oldMessages as $message)
+ {
+ $oldTranslations[$message] = $allTranslations[$message];
+ }
+
+ return $oldTranslations;
+ }
+}
Copied: trunk/lib/task/i18n/i18nRectifyTask.class.php (from r10377,
trunk/lib/task/i18nRectifyTask.class.php)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/lib/task/i18n/i18nRectifyTask.class.php Thu Dec 8 09:28:49
2011 (r10378, copy of r10377, trunk/lib/task/i18nRectifyTask.class.php)
@@ -0,0 +1,113 @@
+<?php
+
+/*
+ * This file is part of Qubit Toolkit.
+ *
+ * Qubit Toolkit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Qubit Toolkit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Qubit Toolkit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Restore i18n strings lost when XLIFF files were broken into plugin-specific
+ * directories
+ *
+ * @package symfony
+ * @subpackage task
+ * @author David Juhasz <[email protected]>
+ * @version SVN: $Id$
+ */
+class i18nRectifyTask extends sfBaseTask
+{
+ /**
+ * @see sfTask
+ */
+ protected function configure()
+ {
+ $this->addArguments(array(
+ new sfCommandArgument('culture', sfCommandArgument::REQUIRED, 'The
target culture'),
+ ));
+
+ $this->addOptions(array(
+
+ // http://trac.symfony-project.org/ticket/8352
+ new sfCommandOption('application', null,
sfCommandOption::PARAMETER_REQUIRED, 'The application name', true),
+ ));
+
+ $this->namespace = 'i18n';
+ $this->name = 'rectify';
+ $this->briefDescription = 'Copy i18n target messages from application
source to plugin source. This prevents losing translated string in the
fragmentation of application message source into multiple plugin message
sources.';
+
+ $this->detailedDescription = <<<EOF
+FIXME
+EOF;
+ }
+
+ /**
+ * @see sfTask
+ */
+ public function execute($arguments = array(), $options = array())
+ {
+ $this->logSection('i18n', sprintf('Rectifying existing i18n strings for
the "%s" application', $options['application']));
+
+ // get i18n configuration from factories.yml
+ $config =
sfFactoryConfigHandler::getConfiguration($this->configuration->getConfigPaths('config/factories.yml'));
+
+ $class = $config['i18n']['class'];
+ $params = $config['i18n']['param'];
+ unset($params['cache']);
+
+ // Get current (saved) messages from ALL sources (app and plugin)
+ $this->i18n = new $class($this->configuration, new sfNoCache(), $params);
+ $this->i18n->getMessageSource()->setCulture($arguments['culture']);
+ $this->i18n->getMessageSource()->load();
+
+ $currentMessages = array();
+ foreach ($this->i18n->getMessageSource()->read() as $catalogue =>
$translations)
+ {
+ foreach ($translations as $key => $value)
+ {
+ // Use first message that has a valid translation
+ if (0 < strlen(trim($value[0])) && !isset($currentMessages[$key][0]))
+ {
+ $currentMessages[$key] = $value;
+ }
+ }
+ }
+
+ // Loop through plugins
+ $pluginNames =
sfFinder::type('dir')->maxdepth(0)->relative()->not_name('.')->in(sfConfig::get('sf_plugins_dir'));
+ foreach ($pluginNames as $pluginName)
+ {
+ $this->logSection('i18n', sprintf('rectifying %s plugin strings',
$pluginName));
+
+ $messageSource =
sfMessageSource::factory($config['i18n']['param']['source'],
sfConfig::get('sf_plugins_dir').'/'.$pluginName.'/i18n');
+ $messageSource->setCulture($arguments['culture']);
+ $messageSource->load();
+
+ // If the current plugin source *doesn't* have a translation, then try
+ // and get translated value from $currentMessages
+ foreach($messageSource->read() as $catalogue => $translations)
+ {
+ foreach ($translations as $key => &$value)
+ {
+ if (0 == strlen(trim($value[0])) && isset($currentMessages[$key]))
+ {
+ $messageSource->update($key, $currentMessages[$key][0], $value[2]);
+ }
+ }
+ }
+
+ $messageSource->save();
+ }
+ }
+}
Copied: trunk/lib/task/i18n/i18nRemoveDuplicatesTask.class.php (from r10377,
trunk/lib/task/i18nRemoveDuplicatesTask.class.php)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/lib/task/i18n/i18nRemoveDuplicatesTask.class.php Thu Dec 8
09:28:49 2011 (r10378, copy of r10377,
trunk/lib/task/i18nRemoveDuplicatesTask.class.php)
@@ -0,0 +1,127 @@
+<?php
+
+/*
+ * This file is part of Qubit Toolkit.
+ *
+ * Qubit Toolkit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Qubit Toolkit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Qubit Toolkit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Restore i18n strings lost when XLIFF files were broken into plugin-specific
+ * directories
+ *
+ * @package symfony
+ * @subpackage task
+ * @author David Juhasz <[email protected]>
+ * @version SVN: $Id$
+ */
+class I18nRemoveDuplicatesTask extends sfBaseTask
+{
+ /**
+ * @see sfTask
+ */
+ protected function configure()
+ {
+ $this->addOptions(array(
+ // http://trac.symfony-project.org/ticket/8352
+ new sfCommandOption('application', null,
sfCommandOption::PARAMETER_REQUIRED, 'The application name', true),
+ new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED,
'The environment', 'cli'),
+ ));
+
+ $this->namespace = 'i18n';
+ $this->name = 'remove-duplicates';
+ $this->briefDescription = 'Delete duplicate source messages';
+
+ $this->detailedDescription = <<<EOF
+FIXME
+EOF;
+ }
+
+ /**
+ * @see sfTask
+ */
+ public function execute($arguments = array(), $options = array())
+ {
+ $this->logSection('i18n', sprintf('Removing duplicate i18n sources for the
"%s" application', $options['application']));
+
+ // Loop through plugins
+ $pluginNames =
sfFinder::type('dir')->maxdepth(0)->relative()->not_name('.')->in(sfConfig::get('sf_plugins_dir'));
+ foreach ($pluginNames as $pluginName)
+ {
+ $this->logSection('i18n', sprintf('Removing %s duplicates',
$pluginName));
+
+ foreach
(sfFinder::type('files')->in(sfConfig::get('sf_plugins_dir').'/'.$pluginName.'/i18n')
as $file)
+ {
+ self::deleteDuplicateSource($file);
+ }
+ }
+ }
+
+ public function deleteDuplicateSource($filename)
+ {
+ $modified = false;
+
+ // create a new dom, import the existing xml
+ $doc = new DOMDocument;
+ $doc->formatOutput = true;
+ $doc->preserveWhiteSpace = false;
+ $doc->load($filename);
+
+ $xpath = new DOMXPath($doc);
+
+ foreach ($xpath->query('//trans-unit') as $unit)
+ {
+ foreach ($xpath->query('./target', $unit) as $target)
+ {
+ break; // Only one target
+ }
+
+ foreach ($xpath->query('./source', $unit) as $source)
+ {
+ // If this is a duplicate source key, then delete it
+ if (isset($sourceStrings[$source->nodeValue]))
+ {
+ // If original target string is null, but *this* node has a valid
+ // translation
+ if (0 == strlen($sourceStrings[$source->nodeValue]->nodeValue) &&
+ 0 < strlen($target->nodeValue))
+ {
+ // Copy this translated string to the trans-unit node we are
keeping
+ $sourceStrings[$source->nodeValue]->nodeValue = $target->nodeValue;
+ }
+
+ // Remove duplicate
+ $unit->parentNode->removeChild($unit);
+ $modified = true;
+ }
+ else
+ {
+ $sourceStrings[$source->nodeValue] = $target;
+ }
+
+ break; // Only one source
+ }
+ }
+
+ // Update xliff file if modified
+ if ($modified)
+ {
+ $fileNode = $xpath->query('//file')->item(0);
+ $fileNode->setAttribute('date', @date('Y-m-d\TH:i:s\Z'));
+
+ $doc->save($filename);
+ }
+ }
+
+}
Copied: trunk/lib/task/i18n/i18nUpdateFixturesTask.class.php (from r10377,
trunk/lib/task/i18nUpdateFixturesTask.class.php)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/lib/task/i18n/i18nUpdateFixturesTask.class.php Thu Dec 8
09:28:49 2011 (r10378, copy of r10377,
trunk/lib/task/i18nUpdateFixturesTask.class.php)
@@ -0,0 +1,179 @@
+<?php
+
+/*
+ * This file is part of Qubit Toolkit.
+ *
+ * Qubit Toolkit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Qubit Toolkit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Qubit Toolkit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Restore i18n strings lost when XLIFF files were broken into plugin-specific
+ * directories
+ *
+ * @package symfony
+ * @subpackage task
+ * @author David Juhasz <[email protected]>
+ * @version SVN: $Id$
+ */
+class I18nUpdateFixturesTask extends sfBaseTask
+{
+ /**
+ * @see sfTask
+ */
+ protected function configure()
+ {
+ $this->addArguments(array(
+ new sfCommandArgument('path', sfCommandArgument::REQUIRED, 'Path for
xliff files'),
+ ));
+
+ $this->addOptions(array(
+ // http://trac.symfony-project.org/ticket/8352
+ new sfCommandOption('application', null,
sfCommandOption::PARAMETER_REQUIRED, 'The application name', true),
+ new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED,
'The environment', 'cli'),
+ new sfCommandOption('filename', 'f',
sfCommandOption::PARAMETER_OPTIONAL, 'Name of XLIFF files', 'fixtures.xml'),
+ ));
+
+ $this->namespace = 'i18n';
+ $this->name = 'update-fixtures';
+ $this->briefDescription = 'Reads XLIFF files from {{path}} and merges
translations to database fixture files';
+
+ $this->detailedDescription = <<<EOF
+Reads XLIFF files from {{path}} and merges translations to database fixture
files
+EOF;
+ }
+
+ /**
+ * @see sfTask
+ */
+ public function execute($arguments = array(), $options = array())
+ {
+ // Extract translation strings from XLIFF files
+ $translations = $this->extractTranslations($arguments, $options);
+
+ $this->updateFixtures($translations);
+ }
+
+ protected function extractTranslations($arguments = array(), $options =
array())
+ {
+ $translations = array();
+
+ $this->logSection('i18n', sprintf('Find XLIFF files named "%s"',
$options['filename']));
+
+ // Search for xliff files
+ $files =
sfFinder::type('file')->name($options['filename'])->in($arguments['path']);
+
+ if (0 == count($files))
+ {
+ $this->logSection('i18n', 'No valid files found. Please check path and
filename');
+
+ return;
+ }
+
+ // Extract translation strings
+ foreach ($files as $file)
+ {
+ $culture = self::getTargetCulture($file);
+ $xliff = new sfMessageSource_XLIFF(substr($file, 0, strrpos('/')));
+
+ if (!($messages = $xliff->loadData($file)))
+ {
+ continue;
+ }
+
+ // Build list of translations, keyed on source value
+ foreach ($messages as $source => $message)
+ {
+ if (0 < strlen($message[0]))
+ {
+ $translations[$source][$culture] = $message[0];
+ }
+ }
+ }
+
+ return $translations;
+ }
+
+ protected function updateFixtures($translations)
+ {
+ $this->logSection('i18n', 'Writing new translations to fixtures...');
+
+ // Search for YAML files
+ $fixturesDirs =
array_merge(array(sfConfig::get('sf_data_dir').'/fixtures'),
$this->configuration->getPluginSubPaths('/data/fixtures'));
+ $files = sfFinder::type('file')->name('*.yml')->in($fixturesDirs);
+
+ if (0 == count($files))
+ {
+ $this->logSection('i18n', 'Error: Couldn\'t find any fixture files to
write.');
+
+ return;
+ }
+
+ // Merge translations to YAML files in data/fixtures
+ foreach ($files as $file)
+ {
+ $modified = false;
+ $yaml = new sfYaml;
+ $fixtures = $yaml->load($file);
+
+ // Descend through fixtures hierarchy
+ foreach ($fixtures as $classname => &$fixture)
+ {
+ foreach ($fixture as $key => &$columns)
+ {
+ foreach ($columns as $column => &$value)
+ {
+ if (is_array($value) && isset($value['en']))
+ {
+ if (isset($translations[$value['en']]))
+ {
+ $value = array_merge($value, $translations[$value['en']]);
+
+ // Sort keys alphabetically
+ ksort($value);
+
+ $modified = true;
+ }
+ }
+ }
+ }
+ }
+
+ if ($modified)
+ {
+ $this->logSection('i18n', sprintf('Updating %s...', $file));
+
+ $contents = $yaml->dump($fixtures, 4);
+
+ if (0 < strlen($contents))
+ {
+ file_put_contents($file, $contents);
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ protected static function getTargetCulture($filename)
+ {
+ libxml_use_internal_errors(true);
+ if (!$xml = simplexml_load_file($filename))
+ {
+ return;
+ }
+ libxml_use_internal_errors(false);
+
+ return (string) $xml->file['target-language'];
+ }
+}
--
You received this message because you are subscribed to the Google Groups
"Qubit Toolkit Commits" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/qubit-commits?hl=en.