From cbcee57496bdcfe62f1fa829780585fbbfe478eb Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Sat, 14 Apr 2012 01:01:59 +0200 Subject: [PATCH] ENHANCEMENT New i18nTextCollector_Writer_RailsYaml --- docs/en/topics/i18n.md | 39 ++++++++++++++++++-- i18n/i18nTextCollector.php | 54 +++++++++++++++++++++++++++- tests/i18n/i18nTextCollectorTest.php | 20 +++++++++++ 3 files changed, 110 insertions(+), 3 deletions(-) diff --git a/docs/en/topics/i18n.md b/docs/en/topics/i18n.md index f60453cfc..42fc371db 100644 --- a/docs/en/topics/i18n.md +++ b/docs/en/topics/i18n.md @@ -220,13 +220,35 @@ If you want to run the text collector for just one module you can use the 'modul **Note**: You'll need to install PHPUnit to run the text collector (see [testing-guide](/topics/testing)). -## Language definitions +## Language definitions (3.x) Each module can have one language table per locale, stored by convention in the `lang/` subfolder. The translation is powered by `[Zend_Translate](http://framework.zend.com/manual/en/zend.translate.html)`, which supports different translation adapters, dealing with different storage formats. -In SilverStripe 2.x, there tables are just PHP files with array notations, +By default, SilverStripe 3.x uses a YAML format (through the [Zend_Translate_RailsYAML adapter](https://github.com/chillu/zend_translate_railsyaml)). + +Example: sapphire/lang/en.yml (extract) + + :::yml + en: + ImageUploader: + Attach: 'Attach %s' + FileIFrameField: + NOTEADDFILES: 'You can add files once you have saved for the first time.' + +Translation table: sapphire/lang/de.yml (extract) + + :::yml + de: + ImageUploader: + ATTACH: '%s anhängen' + FileIframeField: + NOTEADDFILES: 'Sie können Dateien hinzufügen sobald Sie das erste mal gespeichert haben' + +## Language definitions (2.x) + +In SilverStripe 2.x, the tables are just PHP files with array notations, stored based on their locale name (e.g. "en_US.php"). Example: framework/lang/en_US.php (extract) @@ -247,6 +269,19 @@ Translation table: framework/lang/de_DE.php (extract) $lang['de_DE']['ImageUploader']['ATTACH'] = '%s anhängen'; $lang['de_DE']['FileIframeField']['NOTEADDFILES'] = 'Sie können Dateien hinzufügen sobald Sie das erste mal gespeichert haben'; +In order to enable usage of PHP language definitions in 3.x, you need to register a legacy adapter +in your `mysite/_config.php`: + + :::php + i18n::register_translator( + new Zend_Translate(array( + 'adapter' => 'i18nSSLegacyAdapter', + 'locale' => i18n::default_locale(), + 'disableNotices' => true, + )), + 'legacy', + 9 // priority lower than standard translator + ); ## Javascript Usage diff --git a/i18n/i18nTextCollector.php b/i18n/i18nTextCollector.php index 8f9cc5aef..379d43a49 100644 --- a/i18n/i18nTextCollector.php +++ b/i18n/i18nTextCollector.php @@ -61,7 +61,7 @@ class i18nTextCollector extends Object { } public function getWriter() { - if(!$this->writer) $this->writer = new i18nTextCollector_Writer_Php(); + if(!$this->writer) $this->writer = new i18nTextCollector_Writer_RailsYaml(); return $this->writer; } @@ -452,3 +452,55 @@ class i18nTextCollector_Writer_Php implements i18nTextCollector_Writer { return $php; } } + +/** + * Writes files compatible with {@link i18nRailsYamlAdapter}. + */ +class i18nTextCollector_Writer_RailsYaml implements i18nTextCollector_Writer { + + public function write($entities, $locale, $path) { + $content = ''; + + // Create folder for lang files + $langFolder = $path . '/lang'; + if(!file_exists($langFolder)) { + Filesystem::makeFolder($langFolder, Filesystem::$folder_create_mask); + touch($langFolder . '/_manifest_exclude'); + } + + // Open the English file and write the Master String Table + $langFile = $langFolder . '/' . $locale . '.yml'; + if($fh = fopen($langFile, "w")) { + fwrite($fh, $this->getYaml($entities,$locale)); + fclose($fh); + } else { + throw new LogicException("Cannot write language file! Please check permissions of $langFile"); + } + + return true; + } + + public function getYaml($entities, $locale) { + if(!class_exists('sfYamlDumper', false)) require_once 'thirdparty/symfony-yaml/lib/sfYamlDumper.php'; + + // Unflatten array + $entitiesNested = array(); + foreach($entities as $entity => $spec) { + // Legacy support: Don't count *.ss as namespace + $entity = preg_replace('/\.ss\./', '___ss.', $entity); + $parts = explode('.', $entity); + $currLevel = &$entitiesNested; + while($part = array_shift($parts)) { + $part = str_replace('___ss', '.ss', $part); + if(!isset($currLevel[$part])) $currLevel[$part] = array(); + $currLevel = &$currLevel[$part]; + } + $currLevel = $spec[0]; + } + + // Write YAML + $yamlHandler = new sfYaml(); + // TODO Dumper can't handle YAML comments, so the context information is currently discarded + return $yamlHandler->dump(array($locale => $entitiesNested), 99); + } +} \ No newline at end of file diff --git a/tests/i18n/i18nTextCollectorTest.php b/tests/i18n/i18nTextCollectorTest.php index 4296cb318..14e25cf6c 100644 --- a/tests/i18n/i18nTextCollectorTest.php +++ b/tests/i18n/i18nTextCollectorTest.php @@ -329,6 +329,26 @@ PHP; $php ); } + + /** + * @todo Should be in a separate test suite, but don't want to duplicate setup logic + */ + function testYamlWriter() { + $writer = new i18nTextCollector_Writer_RailsYaml(); + $entities = array( + 'Level1.Level2.EntityName' => array('Text', 'Context'), + 'Level1.OtherEntityName' => array('Other Text', 'Other Context'), + ); + $yaml = <<assertEquals($yaml, $writer->getYaml($entities, 'de')); + } function testCollectFromIncludedTemplates() { $c = new i18nTextCollector();