NET MVC3 中的枚举多语言实现,DescriptionPairAttribute

以下是在实际项目中遇到的问题,项目架构:MSSQL2008、NET4.0、MVC3、XSLT视图引擎.

项目需求:要实现多语言站点。

视图引擎使用了弱类型的XSLT引擎;

多国语解决方案:多个XML语言文件(英文语言文件:lang_en-us.xml, 简体中文语言文件:lang_zh-cn.xml).

对于一般字段:

1、直接根据字段名称从语言文件中查找当前语言的字段说明:

<xsl:value-of select="$language/word[@key='UserName']" />


2、对于枚举项,为xslt定义了扩展方法:

<xsl:value-of select="html:WebXEnumText($model/@Class,'Destination',$model/@Destination,$Page.CurrentLanguage,'')" disable-output-escaping="yes" />
html:WebXEnumText参数说明:
$model/@Class:当前对象的类全名 FullName  = Nebula.Components.User;
'Destination'  : Nebula.Components.User 的属性Destination得名称;
$model/@Destination : 当前User对象的 Destination属性的值,Destination 为枚举类型;
$Page.CurrentLanguage: 当前语系,例:zh-cn;
public string WebXEnumText(string typeFullName, string PropertyName, string value, string language = "en-us", string @class = null)
{

}

以下是语言文件:

lang_en-us.xml
 1 <?xml version="1.0" encoding="utf-8"?>
2 <language type="en-us">
3
4 <!--Add:author 2011.4.29-->
5 <word key="USD">U.S. Dollor</word>
6 <word key="CNY">RMB</word>
7 <word key="USDUnit">$</word>
8 <word key="CNYUnit"></word>
9 <word key="TimeZone">Time Zone</word>
10
11 <!--基础标签-->
12 <word key="Current">Current</word>
13 <word key="Select">Select</word>
14 <word key="Enter">Enter</word>
15 <word key="Create">Create</word>
16 <word key="Edit">Edit</word>
17 <word key="Details">Details</word>
18 <word key="Manager">Manager</word>
19 <word key="Delete">Delete</word>
20 <word key="Next">Next</word>
21 <word key="More">还有更多内容..........</word>
22 </language>
lang_zh-cn.xml
 1 <?xml version="1.0" encoding="utf-8"?>
2 <language type="zh-cn">
3 <!--Add:Author 2011.4.29-->
4 <word key="USD">美元</word>
5 <word key="CNY">人民币</word>
6 <word key="USDUnit">美元</word>
7 <word key="CNYUnit"></word>
8
9 <!--基础标签-->
10 <word key="Current">当前</word>
11 <word key="Select">选择</word>
12 <word key="Enter">确定</word>
13 <word key="Create">创建</word>
14 <word key="Edit">编辑</word>
15 <word key="Details">详情</word>
16 <word key="Manager">管理</word>
17 <word key="Delete">物理删除</word>
18 <word key="">还有更多内容未列出.........</word>
19 </language>

以下是枚举的多语言实现:

基于枚举类型的特性 Attribute 解决,但以往的 Framework 内置的 DescriptionAttribute 并不能满足,看来我们只有自己解决了。

1、首先继承 Attribute 实现 DescriptionPairAttribute ,代码如下:

DescriptionPairAttribute
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime;

namespace Nebula.MVC.Components
{
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
public class DescriptionPairAttribute : Attribute
{

public static readonly DescriptionPairAttribute Default;
private KeyValuePair<string, string> description;

public string Key
{
get
{
return description.Key;
}
}
public string Value
{
get
{
return description.Value;
}
}

static DescriptionPairAttribute()
{
Default = new DescriptionPairAttribute();
}

private DescriptionPairAttribute()
: this(String.Empty, String.Empty)
{
}

[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public DescriptionPairAttribute(string key, string value)
{
description = new KeyValuePair<string, string>(key, value);
}

public override bool Equals(object obj)
{
if (obj == this)
return true;
DescriptionPairAttribute attribute = obj as DescriptionPairAttribute;
return ((attribute != null) && attribute.Description.Key == this.Description.Key && attribute.Description.Value == this.Description.Value);
}

public override int GetHashCode()
{
return this.Description.GetHashCode();
}

public override bool IsDefaultAttribute()
{
return this.Equals(Default);
}

public KeyValuePair<string, string> Description
{
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
get { return this.DescriptionValue; }
}
public KeyValuePair<string, string> DescriptionValue
{
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
get { return this.description; }
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
set { this.description = value; }
}

}
}

2、具体用法如下:

    public enum Destination : byte
{
/// <summary>
/// 大陆
/// </summary>
[Description("China")]
[DescriptionPair("zh-cn", "大陆")]
[DescriptionPair("en-us", "China")]
China,

/// <summary>
/// 香港
/// </summary>
[Description("HongKong")]
[DescriptionPair("zh-cn", "香港")]
[DescriptionPair("en-us", "HongKong")]
HongKong,
/// <summary>
/// Taiwan
/// </summary>
[Description("Taiwan")]
[DescriptionPair("zh-cn", "台湾")]
[DescriptionPair("en-us", "Taiwan")]
Taiwan
}


例如: DescriptionPair("zh-cn", "台湾")

zh-cn 为通用的语系名称 ,表示简体中文;

台湾 为 对应枚举项 Taiwan 的简体中文名称。

项目中的枚举都可以使用此特性,实现 N 个语言的说明,xml 语言文件中无需设置。

因为要想取得枚举的 “zh-cn” 需要用到反射,所以具体项目中,将枚举 的DescriptionPair已经加载到缓存(自行实现)中。运行时,根据强类型的枚举值或者若类型的枚举名称"Nebula.Components.Destination" 从缓存中获取对应的DescriptionPair 数据,在根据当前客户端的 语系信息,将对应语系(zh-cn)的输出到客户端(台湾)

获取语系:

System.Web.HttpContext.Current.Request.UserLanguages[0].ToLower();

如此,系统就可以根据浏览器(或者系统)的默认语言,输出对应语言的页面。

3、扩展

可以将语系(zh-cn)信息保存在session中,如此客户就可以自己指定系统语言

 1 public sealed class SiteConfig
2 {
3 public string Language
4 {
5 get
6 {
7 if (System.Web.HttpContext.Current.Session["language"] == null)
8 {
9 if (System.Web.HttpContext.Current.Request.UserLanguages != null && System.Web.HttpContext.Current.Request.UserLanguages.Length > 0)
10 System.Web.HttpContext.Current.Session["language"] = System.Web.HttpContext.Current.Request.UserLanguages[0].ToLower();
11 else
12 System.Web.HttpContext.Current.Session["language"] = "en-us";
13 }
14
15 return System.Web.HttpContext.Current.Session["language"].ToString().ToLower();
16 }
17 set
18 {
19 System.Web.HttpContext.Current.Session["language"] = value.ToLower();
20 }
21 }
22 }

 

初次发文,欢迎拍砖。

NET MVC3 中的枚举多语言实现,DescriptionPairAttribute

posted @ 2011-12-15 15:19  supernebula  阅读(730)  评论(0编辑  收藏  举报