<?php
/*
Simulates gettext functionality. Understands .mo and .po files.
Lookup of plural forms mostly work (but not fully compliant, no
support for Plural-Forms: header). Categories/codesets are ignored.
Besides using setlocale() you should change the $_ENV["LANG"] var
to the desired language manually. Additionally all your scripts
could contain following (may also work with standard gettext):
$_ENV["LANGUAGE"] = $_SERVER["HTTP_ACCEPT_LANGUAGE"];
What's often more user-friendly than hardwired server-side values.
*/
#-- define if not there
if (!function_exists("gettext")) {
#-- all-in-one combined implementation
# (in PHP only the first parameter is used)
function gettext($msg, $msg2=NULL, $domain=NULL, $category=NULL, $plural=NULL, $config=NULL) {
global $_GETTEXT;
#-- params
if (!isset($domain)) {
$domain = $_GETTEXT["%domain"];
}
elseif (empty($_GETTEXT[$domain])) {
bindtextdomain($domain); // load from system dirs
}
#-- config
if (isset($config)) {
return false;
}
#-- plural array position (English)
if (!isset($plural) || ($plural == 1)) {
$pli = 0;
}
else {
if (isset($msg2)) {
$msg = $msg2;
}
$pli = 1;
}
// $pli = ($plural==1) ?0 :1;
#-- look up
if ($trans = $_GETTEXT[$domain][$msg]) {
if (is_array($trans)) {
if (!isset($trans[$pli])) {
$pli = 0;
}
$trans = $trans[$pli];
}
if (strlen($trans)) {
$msg = $trans;
}
}
#-- give out whatever we have
return($msg);
}
#-- wrappers
function ngettext($msg1, $msg2, $plural) {
return gettext($msg1, $msg2, NULL, NULL, $plural);
}
function dngettext($domain, $msg1, $msg2, $plural) {
return gettext($msg1, $msg2, $domain, NULL, $plural);
}
function dcngettext($domain, $msg1, $msg2, $plural, $category) {
return gettext($msg1, $msg2, $domain, $category, $plural);
}
function dcgettext($domain, $msg, $category) {
return gettext($msg, NULL, $domain, $category);
}
function dgettext($domain, $msg) {
return gettext($msg, NULL, $domain);
}
#-- settings
function textdomain($default="NULL") {
global $_GETTEXT;
$prev = $_GETTEXT["%domain"];
if (isset($default)) {
$_GETTEXT["%domain"] = $default;
}
return $prev;
}
#-- loads data files
function bindtextdomain($domain, $directory="/usr/share/locale:/usr/local/share/locale:./locale") {
global $_GETTEXT;
if (isset($_GETTEXT["domain"]) && (count($_GETTEXT["domain"]) > 3)) {
return; // don't load twice
}
$_GETTEXT[$domain]["%dir"] = $directory;
$_GETTEXT["%locale"] = setlocale(LC_CTYPE, 0);
#-- language directories
$langs = "$_ENV[LANGUAGE],$_ENV[LC_ALL],$_ENV[LC_MESSAGE],$_ENV[LANG],"
. "{$_GETTEXT['%locale']},$_SERVER[HTTP_ACCEPT_LANGUAGE],C,en";
foreach (explode(",",$langs) as $d) {
$d = trim($d);
// $dir2[] = $d;
$d = strtok($d, "@.-+=%:; ");
if (strlen($d)) {
$dir2[] = $d;
}
if (strpos($d, "_")) {
$dir2[] = strtok($d, "_");
}
}
#-- repeat
foreach (explode(":", $directory) as $directory)
foreach ($dir2 as $lang) {
$base_fn = "$directory/$lang/LC_MESSAGES/$domain";
#-- binary format
if (file_exists($f = "$base_fn.mo") && ($f = fopen($f, "rb"))) {
$data = fread($f, 1<<20);
fclose($f);
#-- check file magic
if ($data) {
extract(unpack("L1magic/L1version/L1count/L1o_msg/L1o_trn", substr($data, 0, 20)));
if ((dechex($magic) == "950412de") && ($version == 0)) {
for ($n=0; $n<$count; $n++) {
#-- id
$r = unpack("L1len/L1offs", substr($data, $o_msg + $n * 8, 8));
$msgid = substr($data, $r["offs"], $r["len"]);
unset($msgid_plural);
if (strpos($msgid, "\000")) {
list($msgid, $msgid_plural) = explode("\000", $msgid);
}
#-- translation
$r = unpack("L1len/L1offs", substr($data, $o_trn + $n * 8, 8));
$msgstr = substr($data, $r["offs"], $r["len"]);
if (strpos($msgstr, "\000")) {
$msgstr = explode("\000", $msgstr);
}
#-- add
$_GETTEXT[$domain][$msgid] = $msgstr;
if (isset($msgid_plural)) {
$_GETTEXT[$domain][$msgid_plural] = &$_GETTEXT[$domain][$msgid];
}
}
}
}
break;
}
#-- read from text file (not fully correct, and redundant because
# the original gettext/libintl doesn't support this at all)
elseif (file_exists($f = "$base_fn.po") && ($f = fopen($f, "r"))) {
do {
$line = trim(fgets($f));
if (isset($msgid) && isset($msgstr) && (empty($line) || ($line[0]=="m"))) {
foreach ($msgstr as $v) {
$_GETTEXT[$domain][$msgid[0]] = $v;
}
if ($msgid[1]) {
$_GETTEXT[$domain][$msgid[1]] = &$_GETTEXT[$domain][$msgid[0]];
}
unset($msgid);
unset($msgstr);
}
$space = strpos($line, " ");
if ($line[0] == "#") {
continue;
}
elseif (strncmp($line, "msgid", 5)==0) {
$msgid[] = trim(substr($line, $space+1), '"');
}
elseif (strncmp($line, "msgstr", 6)==0) {
$msgstr[] = trim(substr($line, $space+1), '"');
}
elseif ($line[0] == '"') {
$line = trim($line, '"');
if (isset($msggstr)) {
$msgstr[count($msgstr)] .= $line;
}
else {
$msgid[count($msgid)] .= $line;
}
}
}
while (!feof($f));
if ($msgid && $msgstr) { $_GETTEXT[$domain][$msgid[0]] = $msgstr[0]; }
fclose($f);
break;
}
}//foreach
#-- set as default textdomain
if (empty($_GETTEXT["%domain"]) && (count($_GETTEXT[$domain]) > 1)) {
$_GETTEXT["%domain"] = $domain;
}
return($domain);
}
#-- ignored setting (no idea what it really should do)
function bind_textdomain_codeset($domain, $codeset) {
global $_GETTEXT;
$_GETTEXT[$domain]["%codeset"] = $codeset;
return($domain);
}
}
#-- define separately
if (!function_exists("_")) {
function _($str) {
return gettext($str);
}
}
?>