ABP:如何动态加载本地化文本而不重新启动API应用

发布于 2025-01-21 05:05:30 字数 5026 浏览 0 评论 0原文

我与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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文