Main Page | Directories | File List | File Members

i18n.php

Go to the documentation of this file.
00001 <?php
00002 # This file is part of the Savane project
00003 # <http://gna.org/projects/savane/>
00004 #
00005 # $Id: i18n.php 4567 2005-06-30 17:19:37Z toddy $
00006 #
00007 #  Copyright 2003-2004 (c) Stéphane Urbanovski <s.urbanovski@ac-nancy-metz.fr>
00008 #                          Mathieu Roy <yeupou--at--gnu.org>
00009 #
00010 # The Savane project is free software; you can redistribute it and/or
00011 # modify it under the terms of the GNU General Public License
00012 # as published by the Free Software Foundation; either version 2
00013 # of the License, or (at your option) any later version.
00014 #
00015 # The Savane project is distributed in the hope that it will be useful,
00016 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 # GNU General Public License for more details.
00019 #
00020 # You should have received a copy of the GNU General Public License
00021 # along with the Savane project; if not, write to the Free Software
00022 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00023 
00024 # Description : This script is used to configure the locale using if possible
00025 # the user's navigator preferences. The locale is used by gettext and strftime
00026 # functions.
00027 
00028 # Should we use _ENV["LANG"] also?
00029 
00030 
00031 # Get the user's prefered language from the navigator sended headers :
00032 $navigatorLanguages = explode(",",getenv("HTTP_ACCEPT_LANGUAGE"));
00033 
00034 # Set the default language :
00035 $locale = $GLOBALS['sys_default_locale'];
00036 
00037 
00038 # Table of supported languages :
00039 # "lang" => "associated prefered sublanguage"
00040 $supportedLanguages = array(
00041                             "de"        => "DE.UTF-8",
00042                             "de_DE"     => "DE.UTF-8",
00043                             "en"        => "US.UTF-8",
00044                             "fr"        => "FR.UTF-8",
00045                             "fr_FR"     => "FR.UTF-8",
00046                             "it"        => "IT.UTF-8",
00047                             "it_IT"     => "IT.UTF-8",
00048                             "ja"        => "JP.UTF-8",
00049                             "ja_JP"     => "JP.UTF-8",
00050                             "ko"        => "KR.UTF-8",
00051                             "ko_KR"     => "KR.UTF-8",
00052                             "pt"        => "BR.UTF-8",
00053                             "pt_BR"     => "BR.UTF-8",
00054                             "ru"        => "RU.UTF-8",
00055                             "ru_RU"     => "RU.UTF-8"
00056                             );
00057 
00058 # Try to find the best supported language from user's navigator preferences :
00059 while (list(, $lng) = each ($navigatorLanguages)) {
00060 
00061   $lng = trim($lng);
00062   $curlocale = strtolower(substr($lng,0,2));
00063   if  (substr($lng,2,1) == "-") {
00064     $sublocale = $curlocale."_".strtoupper(substr($lng,3,2));
00065     if ( isset($supportedLanguages[$sublocale] )) {
00066       $locale = $curlocale."_".$supportedLanguages[$sublocale];
00067       define(SV_LANG, $curlocale."-".$supportedLanguages[$sublocale]);
00068       break;
00069     }
00070   }
00071   if ( isset($supportedLanguages[$curlocale] )) {
00072     $locale = $curlocale."_".$supportedLanguages[$curlocale];
00073     define(SV_LANG, $curlocale."-".$supportedLanguages[$curlocale]);
00074     break;
00075   }
00076 
00077 }
00078 
00079 # Set the locale used by gettext() and strftime() functions :
00080 setlocale(LC_ALL, $locale);
00081 
00082 # Gettext (i18n) configs :
00083 textdomain('savane');
00084 
00085 
00086 #print "[".$locale.",".setlocale(LC_ALL,0)."]"; //debug
00087 
00088 # this provides a custom ngettext() function for PHP versions < 4.2
00089 # it should have the same functionality, but note that there is the
00090 # encoding of the po-file hardcoded to speed things up
00091 if (!function_exists("ngettext")) {
00092   function ngettext($string1, $string2, $n)
00093   {
00094     $locale = setlocale(LC_ALL, 0);
00095     # strip possible charset extension from the locale (e.g. "de_DE.UTF-8")
00096     $locale = array_shift(explode(".", $locale));
00097 
00098     # assume a sane default for the return value
00099     if ($n != 1)
00100       {
00101         $msgstr = $string2;
00102       }
00103     else
00104       {
00105         $msgstr = $string1;
00106       }
00107 
00108     # FIXME: This should not be hardcoded, but taken from the configure
00109     # script input somehow.
00110     $mo_file = "/usr/share/locale/".$locale."/LC_MESSAGES/savane.mo";
00111     $alternative[] = "/usr/share/locale/".substr($locale, 0, 2)."/LC_MESSAGES/savane.mo";
00112     $alternative[] = "/usr/local/share/locale/".$locale."/LC_MESSAGES/savane.mo";
00113     $alternative[] = "/usr/local/share/locale/".substr($locale, 0, 2)."/LC_MESSAGES/savane.mo";
00114 
00115     foreach ($alternative as $location)
00116       {
00117         if (is_readable($location))
00118           {
00119             $mo_file = $location;
00120             break;
00121           }
00122       }
00123 
00124     # fallback, also used for English
00125     if (!is_readable($mo_file))
00126       {
00127         return $msgstr;
00128       }
00129 
00130     # open mo file for binary reading
00131     $mo = fopen($mo_file, "rb");
00132 
00133     # get the number of strings
00134     fseek($mo, 8);
00135     $str_count = array_pop(unpack("L", fread($mo, 4)));
00136 
00137     # read in the start of the msgids and msgstrs
00138     fseek($mo, 12);
00139     $start = unpack("Loriginal/Ltranslation", fread($mo, 8));
00140 
00141     # read in the table for the lengths and offsets for the msgids
00142     fseek($mo, $start['original']);
00143     $msgids = fread($mo, $str_count*8);
00144     for ($q = 0; $q < $str_count; $q++)
00145       {
00146         $original[$q] = unpack("Llength/Loffset", substr($msgids, $q*8, 8));
00147       }
00148 
00149     # read the msgids in, until the specified msgid is found
00150     $found = false;
00151     for ($q = 0; $q < $str_count; $q++)
00152       {
00153         fseek($mo, $original[$q]['offset']);
00154         if ($original[$q]['length'] != 0)
00155           {
00156             $msgid = array_pop(unpack("a*", fread($mo, $original[$q]['length'])));
00157             if ($msgid == $string1."\0".$string2)
00158               {
00159                 $msgid = $q;
00160                 $found = true;
00161                 break;
00162               }
00163           }
00164       }
00165 
00166     if (!$found)
00167       {
00168         return $msgstr;
00169       }
00170 
00171     # get the length and offset for the corresponding msgstr
00172     fseek($mo, $start['translation'] + 8*$msgid);
00173     $translation = unpack("Llength/Loffset", fread($mo, 8));
00174 
00175     # read the msgstr
00176     fseek($mo, $translation['offset']);
00177     if ($translation['length'] != 0)
00178       {
00179         $msgstr = array_pop(unpack("a*", fread($mo, $translation['length'])));
00180       }
00181 
00182     # the plural forms rule needs to be hardcoded, because
00183     # the PHP operator precedence differs a little bit from
00184     # the one C uses -> the plural rule provided in the po-file
00185     # does not work for complicated rules (e.g. Russian)
00186     #
00187     # for the canonical rules see
00188     # <http://www.gnu.org/software/gettext/manual/html_chapter/gettext_10.html#SEC150>
00189     $plural_rule["de_DE"] = ($n != 1);
00190     $plural_rule["fr_FR"] = ($n > 1);
00191     $plural_rule["it_IT"] = ($n != 1);
00192     $plural_rule["ja_JP"] = 0;
00193     $plural_rule["ko_KR"] = 0;
00194     $plural_rule["pt_BR"] = ($n > 1);
00195     $plural_rule["ru_RU"] = ($n%10 == 1 && $n%100 != 11 ? 0 : ($n%10 >= 2 && $n%10 <= 4 && ($n%100 < 10 || $n%100 >= 20) ? 1 : 2));
00196 
00197     # if there's no plural rule defined, use a generic one
00198     if (!isset($plural_rule[$locale]))
00199       {
00200         $plural_rule[$locale] = 0;
00201       }
00202 
00203     # split the msgstr into the different plural forms
00204     $plural = preg_split("/\\x00/", $msgstr);
00205 
00206     # finally, find the msgstr that's wanted ...
00207     $msgstr = $plural[$plural_rule[$locale]];
00208 
00209     fclose($mo);
00210 
00211     return $msgstr;
00212   }
00213 }
00214 ?>

Generated on Sun Feb 26 13:23:04 2006 for Savane PHP Frontend Developer Reference by  doxygen 1.4.4