Gettext Support for windows & linux

Hello here my solution to implement the real gettext into Yii framework.

I know Yii support gettext him self , but string parsing to open a compiled gettext.mo is 10 000 time slower than the real gettext.

My goal was to get a easy implementation and very low cpu / memory usage.

Gettext-NOTE: inside a gettext .po file you should only use LineFeed(\n) never use CarriageReturnLineFeed(\r\n) to create a new line. thoses are gettext standart. i am saying since i know some of you are editing .po file with normal text editor under windows and that will not make a good .po/.mo file.

Gettext-NOTE2: any change to a gettext file will not show up until you RESTART your http-deamon(apache httpd)

Usage :




     echo Yii::t("myCategory", "This is just a test");



Implementation :

  • edit your config file to reflect that



    'components'=>array(

        '...'

        'messages'=>array(

            'class'=>'path.to.MyCGettextMessageSource',

        ),



MyCGettextMessageSource :

  • create a file where ever you want name it MyCGettextMessageSource.php and add that class to that file.

3179

MyCGettextMessageSource.php




<?php

/**

 *  To make this work you need directory structure like that:

 *      .../protected/messages/gettext/LC_MESSAGES/

 *      File name structure goes like this: 

 *          lang.category.mo

 *          lang        : lang code returned by Yii

 *          category    : category you specified for your message in Yii::t('category',$message)

 *          mo          : the normal extensions for a valid gettext compiled file

 * 

 *  NOTE FOR LINUX USER

 *  To make this work add this line to the file /etc/locale.gen , create the file if not exists

 *      gettext UTF-8

 * 

 */

class MyCGettextMessageSource extends CMessageSource

{

        /**

	 * @var string the base path for all translated messages. Defaults to null, meaning

	 * the "messages" subdirectory of the application directory (e.g. "protected/messages").

	 */

	public $basePath;


        /**

         * @var string used to fool putenv on windows system, this is a FAKE locale value

         * default will be "gettext" mean /LC_MESSAGES will be searched there

         */

        private $fakeLocale = 'gettext';

        

        /**

         *

         * @var type array , keep tract of the last domain name used and charset

         * to make less call to gettext functions

         */

        private $lastDomain;

	/**

	 * Initializes the application component.

	 * This method overrides the parent implementation by preprocessing

	 * the user request data.

	 */

	public function init()

	{

            parent::init();

            if($this->basePath===null)

                $this->basePath=Yii::getPathOfAlias('application.messages');

            

            $this->lastDomain = array('name'=>'','charset'=>'');


            if( strncasecmp(PHP_OS,'WIN',3)===0 )

                putenv("LANG=$this->fakeLocale");       //windows

            else

                setlocale(LC_MESSAGES,$this->fakeLocale);    //linux


            // handle for missing file 

            $this->attachEventHandler('onMissingTranslation', array('MyCGettextMessageSource','handleMissingFile'));

	}


	/**

	 * Translates the specified message.

	 * If the message is not found, an {@link onMissingTranslation}

	 * event will be raised.

	 * @param string $category the category that the message belongs to

	 * @param string $message the message to be translated

	 * @param string $language the target language

	 * @return string the translated message

	 */

	protected function translateMessage($category,$message,$language)

	{

            if($this->lastDomain['name'] !== "$language.$category" || $this->lastDomain['charset'] !== Yii::app()->charset)

            {

                $this->lastDomain['name'] = "$language.$category";

                bindtextdomain($this->lastDomain['name'], $this->basePath);

                textdomain($this->lastDomain['name']);

                bind_textdomain_codeset($this->lastDomain['name'], Yii::app()->charset);

                 

            } 

            if(!file_exists("{$this->basePath}/{$this->fakeLocale}/LC_MESSAGES/$language.$category.mo") && $this->hasEventHandler('onMissingTranslation'))

            {

                $event=new CMissingTranslationEvent($this,$category,$message,$language);

                $this->onMissingTranslation($event);

                return $message;

            }

            return _($message);

	}

        // since we are using real gettext we do not need that

        protected function loadMessages($category,$language){}

        

        // handle onMissingTranslation

        public static function handleMissingFile($event)

        {

            Yii::log("Missing file for translation {$event->language}.{$event->category}", 'warning','application.extensions.MyCGettextMessageSource');

        }

}



P.S. love is everywhere