ThinkPhp 使用PhpExcel导出导入多语言文件
在ThinkPHP 里已经实现了多语言功能,只要在指定的目录下创建对应的语言文件并填充内容,即可实现多语言功能
而多语言的翻译却是一个很麻烦的事情,因为客户特定的行业问题导致我们翻译可能是不准确的
于是就写了一个导入导出多语言功能,让客户根据规则自行翻译多语言内容(撇清责任)
ThinkPHP 具体的语言包文件命名和位置如下:
语言包 | 语言文件位置 |
---|---|
应用语言包 | 应用公共目录/Lang/语言文件.php |
模块语言包 | 模块目录/Lang/语言文件.php |
控制器语言包 | 模块目录/Lang/语言目录/控制器名(小写).php |
<?php /** * @Author: HTL * @Email: Huangyuan413026@163.com * @DateTime: 2016-07-13 17:06:00 * @Description: 多语言导出与导入 */ namespace Admin\Controller; use Common\Controller\AdminbaseController; class LangController extends AdminbaseController { /** * 首页 * @Author HTL * @Email huangyuan413026@163.com * @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 huangyuan413026@163.com * @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 huangyuan413026@163.com * @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 huangyuan413026@163.com * @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格式如下
参考: