Skip to content

Commit

Permalink
Merge pull request #36 from Axemasta/fix/local-only
Browse files Browse the repository at this point in the history
Fix startup crash when only using local provider
  • Loading branch information
Axemasta authored Dec 21, 2023
2 parents 853d428 + a3dd715 commit 3842f5e
Show file tree
Hide file tree
Showing 12 changed files with 574 additions and 22 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/mocale-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ jobs:
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.0.x
- name: Setup Java JDK
uses: actions/setup-java@v4.0.0
with:
distribution: 'microsoft'
java-version: '11'
architecture: 'x64'
- name: Install Maui Workloads
run: dotnet workload install maui --source https://api.nuget.org/v3/index.json
- name: Restore dependencies
run: dotnet restore
- name: Build
Expand Down
7 changes: 7 additions & 0 deletions src/Mocale/AppBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System.Globalization;
using Mocale.Exceptions;
using Mocale.Helper;
using Mocale.Managers;
using Mocale.Providers;
using Mocale.Wrappers;
namespace Mocale;

Expand Down Expand Up @@ -52,6 +54,11 @@ public static MauiAppBuilder UseMocale(
throw new InitializationException($"No external provider was registered when mocale was configured to use one. Please register an external provider or set {nameof(IMocaleConfiguration.UseExternalProvider)} to false.");
}

if (!config.UseExternalProvider)
{
mauiAppBuilder.Services.AddTransient<IExternalLocalizationProvider, InactiveExternalLocalizationProvider>();
}

if (!mocaleBuilder.CacheProviderRegistered)
{
// TODO: Initialize in memory provider
Expand Down
29 changes: 21 additions & 8 deletions src/Mocale/Managers/LocalizationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ public class LocalizationManager : ILocalizationManager
{
private readonly ICurrentCultureManager currentCultureManager;
private readonly ILogger logger;
private readonly IMocaleConfiguration mocaleConfiguration;
private readonly ITranslationResolver translationResolver;
private readonly ITranslationUpdater translationUpdater;

public CultureInfo CurrentCulture { get; private set; }

public LocalizationManager(
ICurrentCultureManager currentCultureManager,
IConfigurationManager<IMocaleConfiguration> configurationManager,
ILogger<LocalizationManager> logger,
ITranslationResolver translationResolver,
ITranslationUpdater translationUpdater)
Expand All @@ -22,19 +24,27 @@ public LocalizationManager(
this.translationResolver = Guard.Against.Null(translationResolver, nameof(translationResolver));
this.translationUpdater = Guard.Against.Null(translationUpdater, nameof(this.translationUpdater));

configurationManager = Guard.Against.Null(configurationManager, nameof(configurationManager));
this.mocaleConfiguration = configurationManager.Configuration;

CurrentCulture = currentCultureManager.GetActiveCulture();
}

public async Task<bool> SetCultureAsync(CultureInfo culture)
{
try
{
var result = await translationResolver.LoadTranslations(culture);

if (!result.Loaded)
if (mocaleConfiguration.UseExternalProvider)
{
logger.LogWarning("Unable to load culture {CultureName}, no localizations found", culture.Name);
return false;
var result = await translationResolver.LoadTranslations(culture);

if (!result.Loaded)
{
logger.LogWarning("Unable to load culture {CultureName}, no localizations found", culture.Name);
return false;
}

translationUpdater.UpdateTranslations(result.Localization, result.Source);
}

var localTranslations = translationResolver.LoadLocalTranslations(culture);
Expand All @@ -46,9 +56,12 @@ public async Task<bool> SetCultureAsync(CultureInfo culture)
else
{
logger.LogInformation("No internal translations found for culture: {CultureName}, consider adding them as a backup", culture.Name);
}

translationUpdater.UpdateTranslations(result.Localization, result.Source);
if (!mocaleConfiguration.UseExternalProvider)
{
return false;
}
}

CurrentCulture = culture;

Expand Down Expand Up @@ -93,7 +106,7 @@ private Task<bool> InitializeInternal()

logger.LogTrace("Loaded local translations from source: {TranslationSource}", localTranslations.Source);

if (localTranslations.Source is TranslationSource.Internal or TranslationSource.ColdCache)
if ((localTranslations.Source is TranslationSource.Internal or TranslationSource.ColdCache) && mocaleConfiguration.UseExternalProvider)
{
logger.LogInformation("External translations can be updated, checking for newer copy...");

Expand Down
23 changes: 9 additions & 14 deletions src/Mocale/Providers/EmbeddedResourceProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,31 @@ public EmbeddedResourceProvider(
this.logger = logger;
}

public Dictionary<string, string> GetValuesForCulture(CultureInfo cultureInfo)
public Dictionary<string, string>? GetValuesForCulture(CultureInfo cultureInfo)
{
// read assembly
if (localConfig.ResourcesAssembly is null)
{
logger.LogWarning("Configured resource assembly was null");
return new Dictionary<string, string>();
return null;
}

var resources = localConfig.ResourcesAssembly.GetManifestResourceNames();

if (resources is null)
{
logger.LogWarning("No embedded resources found in assembly {ResourceAssembly}", localConfig.ResourcesAssembly);
return new Dictionary<string, string>();
}

// look for the right folder
var relativeFolder = localConfig.UseResourceFolder
? $"Resources.{localConfig.ResourcesPath}"
: localConfig.ResourcesPath;

var folderPrefix = localConfig.ResourcesAssembly.GetName().Name + "." + relativeFolder;

var localesFolderResources = resources.Where(r => r.StartsWith(folderPrefix, StringComparison.InvariantCultureIgnoreCase));
var localesFolderResources = resources.Where(r => r.StartsWith(folderPrefix, StringComparison.InvariantCultureIgnoreCase))
.ToList();

if (!localesFolderResources.Any())
{
logger.LogWarning("No assembly resources found with prefix: {FolderPrefix}", folderPrefix);
return new Dictionary<string, string>();
return null;
}

// check if filenames match
Expand All @@ -59,7 +54,7 @@ public Dictionary<string, string> GetValuesForCulture(CultureInfo cultureInfo)

logger.LogWarning("Unable to find resource for selected culture: {CultureName}", cultureInfo.Name);

return new Dictionary<string, string>();
return null;
}

private static bool FileMatchesCulture(string resourceName, CultureInfo culture)
Expand All @@ -73,14 +68,14 @@ private static bool FileMatchesCulture(string resourceName, CultureInfo culture)
return fileName.Equals(culture.Name, StringComparison.OrdinalIgnoreCase);
}

private Dictionary<string, string> ParseFile(string filePath, Assembly assembly)
private Dictionary<string, string>? ParseFile(string filePath, Assembly assembly)
{
using var fileStream = assembly.GetManifestResourceStream(filePath);

if (fileStream is null)
{
logger.LogWarning("File stream was null for assembly resource: {FilePath}", filePath);
return new Dictionary<string, string>();
return null;
}

try
Expand All @@ -92,7 +87,7 @@ private Dictionary<string, string> ParseFile(string filePath, Assembly assembly)
{
logger.LogError(ex, "An exception occurred loading & parsing assembly resource {FilePath}", filePath);

return new Dictionary<string, string>();
return null;
}
}
}
15 changes: 15 additions & 0 deletions src/Mocale/Providers/InactiveExternalLocalizationProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Globalization;
namespace Mocale.Providers;

internal sealed class InactiveExternalLocalizationProvider : IExternalLocalizationProvider
{
public Task<IExternalLocalizationResult> GetValuesForCultureAsync(CultureInfo cultureInfo)
{
IExternalLocalizationResult blankResult = new ExternalLocalizationResult()
{
Success = false,
};

return Task.FromResult(blankResult);
}
}
Loading

0 comments on commit 3842f5e

Please sign in to comment.