Skip to content

Commit

Permalink
Fix Locale Translations Overwrite (#307)
Browse files Browse the repository at this point in the history
* fix issue overwriting locale translations

* fix Nidoran symbols in locales
  • Loading branch information
versx authored Jul 18, 2022
1 parent 3e62c76 commit 13e7a7d
Show file tree
Hide file tree
Showing 15 changed files with 125 additions and 76 deletions.
20 changes: 20 additions & 0 deletions src/Extensions/GenericsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,25 @@ public static T LoadFromFile<T>(this string filePath)

return data.FromJson<T>();
}

public static Dictionary<string, string> Merge(this Dictionary<string, string> locales1, Dictionary<string, string> locales2, bool updateValues = false)
{
var result = locales1;
foreach (var (key, value) in locales2)
{
if (!result.ContainsKey(key))
{
result.Add(key, value);
continue;
}

// Key already exists, check if values are the same
if (result[key] != value && updateValues)
{
result[key] = value;
}
}
return result;
}
}
}
4 changes: 2 additions & 2 deletions src/HostedServices/StatisticReportsHostedService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@

public class StatisticReportsHostedService : IHostedService, IDisposable
{
private readonly ILogger<QuestPurgeHostedService> _logger;
private readonly ILogger<StatisticReportsHostedService> _logger;
private readonly Dictionary<string, MidnightTimer> _tzMidnightTimers;
private readonly ConfigHolder _config;
private readonly IDiscordClientService _discordService;

public StatisticReportsHostedService(
ILogger<QuestPurgeHostedService> logger,
ILogger<StatisticReportsHostedService> logger,
ConfigHolder config,
IDiscordClientService discordService)
{
Expand Down
94 changes: 62 additions & 32 deletions src/Localization/Translator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Linq;
using System.Threading.Tasks;

using Microsoft.Extensions.Logging;
using ActivityType = POGOProtos.Rpc.HoloActivityType;
using AlignmentType = POGOProtos.Rpc.PokemonDisplayProto.Types.Alignment;
using CharacterCategory = POGOProtos.Rpc.EnumWrapper.Types.CharacterCategory;
Expand All @@ -19,6 +20,9 @@

public class Translator : Language<string, string, Dictionary<string, string>>
{
private static readonly ILogger<Translator> _logger =
new Logger<Translator>(LoggerFactory.Create(x => x.AddConsole()));

private const string SourceLocaleUrl = "https://raw.githubusercontent.com/WatWowMap/pogo-translations/master/static/locales/";
private static readonly string _appLocalesFolder = Directory.GetCurrentDirectory() + $"/../{Strings.LocaleFolder}";
private static readonly string _binLocalesFolder = Directory.GetCurrentDirectory() + $"/{Strings.BasePath}/{Strings.LocaleFolder}";
Expand All @@ -35,57 +39,62 @@ public class Translator : Language<string, string, Dictionary<string, string>>

#endregion

public async Task CreateLocaleFiles()
#region Static Methods

public static async Task CreateLocaleFilesAsync()
{
var files = Directory.GetFiles(_appLocalesFolder, "*.json")
.Select(fileName => Path.GetFileName(fileName))
.Where(fileName => fileName.StartsWith('_'))
.ToList();
// Copy any missing base locale files to bin directory
await CopyLocaleFilesAsync();

var files = GetBaseLocaleFileNames();
foreach (var file in files)
{
var locale = Path.GetFileName(file).Replace("_", null);
var localeFile = locale;
// Replace locale prefix
var localeFile = Path.GetFileName(file).Replace("_", null);
var locale = Path.GetFileNameWithoutExtension(localeFile);

var json = await NetUtils.GetAsync(SourceLocaleUrl + locale);
var url = SourceLocaleUrl + localeFile;
var json = await NetUtils.GetAsync(url);
if (json == null)
{
Console.WriteLine($"Failed to fetch locales from {SourceLocaleUrl + locale}, skipping...");
_logger.LogWarning($"Failed to fetch locales from {url}, skipping...");
return;
}
var remote = json.FromJson<Dictionary<string, string>>();

Console.WriteLine($"Creating locale {locale}");

var keys = remote.Keys.ToList();
for (var i = 0; i < keys.Count; i++)
_logger.LogInformation($"Creating locale {locale}...");
var remote = json.FromJson<Dictionary<string, string>>();
foreach (var (key, _) in remote)
{
var key = keys[i];
remote[key] = remote[key].Replace("%", "{");
remote[key] = remote[key].Replace("}", "}}");
// Make locale variables compliant with Handlebars/Mustache templating
remote[key] = remote[key].Replace("%", "{")
.Replace("}", "}}");
}

if (locale != "en")
{
// Include en as fallback first
var appTransFallback = File.ReadAllText(
var enTransFallback = File.ReadAllText(
Path.Combine(_appLocalesFolder, "_en.json")
);
var fallbackTranslations = appTransFallback.FromJson<Dictionary<string, string>>();
remote = MergeDictionaries(remote, fallbackTranslations);
var fallbackTranslations = enTransFallback.FromJson<Dictionary<string, string>>();
remote = remote.Merge(fallbackTranslations, updateValues: true);
}

var appTranslations = File.ReadAllText(Path.Combine(_appLocalesFolder, file));
remote = MergeDictionaries(remote, appTranslations.FromJson<Dictionary<string, string>>());
var appTranslationsData = File.ReadAllText(Path.Combine(_appLocalesFolder, file));
var appTranslations = appTranslationsData.FromJson<Dictionary<string, string>>();
remote = remote.Merge(appTranslations, updateValues: true);

File.WriteAllText(
Path.Combine(_binLocalesFolder, localeFile),
remote.ToJson()
);
Console.WriteLine($"{localeFile} file saved.");
_logger.LogInformation($"{locale} file saved.");
}
}

#endregion

#region Public Methods

public override string Translate(string value)
{
Expand Down Expand Up @@ -196,19 +205,40 @@ public string GetGruntType(InvasionCharacter gruntType)
return Translate($"grunt_{(int)gruntType}");
}

private static Dictionary<string, string> MergeDictionaries(Dictionary<string, string> locales1, Dictionary<string, string> locales2)
#endregion

#region Private Methods

private static async Task CopyLocaleFilesAsync()
{
var result = locales1;
foreach (var (key, value) in locales2)
// Copy base locale files from app directory to bin directory if they do not exist
var files = GetBaseLocaleFileNames();
foreach (var file in files)
{
if (result.ContainsKey(key))
{
// Key already exists, skip...
// Replace locale prefix
var localeFile = Path.GetFileName(file);
var localeBin = Path.Combine(_binLocalesFolder, localeFile);
if (File.Exists(localeBin))
continue;
}
result.Add(key, value);

_logger.LogDebug($"Copying base locale '{localeFile}' to {localeBin}...");
var baseLocalePath = Path.Combine(_appLocalesFolder, file);
File.Copy(baseLocalePath, localeBin);
}
return result;

await Task.CompletedTask;
}

private static List<string> GetBaseLocaleFileNames(string extension = "*.json", string prefix = "_")
{
// Get a list of locale file names that have prefix '_'
var files = Directory.GetFiles(_appLocalesFolder, extension)
.Select(fileName => Path.GetFileName(fileName))
.Where(fileName => fileName.StartsWith(prefix))
.ToList();
return files;
}

#endregion
}
}
1 change: 0 additions & 1 deletion src/Services/Webhook/Models/PokemonData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ public sealed class PokemonData : IWebhookData, IWebhookPokemon, IWebhookPoint
public string IVRounded => IVReal == -1 ? "?" : Math.Round(IVReal) + "%";

[

JsonIgnore,
NotMapped,
]
Expand Down
2 changes: 1 addition & 1 deletion src/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public Startup(IConfiguration configuration)
// Create locale translation files
try
{
Translator.Instance.CreateLocaleFiles().ConfigureAwait(false).GetAwaiter().GetResult();
Translator.CreateLocaleFilesAsync().ConfigureAwait(false).GetAwaiter().GetResult();
Translator.Instance.SetLocale(_config.Instance.Locale);
}
catch (Exception ex)
Expand Down
8 changes: 4 additions & 4 deletions static/locales/_de.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,15 @@
"PVP_ULTRA_LEAGUE": "Ultra League",
"REMOVED_TOTAL_DEPARTED_MEMBERS": "Removed {{removed}} of {{users}} total members.",
"SHINY_STATS_INVALID_CHANNEL": "{{author}} Shiny stats channel does not exist.",
"SHINY_STATS_MESSAGE": "**{{pokemon}} (#{{id}})** | **{{shiny}}** shiny out of **{{total}}** total seen in the last 24 hours.",
"SHINY_STATS_MESSAGE_WITH_RATIO": "**{{pokemon}} (#{{id}})** | **{{shiny}}** shiny out of **{{total}}** total seen in the last 24 hours with a **1/{{chance}}** ratio.",
"SHINY_STATS_MESSAGE": "**{{{pokemon}}} (#{{id}})** | **{{shiny}}** shiny out of **{{total}}** total seen in the last 24 hours.",
"SHINY_STATS_MESSAGE_WITH_RATIO": "**{{{pokemon}}} (#{{id}})** | **{{shiny}}** shiny out of **{{total}}** total seen in the last 24 hours with a **1/{{chance}}** ratio.",
"SHINY_STATS_NEWLINE": "----------------------------------------------",
"SHINY_STATS_TITLE": "[**Shiny Pokemon stats for {{date}}**]",
"SHINY_STATS_TOTAL_MESSAGE": "Found **{{shiny}}** total shinies out of **{{total}}** possiblities.",
"SHINY_STATS_TOTAL_MESSAGE_WITH_RATIO": "Found **{{shiny}}** total shinies out of **{{total}}** possiblities with a **1/{{chance}}** ratio in total.",
"HUNDO_STATS_INVALID_CHANNEL": "{{author}} Hundo stats channel does not exist.",
"HUNDO_STATS_MESSAGE": "**{{pokemon}} (#{{id}})** | **{{count}}** 100% IV out of **{{total}}** total seen in the last 24 hours.",
"HUNDO_STATS_MESSAGE_WITH_RATIO": "**{{pokemon}} (#{{id}})** | **{{count}}** 100% IV out of **{{total}}** total seen in the last 24 hours with a **1/{{chance}}** ratio.",
"HUNDO_STATS_MESSAGE": "**{{{pokemon}}} (#{{id}})** | **{{count}}** 100% IV out of **{{total}}** total seen in the last 24 hours.",
"HUNDO_STATS_MESSAGE_WITH_RATIO": "**{{{pokemon}}} (#{{id}})** | **{{count}}** 100% IV out of **{{total}}** total seen in the last 24 hours with a **1/{{chance}}** ratio.",
"HUNDO_STATS_NEWLINE": "----------------------------------------------",
"HUNDO_STATS_TITLE": "[**Hundo Pokemon stats for {{date}}**]",
"HUNDO_STATS_TOTAL_MESSAGE": "Found **{{count}}** total hundos out of **{{total}}** possiblities.",
Expand Down
8 changes: 4 additions & 4 deletions static/locales/_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,15 @@
"PVP_ULTRA_LEAGUE": "Ultra League",
"REMOVED_TOTAL_DEPARTED_MEMBERS": "Removed {{removed}} of {{users}} total members.",
"SHINY_STATS_INVALID_CHANNEL": "{{author}} Shiny stats channel does not exist.",
"SHINY_STATS_MESSAGE": "**{{pokemon}} (#{{id}})** | **{{shiny}}** shiny out of **{{total}}** total seen in the last 24 hours.",
"SHINY_STATS_MESSAGE_WITH_RATIO": "**{{pokemon}} (#{{id}})** | **{{shiny}}** shiny out of **{{total}}** total seen in the last 24 hours with a **1/{{chance}}** ratio.",
"SHINY_STATS_MESSAGE": "**{{{pokemon}}} (#{{id}})** | **{{shiny}}** shiny out of **{{total}}** total seen in the last 24 hours.",
"SHINY_STATS_MESSAGE_WITH_RATIO": "**{{{pokemon}}} (#{{id}})** | **{{shiny}}** shiny out of **{{total}}** total seen in the last 24 hours with a **1/{{chance}}** ratio.",
"SHINY_STATS_NEWLINE": "----------------------------------------------",
"SHINY_STATS_TITLE": "[**Shiny Pokemon stats for {{date}}**]",
"SHINY_STATS_TOTAL_MESSAGE": "Found **{{shiny}}** total shinies out of **{{total}}** possiblities.",
"SHINY_STATS_TOTAL_MESSAGE_WITH_RATIO": "Found **{{shiny}}** total shinies out of **{{total}}** possiblities with a **1/{{chance}}** ratio in total.",
"HUNDO_STATS_INVALID_CHANNEL": "{{author}} Hundo stats channel does not exist.",
"HUNDO_STATS_MESSAGE": "**{{pokemon}} (#{{id}})** | **{{count}}** 100% IV out of **{{total}}** total seen in the last 24 hours.",
"HUNDO_STATS_MESSAGE_WITH_RATIO": "**{{pokemon}} (#{{id}})** | **{{count}}** 100% IV out of **{{total}}** total seen in the last 24 hours with a **1/{{chance}}** ratio.",
"HUNDO_STATS_MESSAGE": "**{{{pokemon}}} (#{{id}})** | **{{count}}** 100% IV out of **{{total}}** total seen in the last 24 hours.",
"HUNDO_STATS_MESSAGE_WITH_RATIO": "**{{{pokemon}}} (#{{id}})** | **{{count}}** 100% IV out of **{{total}}** total seen in the last 24 hours with a **1/{{chance}}** ratio.",
"HUNDO_STATS_NEWLINE": "----------------------------------------------",
"HUNDO_STATS_TITLE": "[**Hundo Pokemon stats for {{date}}**]",
"HUNDO_STATS_TOTAL_MESSAGE": "Found **{{count}}** total hundos out of **{{total}}** possiblities.",
Expand Down
8 changes: 4 additions & 4 deletions static/locales/_es.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,15 @@
"PVP_ULTRA_LEAGUE": "Ultra League",
"REMOVED_TOTAL_DEPARTED_MEMBERS": "Removed {{removed}} of {{users}} total members.",
"SHINY_STATS_INVALID_CHANNEL": "{{author}} Shiny stats channel does not exist.",
"SHINY_STATS_MESSAGE": "**{{pokemon}} (#{{id}})** | **{{shiny}}** shiny out of **{{total}}** total seen in the last 24 hours.",
"SHINY_STATS_MESSAGE_WITH_RATIO": "**{{pokemon}} (#{{id}})** | **{{shiny}}** shiny out of **{{total}}** total seen in the last 24 hours with a **1/{{chance}}** ratio.",
"SHINY_STATS_MESSAGE": "**{{{pokemon}}} (#{{id}})** | **{{shiny}}** shiny out of **{{total}}** total seen in the last 24 hours.",
"SHINY_STATS_MESSAGE_WITH_RATIO": "**{{{pokemon}}} (#{{id}})** | **{{shiny}}** shiny out of **{{total}}** total seen in the last 24 hours with a **1/{{chance}}** ratio.",
"SHINY_STATS_NEWLINE": "----------------------------------------------",
"SHINY_STATS_TITLE": "[**Shiny Pokemon stats for {{date}}**]",
"SHINY_STATS_TOTAL_MESSAGE": "Found **{{shiny}}** total shinies out of **{{total}}** possiblities.",
"SHINY_STATS_TOTAL_MESSAGE_WITH_RATIO": "Found **{{shiny}}** total shinies out of **{{total}}** possiblities with a **1/{{chance}}** ratio in total.",
"HUNDO_STATS_INVALID_CHANNEL": "{{author}} Hundo stats channel does not exist.",
"HUNDO_STATS_MESSAGE": "**{{pokemon}} (#{{id}})** | **{{count}}** 100% IV out of **{{total}}** total seen in the last 24 hours.",
"HUNDO_STATS_MESSAGE_WITH_RATIO": "**{{pokemon}} (#{{id}})** | **{{count}}** 100% IV out of **{{total}}** total seen in the last 24 hours with a **1/{{chance}}** ratio.",
"HUNDO_STATS_MESSAGE": "**{{{pokemon}}} (#{{id}})** | **{{count}}** 100% IV out of **{{total}}** total seen in the last 24 hours.",
"HUNDO_STATS_MESSAGE_WITH_RATIO": "**{{{pokemon}}} (#{{id}})** | **{{count}}** 100% IV out of **{{total}}** total seen in the last 24 hours with a **1/{{chance}}** ratio.",
"HUNDO_STATS_NEWLINE": "----------------------------------------------",
"HUNDO_STATS_TITLE": "[**Hundo Pokemon stats for {{date}}**]",
"HUNDO_STATS_TOTAL_MESSAGE": "Found **{{count}}** total hundos out of **{{total}}** possiblities.",
Expand Down
8 changes: 4 additions & 4 deletions static/locales/_fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,15 @@
"PVP_ULTRA_LEAGUE": "Ultra League",
"REMOVED_TOTAL_DEPARTED_MEMBERS": "Removed {{removed}} of {{users}} total members.",
"SHINY_STATS_INVALID_CHANNEL": "{{author}} Shiny stats channel does not exist.",
"SHINY_STATS_MESSAGE": "**{{pokemon}} (#{{id}})** | **{{shiny}}** shiny out of **{{total}}** total seen in the last 24 hours.",
"SHINY_STATS_MESSAGE_WITH_RATIO": "**{{pokemon}} (#{{id}})** | **{{shiny}}** shiny out of **{{total}}** total seen in the last 24 hours with a **1/{{chance}}** ratio.",
"SHINY_STATS_MESSAGE": "**{{{pokemon}}} (#{{id}})** | **{{shiny}}** shiny out of **{{total}}** total seen in the last 24 hours.",
"SHINY_STATS_MESSAGE_WITH_RATIO": "**{{{pokemon}}} (#{{id}})** | **{{shiny}}** shiny out of **{{total}}** total seen in the last 24 hours with a **1/{{chance}}** ratio.",
"SHINY_STATS_NEWLINE": "----------------------------------------------",
"SHINY_STATS_TITLE": "[**Shiny Pokemon stats for {{date}}**]",
"SHINY_STATS_TOTAL_MESSAGE": "Found **{{shiny}}** total shinies out of **{{total}}** possiblities.",
"SHINY_STATS_TOTAL_MESSAGE_WITH_RATIO": "Found **{{shiny}}** total shinies out of **{{total}}** possiblities with a **1/{{chance}}** ratio in total.",
"HUNDO_STATS_INVALID_CHANNEL": "{{author}} Hundo stats channel does not exist.",
"HUNDO_STATS_MESSAGE": "**{{pokemon}} (#{{id}})** | **{{count}}** 100% IV out of **{{total}}** total seen in the last 24 hours.",
"HUNDO_STATS_MESSAGE_WITH_RATIO": "**{{pokemon}} (#{{id}})** | **{{count}}** 100% IV out of **{{total}}** total seen in the last 24 hours with a **1/{{chance}}** ratio.",
"HUNDO_STATS_MESSAGE": "**{{{pokemon}}} (#{{id}})** | **{{count}}** 100% IV out of **{{total}}** total seen in the last 24 hours.",
"HUNDO_STATS_MESSAGE_WITH_RATIO": "**{{{pokemon}}} (#{{id}})** | **{{count}}** 100% IV out of **{{total}}** total seen in the last 24 hours with a **1/{{chance}}** ratio.",
"HUNDO_STATS_NEWLINE": "----------------------------------------------",
"HUNDO_STATS_TITLE": "[**Hundo Pokemon stats for {{date}}**]",
"HUNDO_STATS_TOTAL_MESSAGE": "Found **{{count}}** total hundos out of **{{total}}** possiblities.",
Expand Down
Loading

0 comments on commit 13e7a7d

Please sign in to comment.