当前位置 : 主页 > 手机开发 > 其它 >

Hybrid应用,WEB部分的国际化

来源:互联网 收集:自由互联 发布时间:2021-06-12
我们现在的应用已经有一部分功能Hybrid化了,之前也说过,有客户需要国际版的,我这边需要支持到多语言切换。 当时写了一点代码(http://www.voidcn.com/article/p-hnwxiota-da.html),把中文的

我们现在的应用已经有一部分功能Hybrid化了,之前也说过,有客户需要国际版的,我这边需要支持到多语言切换。

当时写了一点代码(http://www.voidcn.com/article/p-hnwxiota-da.html),把中文的东西抓出来,给翻译,所以原生部分在哪个时候已经基本解决了。从中文版切换到英文版,只需要到系统设置里面切换下语言就行。虽然还有一点细节,但是这里就不摊开了。

之前翻译一直没出来,所以,web这边的国际化也就一直挂着。

web这边的国际化有几种方案的,原理都是把文字等东西资源化。

第一种:

就像msdn上的做法一样



原理应该是通过路由来定位给到对应的网页

Global.asax.cs
public static void RegisterRoutes(RouteCollection routes)
{
	routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
	routes.MapRoute(
		"Globalization", // 路由名称
		"{lang}/{controller}/{action}/{id}", // 带有参数的 URL
		new { lang = "zh", controller = "Home", action = "Index", id = UrlParameter.Optional }, // 参数默认值
		new { lang = "^[a-zA-Z]{2}(-[a-zA-Z]{2})?$" }    //参数约束
	);
	routes.MapRoute(
		"Default", // 路由名称
		"{controller}/{action}/{id}", // 带有参数的 URL
		new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值
	);
}

(代码来自:http://www.tuicool.com/articles/bmIbe2)

这种的好处是,可以有针对性的给页面,官方也是这样用的。不过问题可能就是出在会改变链接上,加了一个前缀,所以之前代码中写了不少绝对路径,例如(/Order/Index)都要改一轮,原生那边也要跟着改一轮,切换语言时也要手动改一轮。


第二种:

通过Accept-Language的第一个语言来确定系统当前优先使用的语言

private string innerGetFirstAcceptLanguageInRequest() {
    string language = "zh-CN";
    if (enbaleAutoSwitchLanguage && Request.UserLanguages != null)
    {
        string[] array = Request.UserLanguages;//eg : Accept-Language:zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4
        if (array.Length > 0)
        {
            string firstLanguage = array[0];
            if (!string.IsNullOrWhiteSpace(firstLanguage))
            {
                if (!firstLanguage.StartsWith("zh"))
                {
                    //firstLanguage : zh  zh-cn zh-Hans zh-Hans-CN zh-tw
                    //only support "zh-CN" and "en-US" currently
                    language = "en-US";
                }
            }
        }
    }
    return language;
}

(参考资料:http://www.cnblogs.com/haogj/p/3921756.html)

Accept-Language第一个值 在Chrome中可以这样设置





在手机中就是系统语言了。


然后在把获取到的语言信息同步到cookie、C#中

private void innerUpdateCulture(string language)
{
    //cache lang in cookie,we may use it in js
    if (Request.Cookies != null)
    {
        if (Request.Cookies[cacheCookieName] != null)
        {
            HttpCookie lanCookie = Request.Cookies[cacheCookieName];
            lanCookie[cacheCookieKey] = language;
        }
        else
        {
            HttpCookie lanCookie = new HttpCookie(cacheCookieName);
            lanCookie[cacheCookieKey] = language;
            Response.Cookies.Add(lanCookie);
        }
    }

    //update culture in C#
    if (!string.IsNullOrEmpty(language))
    {
        Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(language);
        Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture(language);
    }
}

(参考资料:http://www.huhailong.cn/article_10.html)


然后C#上的资源就自动转过去了,js上如果需要国际化的信息,就可以从cookie中拿

Tools.isChinese = function() { 
    var arr,reg=new RegExp("(^| )"+"LdLang"+"=([^;]*)(;|$)");
    if(arr=document.cookie.match(reg)){
        var str = unescape(arr[2]); 
        var array = str.split("; "); 
        for(var i=0;i<array.length;i++){ 
            var arr=array[i].split("="); 
            if("lan"==arr[0]){
                return arr[1] == "zh-CN";
            }
        } 
    }
    return true;
};

会写得这么细致,是因为我用的是第二种。

好处就是原生系统切换语言的时候,web上的东西不用做什么处理(基本不用),就能把语言切换过去。地址也不用动(之前有写会跨几个不同版本的那些集团版也不用再来回搞一波)。当然原生那边也不是什么都不用做,它要确保Accept-Language中的值是对的。

接下来就是适配页面了,基本上都是体力活了。


代码都弄进系统了,所以不打算给demo了。这里给下step by step吧 :)

step1、选中项目右键-->“添加”-->“添加ASP.NET文件夹”-->“App_GlobalResources”  选中“App_GlobalResources”右键添加一个资源文件Global.resx

在新建中文和英文的资源:

例如:


这里的命名格式要保持,就是**.en-US.resx   **.zh-CN.resx

可以这样使用,举这个例子是为了说明,字符串中的东西,不要用拼接的方式去做,C#中提供了很方便的string.Format。

以前拼接了怎么办?这是债,要还  :  )

step2、在controller中新建一个BaseController

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Threading;

namespace MobileWeb.Controllers
{
    /// <summary>
    /// Refer to:
    /// http://www.huhailong.cn/article_10.html
    /// http://www.cnblogs.com/haogj/p/3921756.html
    /// 
    /// by Yeshen
    /// 2016.12.13
    /// </summary>
    public class BaseController : Controller
    {
        //config.js "Tools.isChinese()" quto this two key
        private const string cacheCookieName = "LdLang";
        private const string cacheCookieKey = "lan";

        //enbaleAutoSwitchLanguage default value is "true"
        //if disable , set this value to "false";
        private const bool enbaleAutoSwitchLanguage = true;

        /*
         * if any need?
        protected void OnlyEnglish() {
            this.innerUpdateLanguage("en-US");
        }
        */

        protected void Internationalization()
        {
            string language = innerGetFirstAcceptLanguageInRequest();
            this.innerUpdateCulture(language);
        }


        /////////////inner////////////////////////
        private string innerGetFirstAcceptLanguageInRequest() {
            string language = "zh-CN";
            if (enbaleAutoSwitchLanguage && Request.UserLanguages != null)
            {
                string[] array = Request.UserLanguages;//eg : Accept-Language:zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4
                if (array.Length > 0)
                {
                    string firstLanguage = array[0];
                    if (!string.IsNullOrWhiteSpace(firstLanguage))
                    {
                        if (!firstLanguage.StartsWith("zh"))
                        {
                            //firstLanguage : zh  zh-cn zh-Hans zh-Hans-CN zh-tw
                            //only support "zh-CN" and "en-US" currently
                            language = "en-US";
                        }
                    }
                }
            }
            return language;
        }
        private void innerUpdateCulture(string language)
        {
            //cache lang in cookie,we may use it in js
            if (Request.Cookies != null)
            {
                if (Request.Cookies[cacheCookieName] != null)
                {
                    HttpCookie lanCookie = Request.Cookies[cacheCookieName];
                    lanCookie[cacheCookieKey] = language;
                }
                else
                {
                    HttpCookie lanCookie = new HttpCookie(cacheCookieName);
                    lanCookie[cacheCookieKey] = language;
                    Response.Cookies.Add(lanCookie);
                }
            }

            //update culture in C#
            if (!string.IsNullOrEmpty(language))
            {
                Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(language);
                Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture(language);
            }
        }
    }
}

然后全部的controller都要继承它,每个方法都要调用Internationalization,例如


step3、找出项目中的全部中文字符,资源化它。

厚脸皮的说,我年初开始写web的时候,虽然web是新手,但是原生那边有一些经验,所以一开始上来都是直接用资源、用string.format去写,所以这一步反而没什么工作量。

如果需要找出来,可以参考我这篇博客(http://www.voidcn.com/article/p-hnwxiota-da.html)

step4、页面细节调整。

替换过后,每个页面都要看看,真会页面错乱,文字溢出的。


中午吃饭的时候,我们几个小伙伴的讨论这个,PC端的小伙伴有个意见:这里应该保留一个配置,如果一定要指定中文版或者英文版,要给指定到。

我虽然是拒绝的,因为现在产品SAAS化,不可能在针对某个酒店给配置了。然而考虑到我就要离职了,不要给接手的小伙伴造成困扰,我还是留了配置。

在BaseController中,关掉 enbaleAutoSwitchLanguage 选项,或者

/*
 * if any need?
protected void OnlyEnglish() {
	this.innerUpdateLanguage("en-US");
}
*/

然后今天的大部分时间都在弄step3、step4,东西不少,翻译那边也要协助搞,必然是耗时的。


转载请保留地址:http://blog.csdn.net/yeshennet/article/details/53614156

by Yeshen 2016.12.13

网友评论