65.9K
CodeProject 正在变化。 阅读更多。
Home

.NET 基于 XML 的本地化

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.60/5 (7投票s)

2008 年 7 月 30 日

CPOL

3分钟阅读

viewsIcon

39691

downloadIcon

537

一篇关于 .NET 本地化的文章

简介与背景

在开发我的个人项目时,我必须解决本地化的问题。C# 为此提供了一个几乎完美的解决方案。如果你的窗体 (form) 的 Localization 属性设置为 true,并且你指定了默认语言,那么 studio (或 C# express) 将生成一系列组件的可本地化文本属性,这些属性部署在项目中。你可以通过双击 *.resx 文件在表格中编辑这些值。此外,编辑器会生成一个 Resourcename.Designer.cs 文件,该文件包含本地化属性,这些属性作为名为“resourcename”的类的静态成员。

这允许通过唯一的静态属性引用任何文本值,以基于 CultureInfo 属性查找变量的适当字符串值(有关详细信息,请参阅 msdn)。如果你想为你的项目添加一种额外的语言,你必须创建一个具有相同名称的新 .resx 文件,但名称必须包含文化 ID。 例如:LocalisationSample.resx(默认 resx 文件),LocalisationSample.en-EN.resx(英文版本)。

现在,如果你的项目重新编译,并且操作系统语言设置从你的默认语言(在我的例子中是匈牙利语)更改为英语,那么所有翻译的文本将以英语显示。

虽然这是一个强大的本地化问题解决方案,但我有一些额外的要求

  • 我不希望重新编译项目来添加新语言。
  • 我不希望代码大小和编译时间因新语言而增加。
  • 我想为用户提供将显示的文本翻译成任何语言的工具。

结果

为了满足上述要求,数据必须存储在用户可编辑的 XML 文件 (.resxml) 中。这些文件的文件名根据以下规则创建

文件名 + _lang + .resxml,例如
MyResources.resxml -> 英语
MyResources_hu.resxml -> 匈牙利语

resxml 文件的结构非常简单;以下示例 (Fruits.resxml) 包含一些水果的(ID、值、描述)三元组

<?xml version="1.0" encoding="utf-8"?>
<root>
  <it id="APPLE_ID" value="apple" description="my favorite fruit" />
  <it id="PEAR_ID" value="pear" description="a sweet fruit" />

</root>

定义了一个静态类 RManager,它能够在应用程序执行之初根据语言设置加载适当的 resxml 文件。这个类必须包含在你的项目中。为了将字符串变量(静态属性)用作全局变量,应该在 filename.cs(示例中的 Fruits.cs)文件中定义一个额外的静态类,名为“filename”。

/*RMTool 1.0 generated file, do not edit!*/
using RMTool;
using System.ComponentModel;

namespace FruitsNm{
    public static class Fruits
    {
        ///<summary>
        // my favorite fruit
        ///</summary>
        public static string APPLE_ID { get { return RManager.GetValue("Fruits",
            "APPLE_ID"); } }

        ///<summary>
        // a sweet fruit
        ///</summary>

        public static string PEAR_ID { get { return RManager.GetValue("Fruits",
            "PEAR_ID"); } }

    }
} /* end of file */

为了简化 resxml 文件和静态类的生成,我开发了一个免费工具,名为 RMTool。此工具在所选 resxml 文件的表格中显示数据三元组(ID (Name),值 (Text),描述)。

rmtool.JPG

该界面有助于管理、生成和翻译你的资源文件。

Using the Code

我创建了一个新项目,并在 Form1 中放置了一个 Label。

在将 RManager.csFruit.cs 文件添加到项目,并在 Form1 文件中引用 RMTool 和 FruitsNm 命名空间后,我能够将依赖于 APPLE_ID 语言的字符串值分配给 label1Text 属性。

源代码,Form1 的构造函数

public Form1()
{
    InitializeComponent();

    // the path of the application exe,
    // the Fruits.resxml resource file
    // is stored in this directory
    string AppPath = 
        Path.GetDirectoryName(Application.ExecutablePath);
    // get Fruits.resxml           
    RManager.GetFiles(AppPath, "");
    label1.Text = Fruits.APPLE_ID
}

以及结果

result.JPG

摘要

我提出了一种解决本地化问题的替代方法。通过这种方式,你的项目大小和编译时间不会随着新的语言资源而增加,因为它们存储在不同的 XML 文件 (resxml) 中,这些文件在应用程序执行期间动态加载。我还提供了一个工具来方便资源文件的开发。

© . All rights reserved.