posts - 14,  comments - 37,  trackbacks - 0

          DotProject是一個基于AMP(apache+mysql+php)的開源項目管理工具,DotProject可以支持多語言并采用模塊化設計以便于擴展。
          最近需要一個項目管理軟件,于是就下載DotProject進行了試用,感覺不錯,但有中文有亂碼問題,如:日歷和gantt圖。現就對解決DotProject亂碼進行一下總結,由于本人以前沒接觸過PHP,初次修改有錯的地方請大家指正。
           機器環境:WindowsXP SP2簡體中文,apache2.0.59, mysql-5.0.16-win32, php-5.2.0,其他版本沒有測過,不能保證在其他版本下正確運行,由其在PHP4下。
          1. 加入語言包
           DotProject有比較不錯的多語言包,項目叫dot modules,在sourceforge上有。DotProject的語言包目錄./locales,運行可根據配置動態加載語言包進行對照轉換相應的語言。下載中文語言包解壓后并復制到語言目錄locales下,修改語言包文件夾下locales.php文件:
          $locale_char_set = 'GB2312';為$locale_char_set = 'utf-8';
          同時把英文語言包的同名文件也進行修改。使用'utf-8'的好處就是瀏覽器用unicode(utf-8)解碼,頁面可顯示多種語言文字。防照英文語言包創建lang.php文件,加入如下內容:

          <?php
          $dir = basename(dirname(__FILE__));
          $LANGUAGES['zh-cn'= array ( $dir, 'Chinese (Simplified)', '簡體中文', 'chs');
          ?>


          如果繁體則:

          <?php
          $dir = basename(dirname(__FILE__));
          $LANGUAGES['zh-tw'= array ( $dir, 'Chinese (Traditional)', '繁體中文', 'cht');
          ?>

          同時把目錄下的所有對照文件轉換為utf-8編碼存儲(可用ultraEdit等文本編輯器轉換或登錄后用DotProject翻譯管理進行更改),初步漢化完成。
          2. 修正在中文下日歷的亂碼問題
          本地化語言后日歷的星期顯示為亂碼,這是由于DotProject采用讀取操作系統本地語言區域日期格式引起的,在windowsXP中文版默認是“星期幾,xxxx-x-x”,且可能為GB2312編碼(本地區域語言可以更改)。DotProject讀取操作系統的日期用utf8_encode轉換后再顯示,這樣只要操作系統的本地區域日期語言格式和運行DotProject選取的語言不一至時就會出現亂碼,顯然不是聰明的做法。
          1)語言包文件夾下locales.php文件中加入日期格式對照表變量如下:

          $locale_weeks = array('星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六');
          $locale_short_week = array('', '', '', '', '', '', '');
          $locale_months = array(null, '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月');
          $locale_short_months = array(null, '1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月');

          2)DotProject的日期處理基類在lib\PEAR\Date下Calc.php文件中,修改或增加其中的相關幾個函數。
          加入和修改如下函數:

          //***************************************************************
          //得到月全名稱列表

          function getMonthNames()
          {
              
          global $locale_months;
            
          if(!empty($locale_months)){
              
          $months = $locale_months;
           
           }
          else{
              
          for($i=1;$i<13;$i++){
                  
          $months[$i= strftime('%B', mktime(0, 0, 0, $i, 1, 2001));
              }
            }
            
          return($months);
          }

          //****************************************************************
          //得到月短名稱列表    

          function getMonthShortNames($length=3)
          {
                  
          global $locale_short_months;
             
          if(!empty($locale_short_months)){
              
          $months = $locale_short_months;
             
            }
          else{
                      
          for($i=1;$i<13;$i++){
                          
          $months[$i= strftime('%B', mktime(0, 0, 0, $i, 1, 2001));
                          
          $months[$i= substr($months[$i], 0, $length);
                      }
                  }
                  
          return($months);
          }  

          //*****************************************************************
          //得到星期全名稱列表     

          function getWeekDays()
          {
                  
          global $locale_weeks;
             
          if(!empty($locale_weeks)){
              
          $weekdays = $locale_weeks;
            
            }
          else{
                
          for($i=0;$i<7;$i++){
                      
          $weekdays[$i= strftime('%A', mktime(0, 0, 0, 1, $i, 2001));
                      }
                  }        
                  
          return($weekdays);
          }

          //****************************************************************
          //得到星期短名稱列表   

          function getShortWeekDays($length=3)
          {
                  
          global $locale_short_week;
             
          if(!empty($locale_short_week)){
              
          $weekdays = $locale_short_week;
              
            }
          else{
                      
          for($i=0;$i<7;$i++){
                          
          $weekdays[$i= strftime('%A', mktime(0, 0, 0, 1, $i, 2001));
                          
          $weekdays[$i= substr($weekdays[$i],0,$length);                
                      }
                  } 
                  
          return($weekdays);


          //****************************************************************
          //得到月全名稱

          function getMonthFromFullName($month)
          {
                  
          $month = strtolower($month);
                  
          $months = Date_Calc::getMonthNames();
                  
          while(list($id, $name= each($months)){
                      
          if(ereg($month, strtolower($name))){
                          
          return($id);
                      }
                  }
                  
          return(0);
          }  

          //****************************************************************
          //得到月短名稱 

          function getMonthAbbrname($month,$length=3)
          {
                  
          $month = strtolower($month);
                  
          $months = Date_Calc::getMonthShortNames();
                  
          while(list($id, $name= each($months)){
                      
          if(ereg($month, strtolower($name))){
                          
          return($id);
                      }
                  }
                  
          return(0);
          // end func getMonthAbbrname

          //****************************************************************
          //得到星期短名稱

          function getWeekdayFullname($day="",$month="",$year="")
          {
                  
          if(empty($year))
                      
          $year = Date_Calc::dateNow("%Y");
                  
          if(empty($month))
                      
          $month = Date_Calc::dateNow("%m");
                  
          if(empty($day))
                      
          $day = Date_Calc::dateNow("%d");

                  
          $weekday_names = Date_Calc::getWeekDays();
                  
          $weekday = Date_Calc::dayOfWeek($day,$month,$year);

                  
          return $weekday_names[$weekday];

          // end func getWeekdayFullname

          //****************************************************************
          //得到星期短名稱

          function getWeekdayAbbrname($day="",$month="",$year="",$length=3)
          {
                  
          if(empty($year))
                      
          $year = Date_Calc::dateNow("%Y");
                  
          if(empty($month))
                      
          $month = Date_Calc::dateNow("%m");
                  
          if(empty($day))
                      
          $day = Date_Calc::dateNow("%d");

                  
          $weekday_names = Date_Calc::getShortWeekDays();
                  
          $weekday = Date_Calc::dayOfWeek($day,$month,$year);

                  
          return $weekday_names[$weekday];        
                  
          // end func getWeekdayAbbrname

          以上幾個函數有的是修改的,有的是新加的,由于較多,不再一一詳細說明。思路是明顯的,就是通過對日期列表的的映射獲得相應語言名稱。有興趣的朋友可能進行補充和更正。
          3)修改日期顯示的亂碼處,在modules\calendar\calendar.class.php文件把function _drawDays()函數中

             foreach$wk as $day ) {
             
          $s .= " <th width="14%">" . htmlentities(utf8_encode($day), ENT_COMPAT, $locale_char_set. "</th>";
           }

           utf8_encode函數去掉修改為

           foreach$wk as $day ) {
             
          $s .= " <th width="14%">" . htmlentities($day, ENT_COMPAT, $locale_char_set. "</th>";
           }

          完整的函數如下:

          //***************************************************************
          function _drawDays() {
            
          global $locale_char_set;

            
          $bow = Date_Calc::beginOfWeek( null,null,null,null,LOCALE_FIRST_DAY );
            
          $y = substr$bow, 0, 4 );
            
          $m = substr$bow, 4, 2 );
            
          $d = substr$bow, 6, 2 );
            
          $wk = Date_Calc::getCalendarWeek( $d, $m, $y, "%a", LOCALE_FIRST_DAY );

            
          $s = $this->showWeek ? " <th>&nbsp;</th>" : "";
            
          foreach$wk as $day ) {
             
          $s .= " <th width="14%">" . htmlentities($day, ENT_COMPAT, $locale_char_set. "</th>";
            }

            
          return " <tr>$s </tr>";
          }
          //****************************************************************

          修改文件module/tasks/ae_dates.php 

          function cal_work_day_conv($val) {
           
          GLOBAL $locale_char_set;
           
          $wk = Date_Calc::getCalendarWeek( null, null, null, "%a", LOCALE_FIRST_DAY );
           
           
          $day_name = $wk[($val - LOCALE_FIRST_DAY)%7];
           
           
          //把utf8_encode調用處注釋,不進行編碼轉換
          /*

           if ($locale_char_set == "utf-8" && function_exists("utf8_encode")) {
               $day_name = utf8_encode($day_name);
           }
          */ 
           
          return htmlentities($day_name, ENT_COMPAT, $locale_char_set);

          }

          以上是把顯示日期名稱時的utf8_encode轉碼去掉,因為讀到的日期名稱本來就是utf-8編碼,類似的地方可能還有,如果找到都要去掉。

          3. 修正在中文下Gantt圖的亂碼問題
          DotProject的圖形模塊使用了jpgraph。JpGraph是PHP專門進行繪制圖表的類庫。它使得作圖變成了一件非常簡單的事情,你只需從數據庫中取出相關數據,定義標題,圖表類型,然后的事情就交給JpGraph,只需掌握為數不多的JpGraph內置函數(可以參照JpGraph附帶例子學習),就可以畫出非常炫目的圖表!
          JpGraph要求PHP版本為4.04以上,并且支持GD庫且GD庫的版本應為2.0,而不是1.0。JpGraph有PHP4和PHP5兩種版本(由于我的環境是PHP5,所以下載了最新PHP5版本,在附件中修改過的DotProject包含這個版本,請使用PHP4更換相應的版本)。
          Gantt圖的亂碼問題的在于jpgraph中沒有對中文及其他語言文字處理好。
          1)修改jpgraph配置文件
          新建字體文件夾和修改lib/jpgraph/src/jpg-config.inc.php文件,在lib/jpgraph路徑新建fonts文件夾,把所要的字庫復制到該文件夾下。
          在文件lib/jpgraph/src/jpg-config.inc.php中加入如下語句(或把相應的注釋去掉后修改) 

          DEFINE('TTF_DIR','./lib/jpgraph/fonts/'); //設置jpgraphTTF(字體)文件夾
          DEFINE('SIMSUN_TTF_FONT','simsun.ttc');//使用'simsun.ttc'(windows下的宋體)
          DEFINE('CHINESE_TTF_FONT','simsun.ttc');

           2)修改文件module/tasks/gantt.php和module/projects/gantt.php
          新版在繪制Gantt圖時報錯:You are trying to use the locale (%s) which your PHP installation does not support. Hint: Use ‘ ’ to indicate the default locale for this geographic region.
          這是由于jpgraph沒有加入選定的日期格式如'chs',可修改SetDateLocale處如下:

          $jpLocale = dPgetConfig( 'jpLocale' );
          if ($jpLocale) {
           
          $graph->scale->SetDateLocale( $jpLocale );
          }
          else {
              
          $graph->scale->SetDateLocale( $AppUI->user_lang[0] );//第一個估計會有或注釋掉和設為 ‘ ’

          }

          Gantt圖繪制分兩部分,一部分是由DotProject生成的項目管理的標題等,一部分是用戶業務產生的內容區部分如項目和任務名稱。對于第一部分繪制字體編碼保持和DotProject一致。
          在語言包文件夾下locales.php文件中加入如下定義(本例是簡體中文)
          $LOCALE_FONT=30;
          30是在jpgraph中定義的語言字體標識(如中文為DEFINE("FF_SIMSUN",30);),詳見jpgraph.php文件。 這樣在繪制標題部分取FF_SIMSUN索引的字體。
          在文件module/tasks/gantt.php和module/projects/gantt.php中定義當前標題要使用的字體,加入如下語句:

          if (!empty($LOCALE_FONT)){
              
          define("CRURRENT_FONT",$LOCALE_FONT);
          }
          else {
              
          define("CRURRENT_FONT",FF_ARIAL);
          }

          這樣在設定字體的地方設定CRURRENT_FONT就可以了。把
          //$graph->scale->actinfo->SetFont(FF_ARIAL);改為
          $graph->scale->actinfo->SetFont(CRURRENT_FONT, FS_NORMAL, 10);//標題信息
          找到
          if (is_file( TTF_DIR."arialbd.ttf" ))
           $graph->scale->tableTitle->SetFont(FF_ARIAL,FS_BOLD,12); 改為
          $graph->scale->tableTitle->SetFont(CRURRENT_FONT, FS_NORMAL, 11);//標題頭
          在最后
          $vline = new GanttVLine($today, $AppUI->_('Today', UI_OUTPUT_RAW));語句后插入如下語句:
          $vline->title->SetFont(CRURRENT_FONT, FS_NORMAL, 10);//顯示today(今天)
          這樣繪制標題部分就修改完畢。
          第二部分內容區則要根據要繪制的文字編碼動態設定字體。因此在module/tasks/gantt.php和module/projects/gantt.php文件中加入判斷字符在什么語言區返回相應的字體(根據utf-8)本例只實現中文區,可以有不對地方,望大家指正。

          //utf-8 region segment 一-?
          function GetutfTTF($str

            
          if (preg_match("/^([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){1}/",$word== true || preg_match("/([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){1}$/",$word== true || preg_match("/([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){2,}/",$str== true)
            {
               
          return (FF_CHINESE); //返回中文字體標識FF_CHINESE
            }
               
          return (FF_ARIAL); //返回默認字體標識FF_ARIAL
          }

          然后在畫gantt圖相應的項目和任務要顯示的名稱判斷是否在中文,設置對應的字體,如:
          $bar->title->SetFont(GetutfTTF($name), FS_NORMAL, 10);
          $bar2->title->SetFont(GetutfTTF($t["task_name"]), FS_NORMAL, 10);

          所有$bar繪制都屬于內容區,都把相應部分用如上方法設定字體。繪制Gantt圖部分就修改完畢,看看效果:
          英文:
           


          中文: 

          4. 其他補充說明
          以上所有的編碼都設定為utf-8,因此建議把數據庫的服務器端和客戶端字符集都改為utf-8。Mysql修改配置文件my.cnf或my.ini即可。
          如phpmyadmin瀏覽DotProject的mysql數據庫,設定為”中文-Chinese Simplified(utf-8)”,如果發現在亂碼,請在includes/db_adodb.php文件中function db_connect()函數加上
           $db->Query("Set Names 'utf8'");
          這樣字符編碼就和phpmyadmin保持一致,用phpmyadmin瀏覽數據就沒有亂碼了。

          后話:
          本文雖然是解決亂碼問題,其中包含軟件國際化思想。在軟件支持多語言文字時,可以分為兩部分,一部分軟件本身通過配置有多種語言版本,一部分就是支持不同語言文字的處理。就象瀏覽器,雖然各種語言版本,但可以正常瀏覽不同語言的網頁。這主要是由于采用了統一編碼utf8-unicode(大多采用此種編碼)。可以預見,不久亂碼問題由于都采用統一編碼將不復存在。軟件的多語言只是軟件國際化第一步,中國軟件業國際化任重道遠。
          在附件中是由DotProject2.1rc版修改過的壓縮文件,并加入了最新的JpGraph for PHP5版本。有興趣的朋友可以下載大家共同研究。(由于不能上傳附件,需要的朋友可以留下email地址)

          下載地載:http://bbs.php168.com/read.php?tid=136083

          posted on 2007-07-19 15:10 冰封的愛 閱讀(862) 評論(0)  編輯  收藏 所屬分類: 開源項目
          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          常用鏈接

          留言簿(3)

          隨筆檔案

          文章分類

          文章檔案

          相冊

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 南安市| 武定县| 张家川| 娱乐| 阳江市| 平定县| 永福县| 买车| 南和县| 卫辉市| 名山县| 翁源县| 大埔区| 宁陕县| 陆河县| 凤凰县| 广昌县| 舒兰市| 隆尧县| 琼中| 兴安县| 萝北县| 邢台市| 古丈县| 克山县| 巴青县| 安徽省| 类乌齐县| 阿合奇县| 青阳县| 乐业县| 云林县| 电白县| 宣威市| 渭源县| 中西区| 隆林| 南木林县| 喀什市| 裕民县| 个旧市|