前言
以前使用过ecshop,语言包,需要先去定义映射,然后才能使用,这样开发起来非常繁琐,现在的项目需要用到语言包用到的一个方案,记录一下。
大致思路
1.用中文作为键,翻译的语言包作为值。定义语言包文件
2.写一个递归函数来翻译变量。
3.php 中在向前端分配变量的时候,统一调用这个函数,这样保证php所有渲染过的数据,都是被翻译过的。
4.html中同样用这个递归函数去翻译中文
注意的地方。
在我们开发项目的时候,中文全部使用单引号,包括js,php。 这样,我们可以用扫描脚本的方式,将中文导出,不需要人工去查找。
PHP中,代码如下
initLocal($local);
}
/**
* 直接访问属性
* @param $name
* @return mixed
*/
public function __get($name)
{
return $this->$name;
}
/**
* 获取实例
*
* @return object
*/
public static function getInstance()
{
if (!self::$instance instanceof self) {
self::$instance = new self;
}
return self::$instance;
}
/**
* 为html页面提供语言支持
*/
public function langHtml($key, $replace = null)
{
$str = val(self::$langData, trim($key), $key);
//转数组
$replaceArr=is_array($replace)?$replace:[$replace];
if(!is_null($replace)){
foreach($replaceArr as $v){
$str = preg_replace('/'.self::REPLACE_STRING.'/', $v, $str,1);
}
}
return $str;
}
/**
* 递归处理数组翻译
* @param $arr
* @param int $mode 0=翻译key和value,1=翻译value,2=翻译key
*/
public function langArray($arr,$mode=0)
{
if(is_array($arr)){
foreach ($arr as $k=>$v){
if($mode==1){
//只翻译value
$arr[$k]=$this->langArray($v,$mode);
}else{
//翻译key
$kLang=langHtml($k);
$arr[$kLang]=$this->langArray($v,$mode);
if($kLang!=$k) unset($arr[$k]);
}
}
}else{
if(in_array($mode,[0,1])){
//需要翻译value
$arr=$this->langHtml($arr,$mode);
}
}
return $arr;
}
/**
* 将csv文件导成前端语言包文件,生成in-en-html.php
*/
public function makeLangHtmlFileFromCsv()
{
self::$langData=[];
$arrFile = ['operate_manage.csv', 'app_api.csv','caiwu.csv'];//html csv源文件
foreach ($arrFile as $v) {
$file = fopen(dirname(__FILE__) . '/in-en/' . $v, "r");
while (!feof($file)) {
$tmp = fgetcsv($file);
if (empty($tmp[0]) || empty($tmp[1])) continue;
//文件理没有出现过,且没有被翻译过
self::$langData[$tmp[0]] = $tmp[1];
}
fclose($file);
}
$content = 'addCookie(self::LANG_COOKIE_NAME, $lang);
}
/**
* 获取当前的语言环境
* @return string
* @throws Exception
*/
public function getLangFromCookie()
{
return GetOB('Util.Cookie')->getCookie(self::LANG_COOKIE_NAME);
}
//防止克隆
private function __clone()
{
}
/**
* 扫描目录,导出需要翻译的中文
* @param bool $diff
*
*/
public function scanDir($diff = true)
{
$projectDir = $this->getProjectRoot();//项目目录
$scanDir = ['/api/OB', '/account_manage/App','/operate_manage/App'];//需要文件目录'operate_manage/App'
foreach ($scanDir as $v) {
$dir = $projectDir . $v;
$this->scanFile($dir);
}
if ($diff) {
//去掉翻译过的
$inEnData = include dirname(__FILE__) . '/in-en/in-en-html.php';
$keyInEnData = array_keys($inEnData);
foreach ($this->outData as $k => $v) {
if (in_array($v, $keyInEnData)) {
unset($this->outData[$k]);
}
}
foreach ($this->outHtml as $k => $v) {
if (in_array($v, $keyInEnData)) {
unset($this->outHtml[$k]);
}
}
}
$data=[$this->outData,$this->outHtml];
foreach ($data as $k=>$v){
$v= array_unique($v);
switch ($k){
case 0: $filename='zh-cn-p.csv';break;
case 1: $filename='zh-cn-h.csv';break;
}
$fileDir=dirname(__FILE__)."/tmp";
if(!is_dir($fileDir))mkdir($fileDir);
$zhcnFile = fopen($fileDir. "/$filename", "w");
//组装导出数据
foreach ($v as $key => $value) {
fputcsv($zhcnFile, [$value], ',');
}
fclose($zhcnFile);
}
die;
}
/**
* 递归扫描文件
* @param $dir
* @return bool
*/
private function scanFile($dir)
{
$projectRoot = $this->getProjectRoot();
$skipDir = [$projectRoot . '/api/OB/Lang'];//跳过的文件目录
$skipFile = [
$projectRoot . '/api/OB/Util/MathUtil.class.php',
$projectRoot . '/api/OB/Util/DateUtil.class.php',
$projectRoot . '/api/OB/Util/Sms.class.php',
$projectRoot . '/api/OB/Util/SendMail.class.php',
$projectRoot . '/api/OB/Api/BluePay.class.php',
$projectRoot . '/api/OB/Api/Auth.class.php',
$projectRoot . '/api/OB/Api/ApiAction.class.php',
$projectRoot . '/operate_manage/App/View/useradmin/show.html',
$projectRoot . '/operate_manage/App/View/index/modal.html',
];//跳过的文件
if (!is_dir($dir) || in_array($dir, $skipDir)) return false;
$handle = opendir($dir);
if ($handle) {
while (($fl = readdir($handle)) !== false) {
$temp = $dir . DIRECTORY_SEPARATOR . $fl;
//如果不加 $fl!='.' && $fl != '..' 则会造成把$dir的父级目录也读取出来
if (is_dir($temp) && $fl != '.' && $fl != '..') {
$this->scanFile($temp);
} else {
if ($fl != '.' && $fl != '..' && !in_array($temp, $skipFile)) {
if (strpos($temp, '.php')) {
$content = file_get_contents($temp);
if (preg_match_all("/['\"]([\x{4e00}-\x{9fa5}!!,,a-zA-Z_]+[\x{4e00}-\x{9fa5}]+[\x{4e00}-\x{9fa5}!!,,a-zA-Z_0-9]*)['\"]/u", $content, $outArr)) {
$this->outData = array_merge($this->outData, $outArr[1]);
}
} elseif (strpos($temp, '.html')) {
$content = file_get_contents($temp);
if (preg_match_all("/([\x{4e00}-\x{9fa5}!!,,a-zA-Z_\/\/\\%,\[\],\(\)a-zA-Z_0-9\&\;\s:]*)/u", $content, $outArr)) {
foreach ($outArr[1] as $k => $v) {
//去掉注释
if (preg_match('/[\/\/\