本文也是转摘,不过看到它的时候,我想起了discuz的URL解析,discuz在做rewrite的时候,并没有主动都对模版中的链接进行更换,而是在输出前,对于符合规则的那些链接使用rewrite的规范进行了一次批量替换。
这次我转摘的文章也是用了类似的方法,只是他又是.NET处理的,我也不翻译了。知道了原理就行了(和discuz一样,不过这种方法应该只适合做语言包)
原文:
一直以来多语言问题都是个让人头疼的问题,不是这个问题有多难,而是很繁琐,而我们目前的这个项目有点特殊,我希望最大限度的化繁为简,以下是我解决这个问题的方案。
我们的项目有这样两个前提:
1、要支持多语言但最多三种语言,一般情况下就两种语言,所以并没有随时切换语言的要求。
2、我们希望有一种可以初期不用管语言问题,之后统一翻译的方案
基于这么两点,我们提出了这样的方案:
1、初期写程序时不用关心多语言的翻译工作,只要将所有使用到中文的地方都用{}扩上
2、在数据库中Chinese会设置为唯一约束
3、所有的翻译工作会在BasePage中的Render方法中作
4、所有的页面会继承BasePage
5、翻译时会根据当前的语言设置构建以language表中Chinese做key,相应的语言为value的字典,然后查找需要翻译的字符串是不是在字典中,如果不在就生成这一行。
数据库设计四个字段
ID,Chinese,English,Other
BasePage源码:
- using System;
- using System.Data;
- using System.Configuration;
- using System.Linq;
- using System.Web;
- using System.Web.Security;
- using System.Web.UI;
- using System.Web.UI.HtmlControls;
- using System.Web.UI.WebControls;
- using System.Web.UI.WebControls.WebParts;
- using System.Xml.Linq;
- using System.Text.RegularExpressions;
- using System.Text;
- using System.Collections;
- using System.Collections.Generic;
- using System.IO;
- using System.Diagnostics;
- /// <summary>
- ///BasePage 的摘要说明
- /// </summary>
- public class BasePage : System.Web.UI.Page
- {
- //利用Dictionary来筛选所有的多语言标签,然后做替换,可以缓存
- Dictionary<string, string> dic;
- public BasePage()
- {
- }
- //需要替换的标签,标签头为数字字母下划线汉字
- static readonly Regex re = new Regex
- (@"((\{)|(\%7B))[\w\-\+\|u4e00-\u9fa5]+?((\})|(\%7D))",
- RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);
- //不需要替换的标签
- static readonly Regex re_nr = new
- Regex(@"<NOREPLACE>[\w\W]*?</NOREPLACE>", RegexOptions.Multiline | RegexOptions.IgnoreCase);
- private string RenderTag(ref string content)
- {
- if (re_nr.IsMatch(content))//不需要替换标签
- {
- StringBuilder sb = new StringBuilder();
- MatchCollection grouplist = re_nr.Matches(content);
- string[] reList = re_nr.Split(content);
- for (int i = 0; i < grouplist.Count; i++)
- {
- sb.Append(ReplaceTag(ref reList[i]));
- sb.Append(grouplist[i].Value);
- sb.Append(ReplaceTag(ref reList[i + 1]));
- }
- content = sb.ToString();
- }
- else
- {
- content = ReplaceTag(ref content);
- }
- return content;
- }
- private string ReplaceTag(ref string content)
- {
- //模板标签{yes},{no},{search}
- MatchCollection mc = re.Matches(content);
- if (dic == null)
- {
- dic = LanguageManager.GetResource();
- }
- for (int i = 0; i < mc.Count; i++)
- {
- //如果数据库中还没有此字符串
- if (!dic.ContainsKey(mc[i].Value.TrimStart('{').TrimEnd('}')))
- {
- content = content.Replace(mc[i].Value, mc[i].Value.TrimStart('{').TrimEnd('}'));
- if (!dic.ContainsKey(mc[i].Value.TrimStart('{').TrimEnd('}')))
- {
- LanguageManager.AddLanguageString(mc[i].Value.TrimStart('{').TrimEnd('}'));
- }
- }
- else if (dic[mc[i].Value.TrimStart('{').TrimEnd('}')] == null)
- {
- content = content.Replace(mc[i].Value, "$$$$");
- }
- else
- {
- content = content.Replace(mc[i].Value, dic[mc[i].Value.TrimStart('{').TrimEnd('}')].ToString());
- }
- }
- return content;
- }
- protected override void Render(HtmlTextWriter writer)
- {
- Stopwatch stopwatch = new Stopwatch();
- stopwatch.Reset();
- stopwatch.Start();
- try
- {
- //会把页面的输出结果存储在这个StringBuilder中
- StringBuilder sb = new StringBuilder();
- StringWriter sw = new StringWriter(sb);
- HtmlTextWriter htw = new HtmlTextWriter(sw);
- base.Render(htw);
- string content = sb.ToString();
- content = RenderTag(ref content);
- //重新写入页面
- writer.Write(content);
- }
- catch (Exception ex)
- {
- Response.Write(ex.ToString());
- Response.End();
- }
- finally
- {
- stopwatch.Stop();
- Response.Write("runtime:" + stopwatch.ElapsedMilliseconds.ToString() + "ms");
- }
- }
- }
优点
1、初期写程序时不用关心多语言的翻译工作,只要将所有使用到中文的地方都用{}扩上
2、省去了大量命名相应文字的工作
3、直接用中文标示要显示到页面的文字,容易理解
缺点
1、如果中文是一样的翻译,而其他语言翻译却不一样时不好解决,但这种情况似乎不常见
————————END————————
缺点就是我说的,只能用来做语言包,呵呵。