在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)裡單獨處理
因為code裡的多語言路徑是固定的,是以隻會處理:f:\WWW\application\Admin\Lang\*.php檔案
導入的php格式如下
參考:
PHP動态參數
PHP 函數參數:call_user_func_array
PHPExcel - creating multiple sheets by iteration
Thinkphp開發手冊:多語言支援
From WizNote