Chinaunix首页 | 论坛 | 博客
  • 博客访问: 177088
  • 博文数量: 76
  • 博客积分: 1350
  • 博客等级: 中尉
  • 技术积分: 1252
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-22 18:18
文章分类

全部博文(76)

文章存档

2009年(25)

2008年(51)

我的朋友

分类:

2009-10-28 14:44:10

08:53:12  csdn  Andrew(zhuyi)

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文件,加入如下内容:



如果繁体则:


同时把目录下的所有对照文件转换为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 .= " " . htmlentities(utf8_encode($day), ENT_COMPAT, $locale_char_set) . "";
 }

 utf8_encode函数去掉修改为
 foreach( $wk as $day ) {
   $s .= " " . htmlentities($day, ENT_COMPAT, $locale_char_set) . "";
 }

完整的函数如下:
//***************************************************************
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 ? "  " : "";
  foreach( $wk as $day ) {
   $s .= " " . htmlentities($day, ENT_COMPAT, $locale_char_set) . "";
  }

  return " $s ";
}
//****************************************************************

修改文件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绘制都属于内容区,都把相应部分用如上方法设定字体。


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浏览数据就没有乱码了。
阅读(932) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~