1

我想在一个模块中扩展 KOHANA 的 i18n 类,以便在查找默认文件结构之前先查找数据库以查找翻译。问题是我要覆盖的方法是静态的。

原始类有一个方法get(),所以我调用我的类:Appointedd_I18n::get('Term goes here...')并且该方法调用load(). 那是我想要覆盖的方法,但是因为它是静态的,所以它没有加载我的方法,它正在加载原始的方法。

这是我的模块/类:

<?php defined('SYSPATH') or die('No direct script access.');

/**
 * Extends the Kohana translation code to include a db lookup. 
 *
 */

class Appointedd_I18n extends Kohana_I18n {

    /**
     * Returns the translation table for a given language.
     *
     *     // Get all defined Spanish messages
     *     $messages = I18n::load('es-es');
     *
     * @param   string  $lang   language to load
     * @return  array
     */
    public static function load($lang)
    {
        die('think I\'ll look up the db'); // to test this method is being called
        if (isset(I18n::$_cache[$lang]))
        {
            return I18n::$_cache[$lang];
        }

        // New translation table
        $table = array();

        // Split the language: language, region, locale, etc
        $parts = explode('-', $lang);

        do
        {
            // Create a path for this set of parts
            $path = implode(DIRECTORY_SEPARATOR, $parts);

            if ($files = Kohana::find_file('i18n', $path, NULL, TRUE))
            {
                $t = array();
                foreach ($files as $file)
                {
                    // Merge the language strings into the sub table
                    $t = array_merge($t, Kohana::load($file));
                }

                // Append the sub table, preventing less specific language
                // files from overloading more specific files
                $table += $t;
            }

            // Remove the last part
            array_pop($parts);
        }
        while ($parts);

        // Cache the translation table locally
        return I18n::$_cache[$lang] = $table;
    }

} // END class Appointedd_i18n

这是 KOHANA_I18n 类:

<?php defined('SYSPATH') or die('No direct script access.');
/**
 * Internationalization (i18n) class. Provides language loading and translation
 * methods without dependencies on [gettext](http://php.net/gettext).
 *
 * Typically this class would never be used directly, but used via the __()
 * function, which loads the message and replaces parameters:
 *
 *     // Display a translated message
 *     echo __('Hello, world');
 *
 *     // With parameter replacement
 *     echo __('Hello, :user', array(':user' => $username));
 *
 * @package    Kohana
 * @category   Base
 * @author     Kohana Team
 * @copyright  (c) 2008-2012 Kohana Team
 * @license    http://kohanaframework.org/license
 */
class Kohana_I18n {

    /**
     * @var  string   target language: en-us, es-es, zh-cn, etc
     */
    public static $lang = 'en-us';

    /**
     * @var  string  source language: en-us, es-es, zh-cn, etc
     */
    public static $source = 'en-us';

    /**
     * @var  array  cache of loaded languages
     */
    protected static $_cache = array();

    /**
     * Get and set the target language.
     *
     *     // Get the current language
     *     $lang = I18n::lang();
     *
     *     // Change the current language to Spanish
     *     I18n::lang('es-es');
     *
     * @param   string  $lang   new language setting
     * @return  string
     * @since   3.0.2
     */
    public static function lang($lang = NULL)
    {
        if ($lang)
        {
            // Normalize the language
            I18n::$lang = strtolower(str_replace(array(' ', '_'), '-', $lang));
        }

        return I18n::$lang;
    }

    /**
     * Returns translation of a string. If no translation exists, the original
     * string will be returned. No parameters are replaced.
     *
     *     $hello = I18n::get('Hello friends, my name is :name');
     *
     * @param   string  $string text to translate
     * @param   string  $lang   target language
     * @return  string
     */
    public static function get($string, $lang = NULL)
    {
        if ( ! $lang)
        {
            // Use the global target language
            $lang = I18n::$lang;
        }

        // Load the translation table for this language
        $table = I18n::load($lang);

        // Return the translated string if it exists
        return isset($table[$string]) ? $table[$string] : $string;
    }

    /**
     * Returns the translation table for a given language.
     *
     *     // Get all defined Spanish messages
     *     $messages = I18n::load('es-es');
     *
     * @param   string  $lang   language to load
     * @return  array
     */
    public static function load($lang)
    {
        if (isset(I18n::$_cache[$lang]))
        {
            return I18n::$_cache[$lang];
        }

        // New translation table
        $table = array();

        // Split the language: language, region, locale, etc
        $parts = explode('-', $lang);

        do
        {
            // Create a path for this set of parts
            $path = implode(DIRECTORY_SEPARATOR, $parts);

            if ($files = Kohana::find_file('i18n', $path, NULL, TRUE))
            {
                $t = array();
                foreach ($files as $file)
                {
                    // Merge the language strings into the sub table
                    $t = array_merge($t, Kohana::load($file));
                }

                // Append the sub table, preventing less specific language
                // files from overloading more specific files
                $table += $t;
            }

            // Remove the last part
            array_pop($parts);
        }
        while ($parts);

        // Cache the translation table locally
        return I18n::$_cache[$lang] = $table;
    }

} // End I18n

if ( ! function_exists('__'))
{
    /**
     * Kohana translation/internationalization function. The PHP function
     * [strtr](http://php.net/strtr) is used for replacing parameters.
     *
     *    __('Welcome back, :user', array(':user' => $username));
     *
     * [!!] The target language is defined by [I18n::$lang].
     * 
     * @uses    I18n::get
     * @param   string  $string text to translate
     * @param   array   $values values to replace in the translated text
     * @param   string  $lang   source language
     * @return  string
     */
    function __($string, array $values = NULL, $lang = 'en-us')
    {
        if ($lang !== I18n::$lang)
        {
            // The message and target languages are different
            // Get the translation for this message
            $string = I18n::get($string);
        }

        return empty($values) ? $string : strtr($string, $values);
    }
}

有没有办法在不编辑系统类的情况下扩展 Kohana_I18n 以包含数据库更新?

4

2 回答 2

1

由于 Kohana_I18n::get() 调用I18n ::load(),您所要做的就是重写 Kohana_I18n::get() 方法,以便它调用 Appointedd_I18n::load() 方法。

class Appointedd_I18n extends Kohana_I18n {

    ...

    public static function get($string, $lang = NULL)
    {
        if ( ! $lang)
        {
            // Use the global target language
            $lang = I18n::$lang;
        }

        // Load the translation table for this language
        $table = self::load($lang);

        // Return the translated string if it exists
        return isset($table[$string]) ? $table[$string] : $string;
    }

    ...
}
于 2013-10-25T13:20:56.877 回答
1

“有没有办法在不编辑系统类的情况下扩展 Kohana_I18n 以包含数据库更新?” 是的。

听起来您要么不熟悉 Kohana 的级联文件系统,要么不了解它在这种情况下的用途,要么出于任何原因不想更改 I18n 的行为。

如果不是最后一个,那么只需重命名并相应Appointedd_I18nI18n更改文件名。SYSPATH/classes/I18n.php一个只包含class I18n extends Kohana_I18n {}. 如果您查看SYSPATH/classes/Kohana/I18n.php,您将看到selfKohana_I18n从未习惯调用任何东西。它们一直I18nKohana_I18n课堂上使用,以便您可以“替换” I18n 类并改变其行为。

于 2013-10-25T13:55:52.230 回答