Source for file languages.php
Documentation is available at languages.php
* SquirrelMail internationalization functions
* This file contains variuos functions that are needed to do
* internationalization of SquirrelMail.
* Internally the output character set is used. Other characters are
* encoded using Unicode entities according to HTML 4.0.
* Before 1.5.2 functions were stored in functions/i18n.php. Script is moved
* because it executes some code in order to detect functions supported by
* existing PHP installation and implements fallback functions when required
* functions are not available. Scripts in functions/ directory should not
* setup anything when they are loaded.
* @copyright © 1999-2006 The SquirrelMail Project Team
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* @version $Id: languages.php,v 1.5 2006/08/06 08:46:36 tokul Exp $
* Gettext bindtextdomain wrapper.
* Wrapper solves differences between php versions in order to provide
* ngettext support. Should be used if translation uses ngettext
* @param string $domain gettext domain name
* @param string $dir directory that contains all translations
* @return string path to translation directory
global $l10n, $gettext_flags, $sm_notAlias;
// gettext extension without ngettext
if (substr($dir, -
1) !=
'/') $dir .=
'/';
$mofile=
$dir .
$sm_notAlias .
'/LC_MESSAGES/' .
$domain .
'.mo';
* Gettext textdomain wrapper.
* Makes sure that gettext_domain global is modified.
* @param string $name gettext domain name
* @return string gettext domain name
* php setlocale function wrapper
* From php 4.3.0 it is possible to use arrays in order to set locale.
* php gettext extension works only when locale is set. This wrapper
* function allows to use more than one locale name.
* @param int $category locale category name. Use php named constants
* (LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME)
* @param mixed $locale option contains array with possible locales or string with one locale
* @return string name of set locale or false, if all locales fail.
* @see http://www.php.net/setlocale
// string with only one locale
// older php version (second setlocale argument must be string)
while ( ! $ret &&
$index<
count($locale)) {
// php 4.3.0 or better, use entire array
if (preg_match("/^.*\/.*\/.*\/.*\/.*\/.*$/",$ret)) {
* Welcome to We-Don't-Follow-Own-Fine-Manual department
* OpenBSD 3.8, 3.9-current and maybe later versions
* return invalid response to setlocale command.
* SM bug report #1427512.
* Converts string from given charset to charset, that can be displayed by user translation.
* Function by default returns html encoded strings, if translation uses different encoding.
* If Japanese translation is used - function returns string converted to euc-jp
* If iconv or recode functions are enabled and translation uses utf-8 - function returns utf-8 encoded string.
* If $charset is not supported - function returns unconverted string.
* sanitizing of html tags is also done by this function.
* @param string $string Text to be decoded
* @param boolean $force_decode converts string to html without $charset!=$default_charset check.
* Argument is available since 1.5.1 and 1.4.5.
* @param boolean $save_html disables htmlspecialchars() in order to preserve
* html formating. Use with care. Available since 1.5.1
* @return string decoded string
function charset_decode ($charset, $string, $force_decode=
false, $save_html=
false) {
if (isset
($languages[$squirrelmail_language]['XTRA_CODE']) &&
function_exists($languages[$squirrelmail_language]['XTRA_CODE'] .
'_decode')) {
$string =
call_user_func($languages[$squirrelmail_language]['XTRA_CODE'] .
'_decode', $string);
// Variables that allow to use functions without function_exist() calls
if (! isset
($use_php_recode) ||
$use_php_recode==
"" ) {
if (! isset
($use_php_iconv) ||
$use_php_iconv==
"" ) {
// Don't do conversion if charset is the same.
if ( ! $force_decode &&
$charset ==
strtolower($default_charset) )
// catch iso-8859-8-i thing
if ( $charset ==
"iso-8859-8-i" )
* Recode converts html special characters automatically if you use
* 'charset..html' decoding. There is no documented way to put -d option
* into php recode function call.
if ( $default_charset ==
"utf-8" ) {
// other charsets can be converted to utf-8 without loss.
// and output string is smaller
$string =
recode_string($charset .
"..utf-8",$string);
$string =
recode_string($charset .
"..html",$string);
// recode does not convert single quote, htmlspecialchars does.
// undo html specialchars
$string=
str_replace(array('&','"','<','>'),
array('&','"','<','>'),$string);
// iconv functions does not have html target and can be used only with utf-8
if ( $use_php_iconv &&
$default_charset==
'utf-8') {
$string =
iconv($charset,$default_charset,$string);
// If we don't use recode and iconv, we'll do it old way.
/* All HTML special characters are 7 bit and can be replaced first */
/* controls cpu and memory intensive decoding cycles */
if (! isset
($aggressive_decoding) ||
$aggressive_decoding==
"" ) {
$aggressive_decoding=
false; }
$decodefile=
SM_PATH .
'functions/decode/' .
$decode .
'.php';
include_once($decodefile);
// send $save_html argument to decoding function. needed for iso-2022-xx decoding.
$ret =
call_user_func('charset_decode_'.
$decode, $string, $save_html);
* Converts html string to given charset
* @param boolean $htmlencode keep htmlspecialchars encoding
$encodefile=
SM_PATH .
'functions/encode/' .
$encode .
'.php';
include_once($encodefile);
// function replaces all 8bit html entities with question marks.
// it is used when other encoding functions are unavailable
include_once(SM_PATH .
'functions/encode/us_ascii.php');
* fix for yahoo users that remove all us-ascii related things
* Undo html special chars, some places (like compose form) have
* own sanitizing functions and don't need html symbols.
* Undo chars only after encoding in order to prevent conversion of
* html entities in plain text emails.
$ret =
str_replace(array('&','>','<','"'),array('&','>','<','"'),$ret);
* Combined decoding and encoding functions
* If conversion is done to charset different that utf-8, unsupported symbols
* will be replaced with question marks.
* @param string $in_charset initial charset
* @param string $string string that has to be converted
* @param string $out_charset final charset
* @param boolean $htmlencode keep htmlspecialchars encoding
* @return string converted string
function charset_convert($in_charset,$string,$out_charset,$htmlencode=
true) {
* Makes charset name suitable for decoding cycles
* @param string $charset Name of charset
* @return string $charset Adjusted name of charset
/* remove minus and characters that might be used in paths from charset
* name in order to be able to use it in function names and include calls.
// OE ks_c_5601_1987 > cp949
$charset=
str_replace('ks_c_5601_1987','cp949',$charset);
// Moz x-windows-949 > cp949
// windows-125x and cp125x charsets
// iso-8859-8-i -> iso-8859-8
// use same cycle until I'll find differences
$charset=
str_replace('iso_8859_8_i','iso_8859_8',$charset);
* Set up the language to be output
* if $do_search is true, then scan the browser information
* for a possible language that we know
* Function sets system locale environment (LC_ALL, LANG, LANGUAGE),
* gettext translation bindings and html header information.
* Function returns error codes, if there is some fatal error.
* 1 = mbstring support is not present,
* 2 = mbstring support is not present, user's translation reverted to en_US.
* @param string $sm_language translation used by user's interface
* @param bool $do_search use browser's preferred language detection functions. Defaults to false.
* @param bool $default set $sm_language to $squirrelmail_default_language if language detection fails or language is not set. Defaults to false.
* @return int function execution error codes.
function set_up_language($sm_language, $do_search =
false, $default =
false) {
static $SetupAlready =
0;
global $use_gettext, $languages,
$squirrelmail_language, $squirrelmail_default_language, $default_charset,
$sm_notAlias, $username, $data_dir;
* If function is asked to detect preferred language
* OR squirrelmail default language is set to empty string
* squirrelmail language ($sm_language) is empty string
* (not set in user's prefs and no cookie with language info)
* browser provides list of preferred languages
* get preferred language from HTTP_ACCEPT_LANGUAGE header
if (($do_search ||
empty($squirrelmail_default_language)) &&
// TODO: use more than one language, if first language is not available
// FIXME: function assumes that string contains two or more characters.
// FIXME: some languages use 5 chars
$sm_language =
substr($accept_lang, 0, 2);
* If language preference is not set OR script asks to use default language
* default squirrelmail language is not set to empty string
* use default squirrelmail language value from configuration.
if ((!$sm_language||
$default) &&
! empty($squirrelmail_default_language)) {
$squirrelmail_language =
$squirrelmail_default_language;
$sm_language =
$squirrelmail_default_language;
/** provide failsafe language when detection fails */
if (! $sm_language) $sm_language=
'en_US';
$sm_notAlias =
$sm_language;
// Catching removed translation
// System reverts to English translation if user prefs contain translation
// that is not available in $languages array
if (!isset
($languages[$sm_notAlias])) {
while (isset
($languages[$sm_notAlias]['ALIAS'])) {
$sm_notAlias =
$languages[$sm_notAlias]['ALIAS'];
if ( isset
($sm_language) &&
isset
($languages[$sm_notAlias]['CHARSET']) ) {
// set codeset in order to avoid gettext charset conversions
// Japanese translation uses different internal charset
if ($sm_notAlias ==
'ja_JP') {
bind_textdomain_codeset ('squirrelmail', 'EUC-JP');
bind_textdomain_codeset ('squirrelmail', $languages[$sm_notAlias]['CHARSET'] );
// Use LOCALE key, if it is set.
if (isset
($languages[$sm_notAlias]['LOCALE'])){
$longlocale=
$languages[$sm_notAlias]['LOCALE'];
$longlocale=
$sm_notAlias;
// check if locale is set and assign that locale to $longlocale
// in order to use it in putenv calls.
// setting of all locales failed.
// we need string instead of array used in LOCALE key.
$longlocale=
$sm_notAlias;
if ( !((bool)
ini_get('safe_mode')) &&
getenv( 'LC_ALL' ) !=
$longlocale ) {
putenv( "LC_ALL=$longlocale" );
putenv( "LANGUAGE=$longlocale" );
if ($sm_notAlias==
'tr_TR') putenv( "LC_CTYPE=C" );
// Workaround for plugins that use numbers with floating point
// It might be removed if plugins use correct decimal delimiters
// according to locale settings.
// Workaround for specific Turkish strtolower/strtoupper rules.
// Many functions expect English conversion rules.
if ($sm_notAlias==
'tr_TR') setlocale(LC_CTYPE,'C');
* Set text direction/alignment variables
* When language environment is setup, scripts can use these globals
* without accessing $languages directly and making checks for optional
global $text_direction, $left_align, $right_align;
if (isset
($languages[$sm_notAlias]['DIR']) &&
$languages[$sm_notAlias]['DIR'] ==
'rtl') {
* @global string $text_direction
* @global string $left_align
* @global string $right_align
$squirrelmail_language =
$sm_notAlias;
if ($squirrelmail_language ==
'ja_JP') {
header ('Content-Type: text/html; charset=EUC-JP');
// Error messages can't be displayed here
// Revert to English if possible.
setPref($data_dir, $username, 'language', "en_US");
// stop further execution in order not to get php errors on mb_internal_encoding().
mb_internal_encoding('EUC-JP');
} elseif ($squirrelmail_language ==
'en_US') {
header( 'Content-Type: text/html; charset=' .
$default_charset );
header( 'Content-Type: text/html; charset=' .
$languages[$sm_notAlias]['CHARSET'] );
* mbstring.func_overload fix (#929644).
* php mbstring extension can replace standard string functions with their multibyte
* equivalents. See http://www.php.net/ref.mbstring#mbstring.overload. This feature
* was added in php v.4.2.0
* Some SquirrelMail functions work with 8bit strings in bytes. If interface is forced
* to use mbstring functions and mbstring internal encoding is set to multibyte charset,
* interface can't trust regular string functions. Due to mbstring overloading design
* limits php scripts can't control this setting.
* This hack should fix some issues related to 8bit strings in passwords. Correct fix is
* to disable mbstring overloading. Japanese translation uses different internal encoding.
if ($squirrelmail_language !=
'ja_JP' &&
(int)
ini_get('mbstring.func_overload')!=
0) {
mb_internal_encoding('pass');
* Sets default_charset variable according to the one that is used by user's translations.
* Function changes global $default_charset variable in order to be sure, that it
* contains charset used by user's translation. Sanity of $squirrelmail_language
* and $default_charset combination is also tested.
* There can be a $default_charset setting in the
* config.php file, but the user may have a different language
* selected for a user interface. This function checks the
* language selected by the user and tags the outgoing messages
* with the appropriate charset corresponding to the language
* selection. This is "more right" (tm), than just stamping the
* message blindly with the system-wide $default_charset.
$my_language =
getPref($data_dir, $username, 'language');
$my_language =
$squirrelmail_language ;
// Catch removed translation
if (!isset
($languages[$my_language])) {
while (isset
($languages[$my_language]['ALIAS'])) {
$my_language =
$languages[$my_language]['ALIAS'];
$my_charset =
$languages[$my_language]['CHARSET'];
if ($my_language!=
'en_US') {
$default_charset =
$my_charset;
* Replaces non-braking spaces inserted by some browsers with regular space
* This function can be used to replace non-braking space symbols
* that are inserted in forms by some browsers instead of normal
* @param string $string Text that needs to be cleaned
* @param string $charset Charset used in text
* @return string Cleaned text
// reduce number of case statements
$output_charset=
"iso-8859-x";
$output_charset=
"cp125x";
$output_charset=
"koi8-x";
if (! isset
($output_charset)){
// where is non-braking space symbol
// don't change string if charset is unmatched
// return space instead of non-braking space.
* Function informs if it is safe to convert given charset to the one that is used by user.
* It is safe to use conversion only if user uses utf-8 encoding and when
* converted charset is similar to the one that is used by user.
* @param string $input_charset Charset of text that needs to be converted
* @return bool is it possible to convert to user's charset
if (isset
($lossy_encoding) &&
$lossy_encoding )
// Is user's locale Unicode based ?
if ( $default_charset ==
"utf-8" ) {
// Charsets that are similar
switch ($default_charset) {
if ( $input_charset ==
"iso-8859-5" ||
$input_charset ==
"koi8-r" ||
$input_charset ==
"koi8-u" ) {
if ( $input_charset ==
"iso-8859-13" ||
$input_charset ==
"iso-8859-4" ) {
if ( $input_charset ==
"iso-8859-13" ||
$input_charset ==
"windows-1257" ) {
if ( $input_charset ==
"windows-1251" ||
$input_charset ==
"koi8-r" ||
$input_charset ==
"koi8-u" ) {
if ( $input_charset ==
"iso-8859-4" ||
$input_charset ==
"windows-1257" ) {
if ( $input_charset ==
"windows-1251" ||
$input_charset ==
"iso-8859-5" ||
$input_charset ==
"koi8-u" ) {
if ( $input_charset ==
"windows-1251" ||
$input_charset ==
"iso-8859-5" ||
$input_charset ==
"koi8-r" ) {
* Converts html character entities to numeric entities
* SquirrelMail encoding functions work only with numeric entities.
* This function fixes issues with decoding functions that might convert
* some symbols to character entities. Issue is specific to PHP recode
* extension decoding. Function is used internally in charset_convert()
* @param string $str string that might contain html character entities
* @return string string with character entities converted to decimals.
// Spacing Modifier Letters
'ϑ' =>
'ϑ',
'ℵ' =>
'ℵ',
// Mathematical Operators
// Miscellaneous Technical
/* ------------------------------ main --------------------------- */
global $squirrelmail_language, $languages, $use_gettext;
$squirrelmail_language =
'';
* Array specifies the available translations.
* $languages['language']['variable'] = 'value'
* Possible 'variable' names:
* NAME - Translation name in English
* CHARSET - Encoding used by translation
* ALIAS - used when 'language' is only short name and 'value' should provide long language name
* ALTNAME - Native translation name. Any 8bit symbols must be html encoded.
* LOCALE - Full locale name (in xx_XX.charset format). It can use array with more than one locale name since 1.4.5 and 1.5.1
* DIR - Text direction. Used to define Right-to-Left languages. Possible values 'rtl' or 'ltr'. If undefined - defaults to 'ltr'
* XTRA_CODE - translation uses special functions. See doc/i18n.txt
* Each 'language' definition requires NAME+CHARSET or ALIAS variables.
* @global array $languages
$languages['en_US']['NAME'] =
'English';
$languages['en_US']['CHARSET'] =
'iso-8859-1';
$languages['en_US']['LOCALE'] =
'en_US.ISO8859-1';
$languages['en']['ALIAS'] =
'en_US';
* Automatic translation loading from setup.php files.
* Solution for bug. 1240889.
* setup.php file can contain $languages array entries and XTRA_CODE functions.
while($lang_dir=
$localedir->read()) {
// remove trailing slash, if present
if (substr($lang_dir,-
1)==
'/') {
$lang_dir =
substr($lang_dir,0,-
1);
if ($lang_dir !=
'..' &&
$lang_dir !=
'.' &&
$lang_dir !=
'CVS' &&
include_once(SM_PATH.
'locale/'.
$lang_dir.
'/setup.php');
/* Detect whether gettext is installed. */
/* If gettext is fully loaded, cool */
if ($gettext_flags ==
15) {
/* If ngettext support is missing, load it */
elseif ($gettext_flags ==
7) {
// load internal ngettext functions
include_once(SM_PATH .
'class/l10n.class.php');
include_once(SM_PATH .
'functions/ngettext.php');
/* If we can fake gettext, try that */
elseif ($gettext_flags ==
0) {
include_once(SM_PATH .
'functions/gettext.php');
/* Uh-ho. A weird install */
if (! $gettext_flags & 1) {
* Function is used as replacement in broken installs
if (! $gettext_flags & 2) {
* Function is used as replacement in broken installs
if (! $gettext_flags & 4) {
* Function is used as replacemet in broken installs
if (! $gettext_flags & 8) {
* Function is used as replacemet in broken installs
* Replacement for broken setups.
* Replacement for broken setups
function dngettext($domain,$str1,$strn,$number) {
return ($number==
1 ?
$str1 :
$strn);
Documentation generated on Sat, 07 Oct 2006 16:12:05 +0300 by phpDocumentor 1.3.0RC6