Source for file _functions_locale.php
Documentation is available at _functions_locale.php
* Handling of locales and i18n
* b2evolution - {@link http://b2evolution.net/}
* Released under GNU GPL License - {@link http://b2evolution.net/about/license.html}
* @copyright (c)2003-2005 by Francois PLANQUE - {@link http://fplanque.net/}
if( !defined('DB_USER') ) die( 'Please, do not access this page directly.' );
* Translate a text to the desired locale (b2evo localization only)
* or to the current locale
* @param string String to translate, '' to get language file info (as in gettext spec)
* @param string locale to translate to, '' to use current locale (basic gettext does only support '')
{ // We are going to use GETTEXT
function T_( $string, $req_locale =
'' )
global $current_messages;
if( empty( $req_locale ) ||
$req_locale ==
$current_messages )
{ // We have not asked for a different locale than the currently active one:
// We have asked for a funky locale... we'll get english instead:
{ // We are going to use b2evo localization:
function T_( $string, $req_locale =
'' )
global $trans, $current_locale, $locales;
// By default we use the current locale:
if( empty($req_locale) ) $req_locale =
$current_locale;
return $string; // don't translate if we have no locale
$messages =
$locales[$req_locale]['messages'];
// replace special characters that to msgid-equivalents
$search =
str_replace( array("\n", "\r", "\t"), array('\n', '', '\t'), $string );
// echo "Translating ", $search, " to $messages<br />";
if( !isset
($trans[ $messages ] ) )
{ // Translations for current locale have not yet been loaded:
// echo 'LOADING', dirname(__FILE__). '/../locales/'. $messages. '/_global.php';
@include_once dirname(__FILE__
).
'/../locales/'.
$messages.
'/_global.php';
if( !isset
($trans[ $messages ] ) )
{ // Still not loaded... file doesn't exist, memorize that no translation are available
// echo 'file not found!';
$trans[ $messages ] =
array();
if( isset
( $trans[ $messages ][ $search ] ) )
{ // If the string has been translated:
return $trans[ $messages ][ $search ];
// Return the English string:
{ // We are not localizing at all:
function T_( $string, $req_locale =
'' )
* Nevertheless, the string will be extracted by the gettext tools
* Temporarily switch to another locale
* {@internal locale_temp_switch(-)}}
* @param string locale to activate
global $saved_locale, $current_locale;
if( !isset
( $saved_locale ) ) $saved_locale =
array();
* Restore the locale in use before the switch
* {@internal locale_restore_previous(-)}}
* returns true if locale has been changed
* @param string locale to activate
global $use_l10n, $locales, $current_locale, $current_messages, $current_charset, $weekday, $month;
if( $locale ==
$current_locale ||
empty( $locale ) )
$current_locale =
$locale;
$current_charset =
$locales[ $locale ][ 'charset' ];
$current_messages =
$locales[ $locale ][ 'messages' ];
// Activate translations in gettext:
{ // Only if we are using GETTEXT ( if not, look into T_(-) ...)
# Activate the locale->language in gettext:
// Note: default of safe_mode_allowed_env_vars is "PHP_ ",
// so you need to add "LC_" by editing php.ini.
putenv('LC_ALL='.
$current_messages);
// Specify location of translation tables and bind to domain
bindtextdomain( 'messages', dirname(__FILE__
).
'/../locales' );
# Activate the charset for conversions in gettext:
{ // Only if this gettext supports code conversions
bind_textdomain_codeset( 'messages', $current_charset );
# Set locale for default language:
# This will influence the way numbers are displayed, etc.
// We are not using this right now, the default 'C' locale seems just fine
// setlocale( LC_ALL, $locale );
# Use this to check locale: (not relevant)
// echo setlocale( LC_ALL, 0 );
* Find first locale matching lang
global $locales, $default_locale;
foreach( $locales as $locale =>
$locale_params )
if( substr( $locale, 0 ,2 ) ==
$lang )
{ // found first matching locale
if( $fallback_to_default )
* Displays/Returns the current locale. (for backward compatibility)
* {@internal locale_lang(-)}}
* @param boolean true (default) if we want it to be outputted
* @return string current locale, if $disp = false
* Returns the charset of the current locale
* {@internal locale_charset(-)}}
* Returns the current locale's default date format
* {@internal locale_datefmt(-)}}
global $locales, $current_locale;
return $locales[$current_locale]['datefmt'];
* Returns the current locale's default time format
* {@internal locale_timefmt(-)}}
global $locales, $current_locale;
return $locales[$current_locale]['timefmt'];
* Template function: Display locale flag
* {@internal locale_flag(-)}}
* @param string locale to use, '' for current
* @param string collection name (subdir of img/flags)
* @param string name of class for IMG tag
* @param string deprecated HTML align attribute
* @param boolean to echo or not
* @param mixed use absolute url (===true) or path to flags directory
function locale_flag( $locale =
'', $collection =
'w16px', $class =
'flag', $align =
'', $disp =
true, $absoluteurl =
true )
global $locales, $current_locale, $core_dirout, $img_subdir, $img_url;
if( empty($locale) ) $locale =
$current_locale;
if( ! is_file(dirname(__FILE__
).
'/'.
$core_dirout.
'/'.
$img_subdir.
'/flags/'.
$collection.
'/'.
$country.
'.gif') )
if( $absoluteurl !==
true )
$iurl =
$img_url.
'/flags';
$r =
'<img src="'.
$iurl.
'/'.
$collection.
'/'.
$country.
'.gif" alt="' .
(isset
($locales[$locale]['name']) ?
$locales[$locale]['name'] :
$locale) .
if( !empty( $class ) ) $r .=
' class="'.
$class.
'"';
if( !empty( $align ) ) $r .=
' align="'.
$align.
'"';
* Outputs a <option> set with default locale selected
global $locales, $default_locale;
if( empty( $default ) ) $default =
$default_locale;
foreach( $locales as $this_localekey =>
$this_locale )
if( $this_locale['enabled'] ||
$this_localekey ==
$default )
echo
'<option value="'.
$this_localekey.
'"';
if( $this_localekey ==
$default ) echo
' selected="selected"';
echo
'>'.
T_($this_locale['name']).
'</option>';
* Detect language from HTTP_ACCEPT_LANGUAGE
* First matched full locale code in HTTP_ACCEPT_LANGUAGE will win
* Otherwise, first locale in table matching a lang code will win
* {@internal locale_from_httpaccept(-)}}
* @return locale made out of HTTP_ACCEPT_LANGUAGE or $default_locale, if no match
global $locales, $default_locale;
if( isset
($_SERVER['HTTP_ACCEPT_LANGUAGE']) )
// echo $_SERVER['HTTP_ACCEPT_LANGUAGE'];
$accept =
strtolower( $_SERVER['HTTP_ACCEPT_LANGUAGE'] );
// pre_dump($accept, 'http_accept_language');
$selected_match_pos =
10000;
$selected_full_match =
false;
foreach( $locales as $localekey =>
$locale )
if( ! $locale['enabled'] )
{ // We only want to use activated locales
// echo '<br />searching ', $localekey, ' in HTTP_ACCEPT_LANGUAGE ';
{ // We found full locale
if( !$selected_full_match ||
($pos <=
$selected_match_pos) )
{ // This is a better choice than what we had before OR EQUIVALENT but with exact locale
// echo $localekey.' @ '.$pos.' is better than '.
// $selected_locale.' @ '.$selected_match_pos.'<br />';
$selected_locale =
$localekey;
$selected_match_pos =
$pos;
$selected_full_match =
true;
// else echo $localekey.' @ '.$pos.' is not better than '.
// $selected_locale.' @ '.$selected_match_pos.'<br />';
if( !$selected_full_match &&
($pos =
strpos( $accept, substr($localekey, 0, 2) )) !==
false )
{ // We have no exact match yet but found lang code match
if( $pos <
$selected_match_pos )
{ // This is a better choice than what we had before
// echo $localekey.' @ '.$pos.' is better than '.
// $selected_locale.' @ '.$selected_match_pos.'<br />';
$selected_locale =
$localekey;
$selected_match_pos =
$pos;
// else echo $localekey.' @ '.$pos.' is not better than '.
// $selected_locale.' @ '.$selected_match_pos.'<br />';
if( !empty($selected_locale) )
* user sort function to sort locales by priority
return $a['priority'] -
$b['priority'];
* load locales from DB into $locales array. Also sets $default_locale.
global $DB, $locales, $default_locale, $Settings;
$usedprios =
array(); // remember which priorities are used already.
loc_locale, loc_charset, loc_datefmt, loc_timefmt, loc_name,
loc_messages, loc_priority, loc_enabled
FROM T_locales ORDER BY loc_priority';
$rows =
$DB->get_results( $query, ARRAY_A );
if( count( $rows ) ) foreach( $rows as $row )
{ // Loop through loaded locales:
if( $row['loc_priority'] ==
$priocounter )
{ // priority conflict (the same)
$priocounter =
$row['loc_priority'];
//remember that we used this
$usedprios[] =
$priocounter;
$locales[ $row['loc_locale'] ] =
array(
'charset' =>
$row[ 'loc_charset' ],
'datefmt' =>
$row[ 'loc_datefmt' ],
'timefmt' =>
$row[ 'loc_timefmt' ],
'name' =>
$row[ 'loc_name' ],
'messages' =>
$row[ 'loc_messages' ],
'priority' =>
$priocounter,
'enabled' =>
$row[ 'loc_enabled' ],
// set default priorities, if nothing was set in DB.
// Missing "priority gaps" will get filled here.
{ // we have locales from conf file that need a priority
foreach( $locales as $lkey =>
$lval )
{ // Loop through memory locales:
if( !isset
($lval['priority']) )
{ // Found one that has no assigned priority
while( in_array( $priocounter, $usedprios ) )
// Priocounter has max value
$locales[$lkey]['priority'] =
$priocounter;
$usedprios[] =
$priocounter;
uasort( $locales, 'locale_priosort' );
// overwrite default_locale from DB settings - if enabled.
// Checks also if previous $default_locale is enabled. Defaults to en-EU, even if not enabled.
$locale_fromdb =
$Settings->get('default_locale');
if( $locales[$locale_fromdb]['enabled'] )
$default_locale = $locale_fromdb;
elseif( !$locales[$default_locale]['enabled'] )
$default_locale = 'en-EU';
$default_locale =
$locale_fromdb;
* write $locales array to DB table
foreach( $_POST as $pkey =>
$pval ) if( preg_match('/loc_(\d+)_(.*)/', $pkey, $matches) )
if( $matches[1] !=
$lnr )
{ // we have a new locale
// checkboxes default to 0
$templocales[ $plocale ]['enabled'] =
0;
elseif( $lnr !=
0 ) // be sure to have catched a locale before
$query =
"REPLACE INTO T_locales ( loc_locale, loc_charset, loc_datefmt, loc_timefmt, loc_name, loc_messages, loc_priority, loc_enabled ) VALUES ";
foreach( $locales as $localekey =>
$lval )
if( empty($lval['messages']) )
{ // if not explicit messages file is given we'll translate the locale
$lval['messages'] =
strtr($localekey, '-', '_');
$query =
substr($query, 0, -
2);