一直以来多语言问题都是个让人头疼的问题,不是这个问题有多难,而是很繁琐,而我们目前的这个项目有点特殊,我希望最大限度的化繁为简,以下是我解决这个问题的方案。
我们的项目有这样两个前提:
1、要支持多语言但最多三种语言,一般情况下就两种语言,所以并没有随时切换语言的要求。
2、我们希望有一种可以初期不用管语言问题,之后统一翻译的方案
基于这么两点,我们提出了这样的方案:
1、初期写程序时不用关心多语言的翻译工作,只要将所有使用到中文的地方都用{}扩上
2、在数据库中Chinese会设置为唯一约束
3、所有的翻译工作会在BasePage中的Render方法中作
4、所有的页面会继承BasePage
5、翻译时会根据当前的语言设置构建以language表中Chinese做key,相应的语言为value的字典,然后查找需要翻译的字符串是不是在字典中,如果不在就生成这一行。

 
数据库设计四个字段

ID,Chinese,English,Other

BasePage源码

 

 BasePage : System.Web.UI.Page
{
    //利用Dictionary来筛选所有的多语言标签,然后做替换,可以缓存
    Dictionary<stringstring> 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、如果中文是一样的翻译,而其他语言翻译却不一样时不好解决,但这种情况似乎不常见


源码下载

相关文章: