fix #8131 - chinese translations
[Pman.Core] / TimeZone.php
index 499341e..bdad4cf 100644 (file)
@@ -16,17 +16,28 @@ class Pman_Core_TimeZone extends Pman
 
     function get($base, $opts=array())
     {
-        self::getOffsets();
+        $this->lang = !empty($_REQUEST['lang']) && in_array($_REQUEST['lang'], array('en', 'zh_CN')) ? $_REQUEST['lang'] : 'en';
+        self::getTimezones($this->lang);
 
         $data = array();
 
-        foreach(self::$offsets as $tz => $o) {
-            $arr = explode('/', $tz);
+        foreach(self::$timezones as $tz => $o) {
+            if(!empty($_REQUEST['region']) && $_REQUEST['region'] != $o['region']) {
+                continue;
+            }
+
+            if(
+                !empty($_REQUEST['query']['area_start']) 
+                && 
+                substr(strtolower($o['area']), 0, strlen($_REQUEST['query']['area_start'])) != strtolower($_REQUEST['query']['area_start'])
+            ){
+                continue;
+            }
             $data[] = array(
-                'region' => $arr[0],
-                'area' => $arr[1],
-                'offset' => $o,
-                'displayArea' => self::getDisplayArea($tz)
+                'region' => $o['region'],
+                'area' => $o['area'],
+                'displayRegion' => $o['displayRegion'],
+                'displayArea' => $o['displayArea']
             );
         }
 
@@ -39,7 +50,7 @@ class Pman_Core_TimeZone extends Pman
                 'fields' => array(
                     'region',
                     'area',
-                    'offset',
+                    'displayRegion',
                     'displayArea'
                 )
             ),
@@ -54,57 +65,204 @@ class Pman_Core_TimeZone extends Pman
         die('Invalid post');
     }
 
-    static $offsets = array();
+    static $timezones = array();
 
-    static function getOffsets()
+    static function getTimezones($lang)
     {
-        if(!empty(self::$offsets)) {
-            return self::$offsets;
+        if(!empty(self::$timezones)) {
+            return self::$timezones;
         }
-
-        $ce = DB_DataObject::factory('core_enum');
-        $ce->query('
+         $ce = DB_DataObject::factory('core_enum');
+        $ce->query("
             SELECT
-                *, TIME_FORMAT(TIMEDIFF(NOW(), CONVERT_TZ(NOW(), Name, "UTC")), "%H:%i") as offset
+                *, TIME_FORMAT(TIMEDIFF(NOW(), CONVERT_TZ(NOW(), Name, 'UTC')), '%H:%i') as timeOffset
             FROM
                 mysql.time_zone_name
+            WHERE
+                Name LIKE '%/%'
+                AND
+                Name NOT LIKE '%/%/%'
+                AND
+                Name NOT LIKE 'right%'
+                AND
+                Name NOT LIKE 'posix%'
+                AND
+                Name NOT LIKE 'Etc%'
             ORDER BY
-                offset DESC,
-                Name DESC
-        ');
+                SUBSTRING_INDEX(Name, '/', 1) ASC,
+                timeoffset ASC,
+                Name ASC
+        ");
 
-        while($ce->fetch()) {
-            // ignroe timezone such as 'CET' and 'America/Argentina/Buenos_Aires'
-            if(substr_count($ce->Name, '/') != 1) {
+        $regions = DB_DataObject::factory('core_enum');
+        $regions->setFrom(array(
+            'etype' => 'Timezone.Region',
+            'active' => 1
+        ));
+        $regionIds = $regions->fetchAll('display_name', 'id');
+
+        $areas = DB_DataObject::factory('core_enum');
+        $areas->setFrom(array(
+            'etype' => 'Timezone.Area',
+            'active' => 1
+        ));
+        $areaIds = $areas->fetchAll('display_name', 'id');
+
+
+        $ct = DB_DataObject::factory('core_templatestr');
+        $ct->lang = $lang;
+        $ct->on_table = 'core_enum';
+        $ct->active = 1;
+        $translations = array();
+        foreach($ct->fetchAll() as $t) {
+            if(empty($t->txt)) {
                 continue;
             }
+            $translations[$t->on_id][$t->on_col] = $t->txt;
+        }
+
+        while($ce->fetch()) {
+            // ignroe timezone such as 'CET' and 'America/Argentina/Buenos_Aires'
+           
 
             $ar = explode('/', $ce->Name);
             // ignore timezone such as 'Etc/GMT+8'
-            if($ar[0] == 'Etc') {
-                continue;
+
+            $region = $displayRegion = $ar[0];
+
+            if(!empty($translations[$regionIds[$region]]['display_name'])) {
+                $displayRegion = $translations[$regionIds[$region]]['display_name'];
             }
 
-            self::$offsets[$ce->Name] = substr($ce->offset, 0, 1) == '-' ? $ce->offset : '+' . $ce->offset;
+            $area =  $ar[1];
+            $displayArea = str_replace('_', ' ', $area);
+
+            if(!empty($translations[$areaIds[$displayArea]]['display_name'])) {
+                $displayArea = $translations[$areaIds[$displayArea]]['display_name'];
+            }
+
+            $timeOffset = ((substr($ce->timeOffset, 0, 1) == '-') ? '' : '+') . $ce->timeOffset;
+            $displayOffset = '(GMT ' . $timeOffset . ')';
+
+            self::$timezones[$ce->Name] = array(
+                'region' => $region,
+                'area' => $area,
+                'displayName' => $ar[0] . '/' . $displayArea . ' ' . $displayOffset,
+                'displayRegion' => $displayRegion,
+                'displayArea' => $displayArea . ' ' . $displayOffset
+            );
         }
 
-        return self::$offsets;
+        return self::$timezones;
+    }
+
+    static function isValidTimeZone($tz) {
+        try {
+            new DateTimeZone($tz);
+        }
+        catch (Exception $e) {
+            return false;
+        }
+
+        return true;
+    }
+
+    static function toRegion($tz)
+    {
+        if(!self::isValidTimeZone($tz)) {
+            return '';
+        }
+        
+        return explode('/', $tz)[0];
     }
 
-    static function getDisplayArea($timezone)
+    static function toArea($tz)
     {
-        self::getOffsets();
+        if(!self::isValidTimeZone($tz)) {
+            return '';
+        }
 
-        // invalid timezone
-        if(!isset(self::$offsets[$timezone])) {
+        return explode('/', $tz)[1];
+    }
+    
+    static function toTimeOffset($dt, $tz)
+    {
+        if(!self::isValidTimeZone($tz)) {
             return '';
         }
 
-        $ar = explode('/', $timezone);
+        if($dt == '0000-00-00 00:00:00' || $dt == '') {
+            $dt = 'NOW';
+        }
 
-        // e.g. 'Hong_Kong (GMT +08:00)'
-        return $ar[1] . ' (GMT ' . self::$offsets[$timezone] . ')';
+        $date = new DateTime($dt, new DateTimeZone($tz));
+        return $date->format('P');
     }
 
-    
+    static function toDisplayRegion($lang, $tz) 
+    {
+        $region = explode('/', $tz)[0];
+
+        $ce = DB_DataObject::factory('core_enum');
+        $ce->setFrom(array(
+            'etype' => 'Timezone.Region',
+            'active' => 1,
+            'name' => $region,
+            'display_name' => $region
+        ));
+        if(!$ce->find(true)) {
+            return $region;
+        }
+
+        $ct = DB_DataObject::factory('core_templatestr');
+        $ct->setFrom(array(
+            'lang' => $lang,
+            'on_table' => 'core_enum',
+            'on_id' => $ce->id,
+            'on_col' => 'display_name',
+            'active' => 1
+        ));
+        if(!$ct->find(true) || empty($ct->txt)) {
+            return $region;
+        }
+        return $ct->txt;
+    }
+
+    static function toDisplayArea($lang, $dt, $tz)
+    {
+        $displayArea = str_replace('_', ' ', self::toArea($tz));
+        $displayOffset = '(GMT ' . self::toTimeOffset($dt,$tz) . ')';
+
+        $ce = DB_DataObject::factory('core_enum');
+        $ce->setFrom(array(
+            'etype' => 'Timezone.Area',
+            'active' => 1,
+            'name' => $displayArea,
+            'display_name' => $displayArea
+        ));
+
+        if(!$ce->find(true)) {
+            return $displayArea . ' ' . $displayOffset;
+        }
+
+        $ct = DB_DataObject::factory('core_templatestr');
+        $ct->setFrom(array(
+            'lang' => $lang,
+            'on_table' => 'core_enum',
+            'on_id' => $ce->id,
+            'on_col' => 'display_name',
+            'active' => 1
+        ));
+        if(!$ct->find(true) || empty($ct->txt)) {
+            return $displayArea . ' ' . $displayOffset;
+        }
+
+        return $ct->txt . ' ' . $displayOffset;
+
+    }
+
+    static function toDisplayName($lang, $dt, $tz)
+    {
+        return self::toDisplayRegion($lang, $tz) . '/' . self::toDisplayArea($lang, $dt, $tz);
+    }
 }
\ No newline at end of file