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