支持中英文多语言浏览的MVC网站实例

思路大概是这样的,将翻译成不同语言的词句以xml键值对的格式分别存在不同文件夹下,扩展MVC HtmlHelper, 在扩展方法里根据用户当前访问Action所在的路径以及当前所选的语言类型读取语言文件夹下的xml文件,再通过HtmlHelper传过来的key获取对应的value。若找不到,则将key自动添加到相应的文件里面。切换语言时将所选的语言类型保存在Session,再Redirect。

写一个静态类LangHelper,用以操作语言文件。本例中,将中文、英文语言文件分别保存在网站根目录下Resources下的zh-cn和en文件夹里面,文件类型为res。为防止每次访问都去读取操作那些语言文件,我声明一个Dictionary静态变量,用来保存访问过的语言文件里的key\value,在下次(别的用户)访问时先从已保存在服务器内存的静态字典中读取。这样就加快了访问速度。

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Web;

namespace Utility
{
    public static class LangHelper
    {
        //全局静态变量
        private static Dictionary<string, LanguageInfo> Languages = new Dictionary<string, LanguageInfo>();

        public static string GetLangString(string key, string langType)
        {
            if (String.IsNullOrEmpty(key))
                throw new ArgumentException("key can not be null!", "key");
            if (String.IsNullOrEmpty(langType))
                throw new ArgumentException("language type can not be null!", langType);


            string filename = "common";
            langType = langType.ToLower();
            LanguageInfo info = GetLanguageInfo(langType, filename);//默认先到通用的语言文件里去找
            if (info.LanguageDictionary.ContainsKey(key.ToLower()))
                return info.LanguageDictionary[key.ToLower()];
            else
            {
                string filePath = HttpContext.Current.Request.FilePath;
                if (filePath == HttpContext.Current.Request.ApplicationPath)
                {
                    info.AddKey(key, key);//添加到通用语言文件
                    return key;
                }
                else
                {
                    if (filePath[0] == '/') filePath = filePath.Substring(1, filePath.Length - 1);
                    string[] words = filePath.Split(new char[] { '/' });
                    filename = String.Format("{0}", words[0]);//当前Controller所在的文件夹名字,也即语言文件的名字
                    info = GetLanguageInfo(langType, filename);
                    if (info.LanguageDictionary.ContainsKey(key.ToLower()))
                        return info.LanguageDictionary[key.ToLower()];
                    else
                    {
                        info.AddKey(key, key);
                        return key;
                    }
                }
                
            }
        }

        private static LanguageInfo GetLanguageInfo(string langType, string filename)
        {

            string cacheKey = String.Format("{0}{1}", langType, filename);
            LanguageInfo info = null;
            if (Languages.ContainsKey(cacheKey))
                info = Languages[cacheKey];
            else
            {
                info = new LanguageInfo(langType, filename);
                if (filename != "common") Languages.Clear();
                Languages[cacheKey] = info;
            }
            return info;
        }
    }

    public class LanguageInfo
    {

        public string LanguageCode { get; set; }

        public string ResourceFile { get; set; }

        public XElement RootElement { get; private set; }

        public Dictionary<string, string> LanguageDictionary { get; private set; }

        public LanguageInfo(string languageCode, string resourceFile)
        {
            this.LanguageCode = languageCode;
            this.ResourceFile = HttpContext.Current.Server.MapPath(
                String.Format("~/Resources/{0}/{1}.res",languageCode, resourceFile));
            this.LanguageDictionary = this.BuildLanguageDictionary();
        }

        /// <summary>
        /// 读取XML文件构建语言字典
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, string> BuildLanguageDictionary()
        {
            Dictionary<string, string> dic = new Dictionary<string, string>();
            if (System.IO.File.Exists(ResourceFile))
                RootElement = XElement.Load(ResourceFile);
            else
            {
                RootElement = new XElement("language");
            }
            IEnumerable<XElement> adds = RootElement.Elements();
            foreach (XElement add in adds)
            {
                string k = add.Attribute("key").Value;
                string v = add.Attribute("value").Value;
                dic[k.ToLower()] = v;
            }
            return dic;
        }

        public void SaveKey(string key, string value)
        {
            if (String.IsNullOrEmpty(key) || string.IsNullOrEmpty(value)) return;
            XElement e = RootElement.Elements().Where(a => a.Attribute("key").Value.ToLower() == key.ToLower()).FirstOrDefault();
            if (e == null) return;
            e.SetAttributeValue("value", value);
            RootElement.Save(ResourceFile);
        }
        /// <summary>
        /// 向语言文件添加键值对
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void AddKey(string key, string value)
        {
            XElement newel = new XElement("add");
            newel.SetAttributeValue("key", key);
            newel.SetAttributeValue("value", key);
            RootElement.Add(newel);
            try
            {
                RootElement.Save(ResourceFile);
            }
            catch (Exception e)
            {
            }
            LanguageDictionary[key.ToLower()] = value;
        }

        public void RemoveKey(string key)
        {
            if (String.IsNullOrEmpty(key)) return;
            XElement e = RootElement.Elements().Where(a => a.Attribute("key").Value.ToLower() == key.ToLower()).FirstOrDefault();
            if (e == null) return;
            e.Remove();
            RootElement.Save(ResourceFile);
        }
    }
}

GlobalizeUtil 类用来控制当前用户选择的语言类型

View Code
public class GlobalizeUtil
    { 
        public static string GetCurrentLanguage()
        {            
            object lang = HttpContext.Current.Session["language"];
            if (lang == null)
                return "zh-cn";
            else
                return lang.ToString();            
        }

        public static void SetCurrentLanguage(string langCode)
        {
            HttpContext.Current.Session["language"] = langCode;
        }
    }

扩展MVC HtmlHelper,方便在View中调用。扩展方法名为String,需要一个string类型参数,此参数即为key,当语言文件中不存在此key时,将此key直接作为value输出,并保存在语言文件中。

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using System.Xml.Linq;
namespace Utility
{
    public static class Extensions
    {
        /// <summary>
        /// 在Mvc View中调用
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string String(this HtmlHelper htmlHelper, string key)
        {
            return htmlHelper.Encode(GetLangString(key));
        }

        /// <summary>
        /// 在C#代码中使用
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string LangString(string key)
        {
            return GetLangString(key);
        }

        private static string GetLangString(string key)
        {            
            string langType = GlobalizeUtil.GetCurrentLanguage();
            return LangHelper.GetLangString(key, langType);
        } 
      
    } 

 
}

在View中的使用如: Html.String("Username"),在common.res语言文件里面就会添加一条 <add key="Username" value="Username" />记录,将zh-cn文件夹下的common.res里这条记录的value改为"用户名",则当用户在中英文之间切换时就会按不同语言显示。

效果图一:

效果图二:

不知有没有更好的方法,欢迎指教!

posted @ 2013-02-20 14:32  bright-lin  阅读(6881)  评论(13编辑  收藏  举报