Rewrite huge parts of the localization class to support plurals and localized date time formating, also created a TranslationGuildContext class for use in commands
This commit is contained in:
parent
4143180b42
commit
8effc42f92
5 changed files with 211 additions and 79 deletions
|
@ -36,17 +36,18 @@ namespace Geekbot.net.Commands.Rpg
|
|||
{
|
||||
try
|
||||
{
|
||||
var transDict = await _translation.GetDict(Context);
|
||||
var transContext = await _translation.GetGuildContext(Context);
|
||||
var actor = await GetUser(Context.User.Id);
|
||||
if (actor.LastPayout.Value.AddHours(24) > DateTimeOffset.Now)
|
||||
{
|
||||
await ReplyAsync(string.Format(transDict["WaitForMoreCookies"], actor.LastPayout.Value.AddHours(24).ToString("HH:mm:ss")));
|
||||
var formatedWaitTime = transContext.FormatDateTimeAsRemaining(actor.LastPayout.Value.AddHours(24));
|
||||
await ReplyAsync(transContext.GetString("WaitForMoreCookies", formatedWaitTime));
|
||||
return;
|
||||
}
|
||||
actor.Cookies += 10;
|
||||
actor.LastPayout = DateTimeOffset.Now;
|
||||
await SetUser(actor);
|
||||
await ReplyAsync(string.Format(transDict["GetCookies"], 10, actor.Cookies));
|
||||
await ReplyAsync(transContext.GetString("GetCookies", 10, actor.Cookies));
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -61,9 +62,9 @@ namespace Geekbot.net.Commands.Rpg
|
|||
{
|
||||
try
|
||||
{
|
||||
var transDict = await _translation.GetDict(Context);
|
||||
var transContext = await _translation.GetGuildContext(Context);
|
||||
var actor = await GetUser(Context.User.Id);
|
||||
await ReplyAsync(string.Format(transDict["InYourJar"], actor.Cookies));
|
||||
await ReplyAsync(transContext.GetString("InYourJar", actor.Cookies));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -77,12 +78,12 @@ namespace Geekbot.net.Commands.Rpg
|
|||
{
|
||||
try
|
||||
{
|
||||
var transDict = await _translation.GetDict(Context);
|
||||
var transContext = await _translation.GetGuildContext(Context);
|
||||
var giver = await GetUser(Context.User.Id);
|
||||
|
||||
if (giver.Cookies < amount)
|
||||
{
|
||||
await ReplyAsync(string.Format(transDict["NotEnoughToGive"]));
|
||||
await ReplyAsync(transContext.GetString("NotEnoughToGive"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -94,7 +95,7 @@ namespace Geekbot.net.Commands.Rpg
|
|||
await SetUser(giver);
|
||||
await SetUser(taker);
|
||||
|
||||
await ReplyAsync(string.Format(transDict["Given"], amount, user.Username));
|
||||
await ReplyAsync(transContext.GetString("Given", amount, user.Username));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -108,12 +109,12 @@ namespace Geekbot.net.Commands.Rpg
|
|||
{
|
||||
try
|
||||
{
|
||||
var transDict = await _translation.GetDict(Context);
|
||||
var transContext = await _translation.GetGuildContext(Context);
|
||||
var actor = await GetUser(Context.User.Id);
|
||||
|
||||
if (actor.Cookies < 5)
|
||||
{
|
||||
await ReplyAsync(string.Format(transDict["NotEnoughCookiesToEat"]));
|
||||
await ReplyAsync(transContext.GetString("NotEnoughCookiesToEat"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -122,7 +123,7 @@ namespace Geekbot.net.Commands.Rpg
|
|||
|
||||
await SetUser(actor);
|
||||
|
||||
await ReplyAsync(string.Format(transDict["AteCookies"], amount, actor.Cookies));
|
||||
await ReplyAsync(transContext.GetString("AteCookies", amount, actor.Cookies));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -7,8 +7,10 @@ namespace Geekbot.net.Lib.Localization
|
|||
public interface ITranslationHandler
|
||||
{
|
||||
Task<string> GetString(ulong guildId, string command, string stringName);
|
||||
List<string> GetStrings(string language, string command, string stringName);
|
||||
Task<Dictionary<string, string>> GetDict(ICommandContext context);
|
||||
Task<Dictionary<string, string>> GetDict(ICommandContext context, string command);
|
||||
Task<TranslationGuildContext> GetGuildContext(ICommandContext context);
|
||||
Task<bool> SetLanguage(ulong guildId, string language);
|
||||
List<string> SupportedLanguages { get; }
|
||||
}
|
||||
|
|
90
Geekbot.net/Lib/Localization/TranslationGuildContext.cs
Normal file
90
Geekbot.net/Lib/Localization/TranslationGuildContext.cs
Normal file
|
@ -0,0 +1,90 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Geekbot.net.Lib.Localization
|
||||
{
|
||||
public class TranslationGuildContext
|
||||
{
|
||||
public ITranslationHandler TranslationHandler { get; }
|
||||
public string Language { get; }
|
||||
public Dictionary<string, string> Dict { get; }
|
||||
|
||||
public TranslationGuildContext(ITranslationHandler translationHandler, string language, Dictionary<string, string> dict)
|
||||
{
|
||||
TranslationHandler = translationHandler;
|
||||
Language = language;
|
||||
Dict = dict;
|
||||
}
|
||||
|
||||
public string GetString(string stringToFormat, params object[] args)
|
||||
{
|
||||
return string.Format(Dict[stringToFormat] ?? "", args);
|
||||
}
|
||||
|
||||
public string FormatDateTimeAsRemaining(DateTimeOffset dateTime)
|
||||
{
|
||||
var remaining = dateTime - DateTimeOffset.Now;
|
||||
const string formattable = "{0} {1}";
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if (remaining.Days > 0)
|
||||
{
|
||||
var s = GetTimeString(TimeTypes.Days);
|
||||
sb.AppendFormat(formattable, remaining.Days, GetSingOrPlur(remaining.Days, s));
|
||||
}
|
||||
|
||||
if (remaining.Hours > 0)
|
||||
{
|
||||
if (sb.Length > 0) sb.Append(", ");
|
||||
var s = GetTimeString(TimeTypes.Hours);
|
||||
sb.AppendFormat(formattable, remaining.Hours, GetSingOrPlur(remaining.Hours, s));
|
||||
}
|
||||
|
||||
if (remaining.Minutes > 0)
|
||||
{
|
||||
if (sb.Length > 0) sb.Append(", ");
|
||||
var s = GetTimeString(TimeTypes.Minutes);
|
||||
sb.AppendFormat(formattable, remaining.Minutes, GetSingOrPlur(remaining.Minutes, s));
|
||||
}
|
||||
|
||||
if (remaining.Seconds > 0)
|
||||
{
|
||||
if (sb.Length > 0)
|
||||
{
|
||||
var and = TranslationHandler.GetStrings(Language, "dateTime", "And").First();
|
||||
sb.AppendFormat(" {0} ", and);
|
||||
}
|
||||
var s = GetTimeString(TimeTypes.Seconds);
|
||||
sb.AppendFormat(formattable, remaining.Seconds, GetSingOrPlur(remaining.Seconds, s));
|
||||
}
|
||||
|
||||
return sb.ToString().Trim();
|
||||
}
|
||||
|
||||
public Task<bool> SetLanguage(ulong guildId, string language)
|
||||
{
|
||||
return TranslationHandler.SetLanguage(guildId, language);
|
||||
}
|
||||
|
||||
private List<string> GetTimeString(TimeTypes type)
|
||||
{
|
||||
return TranslationHandler.GetStrings(Language, "dateTime", type.ToString());
|
||||
}
|
||||
|
||||
private string GetSingOrPlur(int number, List<string> versions)
|
||||
{
|
||||
return number == 1 ? versions[0] : versions[1];
|
||||
}
|
||||
|
||||
private enum TimeTypes
|
||||
{
|
||||
Days,
|
||||
Hours,
|
||||
Minutes,
|
||||
Seconds
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ namespace Geekbot.net.Lib.Localization
|
|||
private readonly DatabaseContext _database;
|
||||
private readonly IGeekbotLogger _logger;
|
||||
private readonly Dictionary<ulong, string> _serverLanguages;
|
||||
private Dictionary<string, Dictionary<string, Dictionary<string, string>>> _translations;
|
||||
private Dictionary<string, Dictionary<string, Dictionary<string, List<string>>>> _translations;
|
||||
|
||||
public TranslationHandler(DatabaseContext database, IGeekbotLogger logger)
|
||||
{
|
||||
|
@ -33,8 +33,8 @@ namespace Geekbot.net.Lib.Localization
|
|||
try
|
||||
{
|
||||
var translationFile = File.ReadAllText(Path.GetFullPath("./Lib/Localization/Translations.json"));
|
||||
var rawTranslations = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, Dictionary<string, string>>>>(translationFile);
|
||||
var sortedPerLanguage = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
|
||||
var rawTranslations = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, Dictionary<string, List<string>>>>>(translationFile);
|
||||
var sortedPerLanguage = new Dictionary<string, Dictionary<string, Dictionary<string, List<string>>>>();
|
||||
foreach (var command in rawTranslations)
|
||||
{
|
||||
foreach (var str in command.Value)
|
||||
|
@ -43,8 +43,8 @@ namespace Geekbot.net.Lib.Localization
|
|||
{
|
||||
if (!sortedPerLanguage.ContainsKey(lang.Key))
|
||||
{
|
||||
var commandDict = new Dictionary<string, Dictionary<string, string>>();
|
||||
var strDict = new Dictionary<string, string>
|
||||
var commandDict = new Dictionary<string, Dictionary<string, List<string>>>();
|
||||
var strDict = new Dictionary<string, List<string>>
|
||||
{
|
||||
{str.Key, lang.Value}
|
||||
};
|
||||
|
@ -53,8 +53,10 @@ namespace Geekbot.net.Lib.Localization
|
|||
}
|
||||
if (!sortedPerLanguage[lang.Key].ContainsKey(command.Key))
|
||||
{
|
||||
var strDict = new Dictionary<string, string>();
|
||||
strDict.Add(str.Key, lang.Value);
|
||||
var strDict = new Dictionary<string, List<string>>
|
||||
{
|
||||
{str.Key, lang.Value}
|
||||
};
|
||||
sortedPerLanguage[lang.Key].Add(command.Key, strDict);
|
||||
}
|
||||
if (!sortedPerLanguage[lang.Key][command.Key].ContainsKey(str.Key))
|
||||
|
@ -109,10 +111,16 @@ namespace Geekbot.net.Lib.Localization
|
|||
|
||||
public async Task<string> GetString(ulong guildId, string command, string stringName)
|
||||
{
|
||||
var translation = _translations[await GetServerLanguage(guildId)][command][stringName];
|
||||
if (!string.IsNullOrWhiteSpace(translation)) return translation;
|
||||
var serverLang = await GetServerLanguage(guildId);
|
||||
return GetStrings(serverLang, command, stringName).First();
|
||||
}
|
||||
|
||||
public List<string> GetStrings(string language, string command, string stringName)
|
||||
{
|
||||
var translation = _translations[language][command][stringName];
|
||||
if (!string.IsNullOrWhiteSpace(translation.First())) return translation;
|
||||
translation = _translations[command][stringName]["EN"];
|
||||
if (string.IsNullOrWhiteSpace(translation))
|
||||
if (string.IsNullOrWhiteSpace(translation.First()))
|
||||
{
|
||||
_logger.Warning(LogSource.Geekbot, $"No translation found for {command} - {stringName}");
|
||||
}
|
||||
|
@ -125,7 +133,8 @@ namespace Geekbot.net.Lib.Localization
|
|||
{
|
||||
var command = context.Message.Content.Split(' ').First().TrimStart('!').ToLower();
|
||||
var serverLanguage = await GetServerLanguage(context.Guild?.Id ?? 0);
|
||||
return _translations[serverLanguage][command];
|
||||
return _translations[serverLanguage][command]
|
||||
.ToDictionary(dict => dict.Key, dict => dict.Value.First());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -133,13 +142,21 @@ namespace Geekbot.net.Lib.Localization
|
|||
return new Dictionary<string, string>();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<TranslationGuildContext> GetGuildContext(ICommandContext context)
|
||||
{
|
||||
var dict = await GetDict(context);
|
||||
var language = await GetServerLanguage(context.Guild?.Id ?? 0);
|
||||
return new TranslationGuildContext(this, language, dict);
|
||||
}
|
||||
|
||||
public async Task<Dictionary<string, string>> GetDict(ICommandContext context, string command)
|
||||
{
|
||||
try
|
||||
{
|
||||
var serverLanguage = await GetServerLanguage(context.Guild?.Id ?? 0);
|
||||
return _translations[serverLanguage][command];
|
||||
return _translations[serverLanguage][command]
|
||||
.ToDictionary(dict => dict.Key, dict => dict.Value.First());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -1,130 +1,152 @@
|
|||
{
|
||||
"dateTime": {
|
||||
"Days": {
|
||||
"EN": ["day", "days"],
|
||||
"CHDE": ["tag", "täg"]
|
||||
},
|
||||
"Hours": {
|
||||
"EN": ["hour", "hours"],
|
||||
"CHDE": ["stund", "stunde"]
|
||||
},
|
||||
"Minutes": {
|
||||
"EN": ["minute", "minutes"],
|
||||
"CHDE": ["minute", "minute"]
|
||||
},
|
||||
"Seconds": {
|
||||
"EN": ["second", "seconds"],
|
||||
"CHDE": ["sekunde", "sekunde"]
|
||||
},
|
||||
"And": {
|
||||
"EN": ["and"],
|
||||
"CHDE": ["und"]
|
||||
}
|
||||
},
|
||||
"admin": {
|
||||
"NewLanguageSet": {
|
||||
"EN": "I will reply in english from now on",
|
||||
"CHDE": "I werd ab jetzt uf schwiizerdüütsch antworte, äuuä"
|
||||
"EN": ["I will reply in english from now on"],
|
||||
"CHDE": ["I werd ab jetzt uf schwiizerdüütsch antworte, äuuä"]
|
||||
},
|
||||
"GetLanguage": {
|
||||
"EN": "I'm talking english",
|
||||
"CHDE": "I red schwiizerdüütsch"
|
||||
"EN": ["I'm talking english"],
|
||||
"CHDE": ["I red schwiizerdüütsch"]
|
||||
}
|
||||
},
|
||||
"errorHandler": {
|
||||
"SomethingWentWrong": {
|
||||
"EN": "Something went wrong :confused:",
|
||||
"CHDE": "Öppis isch schief gange :confused:"
|
||||
"EN": ["Something went wrong :confused:"],
|
||||
"CHDE": ["Öppis isch schief gange :confused:"]
|
||||
}
|
||||
},
|
||||
"httpErrors": {
|
||||
"403": {
|
||||
"EN": "Seems like i don't have enough permission to that :confused:",
|
||||
"CHDE": "Gseht danach us das ich nid gnueg recht han zum das mache :confused:"
|
||||
"EN": ["Seems like i don't have enough permission to that :confused:"],
|
||||
"CHDE": ["Gseht danach us das ich nid gnueg recht han zum das mache :confused:"]
|
||||
}
|
||||
},
|
||||
"choose": {
|
||||
"Choice": {
|
||||
"EN": "I Choose **{0}**",
|
||||
"CHDE": "I nimme **{0}**"
|
||||
"EN": ["I Choose **{0}**"],
|
||||
"CHDE": ["I nimme **{0}**"]
|
||||
}
|
||||
},
|
||||
"good": {
|
||||
"CannotChangeOwn": {
|
||||
"EN": "Sorry {0}, but you can't give yourself karma",
|
||||
"CHDE": "Sorry {0}, aber du chasch dr selber kei karma geh"
|
||||
"EN": ["Sorry {0}, but you can't give yourself karma"],
|
||||
"CHDE": ["Sorry {0}, aber du chasch dr selber kei karma geh"]
|
||||
},
|
||||
"WaitUntill": {
|
||||
"EN": "Sorry {0}, but you have to wait {1} before you can give karma again...",
|
||||
"CHDE": "Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch geh..."
|
||||
"EN": ["Sorry {0}, but you have to wait {1} before you can give karma again..."],
|
||||
"CHDE": ["Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch geh..."]
|
||||
},
|
||||
"Increased": {
|
||||
"EN": "Karma gained",
|
||||
"CHDE": "Karma becho"
|
||||
"EN": ["Karma gained"],
|
||||
"CHDE": ["Karma becho"]
|
||||
},
|
||||
"By": {
|
||||
"EN": "By",
|
||||
"CHDE": "Vo"
|
||||
"EN": ["By"],
|
||||
"CHDE": ["Vo"]
|
||||
},
|
||||
"Amount": {
|
||||
"EN": "Amount",
|
||||
"CHDE": "Mengi"
|
||||
"EN": ["Amount"],
|
||||
"CHDE": ["Mengi"]
|
||||
},
|
||||
"Current": {
|
||||
"EN": "Current",
|
||||
"CHDE": "Jetzt"
|
||||
"EN": ["Current"],
|
||||
"CHDE": ["Jetzt"]
|
||||
}
|
||||
},
|
||||
"bad": {
|
||||
"CannotChangeOwn": {
|
||||
"EN": "Sorry {0}, but you can't lower your own karma",
|
||||
"CHDE": "Sorry {0}, aber du chasch dr din eigete karma nid weg neh"
|
||||
"EN": ["Sorry {0}, but you can't lower your own karma"],
|
||||
"CHDE": ["Sorry {0}, aber du chasch dr din eigete karma nid weg neh"]
|
||||
},
|
||||
"WaitUntill": {
|
||||
"EN": "Sorry {0}, but you have to wait {1} before you can lower karma again...",
|
||||
"CHDE": "Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch senke..."
|
||||
"EN": ["Sorry {0}, but you have to wait {1} before you can lower karma again..."],
|
||||
"CHDE": ["Sorry {0}, aber du musch no {1} warte bisch d wieder karma chasch senke..."]
|
||||
},
|
||||
"Decreased": {
|
||||
"EN": "Karma lowered",
|
||||
"CHDE": "Karma gsenkt"
|
||||
"EN": ["Karma lowered"],
|
||||
"CHDE": ["Karma gsenkt"]
|
||||
},
|
||||
"By": {
|
||||
"EN": "By",
|
||||
"CHDE": "Vo"
|
||||
"EN": ["By"],
|
||||
"CHDE": ["Vo"]
|
||||
},
|
||||
"Amount": {
|
||||
"EN": "Amount",
|
||||
"CHDE": "Mengi"
|
||||
"EN": ["Amount"],
|
||||
"CHDE": ["Mengi"]
|
||||
},
|
||||
"Current": {
|
||||
"EN": "Current",
|
||||
"CHDE": "Jetzt"
|
||||
"EN": ["Current"],
|
||||
"CHDE": ["Jetzt"]
|
||||
}
|
||||
},
|
||||
"roll": {
|
||||
"Rolled": {
|
||||
"EN": "{0}, you rolled {1}, your guess was {2}",
|
||||
"CHDE": "{0}, du hesch {1} grollt und hesch {2} grate"
|
||||
"EN": ["{0}, you rolled {1}, your guess was {2}"],
|
||||
"CHDE": ["{0}, du hesch {1} grollt und hesch {2} grate"]
|
||||
},
|
||||
"Gratz": {
|
||||
"EN": "Congratulations {0}, your guess was correct!",
|
||||
"CHDE": "Gratuliere {0}, du hesch richtig grate!"
|
||||
"EN": ["Congratulations {0}, your guess was correct!"],
|
||||
"CHDE": ["Gratuliere {0}, du hesch richtig grate!"]
|
||||
},
|
||||
"RolledNoGuess": {
|
||||
"EN": "{0}, you rolled {1}",
|
||||
"CHDE": "{0}, du hesch {1} grollt"
|
||||
"EN": ["{0}, you rolled {1}"],
|
||||
"CHDE": ["{0}, du hesch {1} grollt"]
|
||||
},
|
||||
"NoPrevGuess": {
|
||||
"EN": ":red_circle: {0}, you can't guess the same number again",
|
||||
"CHDE": ":red_circle: {0}, du chasch nid nomol es gliche rate"
|
||||
"EN": [":red_circle: {0}, you can't guess the same number again"],
|
||||
"CHDE": [":red_circle: {0}, du chasch nid nomol es gliche rate"]
|
||||
}
|
||||
},
|
||||
"cookie": {
|
||||
"GetCookies": {
|
||||
"EN": "You got {0} cookies, there are now {1} cookies in you cookie jar",
|
||||
"CHDE": "Du häsch {0} guetzli becho, du häsch jetzt {1} guetzli ih dr büchse"
|
||||
"EN": ["You got {0} cookies, there are now {1} cookies in you cookie jar"],
|
||||
"CHDE": ["Du häsch {0} guetzli becho, du häsch jetzt {1} guetzli ih dr büchse"]
|
||||
},
|
||||
"WaitForMoreCookies": {
|
||||
"EN": "You already got cookies in the last 24 hours, wait until {0} for more cookies",
|
||||
"CHDE": "Du hesch scho guetzli becho ih de letzti 24 stund, wart no bis {0}"
|
||||
"EN": ["You already got cookies in the last 24 hours, you can have more cookies in {0}"],
|
||||
"CHDE": ["Du hesch scho guetzli becho ih de letzti 24 stund, du chasch meh ha in {0}"]
|
||||
},
|
||||
"InYourJar": {
|
||||
"EN": "There are {0} cookies in you cookie jar",
|
||||
"CHDE": "Es hät {0} guetzli ih dineri büchs"
|
||||
"EN": ["There are {0} cookies in you cookie jar"],
|
||||
"CHDE": ["Es hät {0} guetzli ih dineri büchs"]
|
||||
},
|
||||
"Given": {
|
||||
"EN": "You gave {0} cookies to {1}",
|
||||
"CHDE": "Du hesch {1} {0} guetzli geh"
|
||||
"EN": ["You gave {0} cookies to {1}"],
|
||||
"CHDE": ["Du hesch {1} {0} guetzli geh"]
|
||||
},
|
||||
"NotEnoughToGive": {
|
||||
"EN": "You don't have enough cookies",
|
||||
"CHDE": "Du hesch nid gnueg guetzli"
|
||||
"EN": ["You don't have enough cookies"],
|
||||
"CHDE": ["Du hesch nid gnueg guetzli"]
|
||||
},
|
||||
"NotEnoughCookiesToEat": {
|
||||
"EN": "Your cookie jar looks almost empty, you should probably not eat a cookie",
|
||||
"CHDE": "Du hesch chuum no guetzli ih dineri büchs, du sötsch warschinli keini esse"
|
||||
"EN": ["Your cookie jar looks almost empty, you should probably not eat a cookie"],
|
||||
"CHDE": ["Du hesch chuum no guetzli ih dineri büchs, du sötsch warschinli keini esse"]
|
||||
},
|
||||
"AteCookies": {
|
||||
"EN": "You ate {0} cookies, you've only got {1} cookies left",
|
||||
"CHDE": "Du hesch {0} guetzli gesse und hesch jezt no {1} übrig"
|
||||
"EN": ["You ate {0} cookies, you've only got {1} cookies left"],
|
||||
"CHDE": ["Du hesch {0} guetzli gesse und hesch jezt no {1} übrig"]
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue