iamjonesy
iamjonesy

Reputation: 25122

Extending a class which has static methods

I want to extend KOHANA's i18n class in a module so that I can lookup a DB first to look for translations before it looks up the default file structure. The problem is that the method I want to override is static.

The original class has a method get() so I call my class: Appointedd_I18n::get('Term goes here...') and that method calls load(). That is the method I want to override but because it's static it's not loading MY method it's loading the original one.

Here's my module/class:

<?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

Here is the KOHANA_I18n class:

<?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);
    }
}

Is there a way I extend Kohana_I18n to include a db update without editing the system class?

Upvotes: 1

Views: 282

Answers (2)

Darsstar
Darsstar

Reputation: 1895

"Is there a way I extend Kohana_I18n to include a db update without editing the system class?" Yes.

It sounds like you are either unfamiliar with Kohana's Cascading File System, you don't understand how it could be useful in this circumstance or that you don't want to change I18n's behavior for whatever reason.

If the last is not the case then just rename Appointedd_I18n to I18n and change the filename accordingly. SYSPATH/classes/I18n.php a file that just contains class I18n extends Kohana_I18n {}. And if you look at SYSPATH/classes/Kohana/I18n.php you will see self or Kohana_I18n is never used to call anything. They have consistently used I18n in the Kohana_I18n class so that you can 'replace' the I18n class and change its behavior.

Upvotes: 1

Martial
Martial

Reputation: 1562

Since Kohana_I18n::get() calls I18n::load(), all you have to do is override the Kohana_I18n::get() method so that it calls the Appointedd_I18n::load() method.

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;
    }

    ...
}

Upvotes: 1

Related Questions