OSDN Git Service

Merge branch 'skinnable-master'
[nucleus-jp/nucleus-next.git] / nucleus / libs / i18n.php
index 1b494ea..9f846df 100644 (file)
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
 <?php\r
 /**\r
  * i18n class for Nucleus CMS\r
@@ -681,3 +682,689 @@ class i18n
                "portuguese_brazil"     => "pt_Latn_BR"\r
        );\r
 }\r
+=======
+<?php
+/**
+ * i18n class for Nucleus CMS
+ * written by Takashi Sakamoto as of Feb 03, 2012
+ * 
+ * This includes wrapper functions of iconv and mbstring
+ * for multibyte processing and includes parameters related to locale.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * (see nucleus/documentation/index.html#license for more info)
+ *
+ * @license http://nucleuscms.org/license.txt GNU General Public License
+ * @copyright Copyright (C) 2002-2011 The Nucleus Group
+ * @version $Id: i18n.php 1876 2012-06-17 07:33:00Z sakamocchi $
+ */
+class i18n
+{
+       static private $mode = FALSE;
+       
+       static private $current_charset = '';
+       static private $current_language = '';
+       static private $current_script = '';
+       static private $current_region = '';
+       
+       static private $locale_list = array();
+       static private $timezone = 'UTC';
+       
+       static private $forced_charset = '';
+       static private $forced_language = '';
+       static private $forced_script = '';
+       static private $forced_region = '';
+       
+       /**
+        * i18n::init
+        * Initializing i18n class
+        * 
+        * @static
+        * @param       string  $charset        character set
+        * @return      boolean 
+        */
+       static public function init($charset, $dir)
+       {
+               /* i18n is already initialized */
+               if ( self::$mode )
+               {
+                       return TRUE;
+               }
+               
+               /* make locale list in this Nucleus CMS */
+               if ( ($handle = opendir($dir)) === FALSE )
+               {
+                       return FALSE;
+               }
+               while ($filename = readdir($handle))
+               {
+                       if (preg_match("#^(.+_.+_.+)\.{$charset}\.php$#", $filename, $matches) )
+                       {
+                               if ( !in_array($matches[1], self::$locale_list) )
+                               {
+                                       self::$locale_list[] = $matches[1];
+                               }
+                       }
+               }
+               closedir($handle);
+               
+               /* set i18n backend and validate character set */
+               if ( extension_loaded('iconv') )
+               {
+                       /* this is just for checking the charset. */
+                       if ( iconv_set_encoding('internal_encoding', $charset)
+                        && iconv_set_encoding('output_encoding', $charset)
+                        && iconv_set_encoding('internal_encoding', $charset) )
+                       {
+                               self::$current_charset = $charset;
+                               self::$mode = 'iconv';
+                       }
+               }
+               else if ( extension_loaded('mbstring') )
+               {
+                       /* this is just for checking the charset. */
+                       if ( mb_http_output($charset)
+                        && mb_internal_encoding($charset)
+                        && mb_regex_encoding($charset) )
+                       {
+                               self::$current_charset = $charset;
+                               self::$mode = 'mbstring';
+                       }
+               }
+               
+               return TRUE;
+       }
+       
+       /**
+        * i18n::get_available_locale_list
+        * return available locale list with current charset
+        * 
+        * @static
+        * @param       void
+        * @return      array   available locale list
+        */
+       static public function get_available_locale_list()
+       {
+               return self::$locale_list;
+       }
+       
+       /**
+        * i18n::get_current_charset
+        * return current charset
+        * 
+        * @static
+        * @param       void
+        * @return      string  $charset        current character set
+        */
+       static public function get_current_charset()
+       {
+               return self::$current_charset;
+       }
+       
+       /**
+        * i18n::set_locale
+        * Set current locale
+        * 
+        * NOTE:
+        * naming rule is "$language_$script_$region.$charset.php", refer to RFC 5646.
+        * @link http://www.ietf.org/rfc/rfc5646.txt
+        * @see 2.  The Language Tag
+        * 
+        * @static
+        * @param       string  $locale
+        * @return      bool    TRUE/FALSE
+        * 
+        */
+       static public function set_current_locale($locale)
+       {
+               if ( preg_match('#^(.+)_(.+)_(.+)$#', $locale, $match) )
+               {
+                       self::$current_language = $match[1];
+                       self::$current_script   = $match[2];
+                       self::$current_region   = $match[3];
+                       return TRUE;
+               }
+               return FALSE;
+       }
+       
+       /**
+        * i18n::get_locale
+        * Get current locale
+        * 
+        * @static
+        * @param       void
+        * @return      $locale
+        */
+       static public function get_current_locale()
+       {
+               $elements = array(self::$current_language, self::$current_script, self::$current_region);
+               return implode('_', $elements);
+       }
+       
+       /**
+        * i18n::set_forced_locale()
+        * Set forced locale
+        * 
+        * @static
+        * @param       string  $forced_locale
+        * @return      bool    TRUE/FALSE
+        * 
+        */
+       static public function set_forced_locale($forced_locale)
+       {
+               if ( preg_match('#^(.+)_(.+)_(.+)$#', $forced_locale, $match) )
+               {
+                       self::$forced_language  = $match[1];
+                       self::$forced_script    = $match[2];
+                       self::$forced_region    = $match[3];
+                       return TRUE;
+               }
+               return FALSE;
+       }
+       
+       /**
+        * i18n::get_forced_locale
+        * Get forced locale
+        * 
+        * @static
+        * @param       void
+        * @return      $forced_locale
+        */
+       static public function get_forced_locale()
+       {
+               if ( !self::$forced_language )
+               {
+                       return '';
+               }
+               
+               $elements = array(self::$forced_language, self::$forced_script, self::$forced_region);
+               return implode('_', $elements);
+       }
+       
+       /**
+        * i18n::set_forced_charset
+        * return forced charset
+        * 
+        * @static
+        * @param       void    $charset        forced character set
+        * @return      void
+        */
+       static public function set_forced_charset($forced_charset)
+       {
+               self::$forced_charset = $forced_charset;
+               return;
+       }
+       
+       /**
+        * i18n::get_forced_charset
+        * return forced charset
+        * 
+        * @static
+        * @param       void
+        * @return      string  $charset        forced character set
+        */
+       static public function get_forced_charset()
+       {
+               return self::$forced_charset;
+       }
+       
+       /**
+        * i18n::confirm_default_date_timezone
+        * to avoid E_NOTICE or E_WARNING generated when every calling to a date/time function.
+        * 
+        * NOTE:
+        * Some private servers are lack of its timezone setting
+        * http://www.php.net/manual/en/function.date-default-timezone-set.php
+        * 
+        * @static
+        * @param       void
+        * @return      void
+        */
+       static public function confirm_default_date_timezone()
+       {
+               if ( function_exists('date_default_timezone_get') 
+                && FALSE !== ($timezone = @date_default_timezone_get()))
+               {
+                       self::$timezone = $timezone;
+               }
+               if (function_exists('date_default_timezone_set')) {
+                        @date_default_timezone_set(self::$timezone);
+               }
+               return;
+       }
+       
+       /**
+        * i18n::get_current_date_timezone()
+        * get current timezone
+        * 
+        * @static
+        * @param       void
+        * @return      $timezone
+        */
+       static public function get_date_timezone()
+       {
+               return self::$timezone;
+       }
+       
+       /**
+        * i18n::convert
+        * character set converter
+        * 
+        * @static
+        * @param       string  $string target string binary
+        * @param       string  $from   original character set encoding
+        * @param       string  $to     target character set encoding
+        * @return      string  converted string
+        */
+       static public function convert($string, $from, $to='')
+       {
+               if ( $to == '' )
+               {
+                       $to = self::$current_charset;
+               }
+               
+               if ( $from == $to )
+               {
+                       /* do nothing */
+               }
+               else if ( self::$mode == 'iconv' )
+               {
+                       $string = iconv($from, $to.'//TRANSLIT', $string);
+               }
+               else if ( self::$mode == 'mbstring' )
+               {
+                       $string = mb_convert_encoding($string, $to, $from);
+               }
+               return (string) $string;
+       }
+       
+       /**
+        * i18n::convert_handler
+        * callable handler for character set converter
+        * 
+        * @static
+        * @param       string  $string target string binary
+        * @return      void
+        */
+       static public function convert_handler($string)
+       {
+               return self::convert($string, self::$current_charset, self::$forced_charset);
+       }
+       
+       /**
+        * i18n::convert_array
+        * recursively converting array
+        * 
+        * @static
+        * @param       array   $array  array to convert
+        * @return      void
+        */
+       static public function convert_array($array, $from, $to='')
+       {
+               if ( !is_array($array) )
+               {
+                       $array = self::convert($array, $from, $to);
+               }
+               else
+               {
+                       foreach ( $array as $key => $value )
+                       {
+                               if ( !is_array($value) )
+                               {
+                                       $array[$key] = self::convert($value, $from, $to);
+                               }
+                               else
+                               {
+                                       self::convert_array($array[$key]);
+                               }
+                       }
+               }
+               
+               return $array;
+       }
+       
+       /**
+        * i18n::strlen
+        * strlen wrapper
+        * 
+        * @static
+        * @param       string  $string target string
+        * @return      integer the number of letters
+        */
+       static public function strlen($string)
+       {
+               $length = 0;
+               if ( self::$mode == 'iconv' )
+               {
+                       $length = iconv_strlen($string, self::$current_charset);
+               }
+               else if ( self::$mode == 'mbstring' )
+               {
+                       $length = mb_strlen($string, self::$current_charset);
+               }
+               else
+               {
+                       $length = strlen($string);
+               }
+               return (integer) $length;
+       }
+       
+       /**
+        * i18n::strpos
+        * strpos wrapper
+        * 
+        * @static
+        * @param       string  $haystack       string to search
+        * @param       string  $needle string for search
+        * @param       integer $offset the position from which the search should be performed. 
+        * @return      integer/FALSE   the numeric position of the first occurrence of needle in haystack
+        */
+       static public function strpos($haystack, $needle, $offset=0)
+       {
+               $position = 0;
+               if ( self::$mode == 'iconv' )
+               {
+                       $position = iconv_strpos($haystack, $needle, $offset, self::$current_charset);
+               }
+               else if ( self::$mode == 'mbstring' )
+               {
+                       $position = mb_strpos($haystack, $needle, $offset, self::$current_charset);
+               }
+               else
+               {
+                       $position = strpos($haystack, $needle, $offset);
+               }
+               
+               if ( $position !== FALSE)
+               {
+                       $position = (integer) $position;
+               }
+               return $position;
+       }
+       
+       /**
+        * i18n::strrpos
+        * strrpos wrapper
+        * 
+        * @static
+        * @param       string  $haystack       string to search
+        * @param       string  $needle string for search
+        * @return      integer/FALSE   the numeric position of the last occurrence of needle in haystack
+        */
+       static public function strrpos ($haystack, $needle)
+       {
+               $position = 0;
+               if ( self::$mode == 'iconv' )
+               {
+                       $position = iconv_strrpos($haystack, $needle, self::$current_charset);
+               }
+               else if ( self::$mode == 'mbstring' )
+               {
+                       $position = mb_strrpos($haystack, $needle, 0, self::$current_charset);
+               }
+               else
+               {
+                       $position = strrpos($haystack, $needle, 0);
+               }
+               
+               if ( $position !== FALSE)
+               {
+                       $position = (integer) $position;
+               }
+               return $position;
+       }
+       
+       /**
+        * i18n::substr
+        * substr wrapper
+        * 
+        * @static
+        * @param       string  $string string to be cut
+        * @param       string  $start  the position of starting
+        * @param       integer $length the length to be cut
+        * @return      string  the extracted part of string
+        */
+       static public function substr($string, $start, $length=0)
+       {
+               $return = '';
+               
+               if ( $length == 0 )
+               {
+                       $length = self::strlen($string) - $start;
+               }
+               
+               if ( self::$mode == 'iconv' )
+               {
+                       $return = iconv_substr($string, $start, $length, self::$current_charset);
+               }
+               else if ( self::$mode == 'mbstring' )
+               {
+                       $return = mb_substr($string, $start, $length, self::$current_charset);
+               }
+               else
+               {
+                       $return = strrpos($string, $start, $length);
+               }
+               return (string) $return;
+       }
+       
+       /**
+        * i18n::strftime
+        * strftime function based on multibyte processing
+        * 
+        * @static
+        * @param       string  $format format with singlebyte or multibyte
+        * @param       timestamp       $timestamp      UNIX timestamp
+        * @return      string  formatted timestamp
+        */
+       static public function strftime($format, $timestamp='')
+       {
+               return preg_replace_callback('/(%[a-z%])/i',
+                       create_function('$matches', 'return strftime($matches[1], ' . intval($timestamp) . ');'),
+                       $format
+               );
+               }
+               
+       /**
+        * i18n::formatted_datetime()
+        * return formatted datetime string
+        * 
+        * Date and Time Formats
+        * @link        http://www.w3.org/TR/NOTE-datetime
+        * 
+        * Working with Time Zones
+        * @link        http://www.w3.org/TR/timezone/
+        * 
+        * @param       String  $format time expression format
+        * @param       String  $timestamp      UNIX timestamp
+        * @param       Integer $offset timestamp offset
+        * @return      String  formatted datetime
+        */
+       static public function formatted_datetime($format, $timestamp, $offset=0)
+       {
+               $suffix = '';
+               $string = '';
+               
+               switch ( $format )
+               {
+                       case 'mysql':
+                               /*
+                                * MySQL 5.0 Reference Manual
+                                *  10.3.1. The DATE, DATETIME, and TIMESTAMP Types
+                                *   http://dev.mysql.com/doc/refman/5.0/en/datetime.html
+                                */
+                               $timestamp += $offset;
+                               $format = '%Y-%m-%d %H:%M:%S';
+                               $suffix ='';
+                               break;
+                       
+                       case 'rfc822':
+                               /*
+                                * RFC 822: STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES
+                                *  5.  DATE AND TIME SPECIFICATION
+                                *   http://www.ietf.org/rfc/rfc0822.txt
+                                */
+                               $format = '%a, %d %m %y %H:%M:%S ';
+                               if ( $offset < 0 )
+                               {
+                                       $suffix = '-';
+                                       $offset = -$offset;
+                               }
+                               else
+                               {
+                                       $suffix = '+';
+                               }
+                               
+                               $suffix .= sprintf("%02d%02d", floor($offset / 3600), round(($offset % 3600) / 60) );
+                               break;
+                       case 'rfc822GMT':
+                               /*
+                                * RFC 822: STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES
+                                *  5.  DATE AND TIME SPECIFICATION
+                                *   http://www.ietf.org/rfc/rfc0822.txt
+                                */
+                               $format = '%a, %d %m %y %H:%M:%S ';
+                               $timestamp -= $offset;
+                               $suffix = 'GMT';
+                               break;
+                       case 'iso8601':
+                       case 'rfc3339':
+                               /*
+                                * RFC3339: Date and Time on the Internet: Timestamps
+                                *  5. Date and Time format
+                                *   http://www.ietf.org/rfc/rfc3339.txt
+                                */
+                               $format = '%Y-%m-%dT%H:%M:%S';
+                               if ( $offset < 0 )
+                               {
+                                       $suffix = '-';
+                                       $offset = -$offset;
+                               }
+                               else
+                               {
+                                       $suffix = '+';
+                               }
+                               $suffix .= sprintf("%02d:%02d", floor($offset / 3600), round(($offset % 3600) / 60) );
+                               break;
+                       case 'utc':
+                       case 'iso8601UTC':
+                       case 'rfc3339UTC':
+                               /*
+                                * RFC3339: Date and Time on the Internet: Timestamps
+                                *  5. Date and Time format
+                                *   http://www.ietf.org/rfc/rfc3339.txt
+                                */
+                               $timestamp -= $offset;
+                               $format = '%Y-%m-%dT%H:%M:%SZ';
+                               $suffix = '';
+                               break;
+                       case '':
+                               $format = '%X %x';
+                               $offset = '';
+                               break;
+                       default:
+                               $suffix = '';
+                               break;
+               }
+               return i18n::strftime($format, $timestamp) . $suffix;
+       }
+       
+       /**
+        * i18n::convert_locale_to_old_language_file_name()
+        * NOTE: this should be obsoleted near future.
+        * 
+        * @static
+        * @param       string  $target_locale  locale name as language_script_region
+        * @return      string  old translation file name
+        */
+       static public function convert_locale_to_old_language_file_name($target_locale)
+       {
+               $target_language = '';
+               foreach ( self::$lang_refs as $language => $locale )
+               {
+                       if ( preg_match('#-#', $language) )
+                       {
+                               if ( $target_locale . '.' . self::$current_charset == $locale )
+                               {
+                                       $target_language = $language;
+                                       break;
+                               }
+                       }
+                       else if ( $target_locale == $locale )
+                       {
+                               $target_language = $language;
+                       }
+               }
+               return $target_language;
+       }
+       
+       /**
+        * i18n::convert_old_language_file_name_to_locale()
+        * NOTE: this should be obsoleted near future.
+        * 
+        * @static
+        * @param       string  $target_language        old translation file name
+        * @return      string  locale name as language_script_region
+        */
+       static public function convert_old_language_file_name_to_locale($target_language)
+       {
+               $target_locale = '';
+               foreach ( self::$lang_refs as $language => $locale )
+               {
+                       if ( $target_language == $language )
+                       {
+                               if ( preg_match('#^(.+)\.(.+)$#', $locale, $match) )
+                               {
+                                       $target_locale = $match[1];
+                               }
+                               else
+                               {
+                                       $target_locale = $locale;
+                               }
+                               break;
+                       }
+               }
+               return $target_locale;
+       }
+       
+       /**
+        * i18n::$lang_refs
+        * reference table to convert old and new way to name translation files.
+        * NOTE: this should be obsoleted as soon as possible.
+        * 
+        * @static
+        */
+       static private $lang_refs = array(
+               "english"               => "en_Latn_US",
+               "english-utf8"  => "en_Latn_US.UTF-8",
+               "bulgarian"     => "bg_Cyrl_BG",
+               "finnish"               => "fi_Latn_FI",
+               "catalan"               => "ca_Latn_ES",
+               "french"                => "fr_Latn_FR",
+               "russian"               => "ru_Cyrl_RU",
+               "chinese"               => "zh_Hans_CN",
+               "simchinese"    => "zh_Hans_CN",
+               "chineseb5"     => "zh_Hant_TW",
+               "traditional_chinese"   =>      "zh_Hant_TW",
+               "galego"                => "gl_Latn_ES",
+               "german"                => "de_Latn_DE",
+               "korean-utf"    => "ko_Kore_KR.UTF-8",
+               "korean-euc-kr" => "ko_Kore_KR.EUC-KR",
+               "slovak"                => "sk_Latn_SK",
+               "czech"         => "cs_Latn_CZ",
+               "hungarian"     => "hu_Latn_HU",
+               "latvian"               => "lv_Latn_LV",
+               "nederlands"    => "nl_Latn_NL",
+               "italiano"              => "it_Latn_IT",
+               "persian"               => "fa_Arab_IR",
+               "spanish"               => "es_Latn_ES",
+               "spanish-utf8"  => "es_Latn_ES.UTF-8",
+               "japanese-euc"  => "ja_Jpan_JP.EUC-JP",
+               "japanese-utf8" => "ja_Jpan_JP.UTF-8",
+               "portuguese_brazil"     => "pt_Latn_BR"
+       );
+}
+>>>>>>> skinnable-master