Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Nativní Gettext translator v Nette
Pozitiva tohoto reseni
----------------------
- v devel prostredi automaticky resi problem s ulozenim *.mo souboru do cache -> pri zmene *.mo souboru neni potreba restartovat Apache
- pokud preklad neexistuje, automaticky pouzije defaultni jazyk
- vyuziva nativni Gettext knihovnu PHP
Soubor *.pot / respektive *.mo a *.po je mozne jednoduse ziskat pomoci https://github.com/voda/gettext-extractor
<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="gettext">
<!-- Apache ANT soubor -->
<target name="gettext">
<php file="build/gettext-extractor/gettext-extractor.php" arg="-oapp/locale/cs_CZ/LC_MESSAGES/messages.pot -fapp/"/>
</target>
<macrodef name="php" description="RUN php script">
<attribute name="file"/>
<attribute name="arg" default="" />
<sequential>
<echo>[Exec] @{file} @{arg}</echo>
<exec executable="${php.path}php">
<arg line="@{file} @{arg}" />
</exec>
</sequential>
</macrodef>
</project>
<?php
namespace Base;
use Nette\Environment;
abstract class Presenter extends \Nette\Application\UI\Presenter
{
/** @persitent */
public $lang;
private function beforeRender()
{
parent::beforeRender();
$translator = new \Base\Translator();
// app/locale/cs_CZ/LC_MESSAGES/messages.po
// app/locale/cs_CZ/LC_MESSAGES/messages.mo
if ($this->lang == 'cs')
$translator->init(__DIR__ . '/../locale/', 'cs_CZ', 'messages', !Environment::isProduction(), true);
$this->template->setTranslator($translator);
}
}
<?php
namespace nx;
/**
* Implementace rozhrani ITranslator pomoci Gettext
*
* Translator umi predchazet cachovani souboru GETTEXT
* - http://www.php.net/manual/en/function.gettext.php#58310
* - https://gist.github.com/1257619
*
* <code>
* // provadet pouze 1x v ramci requestu
* putenv('LC_MESSAGES=cs_CZ');
* setlocale(LC_MESSAGES, 'cs_CZ');
*
* $translator = new Translator();
* $translator->init(__DIR__ . '/../locale/', 'cs_CZ', 'messages');
* echo $translator->translate('string');
* </code>
*
* <code>
* $translator = new Translator();
* $translator->init(__DIR__ . '/../locale/', 'cs_CZ', 'messages', true, true);
* // domain bude automaticky nastavena na tmg{+timestamp}
* echo $translator->translate('string');
* </code>
*
* Pokud pod Ubuntu cs_CZ nefunguje provedte nasledujici
*
* <code>
* pico /usr/share/i18n/SUPPORTED # seznam podporovanych locales
* sudo apt-get install php-gettext
* sudo locale-gen cs_CZ # pridam cs_CZ
* sudo locale-gen cs_CZ.utf8 # pridam cs_CZ
* locale -a # zkontroluji zda tam je
* </code>
*
* @author Roman Ozana
*/
class Translator implements \Nette\Localization\ITranslator {
/** @var string */
public static $mofile = null;
/** @var boolean */
public static $localesSet = false;
/**
* Nastavi LC_MESSAGES na zvoleny jazyk
* @param string $language
*/
public static function setLocaleMessages($language) {
if (self::$localesSet) throw new \Exception('Locales can\'t be set only once');
putenv('LC_MESSAGES=' . $language);
setlocale(LC_MESSAGES, $language);
self::$localesSet = true;
}
/**
* Inicializace gettext translatoru
*
* @param string $directory
* @param string $language
* @param string $domain
* @param boolean $preventCache
* @param boolean $setLocaleMessages
*/
public static function init($directory, $language, $domain = 'messages', $preventCache = false, $setLocaleMessages = false) {
$directory = realpath($directory);
self::$mofile = sprintf('%s/%s/LC_MESSAGES/%s.mo', $directory, $language, $domain);
if (file_exists(self::$mofile)) {
if ($preventCache === true) {
self::$mofile = self::preventGettextCache(self::$mofile, $domain);
$domain = basename(self::$mofile, '.mo');
}
if ($setLocaleMessages) self::setLocaleMessages($language);
// melo by stacit pouze tohle:
bindtextdomain($domain, $directory);
bind_textdomain_codeset($domain, 'UTF-8');
textdomain($domain);
}
}
/**
* Ochrana gettext prekladu proti cache
* @param string $file
* @return string
*/
protected static function preventGettextCache($mo, $domain) {
$tmp = sprintf('%s/tmp%s.mo', dirname($mo), filemtime($mo));
if (!file_exists($tmp)) {
foreach (new \FilesystemIterator(dirname($mo)) as $file => $info) { /* @var $info \SplFileInfo */
if (!preg_match('/tmp[\d]+\.mo/', $file))
continue;
unlink($file);
}
if (!copy($mo, $tmp))
throw new \Exception('Temporary *.mo can\'t be created');
}
return $tmp;
}
/**
* Prelozi text $message
* @param string $message
* @param int $count
* @return string
*/
public function translate($message, $count = NULL) {
return gettext($message);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.