From 5c1a68ae163f5ddb5fb9b2932e3ffc5fc17a0cd3 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Mon, 1 Feb 2016 13:30:15 +0900 Subject: [PATCH] Keep translations from different sources separate --- classes/context/Context.class.php | 14 ++- common/framework/lang.php | 184 ++++++++++++++++++++++-------- 2 files changed, 150 insertions(+), 48 deletions(-) diff --git a/classes/context/Context.class.php b/classes/context/Context.class.php index 967634d1b..adbe0269a 100644 --- a/classes/context/Context.class.php +++ b/classes/context/Context.class.php @@ -339,8 +339,8 @@ class Context // Load languages $this->lang = Rhymix\Framework\Lang::getInstance($this->lang_type); - $this->lang->addDirectory(RX_BASEDIR . 'common/lang'); - $this->lang->addDirectory(RX_BASEDIR . 'modules/module/lang'); + $this->lang->loadDirectory(RX_BASEDIR . 'common/lang', 'common'); + $this->lang->loadDirectory(RX_BASEDIR . 'modules/module/lang', 'module'); // set session handler if(self::isInstalled() && $this->db_info->use_db_session == 'Y') @@ -915,7 +915,15 @@ class Context */ public static function loadLang($path) { - return self::$_instance->lang->addDirectory($path); + if (preg_match('@/(modules|addons|plugins)/([a-z0-9_]+)/lang/?$@', str_replace('\\', '/', $path), $matches)) + { + $plugin_name = $matches[2]; + } + else + { + $plugin_name = null; + } + return self::$_instance->lang->loadDirectory($path, $plugin_name); } /** diff --git a/common/framework/lang.php b/common/framework/lang.php index 4c2c231fa..fbb66e755 100644 --- a/common/framework/lang.php +++ b/common/framework/lang.php @@ -17,7 +17,8 @@ class Lang */ protected $_language; protected $_loaded_directories = array(); - protected $_loaded_files = array(); + protected $_loaded_plugins = array(); + protected $_search_priority = array(); /** * This method returns the cached instance of a language. @@ -46,74 +47,91 @@ class Lang protected function __construct($language) { $this->_language = preg_replace('/[^a-z0-9_-]/i', '', $language); + $this->_loaded_plugins['_custom_'] = new \stdClass(); } /** - * Add a directory to load translations from. + * Load translations from a plugin (module, addon). + * + * @param string $name + * @return bool + */ + public function loadPlugin($name) + { + if (isset($this->_loaded_plugins[$name])) + { + return true; + } + + if (file_exists(RX_BASEDIR . "plugins/$name/lang")) + { + $this->loadDirectory(RX_BASEDIR . "plugins/$name/lang", $name); + } + elseif (file_exists(RX_BASEDIR . "modules/$name/lang")) + { + $this->loadDirectory(RX_BASEDIR . "modules/$name/lang", $name); + } + elseif (file_exists(RX_BASEDIR . "addons/$name/lang")) + { + $this->loadDirectory(RX_BASEDIR . "addons/$name/lang", $name); + } + } + + /** + * Load translations from a directory. * * @param string $dir * @return bool */ - public function addDirectory($dir) + public function loadDirectory($dir, $plugin_name = null) { // Do not load the same directory twice. $dir = rtrim($dir, '/'); - if (in_array($dir, $this->_loaded_directories)) + $plugin_name = $plugin_name ?: $dir; + if (isset($this->_loaded_directories[$dir]) || isset($this->_loaded_plugins[$plugin_name])) { return true; } - // Alias $this to $lang. - $lang = $this; - - // Check if there is a PHP lang file. - if (file_exists($filename = $dir . '/' . $this->_language . '.php')) + // Look for language files. + if (file_exists($dir . '/' . $this->_language . '.php')) { - $this->_loaded_directories[] = $dir; - $this->_loaded_files[] = $filename; - include $filename; - return true; + $filename = $dir . '/' . $this->_language . '.php'; } - elseif (file_exists($filename = $dir . '/' . ($this->_language === 'ja' ? 'jp' : $this->_language) . '.lang.php')) + elseif (file_exists($dir . '/' . ($this->_language === 'ja' ? 'jp' : $this->_language) . '.lang.php')) { - $this->_loaded_directories[] = $dir; - $this->_loaded_files[] = $filename; - include $filename; - return true; + $filename = $dir . '/' . ($this->_language === 'ja' ? 'jp' : $this->_language) . '.lang.php'; } elseif (($hyphen = strpos($this->_language, '-')) !== false) { - if (file_exists($filename = $dir . '/' . substr($this->_language, 0, $hyphen) . '.php')) + if (file_exists($dir . '/' . substr($this->_language, 0, $hyphen) . '.php')) { - $this->_loaded_directories[] = $dir; - $this->_loaded_files[] = $filename; - include $filename; - return true; + $filename = $dir . '/' . substr($this->_language, 0, $hyphen) . '.php'; } - elseif (file_exists($filename = $dir . '/' . substr($this->_language, 0, $hyphen) . '.lang.php')) + elseif (file_exists($dir . '/' . substr($this->_language, 0, $hyphen) . '.lang.php')) { - $this->_loaded_directories[] = $dir; - $this->_loaded_files[] = $filename; - include $filename; - return true; + $filename = $dir . '/' . substr($this->_language, 0, $hyphen) . '.lang.php'; } } - - // Check if there is a XML lang file. - if (file_exists($filename = $dir . '/lang.xml')) + elseif (file_exists("$dir/lang.xml")) { - $this->_loaded_directories[] = $dir; - $this->_loaded_files[] = $filename; - $compiled_filename = self::compileXMLtoPHP($filename, $this->_language === 'ja' ? 'jp' : $this->_language); - if ($compiled_filename !== false) - { - include $compiled_filename; - return true; - } + $filename = self::compileXMLtoPHP("$dir/lang.xml", $this->_language === 'ja' ? 'jp' : $this->_language); } - // Return false if no suitable lang file is found. - return false; + // Load the language file. + if ($filename) + { + $lang = new \stdClass; + include $filename; + $this->_loaded_directories[$dir] = true; + $this->_loaded_plugins[$plugin_name] = $lang; + array_unshift($this->_search_priority, $plugin_name); + return true; + } + else + { + return false; + } } /** @@ -238,6 +256,77 @@ class Lang return (include RX_BASEDIR . 'common/defaults/lang.php'); } + /** + * Magic method for translations without arguments. + */ + public function __get($key) + { + // Search custom translations first. + if (isset($this->_loaded_plugins['_custom_']->{$key})) + { + return $this->_loaded_plugins['_custom_']->{$key}; + } + + // Search other plugins. + foreach ($this->_search_priority as $plugin_name) + { + if (isset($this->_loaded_plugins[$plugin_name]->{$key})) + { + return $this->_loaded_plugins[$plugin_name]->{$key}; + } + } + + // If no translation is found, return the key. + return $key; + } + + /** + * Magic method for setting a new custom translation. + * + * @param string $key + * @param string $value + * @return void + */ + public function __set($key, $value) + { + $this->_loaded_plugins['_custom_']->{$key} = $value; + } + + /** + * Magic method for checking whether a translation exists. + * + * @param string $key + * @return bool + */ + public function __isset($key) + { + foreach ($this->_loaded_plugins as $plugin_name => $translations) + { + if (isset($translations->{$key})) + { + return true; + } + } + return false; + } + + /** + * Magic method for unsetting a translation. + * + * @param string $key + * @return void + */ + public function __unset($key) + { + foreach ($this->_loaded_plugins as $plugin_name => $translations) + { + if (isset($translations->{$key})) + { + unset($translations->{$key}); + } + } + } + /** * Magic method for translations with arguments. * @@ -250,13 +339,18 @@ class Lang // Remove a colon from the beginning of the string. if ($key !== '' && $key[0] === ':') $key = substr($key, 1); - // If the string does not have a translation, return it verbatim. - if (!isset($this->{$key})) return $key; + // Find the translation. + $translation = $this->__get($key); // If there are no arguments, return the translation. - if (!count($args)) return $this->{$key}; + if (!is_array($args)) + { + $args = func_get_args(); + array_shift($args); + } + if (!count($args)) return $translation; // If there are arguments, interpolate them into the translation and return the result. - return vsprintf($this->{$key}, $args); + return vsprintf($translation, $args); } }