• ASP.NET 多语言的实现(后台消息+前台消息+页面自动绑定)


    一 前言

    界面支持多种语言,在使用ASP.NET自带的多语言方案时遇到下列问题:

    • 在做管理类的功能时,有添加、修改和查看页面,需要支持多语言的控件基本相同,但要维护多处,产生冗余(ASP.NET有共享的资源,但它是全局的,不能分 模 块,我们不能所模块的信息入在全局资源中);
    • 在页面中必须要指定资源文件中的KEY;
    • 当页面慢来慢多时,页面与资源的匹配实在难以维护;

    所以我认为一个理想的支持多语言框架,需要有以下特性:

    • 分模块解决数据冗余问题;
    • 自动匹配页面与资源文件之间的联系;
    • 易于维护,能通过页面快速定位到资源文件中;
    • 支持后台消息的多语言实现
    • 支持前台JS消息的多语言实现

    二 后台消息多语言的实现

    在实现后台消息多言的实现时,主要利用ASP.NET的特性,通过修改当前线程的区域语言,来获取对应版本的资源。因为ASP.NET在处理请求时,会使用一个单独的线程来执行一次请求的所有代码,所以我们只需要在一个地方重写当前线程的语言信息,在其它任何地方都可以获取当前语言版本的资源文件。重写当前线程的区域语言的代码如下:

            protected override void InitializeCulture()
            {
                string language = "en";//默认为英文
                if (Session["Language"] != null) language = Session["Language"].ToString();
                Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(language);
                Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(language);
            }

    在命名资源文件名时,规则如下:

    • 默认语言的版本直接当正常命名,如命名OrderResource.resx
    • 其它版本的资源文件名,应加上区域名称, 如OrderResource.zh-cn.resx, OrderResource.en-us.resx.

    将后台消息放在资源文件后,程序中只引用主的资源文件,这样在线程的区域信息更改后,会自动的引用其它语言版本的资源。比如在程序中使用如下代码:

    Response.Write(OrderResource.FiledRequired);//当区域信息为英文时,输出"The Filed is required!";当区域信息为中文时,输出"字段必填!"

    三 前台JS多语言的实现

    前台的多语言实现,即在JS中需要弹出一些提示也需要多语言。前台多语言的实现方法实现有很多,在本例中,我们采用的统一的管理方式,把JS多语言信息同样放在资源文件中,只不过在一个公共的地方,把资源序列成一个json对象,然后JS中便可以使用了。当然,在实现此功能时,需要做一些缓存的工作。主要代码如下:

    public static Dictionary<string, string> JsonResources = new Dictionary<string, string>();
    
    //把资源文件序列化成JSON
            public static string GetJsonResource() 
            {
                string key = string.Format("JSResource.{0}", System.Threading.Thread.CurrentThread.CurrentCulture.Name);
                if (!JsonResources.ContainsKey(key)) 
                {
                    JavaScriptSerializer serialzer = new JavaScriptSerializer();
                    ResourceSet rs = JSResource.ResourceManager.GetResourceSet(System.Threading.Thread.CurrentThread.CurrentCulture, true, true);
                    string json = string.Format("[{0}]", serialzer.Serialize(rs.OfType<DictionaryEntry>().ToDictionary(x => x.Key, x => x.Value)));
                    JsonResources.Add(key, json);
                }
                return JsonResources[key];
            }
    
     protected override void OnPreRenderComplete(EventArgs e)
            {
                //输出JSON对象到页面
                Page.ClientScript.RegisterStartupScript(Page.GetType(), "", "<script language='javascript'>var json=eval(" + ResourceCache.GetJsonResource() + ");JSResource=json[0];</script>");
             }

    在页面中就可以使用JSResource对象了,如alert(window.JSResource.JSMsg);

    四 页面中的元素自动匹配资源文件

    此功能有一个前提就是资源文件中的KEY为控件ID并且为页面指定特定资源文件,这样我们就可以为控件自动匹配了。在匹配的过程中,如果在指定的资源文件中未找到,那么会到公共的文件中查找。

    注意:

    1>为页面指定特定资源文件,主要是用于多个页面(模块)共享一个资源,模块的大小可以自己控制;

    2>有一个公共的资源文件,在整个项目中,总有一些信息是各个模块所通用的;

     主要代码:

        public class ResourceFactory
        {
            public static ResourceAccess GetResource(System.Resources.ResourceManager resMgr)
            {
                return new ResourceAccess(resMgr, CommonResource.ResourceManager);
            }
        }
    
        public class ResourceAccess
        {
            private ResourceManager resourceManager = null;
    
            private ResourceManager commonResourceManager = null;
    
            public ResourceAccess(ResourceManager resourceManager,ResourceManager commonResourceManager) 
            {
                this.resourceManager = resourceManager;
                this.commonResourceManager = commonResourceManager;
            }
    
            public string GetString(string name) 
            {
                string str =  this.resourceManager.GetString(name);
    
                if (string.IsNullOrEmpty(str))
                {
                    str = this.commonResourceManager.GetString(name);
                    if (string.IsNullOrEmpty(str))
                    {
                        str = string.Format("【{0}】not exist", name);
                    }
                }
                return str;
            }
        }
    
        public class BasePage:Page
        {
            #region Mult Language
            protected override void InitializeCulture()
            {
                string language = "en";//默认为英文
                if (Session["Language"] != null) language = Session["Language"].ToString();
                Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(language);
                Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(language);
            }
    
            public System.Resources.ResourceManager PageResourceManager { set; get; }
            private ResourceAccess resourceAccess;
            private Literal lit;
            private Button btn;
            private LinkButton libtn;
    
            protected override void OnPreRenderComplete(EventArgs e)
            {
                //输出JSON对象到页面
                Page.ClientScript.RegisterStartupScript(Page.GetType(), "", "<script language='javascript'>var json=eval(" + ResourceCache.GetJsonResource() + ");JSResource=json[0];</script>");
                if (!IsPostBack)
                {
                    //绑定页面的文本
                    if (PageResourceManager != null)
                    {
                        resourceAccess = ResourceFactory.GetResource(PageResourceManager);
                        //we do not use recursion, because it create too much stack.
                        foreach (Control c in Page.Controls)//Large control of page,like HTML,Form
                        {
                            foreach (Control childC in c.Controls)//Normal control of page, like button, literal
                            {
                                BindControlLanguage(childC);
    
                                foreach (Control childCC in childC.Controls) //Container control of page(if one contrl has child controls)
                                {
                                    BindControlLanguage(childCC);
    
                                    foreach (Control childCCC in childCC.Controls)
                                    {
                                        BindControlLanguage(childCCC);
                                        foreach (Control childCCCC in childCCC.Controls)
                                        {
                                            BindControlLanguage(childCCCC);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                base.OnPreRenderComplete(e);
            }
    
            private void BindControlLanguage(Control c)
            {
                if (c is Literal)
                {
                    lit = (Literal)c;
                    if (lit.Text == "")
                    {
                        lit.Text = resourceAccess.GetString(lit.ID);
                    }
                }
                else if (c is Button)
                {
                    btn = (Button)c;
                    btn.Text = resourceAccess.GetString(btn.ID);
                }
                else if (c is LinkButton)
                {
                    libtn = (LinkButton)c;
                    if (libtn.Text == "")
                    {
                        libtn.Text = resourceAccess.GetString(libtn.ID);
                    }
                }
            }
            #endregion
        }
    View Code

    五 最终效果

    英文版本

    中版本

    全部代码下载

  • 相关阅读:
    php 使用正则匹配中文 返回结果
    怎样判断一个jquery对象是否为空jquery对象
    关于tp5.0中对象数组转换普通数组使用助手函数collection而不是toArray
    PHP 面试题三
    PHP 面试题二
    PHP 面试题 一
    laravel 学习笔记 —— 神奇的服务容器
    ubuntu下安装opencv库+Python2.7环境安装及开发摄像头拍照应用
    Linux内核分析(七)----并发与竞态
    Linux内核分析(六)----字符设备控制方法实现|揭秘系统调用本质
  • 原文地址:https://www.cnblogs.com/dataadapter/p/3583565.html
Copyright © 2020-2023  润新知