[ Index ] |
|
Code source de b2evolution 2.1.0-beta |
1 <?php 2 /** 3 * This file implements functions for handling locales and i18n. 4 * 5 * This file is part of the evoCore framework - {@link http://evocore.net/} 6 * See also {@link http://sourceforge.net/projects/evocms/}. 7 * 8 * @copyright (c)2003-2007 by Francois PLANQUE - {@link http://fplanque.net/} 9 * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}. 10 * 11 * {@internal License choice 12 * - If you have received this file as part of a package, please find the license.txt file in 13 * the same folder or the closest folder above for complete license terms. 14 * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/) 15 * then you must choose one of the following licenses before using the file: 16 * - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php 17 * - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php 18 * }} 19 * 20 * {@internal Open Source relicensing agreement: 21 * Daniel HAHLER grants Francois PLANQUE the right to license 22 * Daniel HAHLER's contributions to this file and the b2evolution project 23 * under any OSI approved OSS license (http://www.opensource.org/licenses/). 24 * }} 25 * 26 * @package evocore 27 * 28 * {@internal Below is a list of authors who have contributed to design/coding of this file: }} 29 * @author blueyed: Daniel HAHLER. 30 * @author fplanque: Francois PLANQUE. 31 * 32 * @todo Make it a class / global object! 33 * - Provide (static) functions to extract .po files / generate _global.php files (single quoted strings!) 34 * 35 * @version $Id: _locale.funcs.php,v 1.4 2007/11/03 21:04:27 fplanque Exp $ 36 */ 37 if( !defined('EVO_CONFIG_LOADED') ) die( 'Please, do not access this page directly.' ); 38 39 40 /** 41 * TRANSLATE! 42 * 43 * Translate a text to the desired locale (b2evo localization only) 44 * or to the current locale 45 * 46 * @param string String to translate, '' to get language file info (as in gettext spec) 47 * @param string locale to translate to, '' to use current locale (basic gettext does only support '') 48 */ 49 if( ($use_l10n == 1) && function_exists('_') ) 50 { // We are going to use GETTEXT 51 52 function T_( $string, $req_locale = '' ) 53 { 54 global $current_locale, $locales, $evo_charset; 55 56 if( empty( $req_locale ) ) 57 { 58 if( empty( $current_locale ) ) 59 { // don't translate if we have no locale 60 return $string; 61 } 62 63 $req_locale = $current_locale; 64 } 65 66 if( $req_locale == $current_locale ) 67 { // We have not asked for a different locale than the currently active one: 68 $r = _($string); 69 70 $messages_charset = $locales[$req_locale]['charset']; 71 } 72 else 73 { // We have asked for another locale... 74 if( locale_temp_switch( $req_locale ) ) 75 { 76 global $current_charset; 77 $r = _($string); 78 $messages_charset = $current_charset; 79 locale_restore_previous(); 80 } 81 else 82 { // Locale could not be activated: 83 $r = $string; 84 $messages_charset = 'iso-8859-1'; // charset of our .php files 85 } 86 } 87 88 if( ! empty($evo_charset) ) // this extra check is needed, because $evo_charset may not yet be determined.. :/ 89 { 90 $r = convert_charset( $r, $evo_charset, $messages_charset ); 91 } 92 93 return $r; 94 } 95 96 } 97 elseif( $use_l10n == 2 ) 98 { // We are going to use evoCore localization: 99 100 /** 101 * @ignore 102 */ 103 function T_( $string, $req_locale = '' ) 104 { 105 /** 106 * The translations keyed by locale. They get loaded through include() of _global.php 107 * @var array 108 * @static 109 */ 110 static $trans = array(); 111 112 global $current_locale, $locales, $Debuglog, $locales_path, $evo_charset; 113 114 115 if( empty($req_locale) ) 116 { // By default we use the current locale 117 if( empty( $current_locale ) ) 118 { // don't translate if we have no locale 119 return $string; 120 } 121 122 $req_locale = $current_locale; 123 } 124 125 if( !isset( $locales[$req_locale]['messages'] ) ) 126 { 127 $Debuglog->add( 'No messages file path for locale. $locales["' 128 .$req_locale.'"] is '.var_export( @$locales[$req_locale], true ), 'locale' ); 129 $locales[$req_locale]['messages'] = false; 130 } 131 132 $messages = $locales[$req_locale]['messages']; 133 134 // replace special characters to msgid-equivalents 135 $search = str_replace( array("\n", "\r", "\t"), array('\n', '', '\t'), $string ); 136 137 // echo "Translating ", $search, " to $messages<br />"; 138 139 if( ! isset($trans[ $messages ] ) ) 140 { // Translations for current locale have not yet been loaded: 141 // echo 'LOADING', dirname(__FILE__).'/../locales/'. $messages. '/_global.php'; 142 if( file_exists($locales_path.$messages.'/_global.php') ) 143 { 144 include_once $locales_path.$messages.'/_global.php'; 145 } 146 if( ! isset($trans[ $messages ] ) ) 147 { // Still not loaded... file doesn't exist, memorize that no translations are available 148 // echo 'file not found!'; 149 $trans[ $messages ] = array(); 150 151 /* 152 May be an english locale without translation. 153 TODO: when refactoring locales, assign a key for 'original english'. 154 $Debuglog->add( 'No messages found for locale ['.$req_locale.'], 155 message file [/locales/'.$messages.'/_global.php]', 'locale' );*/ 156 157 } 158 } 159 160 if( isset( $trans[ $messages ][ $search ] ) ) 161 { // If the string has been translated: 162 $r = $trans[ $messages ][ $search ]; 163 $messages_charset = $locales[$req_locale]['charset']; 164 } 165 else 166 { 167 // echo "Not found!"; 168 // Return the English string: 169 $r = $string; 170 $messages_charset = 'iso-8859-1'; // our .php file encoding 171 } 172 173 if( ! empty($evo_charset) ) // this extra check is needed, because $evo_charset may not yet be determined.. :/ 174 { 175 $r = convert_charset( $r, $evo_charset, $messages_charset ); 176 } 177 178 return $r; 179 } 180 181 } 182 else 183 { // We are not localizing at all: 184 185 /** 186 * @ignore 187 */ 188 function T_( $string, $req_locale = '' ) 189 { 190 return $string; 191 } 192 193 } 194 195 196 /** 197 * Translate and escape single quotes. 198 * 199 * This is to be used mainly for Javascript strings. 200 * 201 * @uses T_() 202 * @param string String to translate 203 * @param string Locale to use 204 * @return string 205 */ 206 function TS_( $string, $req_locale = '' ) 207 { 208 return str_replace( "'", "\'", T_( $string, $req_locale ) ); 209 } 210 211 212 /** 213 * Temporarily switch to another locale 214 * 215 * Calls can be nested, see {@link locale_restore_previous()}. 216 * 217 * @param string locale to activate 218 * @return boolean true on success, false on failure 219 */ 220 function locale_temp_switch( $locale ) 221 { 222 global $saved_locales, $current_locale, $Timer; 223 224 // $Timer->resume( 'locale_temp_switch' ); 225 226 if( !isset( $saved_locales ) || ! is_array( $saved_locales ) ) 227 { 228 $saved_locales = array(); 229 } 230 231 $prev_locale = $current_locale; 232 if( locale_activate( $locale ) ) 233 { 234 array_push( $saved_locales, $prev_locale ); 235 return true; 236 } 237 238 // $Timer->stop( 'locale_temp_switch' ); 239 return false; 240 } 241 242 243 /** 244 * Restore the locale in use before the switch 245 * 246 * @see locale_temp_switch() 247 * @return boolean true on success, false on failure (no locale stored before) 248 */ 249 function locale_restore_previous() 250 { 251 global $saved_locales; 252 253 if( !empty( $saved_locales ) && is_array( $saved_locales ) ) 254 { 255 locale_activate( array_pop( $saved_locales ) ); 256 return true; 257 } 258 return false; 259 } 260 261 262 /** 263 * Activate a locale. 264 * 265 * @todo dh> this should make sure, that e.g. "charset" is set for the locale in {@link $locales}. See http://forums.b2evolution.net/viewtopic.php?p=43980#43980 266 * 267 * @param string locale to activate 268 * @param boolean True on success/change, false on failure (if already set or not existant) 269 */ 270 function locale_activate( $locale ) 271 { 272 global $use_l10n, $locales, $current_locale, $current_charset, $weekday, $month; 273 274 if( $locale == $current_locale 275 || empty( $locale ) 276 || ! isset( $locales[$locale] ) ) 277 { 278 return false; 279 } 280 281 // Memorize new locale: 282 $current_locale = $locale; 283 // Memorize new charset: 284 $current_charset = $locales[ $locale ][ 'charset' ]; 285 286 // Activate translations in gettext: 287 if( ($use_l10n == 1) && function_exists( 'bindtextdomain' ) ) 288 { // Only if we are using GETTEXT ( if not, look into T_(-) ...) 289 global $locales_path; 290 # Activate the locale->language in gettext: 291 292 // Set locale: either to locale's definition 293 if( isset( $locales[$locale]['set_locales'] ) ) 294 { 295 $set_locale = explode( ' ', $locales[$locale]['set_locales'] ); 296 } 297 else 298 { 299 $set_locale = $locales[ $locale ][ 'messages' ]; 300 } 301 setlocale( LC_MESSAGES, $set_locale ); 302 303 // Specify location of translation tables and bind to domain 304 bindtextdomain( 'messages', $locales_path ); 305 textdomain( 'messages' ); 306 307 # Activate the charset for conversions in gettext: 308 /* 309 TODO: this does not work, as $evo_charset gets set/adjusted, AFTER activating the locale. 310 TODO: If this gets activated we won't need the mb_convert_variables() call in T_() for $use_l10n=1 311 if( function_exists( 'bind_textdomain_codeset' ) ) 312 { // Only if this gettext supports code conversions 313 $r = bind_textdomain_codeset( 'messages', $evo_charset ); 314 } 315 */ 316 } 317 318 # Set locale for default language: 319 # This will influence the way numbers are displayed, etc. 320 // We are not using this right now, the default 'C' locale seems just fine 321 // setlocale( LC_ALL, $locale ); 322 323 # Use this to check locale: (not relevant) 324 // echo setlocale( LC_MESSAGES, 0 ); 325 326 return true; 327 } 328 329 330 /** 331 * locale_by_lang(-) 332 * 333 * Find first locale matching lang 334 */ 335 function locale_by_lang( $lang, $fallback_to_default = true ) 336 { 337 global $locales, $default_locale; 338 339 foreach( $locales as $locale => $locale_params ) 340 { 341 if( substr( $locale, 0 ,2 ) == $lang ) 342 { // found first matching locale 343 return $locale; 344 } 345 } 346 347 // Not found... 348 if( $fallback_to_default ) 349 return $default_locale; 350 else 351 return $lang; 352 } 353 354 355 /** 356 * Displays/Returns the current locale. (for backward compatibility) 357 * 358 * This is for HTML lang attributes 359 * 360 * @param boolean true (default) if we want it to be outputted 361 * @return string current locale, if $disp = false 362 */ 363 function locale_lang( $disp = true ) 364 { 365 global $current_locale; 366 367 if( $disp ) 368 echo $current_locale; 369 else 370 return $current_locale; 371 } 372 373 374 /** 375 * Returns the charset of the current locale 376 */ 377 function locale_charset( $disp = true ) 378 { 379 global $current_charset; 380 381 if( $disp ) 382 echo $current_charset; 383 else 384 return $current_charset; 385 } 386 387 388 /** 389 * Returns the current locale's default date format 390 * @param string Locale, must be set in {@link $locales} 391 * @return string Date format of the locale, e.g. 'd.m.Y' 392 */ 393 function locale_datefmt( $locale = NULL ) 394 { 395 global $locales; 396 397 if( empty($locale) ) 398 { 399 global $current_locale; 400 $locale = $current_locale; 401 } 402 403 return $locales[$locale]['datefmt']; 404 } 405 406 407 /** 408 * Returns the current locale's default time format 409 */ 410 function locale_timefmt() 411 { 412 global $locales, $current_locale; 413 414 return $locales[$current_locale]['timefmt']; 415 } 416 417 /** 418 * Returns the current locale's default short time format 419 */ 420 function locale_shorttimefmt() 421 { 422 global $locales, $current_locale; 423 424 return str_replace( ':s', '', $locales[$current_locale]['timefmt'] ); 425 } 426 427 428 function locale_datetimefmt( $separator = ' ' ) 429 { 430 global $locales, $current_locale; 431 432 return $locales[$current_locale]['datefmt'].$separator.$locales[$current_locale]['timefmt']; 433 } 434 435 /** 436 * Returns the current locale's start of week 437 * 438 * @return integer 0 for Sunday, 1 for Monday 439 */ 440 function locale_startofweek() 441 { 442 global $locales, $current_locale; 443 444 return (int)$locales[$current_locale]['startofweek']; 445 } 446 447 448 /** 449 * Get the country locale 450 * 451 * @param string locale to use, '' for current 452 * 453 * @return string country locale 454 */ 455 function locale_country( $locale = '' ) 456 { 457 global $current_locale; 458 459 if( empty($locale) ) $locale = $current_locale; 460 461 return substr( $locale, 3, 2 ); 462 } 463 464 465 /** 466 * Get the locale country dialing code 467 */ 468 function locale_dialing_code( $locale = '' ) 469 { 470 global $current_locale, $CountryCache; 471 472 if( empty($locale) ) 473 { 474 $locale = locale_country(); 475 } 476 477 $edited_Country = $CountryCache->get_by_ID( $locale); 478 479 return $edited_Country->dialing_code; 480 } 481 482 483 /** 484 * Template function: Display locale flag 485 * 486 * @param string locale to use, '' for current 487 * @param string collection name (subdir of img/flags) 488 * @param string name of class for IMG tag 489 * @param string deprecated HTML align attribute 490 * @param boolean to echo or not 491 * @param mixed use absolute url (===true) or path to flags directory 492 */ 493 function locale_flag( $locale = '', $collection = 'w16px', $class = 'flag', $align = '', $disp = true, $absoluteurl = true ) 494 { 495 global $locales, $current_locale, $rsc_path, $rsc_url; 496 497 if( empty($locale) ) $locale = $current_locale; 498 499 // extract flag name: 500 $country = strtolower(substr( $locale, 3, 2 )); 501 502 if( ! is_file( $rsc_path.'flags/'.$collection.'/'.$country.'.gif') ) 503 { // File does not exist 504 $country = 'default'; 505 } 506 507 if( $absoluteurl !== true ) 508 { 509 $iurl = $absoluteurl; 510 } 511 else 512 { 513 $iurl = $rsc_url.'flags'; 514 } 515 516 $r = '<img src="'.$iurl.'/'.$collection.'/'.$country.'.gif" alt="' . 517 (isset($locales[$locale]['name']) ? $locales[$locale]['name'] : $locale) . 518 '"'; 519 if( !empty( $class ) ) $r .= ' class="'.$class.'"'; 520 if( !empty( $align ) ) $r .= ' align="'.$align.'"'; 521 $r .= ' /> '; 522 523 if( $disp ) 524 echo $r; // echo it 525 else 526 return $r; // return it 527 528 } 529 530 531 /** 532 * [callback function] Outputs an <option> set with default locale selected 533 * 534 * @param string default value 535 * @param boolean echo output? 536 */ 537 function locale_options( $default = '', $disp = true ) 538 { 539 global $locales, $default_locale; 540 541 if( empty( $default ) ) $default = $default_locale; 542 543 $r = ''; 544 545 foreach( $locales as $this_localekey => $this_locale ) 546 { 547 if( $this_locale['enabled'] || $this_localekey == $default ) 548 { 549 $r .= '<option value="'. $this_localekey. '"'; 550 if( $this_localekey == $default ) 551 $r .= ' selected="selected"'; 552 $r .= '>'. T_($this_locale['name']). '</option>'; 553 } 554 } 555 556 if( $disp ) 557 { // the result must be displayed 558 echo $r; 559 return true; 560 } 561 else 562 { //the result must be returned 563 return $r; 564 } 565 } 566 567 568 /** 569 * [callback function] Returns an <option> set with default locale selected 570 * 571 * @param string default value 572 */ 573 function locale_options_return( $default = '' ) 574 { 575 $r = locale_options( $default, false ); 576 return $r; 577 } 578 579 580 /** 581 * Detect language from HTTP_ACCEPT_LANGUAGE 582 * 583 * First matched full locale code in HTTP_ACCEPT_LANGUAGE will win 584 * Otherwise, first locale in table matching a lang code will win 585 * 586 * @return locale made out of HTTP_ACCEPT_LANGUAGE or $default_locale, if no match 587 */ 588 function locale_from_httpaccept() 589 { 590 global $locales, $default_locale; 591 if( isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ) 592 { 593 // echo $_SERVER['HTTP_ACCEPT_LANGUAGE']; 594 $accept = strtolower( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ); 595 // echo 'http_accept_language:<br />'; pre_dump($accept); 596 $selected_locale = ''; 597 $selected_match_pos = 10000; 598 $selected_full_match = false; 599 600 foreach( $locales as $localekey => $locale ) 601 { // Check each locale 602 if( ! $locale['enabled'] ) 603 { // We only want to use activated locales 604 continue; 605 } 606 // echo '<br />searching ', $localekey, ' in HTTP_ACCEPT_LANGUAGE '; 607 if( ($pos = strpos( $accept, strtolower($localekey) )) !== false ) 608 { // We found full locale 609 if( !$selected_full_match || ($pos <= $selected_match_pos) ) 610 { // This is a better choice than what we had before OR EQUIVALENT but with exact locale 611 // echo $localekey.' @ '.$pos.' is better than '. 612 // $selected_locale.' @ '.$selected_match_pos.'<br />'; 613 $selected_locale = $localekey; 614 $selected_match_pos = $pos; 615 $selected_full_match = true; 616 } 617 // else echo $localekey.' @ '.$pos.' is not better than '. 618 // $selected_locale.' @ '.$selected_match_pos.'<br />'; 619 } 620 621 if( !$selected_full_match && ($pos = strpos( $accept, substr($localekey, 0, 2) )) !== false ) 622 { // We have no exact match yet but found lang code match 623 if( $pos < $selected_match_pos ) 624 { // This is a better choice than what we had before 625 // echo $localekey.' @ '.$pos.' is better than '. 626 // $selected_locale.' @ '.$selected_match_pos.'<br />'; 627 $selected_locale = $localekey; 628 $selected_match_pos = $pos; 629 } 630 // else echo $localekey.' @ '.$pos.' is not better than '. 631 // $selected_locale.' @ '.$selected_match_pos.'<br />'; 632 } 633 } 634 635 if( !empty($selected_locale) ) 636 { 637 return $selected_locale; 638 } 639 } 640 return $default_locale; 641 } 642 643 644 /** 645 * user sort function to sort locales by priority 646 * 647 * 1 is highest priority. 648 * 649 */ 650 function locale_priosort( $a, $b ) 651 { 652 return $a['priority'] - $b['priority']; 653 } 654 655 656 /** 657 * load locales from DB into $locales array. Also sets $default_locale. 658 * 659 * @return mixed new default locale on succes, false on failure 660 */ 661 function locale_overwritefromDB() 662 { 663 global $DB, $locales, $default_locale, $Settings, $Debuglog; 664 665 $usedprios = array(); // remember which priorities are used already. 666 $priocounter = 0; 667 $query = 'SELECT 668 loc_locale, loc_charset, loc_datefmt, loc_timefmt, loc_startofweek, 669 loc_name, loc_messages, loc_priority, loc_enabled 670 FROM T_locales ORDER BY loc_priority'; 671 672 foreach( $DB->get_results( $query, ARRAY_A ) as $row ) 673 { // Loop through loaded locales: 674 675 if( $row['loc_priority'] == $priocounter ) 676 { // priority conflict (the same) 677 $priocounter++; 678 } 679 else 680 { 681 $priocounter = $row['loc_priority']; 682 } 683 684 //remember that we used this 685 $usedprios[] = $priocounter; 686 687 $locales[ $row['loc_locale'] ] = array( 688 'charset' => $row[ 'loc_charset' ], 689 'datefmt' => $row[ 'loc_datefmt' ], 690 'timefmt' => $row[ 'loc_timefmt' ], 691 'startofweek' => $row[ 'loc_startofweek' ], 692 'name' => $row[ 'loc_name' ], 693 'messages' => $row[ 'loc_messages' ], 694 'priority' => $priocounter, 695 'enabled' => $row[ 'loc_enabled' ], 696 'fromdb' => 1 697 ); 698 } 699 700 // set default priorities, if nothing was set in DB. 701 // Missing "priority gaps" will get filled here. 702 if( $DB->num_rows != count($locales) ) 703 { // we have locales from conf file that need a priority 704 $priocounter = 1; 705 foreach( $locales as $lkey => $lval ) 706 { // Loop through memory locales: 707 if( !isset($lval['priority']) ) 708 { // Found one that has no assigned priority 709 while( in_array( $priocounter, $usedprios ) ) 710 { 711 $priocounter++; 712 } 713 // Priocounter has max value 714 $locales[$lkey]['priority'] = $priocounter; 715 $usedprios[] = $priocounter; 716 } 717 } 718 } 719 720 // sort by priority 721 uasort( $locales, 'locale_priosort' ); 722 723 // overwrite default_locale from DB settings - if enabled. 724 // Checks also if previous $default_locale is enabled. Defaults to en-EU, even if not enabled. 725 $locale_fromdb = $Settings->get('default_locale'); 726 727 if( $locale_fromdb ) 728 { 729 if( !isset( $locales[$locale_fromdb] ) ) 730 { 731 $Debuglog->add( 'Default locale ['.$locale_fromdb.'] from general settings is not available.', 'locale' ); 732 return false; 733 } 734 else 735 { 736 $default_locale = $locale_fromdb; 737 return $default_locale; 738 } 739 } 740 } 741 742 743 /** 744 * Write $locales array to DB table 745 */ 746 function locale_updateDB() 747 { 748 global $locales, $DB; 749 750 $templocales = $locales; 751 752 $lnr = 0; 753 // Loop through list of all HTTP POSTed params: 754 foreach( $_POST as $pkey => $pval ) 755 { 756 if( ! preg_match('/loc_(\d+)_(.*)/', $pkey, $matches) ) 757 { 758 continue; 759 } 760 761 // This is a locale related parameter, get it now: 762 $pval = param( $pkey, 'string', '' ); 763 764 $lfield = $matches[2]; 765 766 if( $matches[1] != $lnr ) 767 { // we have a new locale 768 $lnr = $matches[1]; 769 $plocale = $pval; 770 771 // checkboxes default to 0 772 $templocales[ $plocale ]['enabled'] = 0; 773 } 774 elseif( $lnr != 0 ) // be sure to have catched a locale before 775 { 776 if( $lfield == 'startofweek' && ( $lfield < 0 || $lfield > 6 ) ) 777 { // startofweek must be between 0 and 6 778 continue; 779 } 780 $templocales[ $plocale ][$lfield] = $pval; 781 } 782 } 783 784 $locales = $templocales; 785 786 $query = "REPLACE INTO T_locales ( loc_locale, loc_charset, loc_datefmt, loc_timefmt, loc_startofweek, loc_name, loc_messages, loc_priority, loc_enabled ) VALUES "; 787 foreach( $locales as $localekey => $lval ) 788 { 789 if( empty($lval['messages']) ) 790 { // if not explicit messages file is given we'll translate the locale 791 $lval['messages'] = strtr($localekey, '-', '_'); 792 } 793 $query .= '( 794 '.$DB->quote($localekey).', 795 '.$DB->quote($lval['charset']).', 796 '.$DB->quote($lval['datefmt']).', 797 '.$DB->quote($lval['timefmt']).', 798 '.$DB->quote($lval['startofweek']).', 799 '.$DB->quote($lval['name']).', 800 '.$DB->quote($lval['messages']).', 801 '.$DB->quote($lval['priority']).', 802 '.$DB->quote($lval['enabled']).' 803 ), '; 804 } 805 $query = substr($query, 0, -2); 806 $q = $DB->query($query); 807 808 return (bool)$q; 809 } 810 811 812 /** 813 * Convert a string from one charset to another. 814 * 815 * @todo Implement iconv and PHP mapping tables 816 * 817 * @see can_convert_charsets() 818 * @param string String to convert 819 * @param string Target charset (TO) 820 * @param string Source charset (FROM) 821 * @return string Encoded string (if it cannot be converted it's the original one) 822 */ 823 function convert_charset( $string, $dest_charset, $src_charset ) 824 { 825 if( $dest_charset == $src_charset ) 826 { // no conversation required 827 return $string; 828 } 829 830 if( function_exists('mb_convert_variables') ) 831 { // mb_string extension: 832 mb_convert_variables( $dest_charset, $src_charset, $string ); 833 } 834 835 return $string; 836 } 837 838 839 /** 840 * Can we convert from charset A to charset B? 841 * @param string Target charset (TO) 842 * @param string Source charset (FROM) 843 * @return boolean 844 */ 845 function can_convert_charsets( $dest_charset, $src_charset ) 846 { 847 if( empty($dest_charset) || empty($src_charset) ) 848 { 849 return false; 850 } 851 852 if( function_exists('mb_internal_encoding') ) 853 { // mb_string extension: 854 $orig = mb_internal_encoding(); 855 856 $r = false; 857 if( @mb_internal_encoding($dest_charset) && @mb_internal_encoding($src_charset) ) 858 { // we can set both encodings, so we should be able to convert: 859 $r = true; 860 } 861 862 mb_internal_encoding($orig); 863 return $r; 864 } 865 866 return false; 867 } 868 869 870 /** 871 * Init charset handling between Input/Output ($io_charset) and the internal 872 * handling ($evo_charset). 873 * 874 * Check and possibly adjust {@link $evo_charset}. 875 * 876 * @staticvar boolean Used to only start mb_output_handler once 877 * @param string I/O (input/output) charset to use 878 * @return boolean true, if encoding has been changed 879 */ 880 function init_charsets( $req_io_charset ) 881 { 882 static $mb_output_handler_started; 883 global $io_charset, $evo_charset, $Debuglog, $DB; 884 global $force_io_charset_if_accepted; 885 886 if( $req_io_charset == $io_charset ) 887 { // no conversation/init needed 888 return false; 889 } 890 891 // check, if we want to force a specific charset (e.g. 'utf-8'): 892 if( ! empty($force_io_charset_if_accepted) ) 893 { // we want to force a specific charset: 894 if( ! isset($_SERVER['HTTP_ACCEPT_CHARSET']) // all allowed 895 || preg_match( '~\b(\*|'.$force_io_charset_if_accepted.')\b~', $_SERVER['HTTP_ACCEPT_CHARSET'] ) ) 896 { 897 $req_io_charset = $force_io_charset_if_accepted; // pretend that the first one has been requested 898 } 899 } 900 901 if( $req_io_charset == $io_charset ) 902 { // no conversation/init needed 903 return false; 904 } 905 906 $io_charset = $req_io_charset; 907 908 if( empty($evo_charset) ) 909 { // empty evo_charset follows I/O charset: 910 // TODO: $evo_charset will not follow, if it has followed before.. (because not empty anymore) 911 $Debuglog->add( '$evo_charset follows $io_charset ('.$io_charset.').', array('locale') ); 912 $evo_charset = $io_charset; 913 } 914 elseif( $evo_charset != $io_charset ) 915 { // we have to convert for I/O 916 // TODO: dh> $io_charset has to forcefully follow $evo_charset, if we cannot convert, e.g. utf-8/iso-8859-1 917 if( ! function_exists('mb_convert_encoding') ) 918 { 919 $Debuglog->add( '$evo_charset differs from $io_charset, but mbstrings is not available - cannot convert I/O to internal charset!', array('errors','locale') ); 920 $evo_charset = $io_charset; // we cannot convert I/O to internal charset 921 } 922 else 923 { // check if the encodings are supported: 924 // NOTE: mb_internal_encoding() is the best way to find out if the encoding is supported 925 $old_mb_internal_encoding = mb_internal_encoding(); 926 if( ! @mb_internal_encoding($io_charset) ) 927 { 928 $Debuglog->add( 'Cannot I/O convert because I/O charset ['.$io_charset.'] is not supported by mbstring!', array('error','locale') ); 929 $evo_charset = $io_charset; 930 mb_internal_encoding($old_mb_internal_encoding); 931 } 932 elseif( ! @mb_internal_encoding($evo_charset) ) 933 { 934 $Debuglog->add( 'Cannot I/O convert because $evo_charset='.$evo_charset.' is not supported by mbstring!', array('error','locale') ); 935 $evo_charset = $io_charset; 936 mb_internal_encoding($old_mb_internal_encoding); 937 } 938 else 939 { // we can convert between I/O 940 mb_http_output( $io_charset ); 941 if( ! $mb_output_handler_started ) 942 { 943 ob_start( 'mb_output_handler' ); // NOTE: this will send a Content-Type header by itself for "text/..." 944 $mb_output_handler_started = true; 945 $Debuglog->add( 'Started mb_output_handler.', 'locale' ); 946 } 947 } 948 } 949 } 950 951 if( isset($DB) // not available in /install/index.php 952 && empty($db_config['connection_charset']) // do not override explicitly set one 953 ) 954 { 955 // Set encoding for MySQL connection: 956 $DB->set_connection_charset( $evo_charset, true ); 957 } 958 959 $Debuglog->add( 'evo_charset: '.$evo_charset, 'locale' ); 960 $Debuglog->add( 'io_charset: '.$io_charset, 'locale' ); 961 962 return true; 963 } 964 965 966 /* 967 * $Log: _locale.funcs.php,v $ 968 * Revision 1.4 2007/11/03 21:04:27 fplanque 969 * skin cleanup 970 * 971 * Revision 1.3 2007/07/09 21:24:12 fplanque 972 * cleanup of admin page top 973 * 974 * Revision 1.2 2007/06/26 02:40:54 fplanque 975 * security checks 976 * 977 * Revision 1.1 2007/06/25 11:00:37 fplanque 978 * MODULES (refactored MVC) 979 * 980 * Revision 1.38 2007/04/26 00:11:02 fplanque 981 * (c) 2007 982 * 983 * Revision 1.37 2007/03/04 20:14:16 fplanque 984 * GMT date now in system checks 985 * 986 * Revision 1.36 2006/12/04 21:20:28 blueyed 987 * Abstracted convert_special_charsets() out of urltitle_validate() 988 * 989 * Revision 1.35 2006/11/27 01:36:04 blueyed 990 * doc typo 991 * 992 * Revision 1.34 2006/11/24 18:27:25 blueyed 993 * Fixed link to b2evo CVS browsing interface in file docblocks 994 * 995 * Revision 1.33 2006/11/16 22:33:52 blueyed 996 * some more charset issue releated TODOs.. :/ 997 * 998 * Revision 1.32 2006/11/14 21:12:38 blueyed 999 * Fix for gettext-T_() 1000 * 1001 * Revision 1.31 2006/11/14 00:47:32 fplanque 1002 * doc 1003 * 1004 * Revision 1.30 2006/11/02 15:58:08 blueyed 1005 * todo/note 1006 * 1007 * Revision 1.29 2006/10/31 00:33:26 blueyed 1008 * Fixed item_issue_date for preview 1009 * 1010 * Revision 1.28 2006/10/29 21:20:53 blueyed 1011 * Replace special characters in generated URL titles 1012 * 1013 * Revision 1.27 2006/10/24 23:04:05 blueyed 1014 * Added can_convert_charsets() function 1015 * 1016 * Revision 1.26 2006/10/04 12:55:24 blueyed 1017 * - Reload $Blog, if charset has changed for Blog locale 1018 * - only update DB connection charset, if not forced with $db_config['connection_charset'] 1019 */ 1020 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Thu Nov 29 23:58:50 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |