tjj*_*son 74 .net c# multilingual localization
我将很快开始研究一个大型的c#项目,并希望从一开始就构建多语言支持.我有一个游戏,可以使用每种语言的单独资源文件,然后使用资源管理器加载字符串.
我还有其他可以研究的好方法吗?
Cul*_*tes 61
我可以从经验中看出这一点,拥有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的
.resw
.ResourceDirectories
反对的
建立
在解决方案中创建语言项目,为其命名,如MyProject.Language.添加一个名为Resources的文件夹,在该文件夹中创建两个Resources文件(.resx).一个名为Resources.resx,另一个名为Resources.en.resx(或特定的.en-GB.resx).在我的实现中,我使用NL(荷兰语)语言作为默认语言,因此在我的第一个文件中,英语在我的第二个文件中.
安装程序应如下所示:
确保将自定义工具命名空间设置为项目命名空间.原因是在WPF中,您无法引用Thread.CurrentThread.CurrentCulture
XAML内部.
在资源文件中,将访问修饰符设置为Public:
在另一个项目中使用
参考您的项目:右键单击References - > Add Reference - > Prjects\Solutions.
在文件中使用命名空间: Resources
在后端使用它如此:
using MyProject.Language;
如果有其他名为Resources的东西,那么只需放入整个命名空间.
在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 }
);
Run Code Online (Sandbox Code Playgroud)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
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)
{
}
}
Run Code Online (Sandbox Code Playgroud)
在.cshtml中的用法
@using MyProject.Language;
<h3>@Resources.w_home_header</h3>
Run Code Online (Sandbox Code Playgroud)
或者如果您不想定义使用,那么只需填写整个命名空间,或者您可以在/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>
Run Code Online (Sandbox Code Playgroud)
这个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; }
}
}
Run Code Online (Sandbox Code Playgroud)
如果您有重塑器,它将自动检查给定的资源名称是否存在.如果您更喜欢类型安全,可以使用T4模板生成枚举
Ofcourse添加对MyProject.Language命名空间的引用,我们知道如何在后端使用它.
在XAML中,在Window或UserControl的标题内,添加一个名为Global.asax
like 的名称空间引用:
<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">
Run Code Online (Sandbox Code Playgroud)
然后,在标签内:
<Label x:Name="lblHeader" Content="{x:Static lang:Resources.w_home_header}" TextBlock.FontSize="20" HorizontalAlignment="Center"/>
Run Code Online (Sandbox Code Playgroud)
由于它是强类型的,因此您确定资源字符串存在.您可能需要在安装过程中重新编译项目,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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在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);
}
}
Run Code Online (Sandbox Code Playgroud)
你去了,你现在可以为你的所有项目使用一个资源文件.这使得将所有内容导出到excl文档非常容易,并让某人翻译并再次导入.
我认为没有"最佳方式".它实际上取决于您正在构建的技术和应用程序类型.
Webapps可以像其他海报建议的那样将信息存储在数据库中,但我建议使用单独的资源文件.这是与您的源分开的资源文件.单独的资源文件减少了对相同文件的争用,并且随着项目的增长,您可能会发现本地化将从业务逻辑中单独完成.(程序员和翻译).
Microsoft WinForm和WPF专家建议使用为每个语言环境定制的单独资源程序集.
WPF将UI元素的大小调整为内容的能力降低了所需的布局工作,例如:(日语单词比英语短得多).
如果您正在考虑WPF:我建议阅读这篇msdn文章 为了说实话,我发现WPF本地化工具:msbuild,locbaml,(也许是一个excel电子表格)使用起来很乏味,但确实有效.
只是略微相关的东西:我面临的一个常见问题是集成发送错误消息的遗留系统(通常是英文版),而不是错误代码.这会强制更改遗留系统,或将后端字符串映射到我自己的错误代码,然后映射到本地化字符串...... yech. 错误代码是本地化的朋友
归档时间: |
|
查看次数: |
76601 次 |
最近记录: |