天天看點

ThinkPhp 使用PhpExcel導出導入多語言檔案

在ThinkPHP 裡已經實作了多語言功能,隻要在指定的目錄下建立對應的語言檔案并填充内容,即可實作多語言功能

而多語言的翻譯卻是一個很麻煩的事情,因為客戶特定的行業問題導緻我們翻譯可能是不準确的

于是就寫了一個導入導出多語言功能,讓客戶根據規則自行翻譯多語言内容(撇清責任)

ThinkPhp 使用PhpExcel導出導入多語言檔案
ThinkPhp 使用PhpExcel導出導入多語言檔案
ThinkPHP 具體的語言封包件命名和位置如下:

語言包 語言檔案位置
應用語言包 應用公共目錄/Lang/語言檔案.php
子產品語言包 子產品目錄/Lang/語言檔案.php
控制器語言包 子產品目錄/Lang/語言目錄/控制器名(小寫).php
<?php
/**
 * @Author:      HTL
 * @Email:       [email protected]
 * @DateTime:    2016-07-13 17:06:00
 * @Description: 多語言導出與導入
 */
namespace Admin\Controller;
use Common\Controller\AdminbaseController;
class LangController extends AdminbaseController
{
 
    /**
     * 首頁
     * @Author   HTL
     * @Email    [email protected]
     * @DateTime 2016-07-13T17:11:40+0800
     * @return   [type]                   [description]
     */
    function index()
    {
        switch (I("get.type")) {
            case 'export_lang':
                $this->_export_lang();
                break;
            case 'import_lang':
                $this->_import_lang();
                break;
            default:
                $this->display();
                break;
        }
    }
    /**
     * 從Excel中導入多語言并生成PHP代碼
     * @Author   HTL
     * @Email    [email protected]
     * @DateTime 2016-07-12T17:08:42+0800
     * @return   [type]                   [description]
     */
    function _import_lang()
    {
        //是否上傳檔案
        if (count($_FILES['file']) <= 0) {
            $this->error("not select file");
            exit;
        }
        //多語言路徑,注意路徑大小寫,Linux是區分大小寫的
        $lang_path = SPAPP . "Admin/Lang/";
        $apps = sp_scan_dir($lang_path . "/*", GLOB_ONLYDIR);
        //多語言數[提供幾種語言]
        $app_count = count($apps);
        if ($app_count <= 0) {
            $this->error(L("_SELECT_NOT_EXIST_"));
            exit;
        }
        //将上傳的多語言檔案上傳到此,需要有寫入權限
        $new_file = './data/upload/' . iconv('UTF-8', 'GB2312', $_FILES['file']['name']);
        //上傳到指定路徑
        move_uploaded_file($_FILES['file']['tmp_name'], $new_file);
        vendor("PHPExcel.PHPExcel");
        //導入PHPExcel類
        $objPHPExcel;
        try {
            $objReader = \PHPExcel_IOFactory::createReader('Excel2007');
            $objPHPExcel = $objReader->load($new_file);
        } catch (Exception $e) {
            $this->error($e->getMessage());
            die;
        }
        //周遊工作表
        foreach ($objPHPExcel->getWorksheetIterator() as $worksheet) {
            $excels = array();
            $highestRow = $worksheet->getHighestRow();
            foreach ($worksheet->getRowIterator() as $row_index => $row) {
                //得到所有列
                $cellIterator = $row->getCellIterator();
                //單元格索引
                $index = 0;
                //周遊列
                foreach ($cellIterator as $cell_index => $cell) {
                    //多語言的名稱[en-us、zh-cn 、more.......]
                    //根據多語言生成不同的數組[每個語言為一個數組]
                    if ($row_index == 1) {
                        break;
                        //導出的文檔語言是否本地的語言一緻
                        // $lang_name = $cell->getCalculatedValue();
                        // foreach ($apps as $key => $value) {
                        //  $excels[$value] = array();
                        // }
                    }
                    //建立多語言資料[0=多語言的字段]
                    //某個語言的字段,用于設定N個多語言的值
                    if ($index == 0) {
                        $lang_name = $cell->getCalculatedValue();
                    } else {
                        $cell_val = $cell->getCalculatedValue();
                        //設定某個語言的字段值
                        if (strlen($cell_val) > 0) {
                            $excels[$apps[$index - 1]][$lang_name] = $cell_val;
                        }
                    }
                    $index++;
                }
            }
            //輸出php代碼到檔案
            //$name:語言名稱
            //$excl:語言内容
            foreach ($excels as $name => $excel) {
                $excel = var_export($excel, true);
                //var_export 生成的數組有一個空值,需要去掉,否則将出現錯誤
                $excel = preg_replace("/\\,\\s\\)/i", ")", $excel);
                //輸出php語言格式
                $excel = "<?php return " . $excel . "?>";
                if ($worksheet->getTitle() == "ALL_Language.php") {
                    file_put_contents($lang_path . '/' . $name . ".php", $excel);
                } else {
                    file_put_contents($lang_path . '/' . $name . '/' . $worksheet->getTitle(), $excel);
                }
            }
        }
        unset($excels);
        unset($objPHPExcel);
        $this->success(L("_OPERATION_SUCCESS_"));
    }
    /**
     * 替代scan_dir的方法
     * @param string $pattern 檢索模式 搜尋模式 *.txt,*.doc; (同glog方法)
     * @param int $flags
     */
    function sp_scan_dir($pattern, $flags = null)
    {
        $files = array_map('basename', glob($pattern, $flags));
        return $files;
    }
    /**
     * 導出自定義多語言到excel
     * @Author   HTL
     * @Email    [email protected]
     * @DateTime 2016-07-12T16:23:36+0800
     * @return   [type]                   [description]
     */
    function _export_lang()
    {
        //多語言檔案所在路徑,注意大小寫
        $lang_path = SPAPP . "Admin/Lang/";
        $apps = sp_scan_dir($lang_path . "/*", GLOB_ONLYDIR);
        //多語言數[提供幾種語言]
        $app_count = count($apps);
        if ($app_count <= 0) {
            $this->error(L("_SELECT_NOT_EXIST_"));
            exit;
        }
        vendor("PHPExcel.PHPExcel");
        //導入PHPExcel類
        $objPHPExcel = new \PHPExcel();
        $app = $lang_path . $apps[0];
        if (!is_dir($app)) {
            $this->error(L("_SELECT_NOT_EXIST_"));
            exit;
        }
        $objPHPExcel->removeSheetByIndex(0);
        //路徑下的語言檔案[/lang/en-us.php & /Lang/zh-cn.php & more]
        $merge_files = array();
        foreach ($apps as $key => $value) {
            $lang_file = $lang_path . $value . '.php';
            if (is_file($lang_file)) {
                //數組的key為多語言名稱
                $merge_files[$value] = (include $lang_file);
            }
            //end if
        }
        //end foreach
        // print_r($merge_files);exit;
        // ALL_Language.php 為全局語言檔案
        $this->_set_sheet_value(0, $objPHPExcel, $merge_files, 'ALL_Language.php');
        //多語言目錄下的語言檔案[/Lang/zh-cn/*.php]
        $files = sp_scan_dir($app . "/*.php");
        foreach ($files as $index => $key) {
            //合并多語言到一個數組
            $merge_files = array();
            //導入多語言并添加到數組中
            foreach ($apps as $_app) {
                $lang_file = $lang_path . $_app . '/' . $key;
                // echo($_app).'<BR>';
                // array_push($merge_files, $_app);
                if (is_file($lang_file)) {
                    //數組的key為多語言名稱
                    $merge_files[$_app] = (include $lang_file);
                    // array_push($merge_files, include ($lang_file));
                }
                //end if
            }
            //end foreach
            $this->_set_sheet_value($index + 1, $objPHPExcel, $merge_files, $key);
        }
        //end forach
        $objPHPExcel->setActiveSheetIndex(0);
        // $objPHPExcel->removeSheetByIndex(0);
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="' . date('ymdHis') . '-Languages.xlsx"');
        header('Cache-Control: max-age=0');
        // If you're serving to IE 9, then the following may be needed
        header('Cache-Control: max-age=1');
        // If you're serving to IE over SSL, then the following may be needed
        header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
        // Date in the past
        header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
        // always modified
        header('Cache-Control: cache, must-revalidate');
        // HTTP/1.1
        header('Pragma: public');
        // HTTP/1.0
        $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
        $objWriter->save('php://output');
    }
    /**
     * 設定sheet和單元格值
     * @Author   HTL
     * @Email    [email protected]
     * @DateTime 2016-07-12T17:06:05+0800
     * @param    [type]                   $sheet_index [sheet的索引]
     * @param    [type]                   $objPHPExcel [phpexcel對象]
     * @param    [type]                   $merge_files [多語言資料]
     * @param    [type]                   $title       [sheet title]
     */
    function _set_sheet_value($sheet_index = 0, $objPHPExcel, $merge_files, $title)
    {
        if (!$objPHPExcel || !$objPHPExcel || count($objPHPExcel) <= 0) {
            return;
        }
        //建立sheet并設定title,每一個多語言檔案都是一個sheet
        $excel = $objPHPExcel->createSheet($sheet_index)->setTitle($title);
        // $excel->setCellValue('A1',"Name")->setCellValue('B1',"")->setCellValue("C1","");
        //多語言定義的字段數量
        $field_count = array_keys($merge_files);
        //計算第一個多語言的key數量[數組的key是多語言名稱: array=('zh-cn'=>array("name"=>"name","age"=>"age"),"en-us"=>array())]
        $field_count = array_keys($merge_files[$field_count[0]]);
        //行索引[excel從1開始]
        $row_index = 1;
        //設定多語言
        foreach ($merge_files as $_key => $_value) {
            //每個shet的第一行第一列為Name[字段的名稱]
            if ($row_index == 1) {
                $excel->setCellValue("A{$row_index}", "Name");
            }
            //第一行的其他列為多語言名稱[zh-cn、en-us、.....]
            $excel->setCellValue(\PHPExcel_Cell::stringFromColumnIndex($row_index) . '1', $_key);
            //每個多語言都是單獨一列
            foreach ($field_count as $key => $values) {
                //第一列為多語言字段名[從1開始,第1行為Name或多語言名稱,是以這裡從2開始]
                $excel->setCellValue('A' . ($key + 2), $field_count[$key]);
                //列索引
                $column_index = \PHPExcel_Cell::stringFromColumnIndex($row_index);
                $excel->setCellValue($column_index . '' . ($key + 2), $_value[$values]);
            }
            //end foreach
            $row_index++;
        }
        //end foreach
    }
}      

導出的多語言檔案,每一個檔案就是一個sheet,不同的多語言會合同到同一個sheet裡

因為根目錄下有兩個多語言檔案zh-cn.php,en-us.php在非子目錄下,是以将這兩個檔案放在一個單獨的sheet(ALL_Language)裡單獨處理

ThinkPhp 使用PhpExcel導出導入多語言檔案

因為code裡的多語言路徑是固定的,是以隻會處理:f:\WWW\application\Admin\Lang\*.php檔案

ThinkPhp 使用PhpExcel導出導入多語言檔案

導入的php格式如下

ThinkPhp 使用PhpExcel導出導入多語言檔案

參考:

PHP動态參數

PHP 函數參數:call_user_func_array

PHPExcel - creating multiple sheets by iteration

Thinkphp開發手冊:多語言支援

From WizNote