ABP:如何动态加载本地化文本而不重新启动API应用
我与Angular Client一起使用ABP v4.7.0(.net Core 2.1)。 我建立了一些自定义本地化提供商。这些提供商从Azure Blob存储中获取翻译词典。我在这些提供商的启动中添加了本地化来源。
localizationConfiguration.Sources.Add(
new DictionaryBasedLocalizationSource(InductothermMVPConsts.LocalizationSourceName,
new BlobEmbeddedFileLocalizationDictionaryProvider(
typeof(InductothermMVPLocalizationConfigurer).GetAssembly(),
"InductothermMVP.Core.Localization.SourceFiles"
)
)
);
在启动时,我称之为此方法,本地化词典是正确构建的。
现在,我创建了一个API端点,该端点将在Azure Blob存储中更新数据,在更新文件后,我再次初始化该词典,
public class BlobEmbeddedFileLocalizationDictionaryProvider : LocalizationDictionaryProviderBase
{
#pragma warning disable GCop406 // Mark {0} field as read-only.
private const int Count = 50;
#pragma warning restore GCop406 // Mark {0} field as read-only.
private readonly Assembly _assembly;
private readonly string _rootNamespace;
/// <summary>
/// Creates a new <see cref="BlobEmbeddedFileLocalizationDictionaryProvider"/> object.
/// </summary>
/// <param name="assembly">Assembly that contains embedded xml files</param>
/// <param name="rootNamespace">Namespace of the embedded xml dictionary files</param>
public BlobEmbeddedFileLocalizationDictionaryProvider(Assembly assembly, string rootNamespace)
{
_assembly = assembly;
_rootNamespace = rootNamespace;
InitializeDictionaries();
}
protected void InitializeDictionaries()
{
var sourceName = "XXXXXX";
var allCultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures);
var storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnection"]);
var blobClient = storageAccount.CreateCloudBlobClient();
var container = blobClient.GetContainerReference("xxxxxx");
var res = container.CreateIfNotExistsAsync().GetAwaiter().GetResult();
var count = BlobEmbeddedFileLocalizationDictionaryProvider.Count;
var listBlobs = container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.None, count, null, null, null).GetAwaiter().GetResult();
foreach (var item in listBlobs.Results)
{
var blockBlob = container.GetBlockBlobReference(((Microsoft.WindowsAzure.Storage.Blob.CloudBlob)item).Name);
string path = _assembly.Location.Replace("xxxxx", "");
path += ((Microsoft.WindowsAzure.Storage.Blob.CloudBlob)item).Name;
blockBlob.DownloadToFileAsync(path, FileMode.OpenOrCreate).GetAwaiter().GetResult();
using (var stream = File.OpenRead(path))
{
var xmlString = Utf8Helper.ReadStringFromStream(stream);
InitializeDictionary(CreateXmlLocalizationDictionary(xmlString), isDefault: ((CloudBlob)item).Name.EndsWith(sourceName + ".xml"));
}
}
}
protected virtual XmlLocalizationDictionary CreateXmlLocalizationDictionary(string xmlString)
{
return XmlLocalizationDictionary.BuildFomXmlString(xmlString);
}
protected void InitializeDictionary<TDictionary>(TDictionary dictionary, bool isDefault = false)
where TDictionary : ILocalizationDictionary
{
if (Dictionaries.ContainsKey(dictionary.CultureInfo.Name))
{
throw new AbpInitializationException(SourceName + " source contains more than one dictionary for the culture: " + dictionary.CultureInfo.Name);
}
Dictionaries[dictionary.CultureInfo.Name] = dictionary;
if (isDefault)
{
if (DefaultDictionary != null)
{
throw new AbpInitializationException("Only one default localization dictionary can be for source: " + SourceName);
}
DefaultDictionary = dictionary;
}
}
}
internal static class Utf8Helper
{
public static string ReadStringFromStream(Stream stream)
{
var bytes = stream.GetAllBytes();
var skipCount = HasBom(bytes) ? 3 : 0;
return Encoding.UTF8.GetString(bytes, skipCount, bytes.Length - skipCount);
}
private static bool HasBom(byte[] bytes)
{
if (bytes.Length < 3)
{
return false;
}
if (!(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF))
{
return false;
}
return true;
}
}
该提供商将按预期执行。 但是,当我刷新我的客户端(Angular)应用程序时,我仍然会看到旧的翻译。
如果重新启动API应用程序,则正确反映了新的翻译。
有人可以帮我理解吗,我在这里想念什么。
感谢提前的帮助。
I am using ABP v4.7.0 (.NET CORE 2.1) with angular client.
I built some custom localization providers. These providers get translation dictionaries from Azure Blob Storage. I add localization sources on startup with these providers.
localizationConfiguration.Sources.Add(
new DictionaryBasedLocalizationSource(InductothermMVPConsts.LocalizationSourceName,
new BlobEmbeddedFileLocalizationDictionaryProvider(
typeof(InductothermMVPLocalizationConfigurer).GetAssembly(),
"InductothermMVP.Core.Localization.SourceFiles"
)
)
);
On StartUp, I call this method and localization dictionaries are built correctly.
Now, I created one api endpoint which will update data in Azure Blob Storage, after files are updated, I am again initializing the dictionaries
public class BlobEmbeddedFileLocalizationDictionaryProvider : LocalizationDictionaryProviderBase
{
#pragma warning disable GCop406 // Mark {0} field as read-only.
private const int Count = 50;
#pragma warning restore GCop406 // Mark {0} field as read-only.
private readonly Assembly _assembly;
private readonly string _rootNamespace;
/// <summary>
/// Creates a new <see cref="BlobEmbeddedFileLocalizationDictionaryProvider"/> object.
/// </summary>
/// <param name="assembly">Assembly that contains embedded xml files</param>
/// <param name="rootNamespace">Namespace of the embedded xml dictionary files</param>
public BlobEmbeddedFileLocalizationDictionaryProvider(Assembly assembly, string rootNamespace)
{
_assembly = assembly;
_rootNamespace = rootNamespace;
InitializeDictionaries();
}
protected void InitializeDictionaries()
{
var sourceName = "XXXXXX";
var allCultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures);
var storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnection"]);
var blobClient = storageAccount.CreateCloudBlobClient();
var container = blobClient.GetContainerReference("xxxxxx");
var res = container.CreateIfNotExistsAsync().GetAwaiter().GetResult();
var count = BlobEmbeddedFileLocalizationDictionaryProvider.Count;
var listBlobs = container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.None, count, null, null, null).GetAwaiter().GetResult();
foreach (var item in listBlobs.Results)
{
var blockBlob = container.GetBlockBlobReference(((Microsoft.WindowsAzure.Storage.Blob.CloudBlob)item).Name);
string path = _assembly.Location.Replace("xxxxx", "");
path += ((Microsoft.WindowsAzure.Storage.Blob.CloudBlob)item).Name;
blockBlob.DownloadToFileAsync(path, FileMode.OpenOrCreate).GetAwaiter().GetResult();
using (var stream = File.OpenRead(path))
{
var xmlString = Utf8Helper.ReadStringFromStream(stream);
InitializeDictionary(CreateXmlLocalizationDictionary(xmlString), isDefault: ((CloudBlob)item).Name.EndsWith(sourceName + ".xml"));
}
}
}
protected virtual XmlLocalizationDictionary CreateXmlLocalizationDictionary(string xmlString)
{
return XmlLocalizationDictionary.BuildFomXmlString(xmlString);
}
protected void InitializeDictionary<TDictionary>(TDictionary dictionary, bool isDefault = false)
where TDictionary : ILocalizationDictionary
{
if (Dictionaries.ContainsKey(dictionary.CultureInfo.Name))
{
throw new AbpInitializationException(SourceName + " source contains more than one dictionary for the culture: " + dictionary.CultureInfo.Name);
}
Dictionaries[dictionary.CultureInfo.Name] = dictionary;
if (isDefault)
{
if (DefaultDictionary != null)
{
throw new AbpInitializationException("Only one default localization dictionary can be for source: " + SourceName);
}
DefaultDictionary = dictionary;
}
}
}
internal static class Utf8Helper
{
public static string ReadStringFromStream(Stream stream)
{
var bytes = stream.GetAllBytes();
var skipCount = HasBom(bytes) ? 3 : 0;
return Encoding.UTF8.GetString(bytes, skipCount, bytes.Length - skipCount);
}
private static bool HasBom(byte[] bytes)
{
if (bytes.Length < 3)
{
return false;
}
if (!(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF))
{
return false;
}
return true;
}
}
This Provider is executed as expected.
But When I Refresh my client(Angular) Application, I still see the old Translations.
If I restart my API application, new translations are reflected correctly.
Can someone help me to understand, what am I missing here.
Thanks for the help in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论