// Copyright: Copyright (C) 2002-2010 Pristine Communications // Set the include path if (!defined("INCPATH_SET")) { require_once dirname(__FILE__) . "/incpath.inc.php"; } // Referenced subroutines require_once "monica/cgiemu.inc.php"; require_once "monica/lninfo.inc.php"; require_once "monica/requri.inc.php"; // getlang: Get the appropriate language from the user-agent. // Input: type: the type of language information to be returned // See lninfo.inc.php for the most current list of available types. // LN_NAME: Language name // LN_CHARSET: It's suggested character set // LN_FILENAME: It's proper format as part of a file name // LN_LOCALE: It's locale // LN_DATABASE: It's proper format as part of a database field name // LN_HTMLID: It's proper format as part of an HTML ID. // LN_SPACE_BREAK: If this language break lines at spaces // LN_IGNORE_CASE: If case can be ignored (can safely do strlower() and strupper()) // LN_COUNTRY_FIRST: If country should be listed first in a mail address // LN_DESC: It's long description, in English // LN_DESC_CURLC: It's long description in the current language (UTF-8) // LN_DESC_SELFLC: It's long description in its own language (UTF-8) function getlang($type = null) { $lang = _getlang_getlang(); // Return in the proper data type return !is_null($type)? ln($lang, $type): $lang; } // getcharset: Get the appropriate character set from the user-agent. function getcharset() { static $charset; // Obtained before if (isset($charset)) { return $charset; } // Default character set of this language $default = getlang(LN_CHARSET); // Obtain all the available character sets $all_charsets = _getlang_all_charsets(); // We have no choice if (count($all_charsets) < 2) { $charset = $all_charsets[0]; return $charset; } // Parse the character set by the Accept-Charset header $charset = _getlang_getcs_accept(); if (!is_null($charset)) { return $charset; } // Cannot parse - return the default $lang = $default; return $lang; } // _getlang_getlang: The real subroutine function _getlang_getlang() { static $lang; // Obtained before if (isset($lang)) { return $lang; } // Default fallback settings if (!array_key_exists("ALL_LINGUAS", $GLOBALS)) { $GLOBALS["ALL_LINGUAS"] = array("en"); } global $ALL_LINGUAS; if (!defined("DEFAULT_LANG")) { define("DEFAULT_LANG", "en"); } // Uni-lingual if (count($ALL_LINGUAS) == 1) { $lang = $ALL_LINGUAS[0]; return $lang; } // Check the file name for specified language // No setting environment in this case $lang = _getlang_getlang_filename(); if (!is_null($lang)) { return $lang; } // Methods below should set the language in the environment // Check the environment for specified language $lang = _getlang_getlang_env(); if (!is_null($lang)) { _getlang_getlang_setenv($lang); return $lang; } // Parse the language by the Accept-Language header $lang = _getlang_getlang_accept(); if (!is_null($lang)) { _getlang_getlang_setenv($lang); return $lang; } // Parse the language by the console locale $lang = _getlang_getlang_locale(); if (!is_null($lang)) { _getlang_getlang_setenv($lang); return $lang; } // Cannot parse - return the default $lang = DEFAULT_LANG; _getlang_getlang_setenv($lang); return $lang; } // _getlang_getlang_filename: Check the file name for specified language function _getlang_getlang_filename() { global $ALL_LINGUAS; // Check the file name format if (!preg_match("/\.([^\.\/]+)\.[^\.\/]+$/", REQUEST_PATH, $m)) { return null; } $langfile = $m[1]; // Check each language for its file name format for ($l = 0, $map = array(); $l < count($ALL_LINGUAS); $l++) { $lang = $ALL_LINGUAS[$l]; if ($langfile == ln($lang, LN_FILENAME)) { return $lang; } } // Not found return null; } // _getlang_getlang_env: Check the environment for specified language function _getlang_getlang_env() { global $ALL_LINGUAS; // Check the query string if ( array_key_exists("lang", $_GET) && in_array($_GET["lang"], $ALL_LINGUAS)) { return $_GET["lang"]; // Check the POSTed form } elseif ( array_key_exists("lang", $_POST) && in_array($_POST["lang"], $ALL_LINGUAS)) { return $_POST["lang"]; // Check the cookies } elseif ( array_key_exists("lang", $_COOKIE) && in_array($_COOKIE["lang"], $ALL_LINGUAS)) { return $_COOKIE["lang"]; // Check the session } elseif ( isset($_SESSION) && array_key_exists("lang", $_SESSION) && in_array($_SESSION["lang"], $ALL_LINGUAS)) { return $_SESSION["lang"]; } // Not set return null; } // _getlang_getlang_accept: Parse the language by the Accept-Language header // Refer to HTTP/1.1 section 14.4 for this algorism function _getlang_getlang_accept() { // Accept-Language not set if (!array_key_exists("HTTP_ACCEPT_LANGUAGE", $_SERVER)) { return null; } global $ALL_LINGUAS; // Split into language ranges $rngs = preg_split("/\s*,\s*/", trim($_SERVER["HTTP_ACCEPT_LANGUAGE"])); $rngqf = array(); // User Assigned quality factor foreach ($rngs as $range) { // Split into attributes $attrs = preg_split("/\s*;\s*/", trim($range)); // First piece is the language range $ln = array_shift($attrs); // Lower-case it $ln = strtolower($ln); // Find the quality factor foreach ($attrs as $attr) { // A numeric quality factor found if (strtolower(substr($attr, 0, 2)) == "q=" && is_numeric(substr($attr, 2))) { $rngqf[$ln] = substr($attr, 2) + 0; } } // Default quality factor to 1 if (!array_key_exists($ln, $rngqf)) { $rngqf[$ln] = 1; } } // The default quality factor if (array_key_exists("*", $rngqf)) { $defqf = $rngqf["*"]; unset($rngqf["*"]); } else { $defqf = 0; } // Language tags (what we have) $tagqf = array(); // Calculated quality factor for ($l = 0; $l < count($ALL_LINGUAS); $l++) { $ln = $ALL_LINGUAS[$l]; // Language tag, as specified in ISO $tag = ln($ln, LN_NAME); unset($match); // Matched range of the quality factor // Language ranges (what the user sent to match us) foreach (array_keys($rngqf) as $range) { // Exactly match or match a prefix if ( $tag == $range || substr($tag, 0, strlen($range)+1) == "$range-") { // Not matched yet if (!isset($match)) { $tagqf[$ln] = $rngqf[$range]; // Quality Factor $match = $range; // Record the matched range // A longer match range } elseif (strlen($range) > strlen($match)) { $tagqf[$ln] = $rngqf[$range]; // Quality Factor $match = $range; // Record the matched range } } } // Not matched - apply a default quality factor if (!array_key_exists($ln, $tagqf)) { $tagqf[$ln] = $defqf; } } // Drop unacceptable languages foreach (array_keys($tagqf) as $ln) { if ($tagqf[$ln] <= 0) { unset($tagqf[$ln]); } } // Nothing acceptable if (count($tagqf) == 0) { return null; } // Sort by the quality factor $GLOBALS["_GETLANG_TAGQF"] =& $tagqf; $GLOBALS["_GETLANG_DEFAULT"] = DEFAULT_LANG; $ln = array_keys($tagqf); usort($ln, "_getlang_cmp_tagqf"); unset($GLOBALS["_GETLANG_TAGQF"]); unset($GLOBALS["_GETLANG_DEFAULT"]); // A preferred match return $ln[0]; } // _getlang_getlang_locale: Parse the language by the console locale function _getlang_getlang_locale() { // Only work on console if (IS_CGI) { return null; } // Check these environment variables in order // See http://www.gnu.org/software/libc/manual/html_node/Using-gettextized-software.html $envs = array("LANGUAGE", "LC_ALL", "LC_MESSAGES", "LANG"); for ($i = 0, $lang = null; $i < count($envs); $i++) { $locale = getenv($envs[$i]); // Obtain the first valid one and discard the rest if ($locale !== false && $locale != "") { $lang = $locale; break; } } // No locale setting was found if (is_null($lang)) { return null; } // Remove the character set $lang = preg_replace("/\..*$/", "", $lang); // Lower-case it $lang = strtolower($lang); // Replace underscore with dash $lang = str_replace("_", "-", $lang); // en-us is en if ($lang == "en-us") { $lang = "en"; } // Not in our available languages list if (!in_array($lang, $GLOBALS["ALL_LINGUAS"])) { return null; } // Return it return $lang; } // _getlang_getlang_setenv: Set the language in the environment function _getlang_getlang_setenv($lang) { // Set the session variable if ( isset($_SESSION) && (!array_key_exists("lang", $_SESSION) || $_SESSION["lang"] != $lang)) { $_SESSION["lang"] = $lang; } // Set the cookie if ( (!array_key_exists("lang", $_COOKIE) || $_COOKIE["lang"] != $lang) && !headers_sent()) { setcookie("lang", $lang, time() + 86400 * 365, "/"); } return; } // _getlang_getcs_accept: Parse the character set by the Accept-Charset header // Refer to HTTP/1.1 section 14.2 for this algorism function _getlang_getcs_accept() { // Accept-Charset not set if (!array_key_exists("HTTP_ACCEPT_CHARSET", $_SERVER)) { return null; } // Obtain all the available character sets $all_charsets = _getlang_all_charsets(); // Split into character set ranges $rngs = preg_split("/\s*,\s*/", trim($_SERVER["HTTP_ACCEPT_CHARSET"])); $rngqf = array(); // User Assigned quality factor foreach ($rngs as $range) { // Split into attributes $attrs = preg_split("/\s*;\s*/", trim($range)); // First piece is the character set range $cs = array_shift($attrs); // Lower-case it $cs = strtolower($cs); // Find the quality factor foreach ($attrs as $attr) { // A numeric quality factor found if (strtolower(substr($attr, 0, 2)) == "q=" && is_numeric(substr($attr, 2))) { $rngqf[$cs] = substr($attr, 2) + 0; } } // Default quality factor to 1 if (!array_key_exists($cs, $rngqf)) { $rngqf[$cs] = 1; } } // The default quality factor if (array_key_exists("*", $rngqf)) { $defqf = $rngqf["*"]; unset($rngqf["*"]); } else { // Default ISO-8859-1 to 1 if (!array_key_exists("iso-8859-1", $rngqf)) { $rngqf["iso-8859-1"] = 1; } $defqf = 0; } $tagqf = array(); // Calculated quality factor // Character set tags (what we have) for ($l = 0; $l < count($all_charsets); $l++) { $cs = $all_charsets[$l]; $tag = strtolower($cs); // Character set ranges (what the user sent to match us) foreach (array_keys($rngqf) as $range) { // Matched if ($tag == $range) { $tagqf[$cs] = $rngqf[$range]; // Quality Factor } } // Not matched - apply a default quality factor if (!array_key_exists($cs, $tagqf)) { $tagqf[$cs] = $defqf; } } // Drop unacceptable languages foreach (array_keys($tagqf) as $cs) { if ($tagqf[$cs] <= 0) { unset($tagqf[$cs]); } } // Nothing acceptable if (count($tagqf) == 0) { return null; } // Sort by the quality factor $GLOBALS["_GETLANG_TAGQF"] =& $tagqf; $GLOBALS["_GETLANG_DEFAULT"] = getlang(LN_CHARSET); $cs = array_keys($tagqf); usort($cs, "_getlang_cmp_tagqf"); unset($GLOBALS["_GETLANG_TAGQF"]); unset($GLOBALS["_GETLANG_DEFAULT"]); // A preferred match return $cs[0]; } // _getlang_all_charsets: Obtain all the available character sets // Available character sets are the default character set of this // language, and UTF-8 function _getlang_all_charsets() { static $charsets; if (isset($charsets)) { return $charsets; } $charsets = array(); $charsets[] = getlang(LN_CHARSET); $charsets[] = "UTF-8"; $charsets = array_values(array_unique($charsets)); return $charsets; } // _getlang_cmp_tagqf: Compare the quality factor of the tags function _getlang_cmp_tagqf($a, $b) { global $_GETLANG_TAGQF, $_GETLANG_DEFAULT; if ($_GETLANG_TAGQF[$a] != $_GETLANG_TAGQF[$b]) { return $_GETLANG_TAGQF[$b] < $_GETLANG_TAGQF[$a]? -1: 1; } if ($a == $_GETLANG_DEFAULT) { return -1; } if ($b == $_GETLANG_DEFAULT) { return 1; } return 0; } ?>