Allow to extend/override existing resources

pull/179/head
Halil İbrahim Kalkan 8 years ago
parent 0100cfe037
commit a26223b57b

@ -37,7 +37,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
var localizationConfig = new ApplicationLocalizationConfigurationDto();
foreach (var resource in _localizationOptions.Resources)
foreach (var resource in _localizationOptions.Resources.Values)
{
var dictionary = new Dictionary<string, string>();

@ -2,11 +2,11 @@
{
public class AbpLocalizationOptions
{
public LocalizationResourceList Resources { get; }
public LocalizationResourceDictionary Resources { get; }
public AbpLocalizationOptions()
{
Resources = new LocalizationResourceList();
Resources = new LocalizationResourceDictionary();
}
}
}

@ -1,11 +1,11 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using Volo.Abp.Localization.Json;
namespace Volo.Abp.Localization
{
@ -29,17 +29,15 @@ namespace Volo.Abp.Localization
_localizerCache = new ConcurrentDictionary<Type, AbpDictionaryBasedStringLocalizer>();;
}
public virtual IStringLocalizer Create(Type resourceSource)
public virtual IStringLocalizer Create(Type resourceType)
{
//TODO: Optimize!
var localizationResource = _abpLocalizationOptions.Resources.FirstOrDefault(l => l.ResourceType == resourceSource);
var localizationResource = _abpLocalizationOptions.Resources.GetOrDefault(resourceType);
if (localizationResource == null)
{
return _innerFactory.Create(resourceSource);
return _innerFactory.Create(resourceType);
}
return _localizerCache.GetOrAdd(resourceSource, _ => CreateAbpStringLocalizer(localizationResource));
return _localizerCache.GetOrAdd(resourceType, _ => CreateAbpStringLocalizer(localizationResource));
}
private AbpDictionaryBasedStringLocalizer CreateAbpStringLocalizer(LocalizationResource resource)

@ -7,7 +7,7 @@ namespace Volo.Abp.Localization
IDictionary<string, ILocalizationDictionary> Dictionaries { get; }
void Initialize();
void Extend(ILocalizationDictionary dictionary);
void Extend(ILocalizationDictionaryProvider dictionaryProvider);
}
}

@ -19,10 +19,12 @@ namespace Volo.Abp.Localization.Json
public override void Initialize()
{
var rootNameSpaceWithDot = _rootNamespace + ".";
var resourceNames = _assembly.GetManifestResourceNames();
foreach (var resourceName in resourceNames)
{
if (resourceName.StartsWith(_rootNamespace))
if (resourceName.StartsWith(rootNameSpaceWithDot))
{
using (var stream = _assembly.GetManifestResourceStream(resourceName))
{

@ -17,19 +17,30 @@ namespace Volo.Abp.Localization
{
}
public void Extend(ILocalizationDictionary dictionary)
public virtual void Extend(ILocalizationDictionaryProvider dictionaryProvider)
{
//Add
ILocalizationDictionary existingDictionary;
if (!Dictionaries.TryGetValue(dictionary.CultureName, out existingDictionary))
foreach (var dictionary in dictionaryProvider.Dictionaries.Values)
{
Extend(dictionary);
}
}
protected virtual void Extend(ILocalizationDictionary dictionary)
{
var existingDictionary = Dictionaries.GetOrDefault(dictionary.CultureName);
if (existingDictionary == null)
{
Dictionaries[dictionary.CultureName] = dictionary;
return;
}
else
{
Overwrite(existingDictionary, dictionary);
}
}
//Override
var localizedStrings = dictionary.GetAllStrings();
foreach (var localizedString in localizedStrings)
protected virtual void Overwrite(ILocalizationDictionary existingDictionary, ILocalizationDictionary dictionary)
{
foreach (var localizedString in dictionary.GetAllStrings())
{
existingDictionary[localizedString.Name] = localizedString;
}

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
namespace Volo.Abp.Localization
@ -20,6 +21,8 @@ namespace Volo.Abp.Localization
}
private ILocalizationDictionaryProvider _dictionaryProvider;
public List<ILocalizationDictionaryProvider> Extensions { get; }
public LocalizationResource([NotNull] Type resourceType, [NotNull] string defaultCultureName, [NotNull] ILocalizationDictionaryProvider dictionaryProvider)
{
Check.NotNull(resourceType, nameof(resourceType));
@ -29,11 +32,19 @@ namespace Volo.Abp.Localization
ResourceType = resourceType;
DefaultCultureName = defaultCultureName;
DictionaryProvider = dictionaryProvider;
Extensions = new List<ILocalizationDictionaryProvider>();
}
public virtual void Initialize(IServiceProvider serviceProvider) //TODO: Create a LocalizationResourceInitializationContext!
{
DictionaryProvider.Initialize();
foreach (var extension in Extensions)
{
extension.Initialize();
DictionaryProvider.Extend(extension);
}
}
}
}

@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
namespace Volo.Abp.Localization
{
public class LocalizationResourceDictionary : Dictionary<Type, LocalizationResource>
{
}
}

@ -1,9 +0,0 @@
using System.Collections.Generic;
namespace Volo.Abp.Localization
{
public class LocalizationResourceList : List<LocalizationResource>
{
}
}

@ -1,24 +1,50 @@
using JetBrains.Annotations;
using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.Abp.Localization.Json;
namespace Volo.Abp.Localization
{
public static class LocalizationResourceListExtensions
{
public static void AddJson<TResource>(this LocalizationResourceList resourceList, [NotNull] string defaultCultureName)
public static void AddJson<TResource>([NotNull] this LocalizationResourceDictionary resourceDictionary, [NotNull] string defaultCultureName)
{
var type = typeof(TResource);
resourceList.Add(
new LocalizationResource(
type,
defaultCultureName,
new JsonEmbeddedFileLocalizationDictionaryProvider(
type.Assembly,
type.Namespace
)
Check.NotNull(resourceDictionary, nameof(resourceDictionary));
Check.NotNull(defaultCultureName, nameof(defaultCultureName));
var resourceType = typeof(TResource);
if (resourceDictionary.ContainsKey(resourceType))
{
throw new AbpException("There is already a resource with given type: " + resourceType.AssemblyQualifiedName);
}
resourceDictionary[resourceType] = new LocalizationResource(
resourceType,
defaultCultureName,
new JsonEmbeddedFileLocalizationDictionaryProvider(
resourceType.Assembly,
resourceType.Namespace
)
);
}
public static void ExtendWithJson<TResource, TResourceExt>([NotNull] this LocalizationResourceDictionary resourceDictionary)
{
Check.NotNull(resourceDictionary, nameof(resourceDictionary));
var resourceType = typeof(TResource);
var resourceExtType = typeof(TResourceExt);
var resource = resourceDictionary.GetOrDefault(resourceType);
if (resource == null)
{
throw new AbpException("Can not find a resource with given type: " + resourceType.AssemblyQualifiedName);
}
resource.Extensions.Add(new JsonEmbeddedFileLocalizationDictionaryProvider(
resourceExtType.Assembly,
resourceExtType.Namespace
));
}
}
}

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

@ -3,6 +3,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Shouldly;
using Volo.Abp.Localization.Source;
using Volo.Abp.Localization.SourceExt;
using Volo.Abp.Modularity;
using Volo.Abp.TestBase;
using Xunit;
@ -40,6 +41,30 @@ namespace Volo.Abp.Localization
_localizer["Car"].Value.ShouldBe("Araba");
_localizer["CarPlural"].Value.ShouldBe("Araba");
}
using (AbpCultureHelper.Use("it"))
{
_localizer["Car"].Value.ShouldBe("Auto");
}
}
[Fact]
public void Should_Get_Extension_Texts()
{
using (AbpCultureHelper.Use("en"))
{
_localizer["SeeYou"].Value.ShouldBe("See you");
}
using (AbpCultureHelper.Use("tr"))
{
_localizer["SeeYou"].Value.ShouldBe("See you"); //Not defined in tr
}
using (AbpCultureHelper.Use("it"))
{
_localizer["SeeYou"].Value.ShouldBe("Ci vediamo");
}
}
[Fact]
@ -48,7 +73,7 @@ namespace Volo.Abp.Localization
_localizer.WithCulture(CultureInfo.GetCultureInfo("en"))["Car"].Value.ShouldBe("Car");
_localizer.WithCulture(CultureInfo.GetCultureInfo("en"))["CarPlural"].Value.ShouldBe("Cars");
_localizer.WithCulture(CultureInfo.GetCultureInfo("tr"))["CarPlural"].Value.ShouldBe("Araba");
_localizer.WithCulture(CultureInfo.GetCultureInfo("tr"))["Car"].Value.ShouldBe("Araba");
_localizer.WithCulture(CultureInfo.GetCultureInfo("tr"))["CarPlural"].Value.ShouldBe("Araba");
}
@ -60,6 +85,7 @@ namespace Volo.Abp.Localization
services.Configure<AbpLocalizationOptions>(options =>
{
options.Resources.AddJson<LocalizationTestResource>("en");
options.Resources.ExtendWithJson<LocalizationTestResource, LocalizationTestResourceExt>();
});
}
}

@ -1,7 +1,7 @@
{
"culture": "en",
"texts": {
"Hello <b>{0}</b>.": "Hello <b>{0}</b>",
"Hello <b>{0}</b>.": "Hello <b>{0}</b>.",
"Car": "Car",
"CarPlural": "Cars"
}

@ -1,7 +1,7 @@
{
"culture": "tr",
"texts": {
"Hello <b>{0}</b>.": "Merhaba <b>{0}</b>",
"Hello <b>{0}</b>.": "Merhaba <b>{0}</b>.",
"Car": "Araba",
"CarPlural": "Araba"
}

@ -0,0 +1,7 @@
namespace Volo.Abp.Localization.SourceExt
{
internal sealed class LocalizationTestResourceExt
{
}
}

@ -0,0 +1,6 @@
{
"culture": "en",
"texts": {
"SeeYou": "See you"
}
}

@ -0,0 +1,8 @@
{
"culture": "it",
"texts": {
"Hello <b>{0}</b>.": "Ciao <b>{0}</b>.",
"Car": "Auto",
"SeeYou": "Ci vediamo"
}
}
Loading…
Cancel
Save