[置顶] 关于网站多语言机制的实现的原型demo

先发个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 {}
利用XML文件作的多语言DEMO程序 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' '' '' 多語系設置類 '' '' Create: Bunny_Young 2010-03-12 '' email:yangmeiwen@163.com '' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' Modification history: '' '' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Imports System.Xml Imports System.Data Imports System.Web Imports System.Web.UI Imports System.Web.UI.WebControls Imports System.IO Public Class MutiLanguage Const _LANGUAGE_NAME = "language" Const _PAGE_NAME = "pageName" Const _CONTROL_NAME = "controlName" Const _CONTROL_TYPE = "controlType" Const _CONTROL_VALUE = "controlValue" Private _PageName As String ''resource讀取路徑 Private _languageType As String '' Private _xmlDoc As XmlDocument Private _savePath As String Private ds As DataSet Sub New(ByVal strLanguage As String, ByVal aspxPage As String) 'savePath = "~/Resource/" + strLanguage _PageName = "~/Resource/" + strLanguage + "/" + aspxPage + ".xml" _savePath = "~/Resource/" + strLanguage _savePath = HttpContext.Current.Server.MapPath(_savePath) _PageName = HttpContext.Current.Server.MapPath(_PageName) _languageType = strLanguage End Sub Public Sub GetDataSet() ds = New DataSet() ds.ReadXml(_PageName, XmlReadMode.Auto) End Sub Public Function UpdateLanguage(ByVal _controlName As String, ByVal _controlType As String, ByVal _controlValue As String) As Boolean GetDataSet() For Each dr As DataRow In ds.Tables(0).Rows If dr("controlName") = _controlName And dr("controlType") = _controlType Then dr("controlValue") = _controlValue End If Next ds.WriteXml(_PageName, XmlWriteMode.IgnoreSchema) ds.ReadXml(_PageName) End Function Public Function GetControlsList() As List(Of UIControl) GetDataSet() Dim dt As DataTable = ds.Tables(0) Dim ResultList As New List(Of UIControl) For Each dr As DataRow In dt.Rows Dim MyControl As New UIControl MyControl.ControlName = dr("controlName") MyControl.ControlType = dr("controlType") MyControl.ControlValue = dr("controlValue") ResultList.Add(MyControl) Next Return ResultList End Function ''' <summary> ''' 主動生成資源文件 ''' </summary> ''' <param name="strLanguage">語言類別</param> ''' <param name="Page">WEB PAGE</param> ''' <remarks></remarks> Public Sub WriteResourceFile(ByVal Page As UI.Page) Try If Not Directory.Exists(_savePath) Then Directory.CreateDirectory(_savePath) End If Dim writer As New XmlTextWriter(_PageName, Nothing) writer.Formatting = Formatting.Indented ''語言類別 writer.WriteStartElement(_LANGUAGE_NAME, _languageType) LoopAllControls(Page, writer) ''語言類別結束 writer.WriteEndElement() writer.Close() Catch ex As Exception End Try End Sub Private Sub LoopAllControls(ByVal oCtrl As Control, ByVal writer As XmlWriter) For Each _Ctrl As Control In oCtrl.Controls Dim _strName As String = _Ctrl.GetType.Name.ToUpper If _strName = "LABEL" Or _strName = "BUTTON" Then Dim strValue As String Dim strComment As String If _strName = "LABEL" Then strValue = CType(_Ctrl, Label).Text strComment = "label control" Else strValue = CType(_Ctrl, Button).Text strComment = "button control" End If writer.WriteComment(strComment) writer.WriteStartElement("Control") writer.WriteAttributeString(_CONTROL_VALUE, strValue) writer.WriteAttributeString(_CONTROL_NAME, _Ctrl.ID) writer.WriteAttributeString(_CONTROL_TYPE, _Ctrl.GetType.Name) writer.WriteEndElement() End If If _Ctrl.GetType.Name.ToUpper() = "GRIDVIEW" Then Continue For End If If _Ctrl.HasControls Then LoopAllControls(_Ctrl, writer) End If Next End Sub Public Sub ApplylanguageResource(ByVal _aspxPage As System.Web.UI.Page) GetDataSet() LoopApply(_aspxPage) End Sub Private Sub LoopApply(ByVal _control As Control) For Each ct As Control In _control.Controls Dim controlName As String = ct.ID Dim dr() As System.Data.DataRow = ds.Tables(0).Select("controlName='" + controlName + "'", "controlName DESC") If dr.Count > 0 Then If ct.GetType.Name.ToUpper = "LABEL" Then CType(ct, Label).Text = dr(0)("controlValue") End If If ct.GetType.Name.ToUpper = "BUTTON" Then CType(ct, Button).Text = dr(0)("controlValue") End If End If If ct.HasControls Then LoopApply(ct) End If Next End Sub End Class
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值