Skip to content

Commit

Permalink
[v3.1.0] GateLocalizator
Browse files Browse the repository at this point in the history
(+) Added: LocalizatorBase
(+) Added: GateLocalizator
(~) Updated: StoredLocalizator
  • Loading branch information
Sargeras02 committed Apr 8, 2024
1 parent efb874a commit 54b6327
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 31 deletions.
54 changes: 54 additions & 0 deletions Model/GateLocalizator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using Newtonsoft.Json;
using SKitLs.Utils.Localizations.Languages;

namespace SKitLs.Utils.Localizations.Model
{
public class GateLocalizator : LocalizatorBase
{
/// <summary>
/// Determines the extension of localization resource files.
/// </summary>
public const string LocalExtension = ".json";

public GateLocalizator(string localsPath, LanguageCode defaultLanguage = LanguageCode.EN) : base(localsPath, defaultLanguage)
{ }

protected override string? InternalResolveString(LanguageCode? lang, string key, bool resolveDefault, params string?[] format)
{
if (!Directory.Exists(LocalsPath))
Directory.CreateDirectory(LocalsPath);

var langName = string.Empty;
if (lang.HasValue)
{
langName = lang.Value.ToString();
}
else if (resolveDefault)
{
langName = DefaultLanguage.ToString();
}
else
return null;

var files = Directory.GetFiles(LocalsPath)
.Select(x => new FileInfo(x))
.Where(x => x.Extension == LocalExtension)
.Where(x => x.Name.StartsWith(langName, true, null));

foreach (var lFile in files)
{
using var reader = new StreamReader(lFile.FullName);
var json = reader.ReadToEnd();
var langCollection = JsonConvert.DeserializeObject<Dictionary<string, string>>(json)
?? throw new Exception($"Was not able to deserialize package with {langName} language ({lFile.FullName})");

if (langCollection.TryGetValue(key, out string? resolved))
return resolved;
}

if (resolveDefault && lang != DefaultLanguage)
return InternalResolveString(DefaultLanguage, key, resolveDefault, format);
return null;
}
}
}
38 changes: 38 additions & 0 deletions Model/LocalizatorBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using SKitLs.Utils.Localizations.Languages;
using SKitLs.Utils.Localizations.Localizators;

namespace SKitLs.Utils.Localizations.Model
{
public abstract class LocalizatorBase : ILocalizator
{
/// <inheritdoc/>
public string NotDefinedKey { get; set; } = "local.KeyNotDefined";

/// <inheritdoc/>
public LanguageCode DefaultLanguage { get; set; }

/// <inheritdoc/>
public string LocalsPath { get; private set; }

public LocalizatorBase(string localsPath, LanguageCode defaultLanguage)
{
LocalsPath = localsPath ?? throw new ArgumentNullException(nameof(localsPath));
DefaultLanguage = defaultLanguage;
}

public virtual string? ResolveString(LanguageCode? lang, string key, bool resolveDefault, params string?[] format)
=> InternalResolveString(lang, key, resolveDefault, format);

public virtual string ResolveStringOrFallback(LanguageCode? lang, string key, bool resolveDefault, params string?[] format)
=> InternalResolveString(lang, key, resolveDefault, format) ?? FallbackString(lang, key, resolveDefault, format);

protected abstract string? InternalResolveString(LanguageCode? lang, string key, bool resolveDefault, params string?[] format);

protected virtual string FallbackString(LanguageCode? lang, string key, bool resolveDefault, params string?[] format)
{
var reply = InternalResolveString(lang, NotDefinedKey, resolveDefault, Enum.GetName(lang ?? DefaultLanguage), key, LocalsPath)
?? $"String Data is not defined ({key}:{Enum.GetName(lang ?? DefaultLanguage)}). Format params: {string.Join(", ", format)}";
return format.Length > 0 ? reply[..(reply.Length - 2)] + "." : reply + "None";
}
}
}
31 changes: 3 additions & 28 deletions Model/StoredLocalizator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,13 @@ namespace SKitLs.Utils.Localizations.Model
/// This implementation, <see cref="StoredLocalizator"/>, optimizes performance by preloading all localizations during initialization and storing them as strings,
/// trading memory consumption for increased speed.
/// </summary>
public class StoredLocalizator : ILocalizator
public class StoredLocalizator : LocalizatorBase
{
/// <summary>
/// Determines the extension of localization resource files.
/// </summary>
public const string LocalExtension = ".json";

/// <inheritdoc/>
public string NotDefinedKey { get; set; } = "local.KeyNotDefined";

/// <inheritdoc/>
public LanguageCode DefaultLanguage { get; set; }

/// <inheritdoc/>
public string LocalsPath { get; private set; }

/// <summary>
/// Dictionary storing localizations for each language code.
/// </summary>
Expand All @@ -36,10 +27,8 @@ public class StoredLocalizator : ILocalizator
/// </summary>
/// <param name="localsPath">The path to the localization resource files.</param>
/// <param name="defaultLanguage">The path to the localization resource files.</param>
public StoredLocalizator(string localsPath, LanguageCode defaultLanguage = LanguageCode.EN)
public StoredLocalizator(string localsPath, LanguageCode defaultLanguage = LanguageCode.EN) : base(localsPath, defaultLanguage)
{
LocalsPath = localsPath;
DefaultLanguage = defaultLanguage;
Localizations = [];
LoadContent();
}
Expand Down Expand Up @@ -77,14 +66,7 @@ private void LoadContent()
}
}

/// <inheritdoc/>
public string? ResolveString(LanguageCode? lang, string key, bool resolveDefault, params string?[] format) => InternalResolveString(lang, key, resolveDefault, format);

/// <inheritdoc/>
public string ResolveStringOrFallback(LanguageCode? lang, string key, bool resolveDefault, params string?[] format) => InternalResolveString(lang, key, resolveDefault, format)
?? FallbackString(lang, key, resolveDefault, format);

private string? InternalResolveString(LanguageCode? lang, string key, bool resolveDefault, params string?[] format)
protected override string? InternalResolveString(LanguageCode? lang, string key, bool resolveDefault, params string?[] format)
{
if (Localizations.TryGetValue(key, out Dictionary<LanguageCode, string>? locals))
{
Expand All @@ -95,12 +77,5 @@ public string ResolveStringOrFallback(LanguageCode? lang, string key, bool resol
}
return null;
}

private string FallbackString(LanguageCode? lang, string key, bool resolveDefault, params string?[] format)
{
var reply = InternalResolveString(lang, NotDefinedKey, resolveDefault, Enum.GetName(lang ?? DefaultLanguage), key, LocalsPath)
?? $"String Data is not defined ({key}:{Enum.GetName(lang ?? DefaultLanguage)}). Format params: {string.Join(", ", format)}";
return format.Length > 0 ? reply[..(reply.Length - 2)] + "." : reply + "None";
}
}
}
7 changes: 4 additions & 3 deletions SKitLs.Utils.Localizations.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<Nullable>enable</Nullable>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Title>$(AssemblyName)</Title>
<AssemblyVersion>3.0.1</AssemblyVersion>
<AssemblyVersion>3.1.0</AssemblyVersion>
<FileVersion>$(AssemblyVersion)</FileVersion>
<PackageProjectUrl>https://github.com/SKitLs-dev/SKitLs.Utils.Localizations.git</PackageProjectUrl>
<Version>$(AssemblyVersion)</Version>
Expand All @@ -19,8 +19,9 @@ https://en.wikipedia.org/wiki/IETF_language_tag</Description>
<Copyright>Copyright (C) 2023-2024, SKitLs</Copyright>
<PackageIcon>libIcon_localizations.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageReleaseNotes>(~) Updated: ResolveString(... bool resolveDefault) added
(~) Updated: StoredLocalizator internal updates</PackageReleaseNotes>
<PackageReleaseNotes>(+) Added: LocalizatorBase
(+) Added: GateLocalizator
(~) Updated: StoredLocalizator</PackageReleaseNotes>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
<PackageTags>Localization, Internationalization, Multilingual, Globalization, IETF</PackageTags>
Expand Down
Binary file added docs/LocalizatorsComparison.xlsx
Binary file not shown.
Binary file added docs/img/MemoryC.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/SpeedC.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 54b6327

Please sign in to comment.