php使用正则表达式和翻译字典json文件做翻译

需求:把页面中的中文翻译成越南文。
思路:在框架渲染页面的地方(这个地方能获取到页面渲染后的所有html数据,设为$str),使用以下方法。

//翻译中文 读取json文件,使用正则表达式替换中文
public static function pregReplaceChinese($str,,$toLanguageType = 'vietnam',$isNotHtml = false){
    if(empty($str)){
        return $str;
    } else {
        //翻译字典json文件 例子
        //$jsonFile ='{
        //  "追风剑": "Truy Phong Kiếm",
        //  "追风镯": "Truy Phong Trạc"
        //}';

        //0、翻译前准备 正则关键字符数组,避免影响到后面正则替换翻译
        $regexChars = ['^', '$', '.', '|', '?', '*', '+', '(', ')', '[', ']', '/', '-'];
        $unicodeChars = ['%u005e','%u0024','%u002e','%u007c','%u003f','%u002a','%u002b','%u0028','%u0029','%u005b','%u005d','%u002f','%u002d'];
        $oldContent = $str;

        //1、获取翻译关键字的json文件,将其转换为数组
        $jsonFile = 'http://admin.vanmac.zagoo.vn/language/vietnam.json';
        $fyChars = file_get_contents($jsonFile);
        $jsonArr = json_decode(str_replace($regexChars,$unicodeChars,$fyChars), true);//翻译json文件转换为数组
        if (is_string($str)) {
            $str = str_replace($regexChars,$unicodeChars,$str);//正则关键字符替换
        }


        //1-1、非页面翻译
        if ($isNotHtml) {
            // 处理数组(如道具数组)翻译
            if (is_array($str)) {
                $jsonArr = json_decode($fyChars, true);//翻译json文件转换为数组
                foreach($str as $key => $item){
                    if (!empty($jsonArr[$item['name']])) {
                        $str[$key]['name'] = $jsonArr[$item['name']];
                    }
                }
                return $str;
            }


            // 处理Excel表格内容和表格文件名称翻译
            if (strpos($str,'交易ID') !== false || strpos($str,',') !== false) {
                $str = iconv('gbk', 'utf-8', $str);
                if (strpos($str,'交易ID') !== false) { $str = str_replace('交易ID','交易id',$str); }
                $arr[0] = explode(',',$str);
            }
            if (empty($arr[0])) { preg_match_all('/[\x{4e00}-\x{9fa5}]+/u', $str, $arr); }

        } else {
            //2、获取页面中的>任意内容<,将其转换为数组
            $pattern = '/>[\s\S]*?<|title="([^"]+)"|value="([^"]+)"/';
            preg_match_all($pattern, $str, $arr);
        }



        //3、使用正则表达式preg_replace翻译替换中文处理,需要生成的两个关联数组,且索引保持一致才能进行顺序替换,其中匹配翻译的数组,当没有找到翻译关键字则设置为当前关键字
        $patterns = [];//需要翻译的数组
        $replaces = [];//匹配翻译的数组
        foreach($arr[0] as $item){
            $itemArr = [];
            $item = trim(str_replace(['>','<','title=','value='],'',$item));
            if(empty($item) || strstr($item, "u005d%u002e") || strstr($item, "'u005d'") || strstr($item, "'%u0029;")|| strstr($item, "}%u0029;") || strstr($item, "html") || strstr($item, "function ") || strstr($item, "label {") || strstr($item, "+json") || strstr($item, "%u002a")){//可能是页面代码如html、js/css代码
                continue;
            }
            $item = trim($item, '"');
            if (strpos($item,' 数量:') !== false) {//邮件列表道具翻译特殊处理
                 $itArr = explode('%u002e',$item);// %u002e--|
                 foreach ($itArr as $it1) {
                     $it1Arr = array_filter(explode(' ',$it1));
                     foreach ($it1Arr as $it2) {
                         $it2Arr = array_filter(explode(':',$it2));
                         foreach ($it2Arr as $it3) {
                             if (strpos($it3,'数量') !== false) { $it3 = ' '.$it3.':'; }
                             if (strpos($it3,'物品') !== false) {
                                 if (strpos($it3,'充值额度%u0029') !== false) {//例 (不增加充值额度)物品
                                     $it4Arr = explode('%u0029',$it3);
                                     $itemArr[] = $it4Arr[0].'%u0029';
                                     $itemArr[] = $it4Arr[1].':';
                                     continue;
                                 } else {
                                     $it3 = $it3.':';
                                 }
                             }
                             $itemArr[] = $it3;
                         }
                     }
                 }
            }
            if (strstr($item, " 总充值")) {//处理个别翻译
                $itemArr[] = '总充值';
            }

            if (!isset($itemArr[$item])) {
                $itemArr[$item] = $item;
            }

            foreach ($itemArr as $item) {
                self::arrayAss($jsonArr,$patterns,$replaces,$item);
            }
        }
        //数组按照键值长度 倒叙排序
        uksort($patterns, function($a, $b) {
            return strlen($a) < strlen($b);
        });
        uksort($replaces, function($a, $b) {
            return strlen($a) < strlen($b);
        });

        $content = preg_replace($patterns, $replaces, $str);
        if(!empty($content)){
            $content = str_replace($unicodeChars,$regexChars,$content);
            if (strpos($content,'<|/|d|i|v|>|') !== false) {//有些页面经过转换后 出现多余|
                $content = str_replace('|','',$content);
            }
        } else {
            $content = $oldContent;
        }
        return $content;
    }
}


//拼接原字符串和翻译字符串的数组
public static function arrayAss($jsonArr,&$patterns,&$replaces,$item){
    $patterns[$item] = '/'.$item.'/';
    if (!empty($jsonArr[$item])) {
        $replaces[$item] = $jsonArr[$item];
    } else {
        $replaces[$item] = $item;
    }
}

调用方法

//页面翻译
if (Tool::isvietnam()) {//翻译(用户点击了翻译按钮,Tool::isvietnam()方法是从缓存中获取用户是否点击了翻译按钮)
    $content = Tool::pregReplaceChinese($content);
}

//或者 Excel内容/文件名(纯中文)翻译
if (Tool::isvietnam()) {//翻译
    $filename = Tool::pregReplaceChinese($filename,'vietnam',true);//Excel文件名
    $data = Tool::pregReplaceChinese($data,'vietnam',true);//Excel内容字符串 交易ID,x,x,商品名称,x,x等
}