先发个demo .....
需求 能够在前台下载 语言文件进行编辑再上传 ....
配置选项如下:
'i18n_multi_languages' => array(
'enabled' => true , // 指示是否启用多语言支持
'writer' => 'Core_Helper_Translate',
'Core_Helper_Translate' => array(
'file_dir' => APPPATH . '/lang',
'default' => 'zh_cn',
),
),
<?php
/**
* 多语言翻译函数
*
* @return string 消息内容
*/
function __()
{
$args = func_get_args();
if (is_object(Core_App::$defaultMultiLanguages)){
$msgid = array_shift($args);
return Core_App::$defaultMultiLanguages->translate($msgid,$args);
}
return call_user_func_array('sprintf', $args);
}
/**
* Core_Helper_Translate类 提供多语言翻译支持
*
* 依赖 session 支持
*
* 开发者不应直接构造此类的实例对象,应该使用 Core_App::$defaultMultiLanguages 来引用此对象
*
* 构造函数的参数数组中必须带着键: file_dir | default
*
* 所有的语言文件必须满足以下条件:
* 1. UTF-8编码
* 2. 标准的 ini 文件格式
* 3. 以 .dc.ini 结尾
* 4. 内容按如下标记
*
* <code>
* [meta]
* description = 文件说明
*
* [trans]
*
* </code>
*
* @package core.helper
* @author 色色
*/
class Core_Helper_Translate {
/**
* 当前语言指示标识
*
* @var string
*/
private static $queryLangAccessor = '--core:lang:d--';
private static $hasConstruct = false;
/**
* 数据字典
*
* @var array
*/
private $dc = array();
function __construct(array $d){
if (self::$hasConstruct){
throw new Core_Helper_Translate_Exception("系统中仅允许 一个 Core_Helper_Translate 实例对象");
}
self::$hasConstruct = true;
$this->dcDir = $d['file_dir'];
$this->defaultLang = $d['default'];
$this->currentLang = Core_App::$defaultSessionWriter->get(self::$queryLangAccessor,null);
if (empty($this->currentLang)){
$this->currentLang = $this->defaultLang;
}
$this->changeLanguage($this->currentLang,false);
$this->dcNoget = true;// 数据字典是否被加载,用于懒惰加载
}
/**
* 导入翻译文件
*
* 对 多个翻译文件进行合并,并将结果进行缓存
* 如果翻译文件被修改,则自动同步缓存
*
*/
private function dcImport(){
$this->dcNoget = false;
$cache_id = self::$queryLangAccessor;
$cache_vcid = self::$queryLangAccessor . 'vc';
$dcFiles = $this->getDcFiles();
if (empty($dcFiles)) {
Core_App::$defaultCacheWriter->remove($cache_id);
Core_App::$defaultCacheWriter->remove($cache_vcid);
return;
}
$last_vc = Core_App::$defaultCacheWriter->get($cache_vcid);
$new_vc = Core_App::$currentTimeStamp;
foreach ($dcFiles as $file){
$new_vc .= filemtime($file);
}
if ($last_vc == $new_vc){
$data = Core_App::$defaultCacheWriter->get($cache_id);
if (!empty($data)){
$this->dc = json_decode($data,true);
}
unset($data);
return ;
}
$data = array();
foreach ($dcFiles as $file){
$d = parse_ini_file($file,true);
if (is_array($d) && isset($d['trans']) && is_array($d['trans'])){
$data = array_merge($data,$d['trans']);
}
unset($d);
}
$this->dc = $data;
Core_App::$defaultCacheWriter->set($cache_vcid,$new_vc);
Core_App::$defaultCacheWriter->set($cache_id,json_encode($data));
}
/**
* 获取 字典文件列表
*
* @return array
*/
function getDcFiles(){
return glob("{$this->dcDir}/{$this->currentLang}/*.dc.ini");
}
/**
* 获取 字典文件信息列表
*
* array(
* '文件路径' => '文件描述'
* )
*
* @return array
*/
function getDcFilesInfo(){
$dcFiles = $this->getDcFiles();
$data = array();
foreach ($dcFiles as $file){
$d = parse_ini_file($file,true);
$meta = Core_AppUtils::val($d,'meta',array());
$data[$file] = Core_AppUtils::val($meta,'description','');
unset($meta);
unset($d);
}
unset($dcFiles);
return $data;
}
/**
* 检测语言支持情况
*
* @param string $lang
* @param bool $throw
*
* @return bool
*/
private function checkSupport($lang,$throw=false){
$lang_dir = "{$this->dcDir}/{$lang}";
if (is_dir($lang_dir) && is_readable($lang_dir)){
return true;
}
if ($throw){
throw new Core_Helper_Translate_Exception("指定语言'{$lang}'并不被支持: ($lang_dir) 非有效目录");
}
return false;
}
/**
* 翻译消息
*
* @param string $msgid
* @param array $args
*
* @return string 消息内容
*/
function translate($msgid,array $args){
if ($this->dcNoget) $this->dcImport();
if (isset($this->dc[$msgid]))
{
$msgid = $this->dc[$msgid];
}
array_unshift($args, $msgid);
return call_user_func_array('sprintf', $args);
}
/**
* 切换访问者语言环境
*
* 如果指定的语言不被支持 将抛出 Core_Helper_Translate_Exception 异常
*
* @param string $lang 要切换的语言
* @param bool $reload 是否立即重新加载语言文件
*/
function changeLanguage($lang, $reload=false){
if ($this->checkSupport($lang,true)){
$this->currentLang = $lang;
Core_App::$defaultSessionWriter->set(self::$queryLangAccessor,$lang);
if ($reload){
$this->dcImport();
}
}
}
}
class Core_Helper_Translate_Exception extends Exception {}