Again fun with PHP warnings

Posted by Jonathan

This time from http://www.bigbold.com/rssdigest/examples/rails.php

The folks at MySQL should know it better...

Posted by Jonathan

Taken from dev.mysql.com while searching the docs:

PHP Warnings at MySQL.com

One of the first things to do on a PHP production server is to turn off the warnings!

Seems like they fixed it now but this shows that even the so-called professionals like the folks at MySQL.com can get it wrong.

PHP-gettext as an alternative to GNU-gettext 0

Posted by Jonathan

For a PHP project that we were working on at Juniter we needed internationalization/localization. The obvious choice was GNU-gettext. With GNU-gettext you have several dictionaries (.po or the compiled .mo files) with the strings/words in the primary language and the translation. In the code you set an environment variable that indicates with language you want and tell PHP were to find the dictionaries. Normally this is done like this:

<?php
$language = ‘EN’;
putenv(“LANG=$language”);
setlocale(LC_ALL, $language);
bindtextdomain(‘messages’, “PATH_TO_LOCALES”);
textdomain(‘messages’);

print gettext(“Hallo”);
print _(“Hallo”);
?>

Under PATH_TO_LOCALES you have the following structure (assuming a ‘DE’ default language):

EN/LC_ALL/messages.po
EN/LC_ALL/messages.mo
FR/LC_ALL/messages.po
FR/LC_ALL/messages.mo

With $language set to ‘EN’, GNU-gettext (called by the function gettext() or it’s alias _()) will lookup the translation in the file EN/LC_ALL/messages.mo. If it does not find a matching entry it will use the original string.

So far so good. The problem is that in order to use this approach you need the GNU-gettext extension compiled into PHP and you have to be able to set environment variables in PHP scripts. While the first requirement is often satisfied by your hoster, the second one is often not due to the PHP safe_mode.

The safe_mode prohibits setting environment variables that are not allowed explicitly in the php.ini config file. Of course you can beg your hoster to include LANG but often this will be hard or take some time. At our project everything was working fine on our test server and the client’s hoster supported GNU-gettext so everything seemed ok. But when we transferred the project to the client’s server, the translation did not work due to the safe_mode.

It took a while for us to figure this out as PHP errors are very helpful…

As an alternative to try to get the hoster to set the variables in php.ini or disable safe_mode for our virtual host we came up with PHP-gettext. From the website:

This project is not part of the GNU Project.

GNU gettext library is one of best localization libraries (if not the best). Unfortunately, in order to use it with most widespread (and ugly) language of PHP, the system has to support desired locale, and library itself must be installed.

Since this is rarely the case, PHP-gettext is developed to be able to read gettext MO files directly, without requiring anything other than PHP.

Currently, it’s usable if you develop most of the infrastructure for choosing language on your own, because it’s possible to use both gettext() and ngettext() calls. In the near future, it should also be fully compatible drop-in replacement for all of gettext functionality written in PHP.

Using PHP-gettext instead of GNU-gettext is very easy. Just include code like this in every file that should use translation:

require_once(“streams.php”);
require_once(“gettext.php”);

$l10n = ””;
if($_SESSION[‘LANG’] != “DE”)// no translation for default language
{
 $input = new FileReader(’./locale/’. $_SESSION[‘LANG’] .’/LC_MESSAGES/messages.mo’);
 $l10n = new gettext_reader($input);
}


if (!function_exists(“T_”))
{
 function T_($text)
 {
 if($_SESSION[‘LANG’] != “DE”)// no translation for default language
 {
  global $l10n;
  return $l10n->translate($text);
 }
 else
 {
  return $text;
 }
 }
}

The files gettext.php and streams.php are from PHP-gettext. You need to define the translation function as for example T_() or T_gettext() as PHP will not allow you to redefine a function. You then have obviously to change all calls to () in you code to T() with something like this %s/(/T(/g.

So far we have no problems with PHP-gettext and by using it we could avoid the problems with safe_mode.