From ab92919b27ea75c25cc26d9f63d939b2c6673020 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Thu, 18 Nov 2010 19:00:13 +0000 Subject: [PATCH] ENHANCEMENT Allowing i18nTextCollector to discover entities in templates stored in themes/ directory (thanks nlou) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@113918 467b73ca-7a2a-4603-9d3b-597d59a354a9 --- .../Includes/i18nTestTheme1Include.ss | 4 + .../templates/Layout/i18nTestTheme1.ss | 5 + .../templates/i18nTestTheme1Main.ss | 3 + .../testtheme2/templates/i18nTestTheme2.ss | 3 + core/i18nTextCollector.php | 38 +++++- .../Includes/i18nTestTheme1Include.ss | 4 + .../templates/Layout/i18nTestTheme1.ss | 5 + .../templates/i18nTestTheme1Main.ss | 3 + .../testtheme2/templates/i18nTestTheme2.ss | 3 + tests/i18n/i18nTest.php | 4 - tests/i18n/i18nTextCollectorTest.php | 122 +++++++++++++++++- 11 files changed, 180 insertions(+), 14 deletions(-) create mode 100644 b/tests/i18n/_fakewebroot/themes/testtheme1/templates/Includes/i18nTestTheme1Include.ss create mode 100644 b/tests/i18n/_fakewebroot/themes/testtheme1/templates/Layout/i18nTestTheme1.ss create mode 100644 b/tests/i18n/_fakewebroot/themes/testtheme1/templates/i18nTestTheme1Main.ss create mode 100644 b/tests/i18n/_fakewebroot/themes/testtheme2/templates/i18nTestTheme2.ss create mode 100644 tests/i18n/_fakewebroot/themes/testtheme1/templates/Includes/i18nTestTheme1Include.ss create mode 100644 tests/i18n/_fakewebroot/themes/testtheme1/templates/Layout/i18nTestTheme1.ss create mode 100644 tests/i18n/_fakewebroot/themes/testtheme1/templates/i18nTestTheme1Main.ss create mode 100644 tests/i18n/_fakewebroot/themes/testtheme2/templates/i18nTestTheme2.ss diff --git a/b/tests/i18n/_fakewebroot/themes/testtheme1/templates/Includes/i18nTestTheme1Include.ss b/b/tests/i18n/_fakewebroot/themes/testtheme1/templates/Includes/i18nTestTheme1Include.ss new file mode 100644 index 000000000..6e3c15178 --- /dev/null +++ b/b/tests/i18n/_fakewebroot/themes/testtheme1/templates/Includes/i18nTestTheme1Include.ss @@ -0,0 +1,4 @@ +<% _t("i18nTestTheme1Include.WITHNAMESPACE", 'Theme1 Include Entity with Namespace') %> +<% _t("NONAMESPACE", 'Theme1 Include Entity without Namespace') %> +<% sprintf(_t('i18nTestTheme1Include.SPRINTFINCLUDENAMESPACE','Theme1 My include replacement: %s'),$TestProperty) %> +<% sprintf(_t('SPRINTFINCLUDENONAMESPACE','Theme1 My include replacement no namespace: %s'),$TestProperty) %> \ No newline at end of file diff --git a/b/tests/i18n/_fakewebroot/themes/testtheme1/templates/Layout/i18nTestTheme1.ss b/b/tests/i18n/_fakewebroot/themes/testtheme1/templates/Layout/i18nTestTheme1.ss new file mode 100644 index 000000000..78751cbfd --- /dev/null +++ b/b/tests/i18n/_fakewebroot/themes/testtheme1/templates/Layout/i18nTestTheme1.ss @@ -0,0 +1,5 @@ +<% _t('i18nTestTheme1.LAYOUTTEMPLATE',"Theme1 Layout Template") %> +<% _t('LAYOUTTEMPLATENONAMESPACE',"Theme1 Layout Template no namespace") %> +<% sprintf(_t('i18nTestTheme1.SPRINTFNAMESPACE','Theme1 My replacement: %s'),$TestProperty) %> +<% sprintf(_t('SPRINTFNONAMESPACE','Theme1 My replacement no namespace: %s'),$TestProperty) %> +<% include i18nTestTheme1Include %> \ No newline at end of file diff --git a/b/tests/i18n/_fakewebroot/themes/testtheme1/templates/i18nTestTheme1Main.ss b/b/tests/i18n/_fakewebroot/themes/testtheme1/templates/i18nTestTheme1Main.ss new file mode 100644 index 000000000..b1ea6444d --- /dev/null +++ b/b/tests/i18n/_fakewebroot/themes/testtheme1/templates/i18nTestTheme1Main.ss @@ -0,0 +1,3 @@ +<% _t('i18nTestTheme1.MAINTEMPLATE',"Theme1 Main Template") %> +$Layout +lonely _t() call that should be ignored \ No newline at end of file diff --git a/b/tests/i18n/_fakewebroot/themes/testtheme2/templates/i18nTestTheme2.ss b/b/tests/i18n/_fakewebroot/themes/testtheme2/templates/i18nTestTheme2.ss new file mode 100644 index 000000000..668b6be2c --- /dev/null +++ b/b/tests/i18n/_fakewebroot/themes/testtheme2/templates/i18nTestTheme2.ss @@ -0,0 +1,3 @@ +<% _t('i18nTestTheme2.MAINTEMPLATE',"Theme2 Main Template") %> +$Layout +lonely _t() call that should be ignored \ No newline at end of file diff --git a/core/i18nTextCollector.php b/core/i18nTextCollector.php index b4480069f..8edc3b253 100644 --- a/core/i18nTextCollector.php +++ b/core/i18nTextCollector.php @@ -13,7 +13,7 @@ * The collector needs to be run whenever you make new translatable * entities available. Please don't alter the arrays in language tables manually. * - * Usage through URL: http://localhost/dev/tasks/i18nTextCollectorTast + * Usage through URL: http://localhost/dev/tasks/i18nTextCollectorTask * Usage through URL (module-specific): http://localhost/dev/tasks/i18nTextCollectorTask/?module=mymodule * Usage on CLI: sake dev/tasks/i18nTextCollectorTask * Usage on CLI (module-specific): sake dev/tasks/i18nTextCollectorTask module=mymodule @@ -39,10 +39,10 @@ class i18nTextCollector extends Object { public $basePath; /** - * @var string $basePath The directory base on which the collector should create new lang folders and files. + * @var string $baseSavePath The directory base on which the collector should create new lang folders and files. * Usually the webroot set through {@link Director::baseFolder()}. * Can be overwritten for testing or export purposes. - * @todo Fully support changing of basePath through {@link SSViewer} and {@link ManifestBuilder} + * @todo Fully support changing of baseSavePath through {@link SSViewer} and {@link ManifestBuilder} */ public $baseSavePath; @@ -70,6 +70,7 @@ class i18nTextCollector extends Object { //Debug::message("Collecting text...", false); $modules = array(); + $themeFolders = array(); // A master string tables array (one mst per module) $entitiesByModule = array(); @@ -82,14 +83,39 @@ class i18nTextCollector extends Object { } else { $modules = scandir($this->basePath); } + + foreach($modules as $index => $module){ + if($module != 'themes') continue; + else { + $themes = scandir($this->basePath."/themes"); + if(count($themes)){ + foreach($themes as $theme) { + if(is_dir($this->basePath."/themes/".$theme) && substr($theme,0,1) != '.' && is_dir($this->basePath."/themes/".$theme."/templates")){ + $themeFolders[] = 'themes/'.$theme; + } + } + } + $themesInd = $index; + } + } + + if(isset($themesInd)) { + unset($modules[$themesInd]); + } + + $modules = array_merge($modules, $themeFolders); foreach($modules as $module) { - // Only search for calls in folder with a _config.php file (which means they are modules) + // Only search for calls in folder with a _config.php file (which means they are modules, including themes folder) $isValidModuleFolder = ( is_dir("$this->basePath/$module") && is_file("$this->basePath/$module/_config.php") && substr($module,0,1) != '.' + ) || ( + substr($module,0,7) == 'themes/' + && is_dir("$this->basePath/$module") ); + if(!$isValidModuleFolder) continue; // we store the master string tables @@ -122,7 +148,7 @@ class i18nTextCollector extends Object { /** * Build the module's master string table * - * @param string $module Module's name + * @param string $module Module's name or 'themes' */ protected function processModule($module) { $entitiesArr = array(); @@ -132,7 +158,7 @@ class i18nTextCollector extends Object { // Search for calls in code files if these exists if(is_dir("$this->basePath/$module/code")) { $fileList = $this->getFilesRecursive("$this->basePath/$module/code"); - } else if($module == 'sapphire') { + } else if($module == 'sapphire' || substr($module, 0, 7) == 'themes/') { // sapphire doesn't have the usual module structure, so we'll scan all subfolders $fileList = $this->getFilesRecursive("$this->basePath/$module"); } diff --git a/tests/i18n/_fakewebroot/themes/testtheme1/templates/Includes/i18nTestTheme1Include.ss b/tests/i18n/_fakewebroot/themes/testtheme1/templates/Includes/i18nTestTheme1Include.ss new file mode 100644 index 000000000..6e3c15178 --- /dev/null +++ b/tests/i18n/_fakewebroot/themes/testtheme1/templates/Includes/i18nTestTheme1Include.ss @@ -0,0 +1,4 @@ +<% _t("i18nTestTheme1Include.WITHNAMESPACE", 'Theme1 Include Entity with Namespace') %> +<% _t("NONAMESPACE", 'Theme1 Include Entity without Namespace') %> +<% sprintf(_t('i18nTestTheme1Include.SPRINTFINCLUDENAMESPACE','Theme1 My include replacement: %s'),$TestProperty) %> +<% sprintf(_t('SPRINTFINCLUDENONAMESPACE','Theme1 My include replacement no namespace: %s'),$TestProperty) %> \ No newline at end of file diff --git a/tests/i18n/_fakewebroot/themes/testtheme1/templates/Layout/i18nTestTheme1.ss b/tests/i18n/_fakewebroot/themes/testtheme1/templates/Layout/i18nTestTheme1.ss new file mode 100644 index 000000000..78751cbfd --- /dev/null +++ b/tests/i18n/_fakewebroot/themes/testtheme1/templates/Layout/i18nTestTheme1.ss @@ -0,0 +1,5 @@ +<% _t('i18nTestTheme1.LAYOUTTEMPLATE',"Theme1 Layout Template") %> +<% _t('LAYOUTTEMPLATENONAMESPACE',"Theme1 Layout Template no namespace") %> +<% sprintf(_t('i18nTestTheme1.SPRINTFNAMESPACE','Theme1 My replacement: %s'),$TestProperty) %> +<% sprintf(_t('SPRINTFNONAMESPACE','Theme1 My replacement no namespace: %s'),$TestProperty) %> +<% include i18nTestTheme1Include %> \ No newline at end of file diff --git a/tests/i18n/_fakewebroot/themes/testtheme1/templates/i18nTestTheme1Main.ss b/tests/i18n/_fakewebroot/themes/testtheme1/templates/i18nTestTheme1Main.ss new file mode 100644 index 000000000..b1ea6444d --- /dev/null +++ b/tests/i18n/_fakewebroot/themes/testtheme1/templates/i18nTestTheme1Main.ss @@ -0,0 +1,3 @@ +<% _t('i18nTestTheme1.MAINTEMPLATE',"Theme1 Main Template") %> +$Layout +lonely _t() call that should be ignored \ No newline at end of file diff --git a/tests/i18n/_fakewebroot/themes/testtheme2/templates/i18nTestTheme2.ss b/tests/i18n/_fakewebroot/themes/testtheme2/templates/i18nTestTheme2.ss new file mode 100644 index 000000000..668b6be2c --- /dev/null +++ b/tests/i18n/_fakewebroot/themes/testtheme2/templates/i18nTestTheme2.ss @@ -0,0 +1,3 @@ +<% _t('i18nTestTheme2.MAINTEMPLATE',"Theme2 Main Template") %> +$Layout +lonely _t() call that should be ignored \ No newline at end of file diff --git a/tests/i18n/i18nTest.php b/tests/i18n/i18nTest.php index fc7b75d5a..083556a17 100644 --- a/tests/i18n/i18nTest.php +++ b/tests/i18n/i18nTest.php @@ -49,10 +49,6 @@ class i18nTest extends SapphireTest { $_TEMPLATE_MANIFEST['i18nTestModuleInclude.ss'] = array( 'Includes' => $this->alternateBasePath . '/i18ntestmodule/templates/Includes/i18nTestModuleInclude.ss', ); - $_TEMPLATE_MANIFEST['i18nTestModule.ss'] = array( - 'main' => $this->alternateBasePath . '/i18ntestmodule/templates/i18nTestModule.ss', - 'Layout' => $this->alternateBasePath . '/i18ntestmodule/templates/Layout/i18nTestModule.ss', - ); $this->originalLocale = i18n::get_locale(); } diff --git a/tests/i18n/i18nTextCollectorTest.php b/tests/i18n/i18nTextCollectorTest.php index f7c98374d..2610314e6 100644 --- a/tests/i18n/i18nTextCollectorTest.php +++ b/tests/i18n/i18nTextCollectorTest.php @@ -44,9 +44,13 @@ class i18nTextCollectorTest extends SapphireTest { $_TEMPLATE_MANIFEST['i18nTestModuleInclude.ss'] = array( 'Includes' => $this->alternateBasePath . '/i18ntestmodule/templates/Includes/i18nTestModuleInclude.ss', ); - $_TEMPLATE_MANIFEST['i18nTestModule.ss'] = array( - 'main' => $this->alternateBasePath . '/i18ntestmodule/templates/i18nTestModule.ss', - 'Layout' => $this->alternateBasePath . '/i18ntestmodule/templates/Layout/i18nTestModule.ss', + + $_TEMPLATE_MANIFEST['i18nTestTheme1.ss'] = array( + 'main' => $this->alternateBasePath . '/themes/testtheme1/templates/i18nTestTheme1.ss', + 'Layout' => $this->alternateBasePath . '/themes/testtheme1/templates/Layout/i18nTestTheme1.ss', + ); + $_TEMPLATE_MANIFEST['i18nTestTheme1Include.ss'] = array( + 'Includes' => $this->alternateBasePath . '/themes/testtheme1/templates/Includes/i18nTestTheme1Include.ss', ); } @@ -406,6 +410,60 @@ PHP; ); } + function testCollectFromThemesTemplates() { + $c = new i18nTextCollector(); + + $templateFilePath = $this->alternateBasePath . '/themes/testtheme1/templates/Layout/i18nTestTheme1.ss'; + $html = file_get_contents($templateFilePath); + $matches = $c->collectFromTemplate($html, 'themes/testtheme1', 'i18nTestTheme1.ss'); + // all entities from i18nTestTheme1.ss + $this->assertEquals( + $matches['i18nTestTheme1.LAYOUTTEMPLATE'], + array('Theme1 Layout Template', null, null) + ); + + $this->assertArrayHasKey('i18nTestTheme1.ss.LAYOUTTEMPLATENONAMESPACE', $matches); + $this->assertEquals( + $matches['i18nTestTheme1.ss.LAYOUTTEMPLATENONAMESPACE'], + array('Theme1 Layout Template no namespace', null, null) + ); + + $this->assertEquals( + $matches['i18nTestTheme1.SPRINTFNAMESPACE'], + array('Theme1 My replacement: %s', null, null) + ); + + $this->assertArrayHasKey('i18nTestTheme1.ss.SPRINTFNONAMESPACE', $matches); + $this->assertEquals( + $matches['i18nTestTheme1.ss.SPRINTFNONAMESPACE'], + array('Theme1 My replacement no namespace: %s', null, null) + ); + + // all entities from i18nTestTheme1Include.ss + $this->assertEquals( + $matches['i18nTestTheme1Include.WITHNAMESPACE'], + array('Theme1 Include Entity with Namespace', null, null) + ); + + $this->assertArrayHasKey('i18nTestTheme1Include.ss.NONAMESPACE', $matches); + $this->assertEquals( + $matches['i18nTestTheme1Include.ss.NONAMESPACE'], + array('Theme1 Include Entity without Namespace', null, null) + ); + + + $this->assertEquals( + $matches['i18nTestTheme1Include.SPRINTFINCLUDENAMESPACE'], + array('Theme1 My include replacement: %s', null, null) + ); + + $this->assertArrayHasKey('i18nTestTheme1Include.ss.SPRINTFINCLUDENONAMESPACE', $matches); + $this->assertEquals( + $matches['i18nTestTheme1Include.ss.SPRINTFINCLUDENONAMESPACE'], + array('Theme1 My include replacement no namespace: %s', null, null) + ); + } + function testCollectFromFilesystemAndWriteMasterTables() { $defaultlocal = i18n::default_locale(); $local = i18n::get_locale(); @@ -426,7 +484,6 @@ PHP; ); $moduleLangFileContent = file_get_contents($moduleLangFile); - $this->assertContains( "\$lang['en_US']['i18nTestModule']['ADDITION'] = 'Addition';", $moduleLangFileContent @@ -471,6 +528,63 @@ PHP; "\$lang['en_US']['i18nOtherModule']['MAINTEMPLATE'] = 'Main Template Other Module';", $otherModuleLangFileContent ); + + // testtheme1 + $theme1LangFile = "{$this->alternateBaseSavePath}/themes/testtheme1/lang/" . $c->getDefaultLocale() . '.php'; + $this->assertTrue( + file_exists($theme1LangFile), + 'Master theme language file can be written to themes/testtheme1 /lang folder' + ); + $theme1LangFileContent = file_get_contents($theme1LangFile); + $this->assertContains( + "\$lang['en_US']['i18nTestTheme1']['MAINTEMPLATE'] = 'Theme1 Main Template';", + $theme1LangFileContent + ); + $this->assertContains( + "\$lang['en_US']['i18nTestTheme1']['LAYOUTTEMPLATE'] = 'Theme1 Layout Template';", + $theme1LangFileContent + ); + $this->assertContains( + "\$lang['en_US']['i18nTestTheme1']['SPRINTFNAMESPACE'] = 'Theme1 My replacement: %s';", + $theme1LangFileContent + ); + $this->assertContains( + "\$lang['en_US']['i18nTestTheme1.ss']['LAYOUTTEMPLATENONAMESPACE'] = 'Theme1 Layout Template no namespace';", + $theme1LangFileContent + ); + $this->assertContains( + "\$lang['en_US']['i18nTestTheme1.ss']['SPRINTFNONAMESPACE'] = 'Theme1 My replacement no namespace: %s';", + $theme1LangFileContent + ); + + $this->assertContains( + "\$lang['en_US']['i18nTestTheme1Include']['SPRINTFINCLUDENAMESPACE'] = 'Theme1 My include replacement: %s';", + $theme1LangFileContent + ); + $this->assertContains( + "\$lang['en_US']['i18nTestTheme1Include']['WITHNAMESPACE'] = 'Theme1 Include Entity with Namespace';", + $theme1LangFileContent + ); + $this->assertContains( + "\$lang['en_US']['i18nTestTheme1Include.ss']['NONAMESPACE'] = 'Theme1 Include Entity without Namespace';", + $theme1LangFileContent + ); + $this->assertContains( + "\$lang['en_US']['i18nTestTheme1Include.ss']['SPRINTFINCLUDENONAMESPACE'] = 'Theme1 My include replacement no namespace: %s';", + $theme1LangFileContent + ); + + // testtheme2 + $theme2LangFile = "{$this->alternateBaseSavePath}/themes/testtheme2/lang/" . $c->getDefaultLocale() . '.php'; + $this->assertTrue( + file_exists($theme2LangFile), + 'Master theme language file can be written to themes/testtheme2 /lang folder' + ); + $theme2LangFileContent = file_get_contents($theme2LangFile); + $this->assertContains( + "\$lang['en_US']['i18nTestTheme2']['MAINTEMPLATE'] = 'Theme2 Main Template';", + $theme2LangFileContent + ); i18n::set_locale($local); //set the locale to the US locale expected in the asserts + i18n::set_default_locale($defaultlocal);