From 89330e1ce8fa172f0c14bfd0b36705f28ec6c74d Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Sat, 14 Dec 2024 03:01:02 +0300 Subject: [PATCH] Update --- .../ILocalizationManager.cs | 10 - .../IPluralStringLocalizer.cs | 14 +- .../ITranslationProvider.cs | 12 - .../LocalizationManager.cs | 3 - .../PoFilesTranslationsProvider.cs | 3 - .../PortableObject/PoParser.cs | 13 - .../PortableObjectHtmlLocalizer.cs | 19 +- .../PortableObjectStringLocalizer.cs | 30 +-- .../Localization/PoParserTests.cs | 240 +++++++++--------- 9 files changed, 131 insertions(+), 213 deletions(-) diff --git a/src/OrchardCore/OrchardCore.Localization.Abstractions/ILocalizationManager.cs b/src/OrchardCore/OrchardCore.Localization.Abstractions/ILocalizationManager.cs index ef62126cf45..76a842b8b6d 100644 --- a/src/OrchardCore/OrchardCore.Localization.Abstractions/ILocalizationManager.cs +++ b/src/OrchardCore/OrchardCore.Localization.Abstractions/ILocalizationManager.cs @@ -1,6 +1,4 @@ -using System; using System.Globalization; -using System.Threading.Tasks; namespace OrchardCore.Localization; @@ -9,14 +7,6 @@ namespace OrchardCore.Localization; /// public interface ILocalizationManager { - /// - /// Retrieves a dictionary for a specified culture. - /// - /// The . - /// A for the specified culture. - [Obsolete("This method has been deprecated, please use GetDictionaryAsync instead.")] - CultureDictionary GetDictionary(CultureInfo culture) => GetDictionaryAsync(culture).GetAwaiter().GetResult(); - /// /// Retrieves a dictionary for a specified culture. /// diff --git a/src/OrchardCore/OrchardCore.Localization.Abstractions/IPluralStringLocalizer.cs b/src/OrchardCore/OrchardCore.Localization.Abstractions/IPluralStringLocalizer.cs index f568411892e..2fbdd4b4b31 100644 --- a/src/OrchardCore/OrchardCore.Localization.Abstractions/IPluralStringLocalizer.cs +++ b/src/OrchardCore/OrchardCore.Localization.Abstractions/IPluralStringLocalizer.cs @@ -1,5 +1,3 @@ -using System; -using System.Threading.Tasks; using Microsoft.Extensions.Localization; namespace OrchardCore.Localization; @@ -15,15 +13,5 @@ public interface IPluralStringLocalizer : IStringLocalizer /// The resource name. /// Optional parameters that can be used inside the resource key. /// A list of localized strings including the plural forms. - [Obsolete("This method is deprecated, please use GetTranslationAsync instead.")] - (LocalizedString, object[]) GetTranslation(string name, params object[] arguments) - => GetTranslationAsync(name, arguments).GetAwaiter().GetResult(); - - /// - /// Gets the localized strings. - /// - /// The resource name. - /// Optional parameters that can be used inside the resource key. - /// A list of localized strings including the plural forms. - Task<(LocalizedString, object[])> GetTranslationAsync(string name, params object[] arguments); + (LocalizedString, object[]) GetTranslation(string name, params object[] arguments); } diff --git a/src/OrchardCore/OrchardCore.Localization.Abstractions/ITranslationProvider.cs b/src/OrchardCore/OrchardCore.Localization.Abstractions/ITranslationProvider.cs index 8079260cbcb..c72a10f7b66 100644 --- a/src/OrchardCore/OrchardCore.Localization.Abstractions/ITranslationProvider.cs +++ b/src/OrchardCore/OrchardCore.Localization.Abstractions/ITranslationProvider.cs @@ -1,6 +1,3 @@ -using System; -using System.Threading.Tasks; - namespace OrchardCore.Localization; /// @@ -8,15 +5,6 @@ namespace OrchardCore.Localization; /// public interface ITranslationProvider { - /// - /// Loads translations from a certain source for a specific culture. - /// - /// The culture name. - /// The that will contains all loaded translations. - [Obsolete("This method has been deprecated, please use LoadTranslationsAsync instead.")] - void LoadTranslations(string cultureName, CultureDictionary dictionary) - => LoadTranslationsAsync(cultureName, dictionary).GetAwaiter().GetResult(); - /// /// Loads translations from a certain source for a specific culture. /// diff --git a/src/OrchardCore/OrchardCore.Localization.Core/LocalizationManager.cs b/src/OrchardCore/OrchardCore.Localization.Core/LocalizationManager.cs index c8ca5bdba10..e64028087de 100644 --- a/src/OrchardCore/OrchardCore.Localization.Core/LocalizationManager.cs +++ b/src/OrchardCore/OrchardCore.Localization.Core/LocalizationManager.cs @@ -1,7 +1,4 @@ -using System.Collections.Generic; using System.Globalization; -using System.Linq; -using System.Threading.Tasks; using Microsoft.Extensions.Caching.Memory; namespace OrchardCore.Localization; diff --git a/src/OrchardCore/OrchardCore.Localization.Core/PortableObject/PoFilesTranslationsProvider.cs b/src/OrchardCore/OrchardCore.Localization.Core/PortableObject/PoFilesTranslationsProvider.cs index 0651a317cc1..6aa65b5ba43 100644 --- a/src/OrchardCore/OrchardCore.Localization.Core/PortableObject/PoFilesTranslationsProvider.cs +++ b/src/OrchardCore/OrchardCore.Localization.Core/PortableObject/PoFilesTranslationsProvider.cs @@ -1,6 +1,3 @@ -using System.IO; -using System.Linq; -using System.Threading.Tasks; using Microsoft.Extensions.FileProviders; namespace OrchardCore.Localization.PortableObject; diff --git a/src/OrchardCore/OrchardCore.Localization.Core/PortableObject/PoParser.cs b/src/OrchardCore/OrchardCore.Localization.Core/PortableObject/PoParser.cs index 1896384e138..df46d222fc1 100644 --- a/src/OrchardCore/OrchardCore.Localization.Core/PortableObject/PoParser.cs +++ b/src/OrchardCore/OrchardCore.Localization.Core/PortableObject/PoParser.cs @@ -1,9 +1,4 @@ using System.Collections.Frozen; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Cysharp.Text; namespace OrchardCore.Localization.PortableObject; @@ -25,14 +20,6 @@ static PoParser() }.ToFrozenDictionary(); } - /// - /// Parses a .po file. - /// - /// The . - /// A list of culture records. - [Obsolete("This methos has been deprecated, please use ParseAsync instead.")] - public IEnumerable Parse(TextReader reader) => ParseAsync(reader).ToEnumerable(); - /// /// Parses a .po file. /// diff --git a/src/OrchardCore/OrchardCore.Localization.Core/PortableObject/PortableObjectHtmlLocalizer.cs b/src/OrchardCore/OrchardCore.Localization.Core/PortableObject/PortableObjectHtmlLocalizer.cs index 7248ed426dc..e45a554bb50 100644 --- a/src/OrchardCore/OrchardCore.Localization.Core/PortableObject/PortableObjectHtmlLocalizer.cs +++ b/src/OrchardCore/OrchardCore.Localization.Core/PortableObject/PortableObjectHtmlLocalizer.cs @@ -43,23 +43,8 @@ public override LocalizedHtmlString this[string name] // Get an unformatted string and all non plural arguments (1st one is the plural count). var (translation, argumentsWithCount) = pluralLocalizer.GetTranslation(name, arguments); - // See https://github.com/aspnet/Mvc/blob/master/src/Microsoft.AspNetCore.Mvc.Localization/LocalizedHtmlString.cs#L97 - - // But with a plural localizer, arguments may be provided for plural localization. So, we - // still use them to get a non formatted translation and extract all non plural arguments. - - // Otherwise an already formatted string containing curly braces will be wrongly reformatted. - - if (_localizer is IPluralStringLocalizer pluralLocalizer && arguments.Length == 1 && arguments[0] is PluralizationArgument) - { - // Get an unformatted string and all non plural arguments (1st one is the plural count). - var (translation, argumentsWithCount) = pluralLocalizer.GetTranslationAsync(name, arguments).GetAwaiter().GetResult(); - - // Formatting will use non plural arguments if any. - return ToHtmlString(translation, argumentsWithCount); - } - - return ToHtmlString(_localizer[name], arguments); + // Formatting will use non plural arguments if any. + return ToHtmlString(translation, argumentsWithCount); } return ToHtmlString(_localizer[name], arguments); diff --git a/src/OrchardCore/OrchardCore.Localization.Core/PortableObject/PortableObjectStringLocalizer.cs b/src/OrchardCore/OrchardCore.Localization.Core/PortableObject/PortableObjectStringLocalizer.cs index bf5d48711b4..a6f238bcf5c 100644 --- a/src/OrchardCore/OrchardCore.Localization.Core/PortableObject/PortableObjectStringLocalizer.cs +++ b/src/OrchardCore/OrchardCore.Localization.Core/PortableObject/PortableObjectStringLocalizer.cs @@ -1,6 +1,4 @@ using System.Globalization; -using System.Linq; -using System.Threading.Tasks; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using OrchardCore.Localization.DataAnnotations; @@ -46,7 +44,7 @@ public virtual LocalizedString this[string name] { ArgumentNullException.ThrowIfNull(name); - var translation = GetTranslationAsync(name, _context, CultureInfo.CurrentUICulture, null).GetAwaiter().GetResult(); + var translation = GetTranslation(name, _context, CultureInfo.CurrentUICulture, null); return new LocalizedString(name, translation ?? name, translation == null); } @@ -57,7 +55,7 @@ public virtual LocalizedString this[string name] { get { - var (translation, argumentsWithCount) = GetTranslationAsync(name, arguments).GetAwaiter().GetResult(); + var (translation, argumentsWithCount) = GetTranslation(name, arguments); var formatted = string.Format(translation.Value, argumentsWithCount); return new LocalizedString(name, formatted, translation.ResourceNotFound); @@ -76,14 +74,14 @@ public virtual IEnumerable GetAllStrings(bool includeParentCult } /// - public virtual async Task<(LocalizedString, object[])> GetTranslationAsync(string name, params object[] arguments) + public virtual (LocalizedString, object[]) GetTranslation(string name, params object[] arguments) { ArgumentNullException.ThrowIfNull(name); // Check if a plural form is called, which is when the only argument is of type PluralizationArgument. if (arguments.Length == 1 && arguments[0] is PluralizationArgument pluralArgument) { - var translation = await GetTranslationAsync(name, _context, CultureInfo.CurrentUICulture, pluralArgument.Count); + var translation = GetTranslation(name, _context, CultureInfo.CurrentUICulture, pluralArgument.Count); object[] argumentsWithCount; @@ -98,7 +96,7 @@ public virtual IEnumerable GetAllStrings(bool includeParentCult argumentsWithCount = [pluralArgument.Count]; } - translation ??= await GetTranslationAsync(pluralArgument.Forms, CultureInfo.CurrentUICulture, pluralArgument.Count); + translation ??= GetTranslation(pluralArgument.Forms, CultureInfo.CurrentUICulture, pluralArgument.Count); return (new LocalizedString(name, translation, translation == null), argumentsWithCount); } @@ -145,13 +143,9 @@ private async IAsyncEnumerable GetAllStringsFromCultureHierarch } while (currentCulture != currentCulture.Parent); } - [Obsolete("This method is deprecated, please use GetTranslationAsync instead.")] protected string GetTranslation(string[] pluralForms, CultureInfo culture, int? count) - => GetTranslationAsync(pluralForms, culture, count).GetAwaiter().GetResult(); - - protected async Task GetTranslationAsync(string[] pluralForms, CultureInfo culture, int? count) { - var dictionary = await _localizationManager.GetDictionaryAsync(culture); + var dictionary = _localizationManager.GetDictionaryAsync(culture).GetAwaiter().GetResult(); var pluralForm = count.HasValue ? dictionary.PluralRule(count.Value) : 0; @@ -169,11 +163,7 @@ protected async Task GetTranslationAsync(string[] pluralForms, CultureIn return pluralForms[pluralForm]; } - [Obsolete("This method has been deprecated please use instead.")] protected string GetTranslation(string name, string context, CultureInfo culture, int? count) - => GetTranslationAsync(name, context, culture, count).GetAwaiter().GetResult(); - - protected async Task GetTranslationAsync(string name, string context, CultureInfo culture, int? count) { string translation = null; try @@ -182,7 +172,7 @@ protected async Task GetTranslationAsync(string name, string context, Cu { do { - if (await ExtractTranslationAsync() != null) + if (ExtractTranslation() != null) { break; } @@ -193,12 +183,12 @@ protected async Task GetTranslationAsync(string name, string context, Cu } else { - await ExtractTranslationAsync(); + ExtractTranslation(); } - async Task< string> ExtractTranslationAsync() + string ExtractTranslation() { - var dictionary = await _localizationManager.GetDictionaryAsync(culture); + var dictionary = _localizationManager.GetDictionaryAsync(culture).GetAwaiter().GetResult(); if (dictionary != null) { diff --git a/test/OrchardCore.Tests/Localization/PoParserTests.cs b/test/OrchardCore.Tests/Localization/PoParserTests.cs index 11fa12d1239..e992c26bb62 100644 --- a/test/OrchardCore.Tests/Localization/PoParserTests.cs +++ b/test/OrchardCore.Tests/Localization/PoParserTests.cs @@ -6,75 +6,72 @@ namespace OrchardCore.Tests.Localization; public class PoParserTests { [Fact] - public void ParseRetursSimpleEntry() + public async Task ParseRetursSimpleEntry() { - [Fact] - public async Task ParseRetursSimpleEntry() - { - // msgid "Unknown system error" - // msgstr "Error desconegut del sistema" - var entries = await ParseTextAsync("SimpleEntry"); + // msgid "Unknown system error" + // msgstr "Error desconegut del sistema" + var entries = await ParseTextAsync("SimpleEntry"); Assert.Equal("Unknown system error", entries[0].Key); Assert.Equal("Error desconegut del sistema", entries[0].Translations[0]); } - [Fact] - public async Task ParseIgnoresEntryWithoutTranslation() - { - // "msgid "Unknown system error" - // "msgstr "" - var entries = await ParseTextAsync("EntryWithoutTranslation"); + [Fact] + public async Task ParseIgnoresEntryWithoutTranslation() + { + // "msgid "Unknown system error" + // "msgstr "" + var entries = await ParseTextAsync("EntryWithoutTranslation"); Assert.Empty(entries); } - [Fact] - public async Task ParseIgnoresPoeditHeader() - { - // # Translation of kstars.po into Spanish. - // # This file is distributed under the same license as the kdeedu package. - // # Pablo de Vicente , 2005, 2006, 2007, 2008. - // # Eloy Cuadra , 2007, 2008. - // msgid "" - // msgstr "" - // "Project-Id-Version: kstars\n" - // "Report-Msgid-Bugs-To: http://bugs.kde.org\n" - // "POT-Creation-Date: 2008-09-01 09:37+0200\n" - // "PO-Revision-Date: 2008-07-22 18:13+0200\n" - // "Last-Translator: Eloy Cuadra \n" - // "Language-Team: Spanish \n" - // "MIME-Version: 1.0\n" - // "Content-Type: text/plain; charset=UTF-8\n" - // "Content-Transfer-Encoding: 8bit\n" - // "Plural-Forms: nplurals=2; plural=n != 1;\n" - - // msgid "Unknown system error" - // msgstr "Error desconegut del sistema" - var entries = await ParseTextAsync("PoeditHeader"); + [Fact] + public async Task ParseIgnoresPoeditHeader() + { + // # Translation of kstars.po into Spanish. + // # This file is distributed under the same license as the kdeedu package. + // # Pablo de Vicente , 2005, 2006, 2007, 2008. + // # Eloy Cuadra , 2007, 2008. + // msgid "" + // msgstr "" + // "Project-Id-Version: kstars\n" + // "Report-Msgid-Bugs-To: http://bugs.kde.org\n" + // "POT-Creation-Date: 2008-09-01 09:37+0200\n" + // "PO-Revision-Date: 2008-07-22 18:13+0200\n" + // "Last-Translator: Eloy Cuadra \n" + // "Language-Team: Spanish \n" + // "MIME-Version: 1.0\n" + // "Content-Type: text/plain; charset=UTF-8\n" + // "Content-Transfer-Encoding: 8bit\n" + // "Plural-Forms: nplurals=2; plural=n != 1;\n" + + // msgid "Unknown system error" + // msgstr "Error desconegut del sistema" + var entries = await ParseTextAsync("PoeditHeader"); Assert.True(entries.Length == 1); Assert.True(entries[0].Translations.Length == 1); } - [Fact] - public async Task ParseSetsContext() - { - // msgctxt "OrchardCore.Localization" - // msgid "Unknown system error" - // msgstr "Error desconegut del sistema" - var entries = await ParseTextAsync("EntryWithContext"); + [Fact] + public async Task ParseSetsContext() + { + // msgctxt "OrchardCore.Localization" + // msgid "Unknown system error" + // msgstr "Error desconegut del sistema" + var entries = await ParseTextAsync("EntryWithContext"); Assert.Equal("OrchardCore.Localization|Unknown system error", entries[0].Key, ignoreCase: true); } - [Fact] - public async Task ParseIgnoresComments() - { - // # translator-comments - // #. extracted-comments - // #: reference… - // #, flag + [Fact] + public async Task ParseIgnoresComments() + { + // # translator-comments + // #. extracted-comments + // #: reference… + // #, flag // #| msgctxt previous-context // #| msgid previous-untranslated-string @@ -82,74 +79,74 @@ public async Task ParseIgnoresComments() // msgid "Unknown system error" // msgstr "Error desconegut del sistema" - var entries = await ParseTextAsync("EntryWithComments"); + var entries = await ParseTextAsync("EntryWithComments"); Assert.Equal("OrchardCore.Localization|Unknown system error", entries[0].Key, ignoreCase: true); Assert.Equal("Error desconegut del sistema", entries[0].Translations[0]); } - [Fact] - public async Task ParseOnlyTrimsLeadingAndTrailingQuotes() - { - // msgid "\"{0}\"" - // msgstr "\"{0}\"" + [Fact] + public async Task ParseOnlyTrimsLeadingAndTrailingQuotes() + { + // msgid "\"{0}\"" + // msgstr "\"{0}\"" - var entries = await ParseTextAsync("EntryWithQuotes"); + var entries = await ParseTextAsync("EntryWithQuotes"); Assert.Equal("\"{0}\"", entries[0].Key); Assert.Equal("\"{0}\"", entries[0].Translations[0]); } - [Fact] - public async Task ParseHandleUnclosedQuote() - { - // msgctxt " - // msgid "Foo \"{0}\"" - // msgstr "Foo \"{0}\"" + [Fact] + public async Task ParseHandleUnclosedQuote() + { + // msgctxt " + // msgid "Foo \"{0}\"" + // msgstr "Foo \"{0}\"" - var entries = await ParseTextAsync("EntryWithUnclosedQuote"); + var entries = await ParseTextAsync("EntryWithUnclosedQuote"); Assert.Equal("Foo \"{0}\"", entries[0].Key); } - [Fact] - public async Task ParseHandlesMultilineEntry() - { - // msgid "" - // "Here is an example of how one might continue a very long string\n" - // "for the common case the string represents multi-line output." - // msgstr "" - // "Here is an example of how one might continue a very long translation\n" - // "for the common case the string represents multi-line output." + [Fact] + public async Task ParseHandlesMultilineEntry() + { + // msgid "" + // "Here is an example of how one might continue a very long string\n" + // "for the common case the string represents multi-line output." + // msgstr "" + // "Here is an example of how one might continue a very long translation\n" + // "for the common case the string represents multi-line output." - var entries = await ParseTextAsync("EntryWithMultilineText"); + var entries = await ParseTextAsync("EntryWithMultilineText"); Assert.Equal("Here is an example of how one might continue a very long string\nfor the common case the string represents multi-line output.", entries[0].Key); Assert.Equal("Here is an example of how one might continue a very long translation\nfor the common case the string represents multi-line output.", entries[0].Translations[0]); } - [Fact] - public async Task ParsePreservesEscapedCharacters() - { - // msgid "Line:\t\"{0}\"\n" - // msgstr "Line:\t\"{0}\"\n" + [Fact] + public async Task ParsePreservesEscapedCharacters() + { + // msgid "Line:\t\"{0}\"\n" + // msgstr "Line:\t\"{0}\"\n" - var entries = await ParseTextAsync("EntryWithEscapedCharacters"); + var entries = await ParseTextAsync("EntryWithEscapedCharacters"); Assert.Equal("Line:\t\"{0}\"\n", entries[0].Key); Assert.Equal("Line:\t\"{0}\"\n", entries[0].Translations[0]); } - [Fact] - public async Task ParseReadsPluralTranslations() - { - // msgid "book" - // msgid_plural "books" - // msgstr[0] "kniha" - // msgstr[1] "knihy" - // msgstr[2] "knih" + [Fact] + public async Task ParseReadsPluralTranslations() + { + // msgid "book" + // msgid_plural "books" + // msgstr[0] "kniha" + // msgstr[1] "knihy" + // msgstr[2] "knih" - var entries = await ParseTextAsync("EntryWithPlural"); + var entries = await ParseTextAsync("EntryWithPlural"); Assert.Equal("book", entries[0].Key); Assert.Equal("kniha", entries[0].Translations[0]); @@ -157,43 +154,43 @@ public async Task ParseReadsPluralTranslations() Assert.Equal("knih", entries[0].Translations[2]); } - [Fact] - public async Task ParseReadsPluralAndMultilineText() - { - // msgid "" - // "Here is an example of how one might continue a very long string\n" - // "for the common case the string represents multi-line output." - // msgid_plural "" - // "Here are examples of how one might continue a very long string\n" - // "for the common case the string represents multi-line output." - // msgstr[0] "" - // "Here is an example of how one might continue a very long translation\n" - // "for the common case the string represents multi-line output." - // msgstr[1] "" - // "Here are examples of how one might continue a very long translation\n" - // "for the common case the string represents multi-line output." - - var entries = await ParseTextAsync("EntryWithPluralAndMultilineText"); + [Fact] + public async Task ParseReadsPluralAndMultilineText() + { + // msgid "" + // "Here is an example of how one might continue a very long string\n" + // "for the common case the string represents multi-line output." + // msgid_plural "" + // "Here are examples of how one might continue a very long string\n" + // "for the common case the string represents multi-line output." + // msgstr[0] "" + // "Here is an example of how one might continue a very long translation\n" + // "for the common case the string represents multi-line output." + // msgstr[1] "" + // "Here are examples of how one might continue a very long translation\n" + // "for the common case the string represents multi-line output." + + var entries = await ParseTextAsync("EntryWithPluralAndMultilineText"); Assert.Equal("Here is an example of how one might continue a very long string\nfor the common case the string represents multi-line output.", entries[0].Key); Assert.Equal("Here is an example of how one might continue a very long translation\nfor the common case the string represents multi-line output.", entries[0].Translations[0]); Assert.Equal("Here are examples of how one might continue a very long translation\nfor the common case the string represents multi-line output.", entries[0].Translations[1]); } - [Fact] - public async Task ParseReadsMultipleEntries() - { - // #. "File {0} does not exist" - // msgctxt "OrchardCore.FileSystems.Media.FileSystemStorageProvider" - // msgid "File {0} does not exist" - // msgstr "Soubor {0} neexistuje" + [Fact] + public async Task ParseReadsMultipleEntries() + { + // #. "File {0} does not exist" + // msgctxt "OrchardCore.FileSystems.Media.FileSystemStorageProvider" + // msgid "File {0} does not exist" + // msgstr "Soubor {0} neexistuje" // #. "Directory {0} does not exist" // msgctxt "OrchardCore.FileSystems.Media.Directory" // msgid "Directory {0} does not exist" // msgstr "Složka {0} neexistuje" - var entries = await ParseTextAsync("MultipleEntries"); + var entries = await ParseTextAsync("MultipleEntries"); Assert.Equal(2, entries.Length); @@ -204,15 +201,14 @@ public async Task ParseReadsMultipleEntries() Assert.Equal("Složka {0} neexistuje", entries[1].Translations[0]); } - private static async Task ParseTextAsync(string resourceName) - { - var parser = new PoParser(); + private static async Task ParseTextAsync(string resourceName) + { + var parser = new PoParser(); - var testAssembly = typeof(PoParserTests).Assembly; - using var resource = testAssembly.GetManifestResourceStream("OrchardCore.Tests.Localization.PoFiles." + resourceName + ".po"); - using var reader = new StreamReader(resource); + var testAssembly = typeof(PoParserTests).Assembly; + using var resource = testAssembly.GetManifestResourceStream("OrchardCore.Tests.Localization.PoFiles." + resourceName + ".po"); + using var reader = new StreamReader(resource); - return (await parser.ParseAsync(reader).ToListAsync()).ToArray(); - } + return (await parser.ParseAsync(reader).ToListAsync()).ToArray(); } }