NadekoBot/NadekoBot.Core/Services/Impl/NadekoStrings.cs
2017-10-13 06:14:54 +02:00

125 lines
5.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using NLog;
namespace NadekoBot.Core.Services.Impl
{
public class NadekoStrings : INService
{
public const string stringsPath = @"_strings/";
private readonly ImmutableDictionary<string, ImmutableDictionary<string, string>> responseStrings;
private readonly Logger _log;
/// <summary>
/// Used as failsafe in case response key doesn't exist in the selected or default language.
/// </summary>
private readonly CultureInfo _usCultureInfo = new CultureInfo("en-US");
private readonly ILocalization _localization;
private readonly Regex formatFinder = new Regex(@"{\d}", RegexOptions.Compiled);
public NadekoStrings(ILocalization loc)
{
_log = LogManager.GetCurrentClassLogger();
_localization = loc;
var sw = Stopwatch.StartNew();
var allLangsDict = new Dictionary<string, ImmutableDictionary<string, string>>(); // lang:(name:value)
foreach (var file in Directory.GetFiles(stringsPath))
{
var langDict = JsonConvert.DeserializeObject<Dictionary<string, string>>(File.ReadAllText(file));
allLangsDict.Add(GetLocaleName(file).ToLowerInvariant(), langDict.ToImmutableDictionary());
}
responseStrings = allLangsDict.ToImmutableDictionary();
sw.Stop();
_log.Info("Loaded {0} languages in {1:F2}s",
responseStrings.Count,
//string.Join(",", responseStrings.Keys),
sw.Elapsed.TotalSeconds);
////improper string format checks
//var compareTo = responseStrings["en-us"]
// .Select(x =>
// {
// return (StringKey: x.Key, Placeholders: formatFinder.Matches(x.Value).Cast<Match>().Select(y => y.Value).ToArray());
// })
// .ToDictionary(x => x.StringKey, x => x.Placeholders);
//var errors = responseStrings
// .Select(a => (a.Key, a.Value.Select(x =>
// {
// if (!compareTo.ContainsKey(x.Key))
// return (StringKey: x.Key, Placeholders: new HashSet<string>(), Missing: true);
// var hs = new HashSet<string>(compareTo[x.Key]);
// hs.SymmetricExceptWith(formatFinder.Matches(x.Value).Cast<Match>().Select(y => y.Value).ToArray());
// return (StringKey: x.Key, Placeholders: hs, Missing: false);
// })
// .Where(x => x.Placeholders.Any() || x.Missing)))
// .Where(x => x.Item2.Any());
//var str = string.Join("\n", errors.Select(x => $"------{x.Item1}------\n" +
// string.Join("\n", x.Item2.Select(y =>
// y.StringKey + ": " + (y.Missing ? "MISSING" : string.Join(", ", y.Placeholders))))));
//if (!string.IsNullOrWhiteSpace(str))
// _log.Warn($"Improperly Formatted strings:\n{str}");
}
private string GetLocaleName(string fileName)
{
var dotIndex = fileName.IndexOf('.') + 1;
var secondDotINdex = fileName.LastIndexOf('.');
return fileName.Substring(dotIndex, secondDotINdex - dotIndex);
}
private string GetString(string text, CultureInfo cultureInfo)
{
if (!responseStrings.TryGetValue(cultureInfo.Name.ToLowerInvariant(), out ImmutableDictionary<string, string> strings))
return null;
strings.TryGetValue(text, out string val);
return val;
}
public string GetText(string key, ulong? guildId, string lowerModuleTypeName, params object[] replacements) =>
GetText(key, _localization.GetCultureInfo(guildId), lowerModuleTypeName, replacements);
public string GetText(string key, CultureInfo cultureInfo, string lowerModuleTypeName)
{
var text = GetString(lowerModuleTypeName + "_" + key, cultureInfo);
if (string.IsNullOrWhiteSpace(text))
{
LogManager.GetCurrentClassLogger().Warn(lowerModuleTypeName + "_" + key + " key is missing from " + cultureInfo + " response strings. PLEASE REPORT THIS.");
text = GetString(lowerModuleTypeName + "_" + key, _usCultureInfo) ?? $"Error: dkey {lowerModuleTypeName + "_" + key} not found!";
if (string.IsNullOrWhiteSpace(text))
return "I can't tell you if the command is executed, because there was an error printing out the response. Key '" +
lowerModuleTypeName + "_" + key + "' " + "is missing from resources. Please report this.";
}
return text;
}
public string GetText(string key, CultureInfo cultureInfo, string lowerModuleTypeName,
params object[] replacements)
{
try
{
return string.Format(GetText(key, cultureInfo, lowerModuleTypeName), replacements);
}
catch (FormatException)
{
return "I can't tell you if the command is executed, because there was an error printing out the response. Key '" +
lowerModuleTypeName + "_" + key + "' " + "is not properly formatted. Please report this.";
}
}
}
}