当前位置:  开发笔记 > 编程语言 > 正文

在大型.NET项目中实现多语言/全球化的最佳方式

如何解决《在大型.NET项目中实现多语言/全球化的最佳方式》经验,为你挑选了3个好方法。

我将很快开始研究一个大型的c#项目,并希望从一开始就构建多语言支持.我有一个游戏,可以使用每种语言的单独资源文件,然后使用资源管理器加载字符串.

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



1> CularBytes..:
使用与Resources相关的单独项目

我可以从经验中看出这一点,拥有12个 24项目的当前解决方案,包括API,MVC,项目库(核心功能),WPF和Xamarin.值得一读这篇长篇文章,因为我觉得这是最好的方法.在VS工具的帮助下,可以轻松导出和导入,发送给翻译机构或由其他人审核.

编辑02/2018:仍然很强大,将其转换为.NET标准库使得甚至可以在.NET Framework和.NET Core中使用它.我添加了一个额外的部分,用于将其转换为JSON,例如angular可以使用它.

编辑:2019:与Xamarin一起前进,这仍适用于所有平台.例如,Xamarin.Forms也建议使用resx文件.(我还没有在Xamarin.Forms中开发应用程序,但文档,这是详细的入门方式,涵盖了它:Xamarin.Forms文档).就像将它转换为JSON一样,我们也可以将它转换为Xamarin.Android的一个.xml文件(目前正在处理).

所以,让我们来做吧.

Pro的

几乎无处不在.

在WPF中,您无需处理.resw.

据我测试,支持ASP.NET,类库,WPF,Xamarin,.NET Core,.NET Standard.

无需额外的第三方库.

支持文化回退:en-US - > en.

不仅是后端,也适用于WPF的XAML和MVC的.cshtml中的Xamarin.Forms.

通过改变来轻松操纵语言 ResourceDirectories

搜索引擎可以使用不同语言进行爬网,用户可以发送或保存特定于语言的网址.

反对的

WPF XAML有时会出错,新添加的字符串不会直接显示.重建是临时修复(vs2015).

告诉我.

建立

在解决方案中创建语言项目,为其命名,如MyProject.Language.添加一个名为Resources的文件夹,在该文件夹中创建两个Resources文件(.resx).一个名为Resources.resx,另一个名为Resources.en.resx(或特定的.en-GB.resx).在我的实现中,我使用NL(荷兰语)语言作为默认语言,因此在我的第一个文件中,英语在我的第二个文件中.

安装程序应如下所示:

语言设置项目

Resources.resx的属性必须是: 性能

确保将自定义工具命名空间设置为项目命名空间.原因是在WPF中,您无法引用Thread.CurrentThread.CurrentCultureXAML内部.

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

访问修饰符

在另一个项目中使用

参考您的项目:右键单击References - > Add Reference - > Prjects\Solutions.

在文件中使用命名空间: Resources

在后端使用它如此: using MyProject.Language; 如果有其他名为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(可能需要添加,如果是这样,请添加string someText = Resources.orderGeneralError;FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);方法中)Application_start()

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;

@Resources.w_home_header

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




  
    ...
    
  


这个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; }
    }
}

如果您有重塑器,它将自动检查给定的资源名称是否存在.如果您更喜欢类型安全,可以使用T4模板生成枚举

在WPF中使用.

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

在XAML中,在Window或UserControl的标题内,添加一个名为Global.asaxlike 的名称空间引用:


             mc:Ignorable="d" 
            d:Design d:Design>

然后,在标签内:

    

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

WPF的另一件事,设置内部的语言lang.您可以自己执行(在安装期间选择)或让系统决定.

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;
        }

    }
}

在Angular中使用它(转换为JSON)

现在,将Angular这样的框架与组件结合起来更为常见,因此没有cshtml.翻译存储在json文件中,我不打算介绍它是如何工作的,但如果你想将它转换为JSON文件,那很简单,我使用T4模板脚本将Resources文件转换为json文件.我建议安装T4编辑器来阅读语法并正确使用它,因为您需要进行一些修改.

只需注意一件事:无法生成数据,复制数据,清理数据并为其他语言生成数据.因此,您必须将下面的代码复制到您拥有的语言中,并在"//在此处选择语言"之前更改条目.目前没有时间来解决这个问题,但可能会在以后更新(如果感兴趣).

路径:MyProject.Language/T4/CreateWebshopLocalizationEN.tt

using Windows.UI.Xaml.Resources;

public class MyXamlResourceLoader : CustomXamlResourceLoader
{
    protected override object GetResource(string resourceId, string objectType, string propertyName, string propertyType)
    {
        return MyProject.Language.Resources.ResourceManager.GetString(resourceId);
    }
}

你去了,你现在可以为你的所有项目使用一个资源文件.这使得将所有内容导出到excl文档非常容易,并让某人翻译并再次导入.


我能否提出自己的答案?我只是不得不愚蠢地检查我自己的答案来修复WPF中语言之间切换的错误 - .-
1:刚出版Resources.xx.resx并更改xx以及我在哪里使用switch语句添加语言.2我使用ResxManager(通过TomEnglert)扩展,可以通过工具 - >扩展安装,很好的方式让语言彼此相邻,但实际的翻译是由其他人完成的(使用ResxManager轻松导出和导入excel).3.通过添加一个也遇到了最后一次,检查上面列出的所有文件,但是有些断点.我没有在WinForms中使用它.

2> BenAlabaster..:

我已经看到使用多种不同方法实施的项目,每种方法都有其优点和缺点.

一个人在配置文件中做到了(不是我最喜欢的)

一个人使用数据库做到了 - 这非常有效,但是你知道要维护什么是痛苦的.

一个人使用的资源文件就像你建议的那样,我不得不说这是我最喜欢的方法.

最基本的一个是使用一个充满字符串的包含文件 - 丑陋.

我会说你选择的资源方法很有意义.看到其他人的答案也会很有趣,因为我常常想知道是否有更好的办法来做这样的事情.我已经看到了许多资源都指向使用资源方法,包括一个就在SO上.



3> MW_dev..:

我认为没有"最佳方式".它实际上取决于您正在构建的技术和应用程序类型.

Webapps可以像其他海报建议的那样将信息存储在数据库中,但我建议使用单独的资源文件.这是与您的源分开的资源文件.单独的资源文件减少了对相同文件的争用,并且随着项目的增长,您可能会发现本地化将从业务逻辑中单独完成.(程序员和翻译).

Microsoft WinForm和WPF专家建议使用为每个语言环境定制的单独资源程序集.

WPF将UI元素的大小调整为内容的能力降低了所需的布局工作,例如:(日语单词比英语短得多).

如果您正在考虑WPF:我建议阅读这篇msdn文章 为了说实话,我发现WPF本地化工具:msbuild,locbaml,(也许是一个excel电子表格)使用起来很乏味,但确实有效.

只是略微相关的东西:我面临的一个常见问题是集成发送错误消息的遗留系统(通常是英文版),而不是错误代码.这会强制更改遗留系统,或将后端字符串映射到我自己的错误代码,然后映射到本地化字符串...... yech. 错误代码是本地化的朋友

推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有