zoukankan      html  css  js  c++  java
  • 使用gettext技术为ASP.NET网站实现国际化支持

    不知道有多少人对这个题目感兴趣,因为最近在做一个网站玩玩,有点闲心给网站加了国际化支持。虽然ASP.NET已经有ResourceManager这个类,并且有标签实现国际化的支持了,但是它的问题是,ResourceManager对每一个需要翻译的句子都要求有一个键(Key):

    1.       要先创建一个.resx文件,在Visual Studio里,有一个工具编辑这个.resx文件。

    2.       对每一个需要翻译的句子,添加一个键值对。

    3.       然后在代码里,使用ResourceManager或者<%#这个标签,通过定义好的键来告诉ASP.NET在运行的时候查找正确的翻译文本。

    太麻烦了,不知道大家有什么其它好的方法,我使用的方法是从unix gettext那边借用过来的理念。

    理念

    Gettext的理念很简单,文本翻译吗,说白了就是把一句话翻译成另外一句话嘛,这个要翻译的句子,本身就可以当做检索要用的关键字,何必要再新建一个另外的关键字呢?gettext的方式很简单:

    1.       在源代码里,你可以编写一个特殊的函数执行翻译,这个函数只接受一个参数,就是要翻译的文本。

    2.       使用一个辅助程序xgettext扫描源代码的文本,将所有待翻译的文本都找出来,保存到一个文件里,一般来说,这个文件叫做po文件。

    3.       因为ASP.NET程序不支持po文件,再使用一个辅助程序msgfmtpo文件转换成ASP.NET支持的.resources文件。

    这个方法的优点在于:

    1.       你在编写程序的时候,不用为需要翻译的句子,定义一个新的关键字——这个关键字一般都比较难理解,也不好取名。在维护代码的时候很麻烦——因为你需要不停地在.resx编辑器和cs文件之间切换。

    2.       不知道怎么搞的,很难找到可以编辑.resx文件的工具,而gettext生成的po文件是普通的文本文件,而且格式非常简单。这样在翻译的时候,就很方便了。

    做法

    比如写了一个ASP.NET MVC程序,当然窗体(Web Form)形式的程序理念也是一样的,

    1.       写一个控制器和视图页的基类,里面都有一个执行翻译的函数T

        public class G18nController : Controller

        {

            public CultureInfo Culture { get; set; }

     

            public string T(string message)

            {

                var obj = HttpContext.GetGlobalResourceObject("website", message, Culture);

                var translated = obj == null ? null : obj.ToString();

                if (string.IsNullOrEmpty(translated))

                    return message;

                else

                    return translated;

            }

        }

     

        public abstract class G18nWebViewPage<U> : WebViewPage<U>

        {

            public CultureInfo Culture { get; set; }

     

            public string T(string message)

            {

                var obj = HttpContext.GetGlobalResourceObject("website", message, Culture);

                var translated = obj == null ? null : obj.ToString();

                if (string.IsNullOrEmpty(translated))

                    return message;

                else

                    return translated;

            }

        }

     

    上面的Culture属性,可以从Request.Headers["Accept-Language"]属性取得。

     

    2.       在代码里,针对每个要翻译的句子,直接调用这个T函数好了:

    throw new ArgumentException(string.Format(T("找不到ID{0}的项目!"), id));

     

    3.       程序写好后,要开始翻译,调用gettext程序将所有要翻译的句子找出来,保存到指定的po文件里。可以在http://gnuwin32.sourceforge.net/packages/gettext.htm这个网页下载gettext

     

    但是悲剧的是,gettext好像要求主语言是英文,对中文字符串支持的不是很好。所以我就用C#自己写了一个gettext,你可以在本文的附件里下载它,命令的格式是:

    Zgettext -k T -i 源代码路径名 -o 输出的po文件名

    Zgettext -k T -f 源代码路径列表文件 -o 输出的po文件名

     

    比如:

    Zgettext -k T -i AccountController.cs -o test.po

     

    4.       生成的po文件格式其实非常简单易懂:

    1.  #: C:\workspace\Views\Role\Edit.cshtml:9

    2.  msgid "管理用户组"

    3.  msgstr ""

    4.   

    5.  #: C:\workspace\Views\Role\Edit.cshtml:23

    6.  msgid "用户组[{0}]的权限"

    7.  msgstr ""

           

            Msgid就是要翻译的句子,msgstr就是翻译好的句子。

    5.       完成翻译后,使用一个辅助程序msgfmt将翻译好的po文件转换成ASP.NET支持的格式。因为原始的gettext程序包里的msgfmt.exe好像不能生成ASP.NET识别的.resources文件,所以 我也写了一个msgfmt程序完成这个工作——在本文的附件里可以下载到,命令格式是:

     

    Msgfmt -o 输出的resource文件路径 -i 输入的po文件路径

     

    例如:

    Msgfmt -o website.en-US.resources -i website.po

     

    注意:输出的resource文件名,必须与你在第一步里,使用HttpContext.GetGlobalResourceObject函数的第一个参数相同。

     

    6.       我写了一个小的批处理,将345步结合在一起执行:

    1.  pushd src

    2.  del /F source.lst

    3.  dir /s /b src\*.cs >> source.lst

    4.  dir /s /b src\*.cshtml >> source.lst

    5.  tools\zgettext\zgettext\bin\Debug\zgettext.exe -k T -f source.lst -o glob\website.po

    6.  tools\zgettext\msgfmt\bin\Debug\msgfmt.exe -o src\App_GlobalResources\website.resources -i glob\ website.po

    7.       popd

     

    希望对你有点帮助。



  • 相关阅读:
    [LeetCode]2. Add Two Numbers链表相加
    Integration between Dynamics 365 and Dynamics 365 Finance and Operation
    向视图列添加自定义图标和提示信息 -- PowerApps / Dynamics365
    Update the Power Apps portals solution
    Migrate portal configuration
    Use variable to setup related components visible
    Loyalty management on Retail of Dynamic 365
    Modern Fluent UI controls in Power Apps
    Change screen size and orientation of a canvas app in Power App
    Communication Plan for Power Platform
  • 原文地址:https://www.cnblogs.com/killmyday/p/2023816.html
Copyright © 2011-2022 走看看