$v){ $str .= ""; $str .= "".str2xml_replace($k).""; if($flag){ $str .= "".str2xml_replace($v).""; } $str .= "\n"; } $tpl = read_file(LANG_XML_TPL); $str = str_replace("{{rows}}", $str, $tpl); save_file($file, $str); } // xml特殊字符替换处理 function str2xml_replace($str){ $str = str_replace("<", "<", $str); $str = str_replace(">", ">", $str); $str = str_replace("\n", " ", $str); $str = str_replace("\"", """, $str); return trim($str); } // 写数组文件 function save_array($file, $arr){ $str = " $v){ $k = trim(str_replace("'", "\'", $k)); $v = trim(str_replace("'", "\'", $v)); $str .= "\n\$words['$k'] = '$v';"; } $str .= "\nreturn \$words;"; save_file($file, $str); } // 获取数组文件中数组 function get_file_array($file){ if(!is_file($file)) return array(); return require($file); } // 比对数组获取未翻译集合 function diff_array($all, $need){ $arr = array(); foreach($need as $k => $v){ if(!isset($all[$k])){ $arr[$k] = $v; } } return $arr; } // 目录历遍处理 function fordir($path, $callfun, $funparams = array(), $is_next = true){ $handle = @opendir($path); while($f = readdir($handle)){ if($f == '.' || $f == '..' || $f == '.svn' || $f == '.git') continue; $file = $path.'/'.$f; if(is_file($file) || $is_next){ call_user_func_array($callfun, array_merge(array($file), $funparams)); } if(is_dir($file)) fordir($file, $callfun, $funparams, $is_next); } closedir($handle); } // 匹配多语言 function match_lang($lang){ $cli = array(); $srv = array(); // cli_config_match(cli_dir($lang)."/src/config", $cli, false); cli_match(cli_dir($lang)."/src", $cli, true); srv_match(srv_dir($lang)."/src/mod", $srv, true); echo("需翻译客户端内容数量:".count($cli)."\n"); echo("需翻译服务端内容数量:".count($srv)."\n"); $all = get_file_array(LANG_DATA."/$lang/".LANG_DATA_ALL); # $oldcli = get_file_array(LANG_DATA."/$lang/".LANG_DATA_CLI); # $oldsrv = get_file_array(LANG_DATA."/$lang/".LANG_DATA_SRV); # $cli = array_merge($cli, $oldcli); # $srv = array_merge($srv, $oldsrv); $need = array_merge($cli, $srv); $diff = diff_array($all, $need); save_array(LANG_DATA."/$lang/".LANG_DATA_CLI, $cli); save_array(LANG_DATA."/$lang/".LANG_DATA_SRV, $srv); save_xml(LANG_DATA."/$lang/".LANG_DATA_XML, $diff); echo("需翻译内容数量:".count($diff)."\n"); echo("生成待翻译文件,请手动翻译:". LANG_DATA."/$lang/".LANG_DATA_XML. "\n"); } // 合并翻译结果 function merge_lang($lang){ $rows = parse_xml(LANG_DATA."/$lang/".LANG_DATA_XML, "语言转换或翻译"); $all = get_file_array(LANG_DATA."/$lang/".LANG_DATA_ALL); $cli = get_file_array(LANG_DATA."/$lang/".LANG_DATA_CLI); $srv = get_file_array(LANG_DATA."/$lang/".LANG_DATA_SRV); $need = array_merge($cli, $srv); $num = 0; foreach($rows as $row){ // echo("===============".$row['cn']."\n"); if(!isset($need[$row['cn']])) continue; if(!isset($row['ret'])) continue; if($row['ret'] == '') continue; if(isset($all[$row['cn']])) if($all[$row['cn']] == $row['ret']) continue; if(!check_lang_ret($row['cn'], $row['ret'])) continue; $all[$row['cn']] = $row['ret']; // 未做校验 ++$num; } echo("正确翻译合并数量:$num\n"); if($num){ save_array(LANG_DATA."/$lang/".LANG_DATA_ALL, $all); $diff = diff_array($all, $need); save_xml(LANG_DATA."/$lang/".LANG_DATA_XML, $diff); } } // 判断2个字符串包含某字符的数量是否一致 function check_lang_ret($str1, $str2, $arr = array('~ts','~s','~w','~f','{','}','[',']',',','%s','%d')){ foreach($arr as $v){ if(substr_count($str1, $v) != substr_count($str2, $v)) { echo("翻译不正确: $str1 <> $str2\n"); return false; } } return true; } // 判断语言类型 function check_lang_type($lang){ $types = explode(",", LANG_TYPES); if(!in_array($lang, $types)){ exit("多语言类型[$lang]不正确:" . LANG_TYPES . "\n"); } if(!is_dir(LANG_DATA."/$lang")){ mkdir(LANG_DATA."/$lang",0777,true); } } // xml解析 function parse_xml($xmlfile, $sheetName, $headIndex = 1){ $res = simplexml_load_file($xmlfile); $table = null; $keys = array(); $rows = array(); $index = 0; for($i=0; $iWorksheet); $i++){ if($res->Worksheet[$i]->attributes('ss', true)->Name == $sheetName){ $table = $res->Worksheet[$i]->Table; break; } } foreach($table->Row[$headIndex] as $cell){ $keys[trim($cell->Data)] = $index; ++$index; }; $index = 0; foreach($table->Row as $row){ if(($index++)<=$headIndex) continue; //排除首行 if(!$row->Cell[0]->Data) continue; $tmp = array(); foreach($keys as $key => $col){ $val = (string)$row->Cell[$col]->Data; if(!$row->Cell[$col]){ $val = ""; }elseif($val == null){ $cell_ss = $row->Cell[$col]->children('ss', true); if($cell_ss->Data){ $val = (string)$cell_ss->Data->children()->Font; } } $tmp[$key] = trim($val); } $rows[] = $tmp; } return $rows; } /* 控制台颜色 */ function colorize($text, $status = "INFO"){ $out = ""; $status = strtoupper($status); switch($status) { case "INFO": $out = "[92m"; //Green background break; case "ERROR": $out = "[91m"; //Red background break; case "WARNING": $out = "[93m"; //Yellow background break; default: throw new Exception("Invalid status: " . $status); } return chr(27) . "$out" . "$text" . chr(27) . "[0m"; } /* 警告、错误、Notice等抛出*/ function error_handler($errno, $errstr, $errfile, $errline, array $errcontext) { if (0 === error_reporting()) { return false; } throw new ErrorException($errstr, 0, $errno, $errfile, $errline); } // 帮助接口 function help(){ echo("php lang.php cin {FILE} // 对客户端指定文件注入多语言函数\n"); echo("php lang.php sin {FILE} // 对服务端指定文件注入多语言函数\n"); echo("php lang.php match {LANG} // 匹配客户端/服务端多语言信息并生成需翻译文件\n"); echo("php lang.php merge {LANG} // 合并翻译结果\n"); echo("php lang.php gen {LANG} // 导出生成客户端/服务端翻译结果文件\n"); exit(); } // 入口函数 function main($argc, $argv){ if($argc < 3){ help(); } $cmd = $argv[1]; set_error_handler('error_handler'); try { if($cmd == 'cin'){ check_lang_type($argv[2]); cli_infun(cli_dir($argv[2])."/src/".$argv[3]); }else if($cmd == 'sin'){ check_lang_type($argv[2]); $sinDir = ""; if($argv[3] == 'inc') $sinDir = srv_dir($argv[2])."/inc"; else $sinDir = srv_dir($argv[2])."/src/mod/".$argv[3]; srv_infun($sinDir); }else if($cmd == 'match'){ check_lang_type($argv[2]); match_lang($argv[2]); }else if($cmd == 'merge'){ check_lang_type($argv[2]); merge_lang($argv[2]); }else if($cmd == 'gen'){ check_lang_type($argv[2]); cli_lang($argv[2]); srv_lang($argv[2]); }else{ help(); } restore_error_handler(); } catch (ErrorException $e) { echo colorize("Code: ".$e->getCode()."\n", "ERROR"); echo colorize("File: ".$e->getFile()."\n", "ERROR"); echo colorize("Line: ".$e->getLine()."\n", "ERROR"); echo colorize("Message: ".$e->getMessage()."\n", "ERROR"); restore_error_handler(); exit; } } main($argc, $argv);