本地化模块
ABP的本地化系统与Microsoft.Extensions.Localization
无缝集成,并与AspnetCore的本地化文档兼容. 它添加了一些实用功能和增强功能, 使其更易于在实际开发中应用.
SupportedCultures
的 CultureInfo 对象决定了和文化相关的函数,如日期,时间,数字和货币格式的结果。 SupportedCultures
同时决定了文字如何排序,大小写转换以及字符串比较。参考CultureInfo.CurrentCulture 获取更多关于服务器如何获取文化的信息。SupportedUICultures
决定如何通过 ResourceManager 查找翻译字符串(从 .resx 文件)
Volo.Abp.Localization是本地化系统的核心包.本地化资源用于将相关的本地化字符串组合在一起,并将它们与应用程序的其他本地化字符串分开.通常一个模块会定义自己的本地化资源. 本地化资源就是一个普通的类.
注意虚拟文件的命名空间与路径,比如AbpValidation,它的命令空间是Volo.Abp.Localization.Resources.AbpValidation,
则options.FileSets.AddEmbedded<AbpLocalizationModule>("Volo.Abp", "Volo/Abp"),而在AddVirtualJson("/Localization/Resources/AbpValidation")
public class TestResource { } [DependsOn(typeof(AbpLocalizationModule))] public class MyModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { Configure<VirtualFileSystemOptions>(options => { // "YourRootNameSpace" 是项目的根命名空间名字. 如果你的项目的根命名空间名字为空,则无需传递此参数. options.FileSets.AddEmbedded<MyModule>("YourRootNameSpace"); }); Configure<AbpLocalizationOptions>(options => { options.Resources .Add<TestResource>("en") .AddVirtualJson("/Localization/Resources/Test"); }); } }
- 添加了一个新的本地化资源, 使用"en"(英语)作为默认的本地化.
- 用JSON文件存储本地化字符串.
- 使用虚拟文件系统 将JSON文件嵌入到程序集中
{ "culture": "en", "texts": { "HelloWorld": "Hello World!" } }
- 每个本地化文件都需要定义
culture
(文化) 代码 (例如 "en" 或 "en-US"). //zh-Hans texts
部分只包含本地化字符串的键值集合 (键也可能有空格)
本地化资源也可以在客户端(JavaScript)使用. 因此, 为本地化资源设置一个简短的名称可以更方便的本地化文本. 例如
[LocalizationResourceName("Test")] public class TestResource { }
资源可以从其他资源继承,这使得可以在不引用现有资源的情况下重用现有的本地化字符串. 例如:[InheritResource(typeof(AbpValidationResource))]
也可以通过 AbpLocalizationOptions
配置:
services.Configure<AbpLocalizationOptions>(options => { options.Resources .Add<TestResource>("en") //Define the resource by "en" default culture .AddVirtualJson("/Localization/Resources/Test") //Add strings from virtual json files .AddBaseTypes(typeof(AbpValidationResource)); //Inherit from an existing resource });
资源可以从多个资源继承.如果新的本地化资源定义了相同的本地化字符串, 那么它会覆盖该字符串
使用AbpStringLocalizerFactory替换了IStringLocalizerFactory,增加单例ResourceManagerStringLocalizerFactory,
虚拟文件定义,本地化配置文件
所以整个过程,通过AbpStringLocalizerFactory创建IStringLocalizer,Create(ResourceType)方法,根据这个ResourceType从AbpLocationOption中LocalizationResourceDictionary获取到LocationResource,IStringLocalizer是包装这个LocationResource,用到是LocationResource.Contributor,即JsonVirtualFileLocationResourceContributor去得到相应的语言的值
应用里要先对AbpLocationOption进行配置,首先是根据resourceType(自定义的类,可使用LocalizationResourceName、InheritResource扩展
在AbpLocalizationOptions.Resources.Add<ResourceType>(默认语言).AddVirtualJson(这个是sonContributor,虚拟文件路径)),增加到LocalizationResourceDictionary,它是管理LocationResource的列表,三个方法 Add<TResouce>(默认语言),AddVirtualJson(),AddBaseTypes
LocationResource的属性,
1、ResourceType,在资源文件里新建的类,可加上Attributor可以LocalizationResourceName(), InheritResource(typeof(另一个资源类))
2、ResourceName》从LocalizationResourceNameAttribute
3、DefaultCultureName:上面Option方法new要传进来,后续的作用是?如果当前的线程的CultureInfo找不到这个值,则使用这个
4、BaseResourceTypes:来自InheritResourceAttribute,用于遍历,如果当前找不到,就遍历找InheritResource的type
5、Contributor List<ILocalizationResourceContributor>: ,获取对应的值实现由它要提供,即LocationResource.Contributor.GetOrNull(),只要遍历到一个就返回,实现使用是JsonVirtualFileLocalizationResourceContributor,它扩展
AbpLocationOption有一个全局的Contributor,这个增加到上面LocaionResource.Contributor里面去。
在Volo.Abp.AspNetCore.Mvc.Client添加 一个GlobalContributors是RemoteLocalizationContributor,
从工厂Create出来的IStringLocalizer<ResourceType>是AbpDictionaryBasedStringLocalizer,
首先是AbpLocalizationOptions.Add方法是增加到Resources,LocationResources列表,返回在这个ResourceType的LocaltionResource,再AddVirtualJson是增加到LocationResources的贡献者(Contributes)里面,AddBaseTypes是增加到BaseResourceType里面。 同在Location的初始化的时候,已经将InheritResource作为baseresourceType的增加进去了
查找到这个前面Add这个Resource里面对应的LocationResource,找不到就使用原来的ResourceManagerStringLocalizerFactory。
使用ABP,其中要使用的AbpDictionaryBasedStringLocalizer,也要连带List<IStringLocalizer> baseLocalizers
索引获取方法
public virtual LocalizedString this[string name] => GetLocalizedString(name); protected virtual LocalizedString GetLocalizedString(string name) { return GetLocalizedString(name, CultureInfo.CurrentUICulture.Name); /当前线程的CultureInfo }
IStringLocalizer<ResourceType> 的GetLocalizedString(“字符串”)的方法
它是使用此ResourceType的LocationResource,先使用contributor(这个是JsonVirtualFileLocalizationResourceContributor,读取虚拟文件值,增加到字典里),再从BaseLocationResourceType添加进去
这个存储的数据结构是Dictionary<string, ILocalizationDictionary>,其中key的索引是cultureCode,而ILocalizationDictionary是StaticLocalizationDictionary(特定语言)
再根据当前语言值,获取到StaticLocalizationDictionary,再获取对应值LocalizedString
dictionary[item.Key] = new LocalizedString(item.Key, item.Value.NormalizeLineEndings());
若GetAllStrings(语言,是否包含默认语言,是否包含基类)
在AbpApplicationConfigurationController,控制器,[Route("api/abp/application-configuration")],对所有Location进行配置
protected virtual async Task<ApplicationLocalizationConfigurationDto> GetLocalizationConfigAsync() { var localizationConfig = new ApplicationLocalizationConfigurationDto(); localizationConfig.Languages.AddRange(await _languageProvider.GetLanguagesAsync()); foreach (var resource in _localizationOptions.Resources.Values) //所有的Resources { var dictionary = new Dictionary<string, string>(); var localizer = _serviceProvider.GetRequiredService( typeof(IStringLocalizer<>).MakeGenericType(resource.ResourceType) ) as IStringLocalizer; foreach (var localizedString in localizer.GetAllStrings()) { dictionary[localizedString.Name] = localizedString.Value; } localizationConfig.Values[resource.ResourceName] = dictionary; } localizationConfig.CurrentCulture = GetCurrentCultureInfo(); return localizationConfig; }
模块的定义
[DependsOn( typeof(AbpVirtualFileSystemModule), typeof(AbpSettingsModule), typeof(AbpLocalizationAbstractionsModule) )] public class AbpLocalizationModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { AbpStringLocalizerFactory.Replace(context.Services); Configure<VirtualFileSystemOptions>(options => { options.FileSets.AddEmbedded<AbpLocalizationModule>("Volo.Abp", "Volo/Abp"); }); Configure<AbpLocalizationOptions>(options => { options .Resources .Add<DefaultResource>("en"); options .Resources .Add<AbpValidationResource>("en") .AddVirtualJson("/Localization/Resources/AbpValidation"); }); } }
配置Options有三个集合,本地化资源LocalizationResource,本地化资源贡献者ILocalizationResourceContributor,语言种类LanguageInfo
public class AbpLocalizationOptions { public LocalizationResourceDictionary Resources { get; } public ITypeList<ILocalizationResourceContributor> GlobalContributors { get; } public List<LanguageInfo> Languages { get; } public AbpLocalizationOptions() { Resources = new LocalizationResourceDictionary(); GlobalContributors = new TypeList<ILocalizationResourceContributor>(); Languages = new List<LanguageInfo>(); } }
AbpCultureHelper.Use,设置当前的语言,同设置租户功能差不多,可以自定义当前线程的CultureInfo和CurrentUICulture,而不用通过中间件进行设置
public static IDisposable Use([NotNull] CultureInfo culture, CultureInfo uiCulture = null) { Check.NotNull(culture, nameof(culture)); var currentCulture = CultureInfo.CurrentCulture; var currentUiCulture = CultureInfo.CurrentUICulture; CultureInfo.CurrentCulture = culture; CultureInfo.CurrentUICulture = uiCulture ?? culture; return new DisposeAction(() => { CultureInfo.CurrentCulture = currentCulture; CultureInfo.CurrentUICulture = currentUiCulture; }); }
2、获取本地化文本,在服务端获取本地化文本的用法是非常标准的(它与AspNetCore提供的获取本地化资源方式无缝集成).
本地化字符串访问器IStringLocalizer<T>,IStringLocalizer
是一个实现了 IEnumerable
的简单接口并且拥有索引器来来返回本地化的字符串。
AbpDictionaryBasedStringLocalizer,如_localizer["About Title"] 没有发现 “About Title” 的本地化值,则索引的键值被返回
3、中间件
RequestLocalizationOptions:
Abp赋值了DefaultRequestCulture,SupportedCultures,SupportedUICultures,并且增加Action<RequestLocalizationOptions> optionsAction 委托
DefaultRequestCulture是默认的cultureName、uiCultureName ,ABP定义是从SettingProviders中获取得到,GetLanguages
List<IRequestCultureProvider> RequestCultureProviders,如果有设置,则根据这个是设置当前Culture。默认顺序QueryStringRequestCultureProvider、CookieRequestCultureProvider、AcceptLanguageHeaderRequestCultureProvider
await provider.DetermineProviderCultureResult(context) 返回地的 ProviderCultureResult,即是List<StringSegment> cultures UIcultures
目的首先将Culture和UICulture写入当前线程,将Context.Features.设置请求CultureFeature,设置是否将当前Culture返回给客户端,HeaderName.ContentLanguage
NET 的每个线程都会拥有 CurrentCulture
和CurrentUICulture
对象
FixedLocalizableString
public class FixedLocalizableString : ILocalizableString { public string Value { get; } public FixedLocalizableString(string value) { Value = value; } public LocalizedString Localize(IStringLocalizerFactory stringLocalizerFactory) { return new LocalizedString(Value, Value); } }
客户端:ABP提供了JavaScript服务, 可以在客户端使用相同的本地化文本.
var testResource = abp.localization.getResource('Test'); var str = testResource('HelloWorld');