From 0872f873588f6a99eba6b9933aba7e9ce43d50ca Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Sat, 15 Sep 2007 00:21:51 +0000 Subject: [PATCH] bfojcapell: Renaming of functions and new function prototype of the translator function (merged from branches/gsoc) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@41835 467b73ca-7a2a-4603-9d3b-597d59a354a9 --- _config.php | 2 +- core/Core.php | 23 +-- core/SSViewer.php | 7 +- core/i18n.php | 469 ++++++++++++++++++++++++---------------------- 4 files changed, 254 insertions(+), 247 deletions(-) diff --git a/_config.php b/_config.php index 0e6bf6b36..bb0e6b178 100644 --- a/_config.php +++ b/_config.php @@ -56,5 +56,5 @@ Authenticator::registerAuthenticator('OpenIDAuthenticator'); /** * Define a default language different than english */ -//LocaleAPI::setLocale('ca_AD'); +//LocaleAPI::set_locale('ca_AD'); ?> \ No newline at end of file diff --git a/core/Core.php b/core/Core.php index 7e70f2447..32f97836a 100755 --- a/core/Core.php +++ b/core/Core.php @@ -86,8 +86,8 @@ function stripslashes_recursively(&$array) { /** * This is the main translator function. Returns the string defined by $class and $entity according to the currently set locale * - * @param string $class Class where the entity was defined. It acts as a namespace. - * @param string $entity Entity that identifies the string inside the namespace. + * @param string $entity Entity that identifies the string. It must be in the form "Namespace.Entity" where Namespace will be usually + * the class name where this string is used and Entity identifies the string inside the namespace. * @param string $string The original string itself. In a usual call this is a mandatory parameter, but if you are reusing a string which * has already been "declared" (using another call to this function, with the same class and entity), you can omit it. * @param string $priority Optional parameter to set a translation priority. If a string is widely used, should have a high priority (PR_HIGH), @@ -95,19 +95,16 @@ function stripslashes_recursively(&$array) { * You can use PR_MEDIUM as well. Leaving this field blank will be interpretated as a "normal" priority (less than PR_MEDIUM). * @param string $context If the string can be difficult to translate by any reason, you can help translators with some more info using this param * - * @return string The translated string, according to the currently set locale {@link i18n::setLocale()} + * @return string The translated string, according to the currently set locale {@link i18n::set_locale()} */ -function _($class, $entity, $string = "", $priority = 40, $context = "") { +function _t($entity, $string = "", $priority = 40, $context = "") { global $lang; - $locale = i18n::getLocale(); - $class = ereg_replace('.*([/\\]+)', "", $class); - if(substr($class, -4) == '.php') - $class = substr($class, 0, -4); - - if(isset($lang[$locale][$class]) == false) - i18n::includeByClass($class); - - $transEntity = $lang[i18n::getLocale()][$class][$entity]; + $locale = i18n::get_locale(); + $entityParts = explode('.',$entity); + $realEntity = array_pop($entityParts); + $class = implode('.',$entityParts); + if(!isset($lang[$locale][$class])) i18n::include_by_class($class); + $transEntity = $lang[i18n::get_locale()][$class][$realEntity]; return (is_array($transEntity) ? $transEntity[0] : $transEntity); } diff --git a/core/SSViewer.php b/core/SSViewer.php index 510a4fc51..44355236d 100644 --- a/core/SSViewer.php +++ b/core/SSViewer.php @@ -154,7 +154,7 @@ class SSViewer extends Object { if(isset($_GET['debug_profile'])) Profiler::mark("SSViewer::process - compile", " for $template"); $content = file_get_contents($template); - $content = SSViewer::parseTemplateContent($content, $template); + $content = SSViewer::parseTemplateContent($content); $fh = fopen($cacheFile,'w'); fwrite($fh, $content); @@ -199,7 +199,7 @@ class SSViewer extends Object { return $output; } - static function parseTemplateContent($content, $template="") { + static function parseTemplateContent($content) { while(true) { $oldContent = $content; $content = preg_replace_callback('/<' . '% include +([A-Za-z0-9_]+) +%' . '>/', create_function( @@ -282,8 +282,7 @@ class SSViewer extends Object { $content = ereg_replace('<' . '% +end_if +%' . '>', '', $content); // i18n - ereg('.*[\/](.*)',$template,$path); - $content = ereg_replace('<' . '% +_\(([^)]*)\) +%' . '>', '', $content); + $content = ereg_replace('<' . '% +_t\((([^)]|\)[^;])*)\); +%' . '>', '', $content); // isnt valid html? !? $content = ereg_replace('<' . '% +base_tag +%' . '>', '', $content); diff --git a/core/i18n.php b/core/i18n.php index ab2e597c0..b3e1aa74f 100755 --- a/core/i18n.php +++ b/core/i18n.php @@ -1,230 +1,241 @@ - - */ - -/** - * Priorities definition. These constants are used in calls to _() as an optional argument - */ -define('PR_HIGH',100); -define('PR_MEDIUM',50); -define('PR_LOW',10); - -class i18n extends Controller { - - /** - * This static variable is used to store the current defined locale. Default value is 'en' - */ - static $currentlocale = 'en'; - - /** - * This is the main method to build the master string tables with the original strings. - * It will search for existent modules that use the i18n feature, parse the _() calls - * and write the resultant files in the lang folder of each module. - */ - static function textCollector() { - - if (!Permission::check("ADMIN")) die("You must be an admin to enable text collector mode"); - echo "Collecting text...

"; - - //Calculate base directory - $baseDir = Director::baseFolder(); - - //Search for and process existent modules, or use the passed one instead - if (!isset($_GET['module'])) { - $topLevel = scandir($baseDir); - foreach($topLevel as $module) { - i18n::processModule($baseDir, $module); - } - } else { - i18n::processModule($baseDir, $_GET['module']); - } - - echo "Done!"; - - } - - /** - * Searches for all the files in a given module - * - * @param string $baseDir Silverstripe's base directory - * @param string $module Module's name - */ - private static function processModule($baseDir, $module) { - if(is_dir("$baseDir/$module") && !in_array($module, array('sapphire','jsparty','assets')) && substr($module,0,1) != '.') { - i18n::getFilesRec("$baseDir/$module/code", $fileList); - foreach($fileList as $index => $file) { - $mst .= i18n::reportCallsCode($index, $file); - } - $fileList = NULL; - i18n::getFilesRec("$baseDir/$module/templates", $fileList); - foreach($fileList as $index => $file) { - $mst .= i18n::reportCallsTpl($index, $file); - } - if ($mst) { - // Create folder for lang files - $langFolder = $baseDir . '/' . $module . '/lang'; - if(!file_exists($baseDir. '/' . $module . '/lang')) { - mkdir($langFolder); - } - - // Open the English file and write the Master String Table - if($fh = fopen($langFolder . '/en.php', "w")) { - fwrite($fh, ""); - fclose($fh); - echo "Created file: $langFolder/en.php
"; - - } else { - die("Cannot write language file! Please check permissions of $langFolder/en.php"); - } - } - } - } - - /** - * Helper function that searches for potential files to be parsed - * - * @param string $folder base directory to scan (will scan recursively) - * @param array $fileList Array where potential files will be added to - */ - private static function getFilesRec($folder, &$fileList) { - $items = scandir($folder); - if($items) foreach($items as $item) { - if(substr($item,0,1) == '.') continue; - if(substr($item,-4) == '.php') $fileList[substr($item,0,-4)] = "$folder/$item"; - else if(substr($item,-3) == '.ss') $fileList[$item] = "$folder/$item"; - else if(is_dir("$folder/$item")) i18n::getFilesRec("$folder/$item", $fileList); - } - } - - /** - * Look for calls to the underscore function in php files and build our MST - * - * @param string $index Classname used to namespace strings - * @param string $file Path to the file to be parsed - * @return string Built Master String Table from this file - */ - private static function reportCallsCode($index, $file) { - static $callMap; - $content = file_get_contents($file); - while (ereg('_\(([^$][^,"\']*|"[^,]*"|\'[^,]*\')(,[^$][^,]*)(,[^$][^,)]*)(,[^,)]*)?(,[^)]*)?\)',$content,$regs)) { - - $class = ($regs[1] == '__FILE__' ? $index : $regs[1]); - $entity = substr($regs[2],2,-1); - - if ($callMap[$class.'--'.$entity]) echo "Warning! Redeclaring entity $entity in file $file
"; - - $mst .= '$lang[\'en\'][\'' . $class . '\'][\'' . substr($regs[2],2,-1) . '\'] = '; - if ($regs[4]) { - $mst .= "array(\n\t'" . substr($regs[3],2,-1) . "',\n\t" . substr($regs[4],1); - if ($regs[5]) $mst .= ",\n\t'" . substr($regs[5],2,-1) . '\''; - $mst .= "\n);"; - } else $mst .= '\'' . substr($regs[3],2,-1) . '\';'; - $mst .= "\n"; - $content = str_replace($regs[0],"",$content); - - $callMap[$class.'--'.$entity] = $regs[3]; - } - - return $mst; - } - - /** - * Look for calls to the underscore function in template files and build our MST - * Template version - no "class" argument - * - * @param string $index Index used to namespace strings - * @param string $file Path to the file to be parsed - * @return string Built Master String Table from this file - */ - private static function reportCallsTpl($index, $file) { - static $callMap; - $content = file_get_contents($file); - while (ereg('_\(([^$][^,"\']*|"[^,]*"|\'[^,]*\')(,[^$][^,)]*)(,[^,)]*)?(,[^)]*)?\)',$content,$regs)) { - - $entity = substr($regs[1],2,-1); - - if ($callMap[$index.'--'.$entity]) echo "Warning! Redeclaring entity $entity in file $file
"; - - $mst .= '$lang[\'en\'][\'' . $index . '\'][\'' . substr($regs[1],1,-1) . '\'] = '; - if ($regs[3]) { - $mst .= "array(\n\t'" . substr($regs[2],2,-1) . "',\n\t" . substr($regs[3],1); - if ($regs[4]) $mst .= ",\n\t'" . substr($regs[4],2,-1) . '\''; - $mst .= "\n);"; - } else $mst .= '\'' . substr($regs[2],2,-1) . '\';'; - $mst .= "\n"; - $content = str_replace($regs[0],"",$content); - - $callMap[$index.'--'.$entity] = $regs[3]; - } - - return $mst; - } - - /** - * Set the current locale - * See http://unicode.org/cldr/data/diff/supplemental/languages_and_territories.html for a list of possible locales - * - * @param string $locale Locale to be set - */ - static function setLocale($locale) { - if ($locale) i18n::$currentlocale = $locale; - } - - /** - * Get the current locale - * - * @return string Current locale in the system - */ - static function getLocale() { - return i18n::$currentlocale; - } - - /** - * Includes all available language files for a certain defined locale - * - * @param string $locale All resources from any module in locale $locale will be loaded - */ - static function includeByLocale($locale) { - if (file_exists($file = Director::getAbsFile("cms/lang/$locale.php"))) include_once($file); - $topLevel = array_diff(scandir(Director::baseFolder()),array('cms')); - foreach($topLevel as $module) { - if (file_exists($file = Director::getAbsFile("$module/lang/$locale.php"))) { - include_once($file); - } - } - } - - /** - * Given a class name (a "locale namespace"), will search for its module and, if available, - * will load the resources for the currently defined locale. - * If not available, the original English resource will be loaded instead (to avoid blanks) - * - * @param string $class Resources for this class will be included, according to the set locale. - */ - static function includeByClass($class) { - if (substr($class,-3) == '.ss') { - global $_TEMPLATE_MANIFEST; - $path = current($_TEMPLATE_MANIFEST[substr($class,0,-3)]); - ereg('.*/([^/]+)/templates/',$path,$module); - } - else { - global $_CLASS_MANIFEST; - $path = $_CLASS_MANIFEST[$class]; - ereg('.*/([^/]+)/code/',$path,$module); - } - if (file_exists($file = Director::getAbsFile("{$module[1]}/lang/". i18n::getLocale() . '.php'))) { - include_once($file); - } else if (i18n::getLocale() != 'en') { - i18n::setLocale('en'); - i18n::includeByClass($class); - } else { - user_error("Locale file $file should exist", E_USER_WARNING); - } - } -} - + + */ + +/** + * Priorities definition. These constants are used in calls to _() as an optional argument + */ +define('PR_HIGH',100); +define('PR_MEDIUM',50); +define('PR_LOW',10); + +class i18n extends Controller { + + /** + * This static variable is used to store the current defined locale. Default value is 'en_US' + */ + static $currentlocale = 'en_US'; + + /** + * This is the main method to build the master string tables with the original strings. + * It will search for existent modules that use the i18n feature, parse the _() calls + * and write the resultant files in the lang folder of each module. + */ + static function text_collector() { + + if (!Permission::check("ADMIN")) die("You must be an admin to enable text collector mode"); + echo "Collecting text...

"; + + //Calculate base directory + $baseDir = Director::baseFolder(); + + //Search for and process existent modules, or use the passed one instead + if (!isset($_GET['module'])) { + $topLevel = scandir($baseDir); + foreach($topLevel as $module) { + i18n::process_module($baseDir, $module); + } + } else { + i18n::process_module($baseDir, $_GET['module']); + } + + echo "Done!"; + + } + + /** + * Searches for all the files in a given module + * + * @param string $baseDir Silverstripe's base directory + * @param string $module Module's name + */ + private static function process_module($baseDir, $module) { + if(is_dir("$baseDir/$module") && !in_array($module, array('sapphire','jsparty','assets')) && substr($module,0,1) != '.') { + i18n::get_files_rec("$baseDir/$module/code", $fileList); + $mst = ''; + foreach($fileList as $file) { + $mst .= i18n::report_calls_code($file); + } + $fileList = NULL; + i18n::get_files_rec("$baseDir/$module/templates", $fileList); + foreach($fileList as $index => $file) { + $mst .= i18n::report_calls_tpl($index, $file); + } + if ($mst) { + // Create folder for lang files + $langFolder = $baseDir . '/' . $module . '/lang'; + if(!file_exists($baseDir. '/' . $module . '/lang')) { + mkdir($langFolder); + } + + // Open the English file and write the Master String Table + if($fh = fopen($langFolder . '/en_US.php', "w")) { + fwrite($fh, ""); + fclose($fh); + echo "Created file: $langFolder/en_US.php
"; + + } else { + die("Cannot write language file! Please check permissions of $langFolder/en_US.php"); + } + } + } + } + + /** + * Helper function that searches for potential files to be parsed + * + * @param string $folder base directory to scan (will scan recursively) + * @param array $fileList Array where potential files will be added to + */ + private static function get_files_rec($folder, &$fileList) { + $items = scandir($folder); + if($items) foreach($items as $item) { + if(substr($item,0,1) == '.') continue; + if(substr($item,-4) == '.php') $fileList[substr($item,0,-4)] = "$folder/$item"; + else if(substr($item,-3) == '.ss') $fileList[$item] = "$folder/$item"; + else if(is_dir("$folder/$item")) i18n::get_files_rec("$folder/$item", $fileList); + } + } + + /** + * Look for calls to the underscore function in php files and build our MST + * + * @param string $file Path to the file to be parsed + * @return string Built Master String Table from this file + */ + private static function report_calls_code($file) { + static $callMap; + $content = file_get_contents($file); + $mst = ''; + while (ereg('_t[[:space:]]*\([[:space:]]*("[^,]*"|\\\'[^,]*\\\')[[:space:]]*,[[:space:]]*("([^"]|\\\")*"|\'([^\']|\\\\\')*\')([[:space:]]*,[[:space:]]*[^,)]*)?([[:space:]]*,[[:space:]]*("([^"]|\\\")*"|\'([^\']|\\\\\')*\'))?[[:space:]]*\)', $content, $regs)) { + $entityParts = explode('.',substr($regs[1],1,-1)); + $entity = array_pop($entityParts); + $class = implode('.',$entityParts); + + if (isset($callMap[$class.'--'.$entity])) echo "Warning! Redeclaring entity $entity in file $file
"; + + $mst .= '$lang[\'en_US\'][\'' . $class . '\'][\'' . $entity . '\'] = '; + if ($regs[5]) { + $mst .= "array(\n\t'" . substr($regs[2],1,-1) . "',\n\t" . substr($regs[5],1); + if ($regs[6]) { + if (substr($regs[6],1,1) == '"') $regs[6] = addcslashes($regs[6],'\''); + $mst .= ",\n\t'" . substr($regs[6],2,-1) . '\''; + } + $mst .= "\n);"; + } else $mst .= '\'' . substr($regs[2],1,-1) . '\';'; + $mst .= "\n"; + $content = str_replace($regs[0],"",$content); + + $callMap[$class.'--'.$entity] = $regs[2]; + } + + return $mst; + } + + /** + * Look for calls to the underscore function in template files and build our MST + * Template version - no "class" argument + * + * @param string $index Index used to namespace strings + * @param string $file Path to the file to be parsed + * @return string Built Master String Table from this file + */ + private static function report_calls_tpl($index, $file) { + static $callMap; + $content = file_get_contents($file); + $mst = ''; + while (ereg('_t[[:space:]]*\([[:space:]]*("[^,]*"|\\\'[^,]*\\\')[[:space:]]*,[[:space:]]*("([^"]|\\\")*"|\'([^\']|\\\\\')*\')([[:space:]]*,[[:space:]]*[^,)]*)?([[:space:]]*,[[:space:]]*("([^"]|\\\")*"|\'([^\']|\\\\\')*\'))?[[:space:]]*\)',$content,$regs)) { + + $entityParts = explode('.',substr($regs[1],1,-1)); + $entity = array_pop($entityParts); + + // Entity redeclaration check + if (isset($callMap[$index.'--'.$entity])) echo "Warning! Redeclaring entity $entity in file $file
"; + + if (substr($regs[2],0,1) == '"') $regs[2] = addcslashes($regs[2],'\''); + $mst .= '$lang[\'en_US\'][\'' . $index . '\'][\'' . $entity . '\'] = '; + if ($regs[5]) { + $mst .= "array(\n\t'" . substr($regs[2],1,-1) . "',\n\t" . substr($regs[5],1); + if ($regs[6]) { + if (substr($regs[6],1,1) == '"') $regs[6] = addcslashes($regs[6],'\'\\'); + $mst .= ",\n\t'" . substr($regs[6],2,-1) . '\''; + } + $mst .= "\n);"; + } else $mst .= '\'' . substr($regs[2],2,-1) . '\';'; + $mst .= "\n"; + $content = str_replace($regs[0],"",$content); + + $callMap[$index.'--'.$entity] = $regs[3]; + } + + return $mst; + } + + /** + * Set the current locale + * See http://unicode.org/cldr/data/diff/supplemental/languages_and_territories.html for a list of possible locales + * + * @param string $locale Locale to be set + */ + static function set_locale($locale) { + if ($locale) i18n::$currentlocale = $locale; + } + + /** + * Get the current locale + * + * @return string Current locale in the system + */ + static function get_locale() { + return i18n::$currentlocale; + } + + /** + * Includes all available language files for a certain defined locale + * + * @param string $locale All resources from any module in locale $locale will be loaded + */ + static function include_by_locale($locale) { + if (file_exists($file = Director::getAbsFile("cms/lang/$locale.php"))) include_once($file); + $topLevel = array_diff(scandir(Director::baseFolder()),array('cms')); + foreach($topLevel as $module) { + if (file_exists($file = Director::getAbsFile("$module/lang/$locale.php"))) { + include_once($file); + } + } + } + + /** + * Given a class name (a "locale namespace"), will search for its module and, if available, + * will load the resources for the currently defined locale. + * If not available, the original English resource will be loaded instead (to avoid blanks) + * + * @param string $class Resources for this class will be included, according to the set locale. + */ + static function include_by_class($class) { + if (substr($class,-3) == '.ss') { + global $_TEMPLATE_MANIFEST; + $path = current($_TEMPLATE_MANIFEST[substr($class,0,-3)]); + ereg('.*/([^/]+)/templates/',$path,$module); + } + else { + global $_CLASS_MANIFEST; + $path = $_CLASS_MANIFEST[$class]; + ereg('.*/([^/]+)/code/',$path,$module); + } + if (file_exists($file = Director::getAbsFile("{$module[1]}/lang/". i18n::get_locale() . '.php'))) { + include_once($file); + } else if (i18n::get_locale() != 'en_US') { + i18n::set_locale('en_US'); + i18n::include_by_class($class); + } else { + user_error("Locale file $file should exist", E_USER_WARNING); + } + } +} + ?> \ No newline at end of file