Browse Source

Resolved #176: Allow to change localization and see the result without recompile on development time.

pull/183/head
Halil İbrahim Kalkan 8 years ago
parent
commit
abaebd37d9
  1. 8
      src/Volo.Abp.Localization/Volo/Abp/Localization/AbpStringLocalizerFactory.cs
  2. 2
      src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizationDictionary.cs
  3. 5
      src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizationDictionaryProvider.cs
  4. 7
      src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationDictionary.cs
  5. 8
      src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationDictionaryProviderBase.cs
  6. 27
      src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResource.cs
  7. 2
      src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/Json/JsonEmbeddedFileLocalizationDictionaryProvider.cs
  8. 52
      src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationDictionaryProviderBase.cs
  9. 2
      src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/VirtualFileProvider.cs

8
src/Volo.Abp.Localization/Volo/Abp/Localization/AbpStringLocalizerFactory.cs

@ -20,13 +20,14 @@ namespace Volo.Abp.Localization
//TODO: It's better to use decorator pattern for IStringLocalizerFactory instead of getting ResourceManagerStringLocalizerFactory as a dependency.
public AbpStringLocalizerFactory(
ResourceManagerStringLocalizerFactory innerFactory,
IOptions<AbpLocalizationOptions> abpLocalizationOptions, IServiceProvider serviceProvider)
IOptions<AbpLocalizationOptions> abpLocalizationOptions,
IServiceProvider serviceProvider)
{
_innerFactory = innerFactory;
_serviceProvider = serviceProvider;
_abpLocalizationOptions = abpLocalizationOptions.Value;
_localizerCache = new ConcurrentDictionary<Type, AbpDictionaryBasedStringLocalizer>();;
_localizerCache = new ConcurrentDictionary<Type, AbpDictionaryBasedStringLocalizer>();
}
public virtual IStringLocalizer Create(Type resourceType)
@ -42,7 +43,8 @@ namespace Volo.Abp.Localization
private AbpDictionaryBasedStringLocalizer CreateAbpStringLocalizer(LocalizationResource resource)
{
resource.Initialize(_serviceProvider);
resource.Initialize(_serviceProvider); //TODO: Use CreateScope?
return new AbpDictionaryBasedStringLocalizer(
resource,
resource.BaseResourceTypes.Select(Create).ToList()

2
src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizationDictionary.cs

@ -29,5 +29,7 @@ namespace Volo.Abp.Localization
IReadOnlyList<LocalString> GetAllStrings();
void Extend(ILocalizationDictionary dictionary);
void Clear();
}
}

5
src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizationDictionaryProvider.cs

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
namespace Volo.Abp.Localization
{
@ -6,6 +7,8 @@ namespace Volo.Abp.Localization
{
IDictionary<string, ILocalizationDictionary> Dictionaries { get; }
event EventHandler Updated;
void Initialize(LocalizationResourceInitializationContext context);
void Extend(ILocalizationDictionaryProvider dictionaryProvider);

7
src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationDictionary.cs

@ -11,7 +11,7 @@ namespace Volo.Abp.Localization
{
/// <inheritdoc/>
public string CultureName { get; }
/// <inheritdoc/>
public virtual LocalString this[string name]
{
@ -51,6 +51,11 @@ namespace Volo.Abp.Localization
}
}
public void Clear()
{
_dictionary.Clear();
}
/// <inheritdoc/>
public virtual IEnumerator<LocalString> GetEnumerator()
{

8
src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationDictionaryProviderBase.cs

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
namespace Volo.Abp.Localization
@ -6,6 +7,8 @@ namespace Volo.Abp.Localization
{
public IDictionary<string, ILocalizationDictionary> Dictionaries { get; }
public event EventHandler Updated;
protected LocalizationDictionaryProviderBase()
{
Dictionaries = new Dictionary<string, ILocalizationDictionary>();
@ -35,5 +38,10 @@ namespace Volo.Abp.Localization
existingDictionary.Extend(dictionary);
}
}
protected virtual void OnUpdated()
{
Updated.InvokeSafely(this);
}
}
}

27
src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizationResource.cs

@ -38,10 +38,30 @@ namespace Volo.Abp.Localization
public virtual void Initialize(IServiceProvider serviceProvider)
{
//TODO: We should refactor here to create a better design!
var context = new LocalizationResourceInitializationContext(serviceProvider);
DictionaryProvider.Initialize(context);
InitializeDictionaryProvider(context);
InitializeExtensions(context);
DictionaryProvider.Updated += (sender, args) =>
{
InitializeExtensions(context);
};
foreach (var extension in Extensions)
{
extension.Updated += (sender, args) =>
{
InitializeDictionaryProvider(context);
InitializeExtensions(context);
};
}
}
private void InitializeExtensions(LocalizationResourceInitializationContext context)
{
foreach (var extension in Extensions)
{
extension.Initialize(context);
@ -49,6 +69,11 @@ namespace Volo.Abp.Localization
}
}
private void InitializeDictionaryProvider(LocalizationResourceInitializationContext context)
{
DictionaryProvider.Initialize(context);
}
protected virtual void AddBaseResourceTypes()
{
var descriptors = ResourceType

2
src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/Json/JsonEmbeddedFileLocalizationDictionaryProvider.cs

@ -17,7 +17,7 @@ namespace Volo.Abp.Localization.VirtualFiles.Json
return file.Name.EndsWith(".json", StringComparison.OrdinalIgnoreCase);
}
protected override ILocalizationDictionary CreateDictionary(string jsonString)
protected override ILocalizationDictionary CreateDictionaryFromFileContent(string jsonString)
{
return JsonLocalizationDictionaryBuilder.BuildFromJsonString(jsonString); //TODO: Use composition over inheritance!
}

52
src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationDictionaryProviderBase.cs

@ -1,5 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives;
using Volo.Abp.Internal;
using Volo.Abp.VirtualFileSystem;
@ -9,6 +11,8 @@ namespace Volo.Abp.Localization.VirtualFiles
{
private readonly string _virtualPath;
private bool _subscribedForChanges;
protected VirtualFileLocalizationDictionaryProviderBase(string virtualPath)
{
_virtualPath = virtualPath;
@ -17,32 +21,52 @@ namespace Volo.Abp.Localization.VirtualFiles
public override void Initialize(LocalizationResourceInitializationContext context) //TODO: Extract initialization to a factory..?
{
var virtualFileProvider = context.ServiceProvider.GetRequiredService<IVirtualFileProvider>();
var directoryContents = virtualFileProvider.GetDirectoryContents(_virtualPath);
foreach (var file in directoryContents)
CreateDictionaries(virtualFileProvider);
if (!_subscribedForChanges)
{
ChangeToken.OnChange(() => virtualFileProvider.Watch(_virtualPath.EnsureEndsWith('/') + "**/*.*"), () =>
{
CreateDictionaries(virtualFileProvider);
OnUpdated();
});
_subscribedForChanges = true;
}
}
private void CreateDictionaries(IFileProvider fileProvider)
{
Dictionaries.Clear();
foreach (var file in fileProvider.GetDirectoryContents(_virtualPath))
{
if (file.IsDirectory || !CanParseFile(file))
{
continue;
}
using (var stream = file.CreateReadStream())
var dictionary = CreateDictionaryFromFile(file);
if (Dictionaries.ContainsKey(dictionary.CultureName))
{
var fileContent = Utf8Helper.ReadStringFromStream(stream);
var dictionary = CreateDictionary(fileContent);
if (Dictionaries.ContainsKey(dictionary.CultureName))
{
throw new AbpException($"{file.PhysicalPath} dictionary has a culture name '{dictionary.CultureName}' which is already defined!");
}
Dictionaries[dictionary.CultureName] = dictionary;
throw new AbpException($"{file.PhysicalPath} dictionary has a culture name '{dictionary.CultureName}' which is already defined!");
}
Dictionaries[dictionary.CultureName] = dictionary;
}
}
protected abstract bool CanParseFile(IFileInfo file);
protected abstract ILocalizationDictionary CreateDictionary(string fileContent);
protected virtual ILocalizationDictionary CreateDictionaryFromFile(IFileInfo file)
{
using (var stream = file.CreateReadStream())
{
return CreateDictionaryFromFileContent(Utf8Helper.ReadStringFromStream(stream));
}
}
protected abstract ILocalizationDictionary CreateDictionaryFromFileContent(string fileContent);
}
}

2
src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/VirtualFileProvider.cs

@ -41,7 +41,7 @@ namespace Volo.Abp.VirtualFileSystem
if (_options.FileSets.PhysicalPaths.Any())
{
var fileProviders = _options.FileSets.PhysicalPaths
.Select(p => new PhysicalFileProvider(p))
.Select(rootPath => new PhysicalFileProvider(rootPath))
.Cast<IFileProvider>()
.ToList();

Loading…
Cancel
Save