在大型.NET项目中实现多语言/全球化的最佳方法是什么?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (20)

我很快就会在一个大型的C#项目上工作,并希望从一开始就构建多语言支持。我有一个游戏,并可以使用每种语言的单独资源文件来工作,然后使用资源管理器加载字符串。

还有其他可以研究的好方法吗?

提问于
用户回答回答于

与资源一起使用单独的项目

我可以从经验中得知这一点,拥有包含API,MVC,项目库(核心功能)和WPF的12个项目的最新解决方案。我还没有使用可移植的库进行测试,因为我没有为语言库创建便携式库。

所以,让我们开始吧。

Pro

  • 几乎到处都是强打字。
  • 在WPF中,你不必处理ResourceDirectories
  • 据我所测试,它支持ASP.NET,Class Libraries和WPF。
  • 没有额外的第三方库需要。
  • 支持文化回归:en-US - > en。
  • 不仅后端,也适用于WPF的XAML,适用于MVC的.cshtml。
  • 通过更改轻松操纵语言 Thread.CurrentThread.CurrentCulture
  • 搜索引擎可以使用不同的语言进行爬网,用户可以发送或保存语言特定的网址。

反对的

  • WPF XAML有时是bug,新添加的字符串不直接显示。重建是临时修复(vs2015)。
  • 告诉我。

建立

在你的解决方案中创建语言项目,给它一个像MyProject.Language这样的名字。向其中添加一个名为Resources的文件夹,并在该文件夹中创建两个资源文件(.resx)。一个名为Resources.resx,另一个名为Resources.en.resx(或特定的.en-GB.resx)。在我的实现中,我将NL(荷兰语)语言作为默认语言,所以这将在我的第一个文件中进行,而英语将在我的第二个文件中进行。

安装应该如下所示:

Resources.resx的属性必须为:

确保将自定义工具名称空间设置为您的项目名称空间。原因是在WPF中,你不能引用到ResourcesXAML内部。

在资源文件中,将访问修饰符设置为Public:

在另一个项目中使用

引用项目:右键单击引用 - >添加引用 - > Prjects \ Solutions。

在文件中使用命名空间: using MyProject.Language;

在后台像这样使用它: string someText = Resources.orderGeneralError; 如果有其他名为Resources的东西,那么只需放入整个名称空间即可。

在MVC中使用

在MVC中,你可以做但是你喜欢设置语言,但是我使用了参数化的URL,可以这样设置:

RouteConfig.cs 在其他映射下

routes.MapRoute(
    name: "Locolized",
    url: "{lang}/{controller}/{action}/{id}",
    constraints: new { lang = @"(\w{2})|(\w{2}-\w{2})" },   // en or en-US
    defaults: new { controller = "shop", action = "index", id = UrlParameter.Optional }
);

FilterConfig.cs(可能需要添加,如果添加FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);Application_start()方法)Global.asax

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new ErrorHandler.AiHandleErrorAttribute());
        //filters.Add(new HandleErrorAttribute());
        filters.Add(new LocalizationAttribute("nl-NL"), 0);
    }
}

LocalizationAttribute

public class LocalizationAttribute : ActionFilterAttribute
{
    private string _DefaultLanguage = "nl-NL";
    private string[] allowedLanguages = { "nl", "en" };

    public LocalizationAttribute(string defaultLanguage)
    {
        _DefaultLanguage = defaultLanguage;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        string lang = (string) filterContext.RouteData.Values["lang"] ?? _DefaultLanguage;
        LanguageHelper.SetLanguage(lang);
    }
}

LanguageHelper只是设置文化信息。

//fixed number and date format for now, this can be improved.
public static void SetLanguage(LanguageEnum language)
{
    string lang = "";
    switch (language)
    {
        case LanguageEnum.NL:
            lang = "nl-NL";
            break;
        case LanguageEnum.EN:
            lang = "en-GB";
            break;
        case LanguageEnum.DE:
            lang = "de-DE";
            break;
    }
    try
    {
        NumberFormatInfo numberInfo = CultureInfo.CreateSpecificCulture("nl-NL").NumberFormat;
        CultureInfo info = new CultureInfo(lang);
        info.NumberFormat = numberInfo;
        //later, we will if-else the language here
        info.DateTimeFormat.DateSeparator = "/";
        info.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy";
        Thread.CurrentThread.CurrentUICulture = info;
        Thread.CurrentThread.CurrentCulture = info;
    }
    catch (Exception)
    {

    }
}

.cshtml中的用法

@using MyProject.Language;
<h3>@Resources.w_home_header</h3>

或者如果不想定义使用,那么只需填写整个名称空间,或者可以在/Views/web.config下定义名称空间:

<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
  <namespaces>
    ...
    <add namespace="MyProject.Language" />
  </namespaces>
</pages>
</system.web.webPages.razor>

这个mvc实现源码教程:教程博客

在类库中使用模型

后端使用是相同的,但只是使用属性的一个例子

using MyProject.Language;
namespace MyProject.Core.Models
{
    public class RegisterViewModel
    {
        [Required(ErrorMessageResourceName = "accountEmailRequired", ErrorMessageResourceType = typeof(Resources))]
        [EmailAddress]
        [Display(Name = "Email")]
        public string Email { get; set; }
    }
}

在WPF中使用。

Ofcourse为您的MyProject.Language命名空间添加一个引用,我们知道如何在后端使用它。

在XAML中,在Window或UserControl的头文件中,添加一个lang像这样调用的名称空间引用:

<UserControl x:Class="Babywatcher.App.Windows.Views.LoginView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:MyProject.App.Windows.Views"
              xmlns:lang="clr-namespace:MyProject.Language;assembly=MyProject.Language" <!--this one-->
             mc:Ignorable="d" 
            d:DesignHeight="210" d:DesignWidth="300">

然后,在标签内:

    <Label x:Name="lblHeader" Content="{x:Static lang:Resources.w_home_header}" TextBlock.FontSize="20" HorizontalAlignment="Center"/>

由于它是强类型的,你确定资源字符串存在。有时您可能需要在安装过程中重新编译项目,WPF有时会有新的命名空间。

对WPF来说还有一件事,就是将语言设置在App.xaml.cs。你可以做你自己的实现(在安装过程中选择)或让系统决定。

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        SetLanguageDictionary();
    }

    private void SetLanguageDictionary()
    {
        switch (Thread.CurrentThread.CurrentCulture.ToString())
        {
            case "nl-NL":
                MyProject.Language.Resources.Culture = new System.Globalization.CultureInfo("nl-NL");
                break;
            case "en-GB":
                MyProject.Language.Resources.Culture = new System.Globalization.CultureInfo("en-GB");
                break;
            default://default english because there can be so many different system language, we rather fallback on english in this case.
                MyProject.Language.Resources.Culture = new System.Globalization.CultureInfo("en-GB");
                break;
        }

    }
}

现在,可以为所有项目使用一个资源文件。这使得它非常容易将所有内容导出到excl文档并让其他人翻译它。

用户回答回答于

我看过使用多种不同方法实施的项目,每个项目都有其优点和缺点。

  • 一个在配置文件中(不是我最喜欢的)
  • 其中一个使用数据库 - 这个工作非常好,但是在你知道要维护什么的时候很痛苦。
  • 一个使用过的资源按照你所建议的方式存档,我不得不说这是我最喜欢的方法。
  • 最基本的是使用包含字符串的包含文件 - 很难看。

我会说你选择的资源方法很有意义。看到其他人的答案也会很有趣,因为我经常想知道是否有更好的方式来做这样的事情。我已经看到许多资源都指向使用资源的方法。

扫码关注云+社区