using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using Discord.Commands; using Geekbot.net.Lib.GuildSettingsManager; using Geekbot.net.Lib.Logger; using YamlDotNet.Core; using YamlDotNet.Serialization; namespace Geekbot.net.Lib.Localization { public class TranslationHandler : ITranslationHandler { private readonly IGeekbotLogger _logger; private readonly IGuildSettingsManager _guildSettingsManager; private readonly Dictionary _serverLanguages; private Dictionary>> _translations; public TranslationHandler(IGeekbotLogger logger, IGuildSettingsManager guildSettingsManager) { _logger = logger; _guildSettingsManager = guildSettingsManager; _logger.Information(LogSource.Geekbot, "Loading Translations"); LoadTranslations(); _serverLanguages = new Dictionary(); } private void LoadTranslations() { try { // Read the file var translationFile = File.ReadAllText(Path.GetFullPath("./Lib/Localization/Translations.yml")); // Deserialize var input = new StringReader(translationFile); var mergingParser = new MergingParser(new Parser(input)); var deserializer = new DeserializerBuilder().Build(); var rawTranslations = deserializer.Deserialize>>>(mergingParser); // Sort var sortedPerLanguage = new Dictionary>>(); foreach (var command in rawTranslations) { foreach (var str in command.Value) { foreach (var lang in str.Value) { if (!sortedPerLanguage.ContainsKey(lang.Key)) { var commandDict = new Dictionary>(); var strDict = new Dictionary { {str.Key, lang.Value} }; commandDict.Add(command.Key, strDict); sortedPerLanguage.Add(lang.Key, commandDict); } if (!sortedPerLanguage[lang.Key].ContainsKey(command.Key)) { var strDict = new Dictionary { {str.Key, lang.Value} }; sortedPerLanguage[lang.Key].Add(command.Key, strDict); } if (!sortedPerLanguage[lang.Key][command.Key].ContainsKey(str.Key)) { sortedPerLanguage[lang.Key][command.Key].Add(str.Key, lang.Value); } } } } _translations = sortedPerLanguage; // Find Languages SupportedLanguages = new List(); foreach (var lang in sortedPerLanguage) { SupportedLanguages.Add(lang.Key); } } catch (Exception e) { _logger.Error(LogSource.Geekbot, "Failed to load Translations", e); Environment.Exit(GeekbotExitCode.TranslationsFailed.GetHashCode()); } } private async Task GetServerLanguage(ulong guildId) { try { string lang; try { lang = _serverLanguages[guildId]; if (!string.IsNullOrEmpty(lang)) { return lang; } throw new Exception(); } catch { lang = _guildSettingsManager.GetSettings(guildId, false)?.Language ?? "EN"; _serverLanguages[guildId] = lang; return lang; } } catch (Exception e) { _logger.Error(LogSource.Geekbot, "Could not get guild language", e); return "EN"; } } public async Task GetString(ulong guildId, string command, string stringName) { var serverLang = await GetServerLanguage(guildId); return GetString(serverLang, command, stringName); } public string GetString(string language, string command, string stringName) { var translation = _translations[language][command][stringName]; if (!string.IsNullOrWhiteSpace(translation)) return translation; translation = _translations[command][stringName]["EN"]; if (string.IsNullOrWhiteSpace(translation)) { _logger.Warning(LogSource.Geekbot, $"No translation found for {command} - {stringName}"); } return translation; } private async Task> GetDict(ICommandContext context) { try { var command = context.Message.Content.Split(' ').First().TrimStart('!').ToLower(); var serverLanguage = await GetServerLanguage(context.Guild?.Id ?? 0); return _translations[serverLanguage][command]; } catch (Exception e) { _logger.Error(LogSource.Geekbot, "No translations for command found", e); return new Dictionary(); } } public async Task 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> GetDict(ICommandContext context, string command) { try { var serverLanguage = await GetServerLanguage(context.Guild?.Id ?? 0); return _translations[serverLanguage][command]; } catch (Exception e) { _logger.Error(LogSource.Geekbot, "No translations for command found", e); return new Dictionary(); } } public async Task SetLanguage(ulong guildId, string language) { try { if (!SupportedLanguages.Contains(language)) return false; var guild = _guildSettingsManager.GetSettings(guildId); guild.Language = language; await _guildSettingsManager.UpdateSettings(guild); _serverLanguages[guildId] = language; return true; } catch (Exception e) { _logger.Error(LogSource.Geekbot, "Error while changing language", e); return false; } } public List SupportedLanguages { get; private set; } } }