Inherit from existing resources. Thus we can share common localizations accross modules.

#171.
pull/179/head
Halil İbrahim Kalkan 8 years ago
parent a26223b57b
commit 1ea0592c87

@ -10,13 +10,16 @@ namespace Volo.Abp.Localization
{
public LocalizationResource Resource { get; }
public LocalizedString this[string name] => GetLocalizedString(name, CultureInfo.CurrentUICulture.Name);
public List<IStringLocalizer> BaseLocalizers { get; }
public LocalizedString this[string name, params object[] arguments] => GetLocalizedStringFormatted(name, CultureInfo.CurrentUICulture.Name, arguments);
public virtual LocalizedString this[string name] => GetLocalizedString(name);
public AbpDictionaryBasedStringLocalizer(LocalizationResource resource)
public virtual LocalizedString this[string name, params object[] arguments] => GetLocalizedStringFormatted(name, arguments);
public AbpDictionaryBasedStringLocalizer(LocalizationResource resource, List<IStringLocalizer> baseLocalizers)
{
Resource = resource;
BaseLocalizers = baseLocalizers;
}
public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures)
@ -29,19 +32,38 @@ namespace Volo.Abp.Localization
return new CultureWrapperStringLocalizer(culture.Name, this);
}
protected virtual LocalizedString GetLocalizedStringFormatted(string name, params object[] arguments)
{
return GetLocalizedStringFormatted(name, CultureInfo.CurrentUICulture.Name, arguments);
}
protected virtual LocalizedString GetLocalizedStringFormatted(string name, string cultureName, params object[] arguments)
{
var localizedString = GetLocalizedString(name, cultureName);
return new LocalizedString(name, string.Format(localizedString.Value, arguments), localizedString.ResourceNotFound, localizedString.SearchedLocation);
}
protected virtual LocalizedString GetLocalizedString(string name)
{
return GetLocalizedString(name, CultureInfo.CurrentUICulture.Name);
}
protected virtual LocalizedString GetLocalizedString(string name, string cultureName)
{
var value = GetLocalizedStringOrNull(name, cultureName);
if (value == null)
{
return new LocalizedString(name, name, true);
foreach (var baseLocalizer in BaseLocalizers)
{
var baseLocalizedString = baseLocalizer.WithCulture(CultureInfo.GetCultureInfo(cultureName))[name];
if (baseLocalizedString != null && !baseLocalizedString.ResourceNotFound)
{
return baseLocalizedString;
}
}
return new LocalizedString(name, name, resourceNotFound: true);
}
return value;

@ -44,12 +44,13 @@ namespace Volo.Abp.Localization
{
resource.Initialize(_serviceProvider);
//Extend dictionary with extensions
//Wrap reader by wrappers (like db wrapper which implement multitenancy/regions and so on...)
//Notes: Localizer will be cached, so wrappers are responsible to cache/invalidate themselves!
var localizer = new AbpDictionaryBasedStringLocalizer(resource);
var baseLocalizers = resource.BaseResourceTypes.Select(Create).ToList();
var localizer = new AbpDictionaryBasedStringLocalizer(resource, baseLocalizers);
//TODO: Wrap with DB provider or other premium sources

@ -10,19 +10,12 @@ namespace Volo.Abp.Localization
public string DefaultCultureName { get; set; }
public ILocalizationDictionaryProvider DictionaryProvider
{
get => _dictionaryProvider;
set
{
Check.NotNull(value, nameof(value));
_dictionaryProvider = value;
}
}
private ILocalizationDictionaryProvider _dictionaryProvider;
public ILocalizationDictionaryProvider DictionaryProvider { get; }
public List<ILocalizationDictionaryProvider> Extensions { get; }
public List<Type> BaseResourceTypes { get; }
public LocalizationResource([NotNull] Type resourceType, [NotNull] string defaultCultureName, [NotNull] ILocalizationDictionaryProvider dictionaryProvider)
{
Check.NotNull(resourceType, nameof(resourceType));
@ -33,6 +26,7 @@ namespace Volo.Abp.Localization
DefaultCultureName = defaultCultureName;
DictionaryProvider = dictionaryProvider;
BaseResourceTypes = new List<Type>();
Extensions = new List<ILocalizationDictionaryProvider>();
}

@ -0,0 +1,18 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.Localization
{
public static class LocalizationResourceExtensions
{
public static LocalizationResource InheritFrom([NotNull] this LocalizationResource resource, [NotNull] params Type[] baseResourceTypes)
{
Check.NotNull(resource, nameof(resource));
Check.NotNull(baseResourceTypes, nameof(baseResourceTypes));
resource.BaseResourceTypes.AddRange(baseResourceTypes);
return resource;
}
}
}

@ -6,7 +6,7 @@ namespace Volo.Abp.Localization
{
public static class LocalizationResourceListExtensions
{
public static void AddJson<TResource>([NotNull] this LocalizationResourceDictionary resourceDictionary, [NotNull] string defaultCultureName)
public static LocalizationResource AddJson<TResource>([NotNull] this LocalizationResourceDictionary resourceDictionary, [NotNull] string defaultCultureName)
{
Check.NotNull(resourceDictionary, nameof(resourceDictionary));
Check.NotNull(defaultCultureName, nameof(defaultCultureName));
@ -18,7 +18,7 @@ namespace Volo.Abp.Localization
throw new AbpException("There is already a resource with given type: " + resourceType.AssemblyQualifiedName);
}
resourceDictionary[resourceType] = new LocalizationResource(
return resourceDictionary[resourceType] = new LocalizationResource(
resourceType,
defaultCultureName,
new JsonEmbeddedFileLocalizationDictionaryProvider(

@ -12,8 +12,7 @@
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Volo\Abp\Localization\SourceExt\*.json" />
<EmbeddedResource Include="Volo\Abp\Localization\Source\*.json" />
<EmbeddedResource Include="Volo\Abp\Localization\**\*.json" />
</ItemGroup>
<ItemGroup>

@ -2,6 +2,8 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Shouldly;
using Volo.Abp.Localization.Base.CountryNames;
using Volo.Abp.Localization.Base.Validation;
using Volo.Abp.Localization.Source;
using Volo.Abp.Localization.SourceExt;
using Volo.Abp.Modularity;
@ -58,7 +60,7 @@ namespace Volo.Abp.Localization
using (AbpCultureHelper.Use("tr"))
{
_localizer["SeeYou"].Value.ShouldBe("See you"); //Not defined in tr
_localizer["SeeYou"].Value.ShouldBe("See you"); //Not defined in tr, getting from default lang
}
using (AbpCultureHelper.Use("it"))
@ -67,6 +69,30 @@ namespace Volo.Abp.Localization
}
}
[Fact]
public void Should_Get_From_Inherited_Texts()
{
using (AbpCultureHelper.Use("en"))
{
_localizer["USA"].Value.ShouldBe("United States of America"); //Inherited from CountryNames/en.json
_localizer["ThisFieldIsRequired"].Value.ShouldBe("This field is required"); //Inherited from Validation/en.json
}
using (AbpCultureHelper.Use("tr"))
{
_localizer["USA"].Value.ShouldBe("Amerika Birleşik Devletleri"); //Inherited from CountryNames/tr.json
}
}
[Fact]
public void Should_Override_Inherited_Text()
{
using (AbpCultureHelper.Use("en"))
{
_localizer["MaxLenghtErrorMessage", 42].Value.ShouldBe("This field's length can be maximum of '42' chars"); //Overriden in Source/en.json
}
}
[Fact]
public void Should_Get_Localized_Text_If_Defined_In_Requested_Culture()
{
@ -84,7 +110,15 @@ namespace Volo.Abp.Localization
{
services.Configure<AbpLocalizationOptions>(options =>
{
options.Resources.AddJson<LocalizationTestResource>("en");
options.Resources.AddJson<LocalizationTestValidationResource>("en");
options.Resources.AddJson<LocalizationTestCountryNamesResource>("en");
options.Resources.AddJson<LocalizationTestResource>("en")
.InheritFrom(
typeof(LocalizationTestValidationResource),
typeof(LocalizationTestCountryNamesResource)
);
options.Resources.ExtendWithJson<LocalizationTestResource, LocalizationTestResourceExt>();
});
}

@ -0,0 +1,7 @@
namespace Volo.Abp.Localization.Base.CountryNames
{
public sealed class LocalizationTestCountryNamesResource
{
}
}

@ -0,0 +1,6 @@
{
"culture": "en",
"texts": {
"USA": "United States of America"
}
}

@ -0,0 +1,6 @@
{
"culture": "tr",
"texts": {
"USA": "Amerika Birleşik Devletleri"
}
}

@ -0,0 +1,7 @@
namespace Volo.Abp.Localization.Base.Validation
{
public sealed class LocalizationTestValidationResource
{
}
}

@ -0,0 +1,7 @@
{
"culture": "en",
"texts": {
"ThisFieldIsRequired": "This field is required",
"MaxLenghtErrorMessage": "This field can be maximum of '{0}' chars"
}
}

@ -3,6 +3,7 @@
"texts": {
"Hello <b>{0}</b>.": "Hello <b>{0}</b>.",
"Car": "Car",
"CarPlural": "Cars"
"CarPlural": "Cars",
"MaxLenghtErrorMessage": "This field's length can be maximum of '{0}' chars"
}
}
Loading…
Cancel
Save