[ASP.NET] 多國語系 - 讓 JavaScript 也能套用資源檔

利用 Generic Handler 把 Global Resource 動態轉成物件給 JavaScript 使用,結果如下:

上篇,我們了解如何使用本地與全域資源,現在我也想要讓 JavaScript 也能套用資源檔,馬上來看怎麼做

@JavaScriptGlobalResourceHandler.ashx

ResourceManager+GetResourceSet 用來列舉資源檔定義,主要是把資源檔轉成 Dictionary<object,object>

private Dictionary<object, object> ReadResources(
   string resourceKey, string requestedUICulture)
{
    var uiCultureInfo = CultureInfo.GetCultureInfo(requestedUICulture);
    var resourceManager = this.CreateResourceManager(resourceKey);

    var resourceSet = resourceManager.GetResourceSet(uiCultureInfo, true, true);
    Dictionary<object, object> result = null;
    result = resourceSet.Cast<DictionaryEntry>().ToDictionary(
        x => x.Key,
        x => resourceManager.GetObject((string)x.Key, uiCultureInfo));

    return result;
}

 

將 ResourceManager 放在一個 Pool 裡面,需要用的時候再拿取來

private ResourceManager CreateResourceManager(string resourceKey)
{
    //var assembly = s_globalAssembly;
    var key = "Resources." + resourceKey;

    ResourceManager resourceManager = null;
    if (s_resourceManagerPool.ContainsKey(key))
    {
        resourceManager = s_resourceManagerPool[key];
    }
    else
    {
        resourceManager = new ResourceManager(key, s_globalAssembly);
        s_resourceManagerPool.Add(key, resourceManager);
    }
    return resourceManager;
}

 

再將 Dictionary<object,object> 換成 JavaScript 的物件

private string GenerateJavaScriptObject(string requestResourceKey, Dictionary<object, object> globalResources)
{
    var javaScriptSerializer = new JavaScriptSerializer();

    var script =
        @"
if (typeof(Resources) == ""undefined"") Resources = {};
Resources." + requestResourceKey + " = " +
        javaScriptSerializer.Serialize(globalResources) + ";";
    return script;
}

 

最後我用 Generic Handler 裝載,Cache一天,並寫到 Client端

public void ProcessRequest(HttpContext context)
{
    var requestedUICulture = context.Request.QueryString["UICulture"];
    var requestResourceKey = context.Request.QueryString["ResourceKey"];

    if (string.IsNullOrWhiteSpace(requestedUICulture))
    {
        throw new ArgumentNullException("UICulture");
    }
    if (string.IsNullOrWhiteSpace(requestResourceKey))
    {
        throw new ArgumentNullException("ResourceKey");
    }

    var globalResources = this.ReadResources(requestResourceKey, requestedUICulture);
    var javaScriptObject = this.GenerateJavaScriptObject(requestResourceKey, globalResources);

    context.Response.ContentType = "application/javascript";
    context.Response.Expires = 1440;//1天
    context.Response.Cache.SetLastModified(DateTime.UtcNow);
    context.Response.Write(javaScriptObject);
}

完整程式碼:

https://dotblogsamples.codeplex.com/SourceControl/latest#Simple.JavaScriptUseResource/Simple.JavaScriptUseResource/JavaScriptGlobalResourceHandler.ashx.cs

@Default.aspx

javascript 參考 JavaScriptGlobalResourceHandler

<%@ Import Namespace="System.Globalization" %>
...
<head runat="server">
    <title></title>
    <script type="text/javascript" src="JavaScriptGlobalResourceHandler.ashx?ResourceKey=SystemConfig&UICulture=<%= CultureInfo.CurrentUICulture %>"></script>
</head>

在 javaScript 就能使用 Resources.SystemConfig.Love,這就跟我們在使用 Global 的後端資源一樣

<script type="text/javascript">
    function clicked(sender, args) {
        var msg = Resources.SystemConfig.Love;
        alert(msg);
    }
</script>

完整程式碼:

https://dotblogsamples.codeplex.com/SourceControl/latest#Simple.JavaScriptUseResource/Simple.JavaScriptUseResource/Default.aspx

切換語系

利用 Cookie 存放 Culture 狀態

@Global.asax

 

protected void Application_BeginRequest(object sender, EventArgs e)
{
    var language = Utility.GetLanguage();

    CultureInfo currentInfo = CultureInfo.GetCultureInfo(language);
    Thread.CurrentThread.CurrentCulture = currentInfo;
    Thread.CurrentThread.CurrentUICulture = currentInfo;
}

完整程式碼:

https://dotblogsamples.codeplex.com/SourceControl/latest#Simple.JavaScriptUseResource/Simple.JavaScriptUseResource/Global.asax.cs

@Default.aspx.cs

protected void English_Button_Click(object sender, EventArgs e)
{
    Utility.WriteLanguage("en-US");
    this.Response.Redirect(this.Request.RawUrl);
}

protected void Chinese_Button_Click(object sender, EventArgs e)
{
    Utility.WriteLanguage("zh-TW");
    this.Response.Redirect(this.Request.RawUrl);
}

完整程式碼:
https://dotblogsamples.codeplex.com/SourceControl/latest#Simple.JavaScriptUseResource/Simple.JavaScriptUseResource/Default.aspx.cs

@Utility.cs

預設拿瀏覽器的 HttpContext.Current.Request.UserLanguages 語系,cookie 若有狀態,則替換
 

public static string GetLanguage()
{
    string language = HttpContext.Current.Request.UserLanguages[0];
    var cookie = HttpContext.Current.Request.Cookies[LANGUAGE];
    if (cookie != null)
    {
        language = cookie.Value;
    }

    return language;
}

public static void WriteLanguage(string culture)
{
    var cookie = HttpContext.Current.Request.Cookies[LANGUAGE];
    if (cookie == null)
    {
        cookie = new HttpCookie(LANGUAGE);
    }
    cookie.HttpOnly = true;
    cookie.Expires = DateTime.Now.AddDays(1);
    cookie.Value = culture;
    HttpContext.Current.Response.Cookies.Add(cookie);
}

完整程式碼:
https://dotblogsamples.codeplex.com/SourceControl/latest#Simple.JavaScriptUseResource/Simple.JavaScriptUseResource/Utility.cs

執行結果

利用 Generic Handler 把 Global Resource 動態轉成物件給 JavaScript 使用,結果如下:

 

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo