using CarCareTracker.Models; using Microsoft.Extensions.Caching.Memory; using System.Text.Json; namespace CarCareTracker.Helper { public interface ITranslationHelper { string Translate(string userLanguage, string text); Dictionary GetTranslations(string userLanguage); OperationResponse SaveTranslation(string userLanguage, Dictionary translations); } public class TranslationHelper : ITranslationHelper { private readonly IFileHelper _fileHelper; private readonly IConfiguration _config; private readonly ILogger _logger; private IMemoryCache _cache; public TranslationHelper(IFileHelper fileHelper, IConfiguration config, IMemoryCache memoryCache, ILogger logger) { _fileHelper = fileHelper; _config = config; _cache = memoryCache; _logger = logger; } public string Translate(string userLanguage, string text) { bool create = bool.Parse(_config["LUBELOGGER_TRANSLATOR"] ?? "false"); //transform input text into key. string translationKey = text.Replace(" ", "_"); var translationFilePath = userLanguage == "en_US" ? _fileHelper.GetFullFilePath($"/defaults/en_US.json") : _fileHelper.GetFullFilePath($"/translations/{userLanguage}.json", false); var dictionary = _cache.GetOrCreate>($"lang_{userLanguage}", entry => { entry.SlidingExpiration = TimeSpan.FromHours(1); if (File.Exists(translationFilePath)) { try { var translationFile = File.ReadAllText(translationFilePath); var translationDictionary = JsonSerializer.Deserialize>(translationFile); return translationDictionary ?? new Dictionary(); } catch (Exception ex) { _logger.LogError(ex.Message); return new Dictionary(); } } else { _logger.LogError($"Could not find translation file for {userLanguage}"); return new Dictionary(); } }); if (dictionary != null && dictionary.ContainsKey(translationKey)) { return dictionary[translationKey]; } else if (create && File.Exists(translationFilePath)) { //create entry dictionary.Add(translationKey, text); _logger.LogInformation($"Translation key added to {userLanguage} for {translationKey} with value {text}"); File.WriteAllText(translationFilePath, JsonSerializer.Serialize(dictionary)); return text; } return text; } private Dictionary GetDefaultTranslation() { //this method always returns en_US translation. var translationFilePath = _fileHelper.GetFullFilePath($"/defaults/en_US.json"); if (!string.IsNullOrWhiteSpace(translationFilePath)) { //file exists. try { var translationFile = File.ReadAllText(translationFilePath); var translationDictionary = JsonSerializer.Deserialize>(translationFile); return translationDictionary ?? new Dictionary(); } catch (Exception ex) { _logger.LogError(ex.Message); return new Dictionary(); } } _logger.LogError($"Could not find translation file for en_US"); return new Dictionary(); } public Dictionary GetTranslations(string userLanguage) { var defaultTranslation = GetDefaultTranslation(); if (userLanguage == "en_US") { return defaultTranslation; } var translationFilePath = _fileHelper.GetFullFilePath($"/translations/{userLanguage}.json"); if (!string.IsNullOrWhiteSpace(translationFilePath)) { //file exists. try { var translationFile = File.ReadAllText(translationFilePath); var translationDictionary = JsonSerializer.Deserialize>(translationFile); if (translationDictionary != null) { foreach(var translation in translationDictionary) { if (defaultTranslation.ContainsKey(translation.Key)) { defaultTranslation[translation.Key] = translation.Value; } } } return defaultTranslation ?? new Dictionary(); } catch (Exception ex) { _logger.LogError(ex.Message); return new Dictionary(); } } _logger.LogError($"Could not find translation file for {userLanguage}"); return new Dictionary(); } public OperationResponse SaveTranslation(string userLanguage, Dictionary translations) { bool create = bool.Parse(_config["LUBELOGGER_TRANSLATOR"] ?? "false"); bool isDefaultLanguage = userLanguage == "en_US"; if (isDefaultLanguage && !create) { return OperationResponse.Failed("The translation file name en_US is reserved."); } if (string.IsNullOrWhiteSpace(userLanguage)) { return OperationResponse.Failed("File name is not provided."); } if (!translations.Any()) { return OperationResponse.Failed("Translation has no data."); } var translationFilePath = isDefaultLanguage ? _fileHelper.GetFullFilePath($"/defaults/en_US.json") : _fileHelper.GetFullFilePath($"/translations/{userLanguage}.json", false); try { if (File.Exists(translationFilePath)) { //write to file File.WriteAllText(translationFilePath, JsonSerializer.Serialize(translations)); _cache.Remove($"lang_{userLanguage}"); //clear out cache, force a reload from file. } else { //check if directory exists first. var translationDirectory = _fileHelper.GetFullFilePath("translations/", false); if (!Directory.Exists(translationDirectory)) { Directory.CreateDirectory(translationDirectory); } //write to file File.WriteAllText(translationFilePath, JsonSerializer.Serialize(translations)); } return OperationResponse.Succeed("Translation Updated"); } catch (Exception ex) { _logger.LogError(ex.Message); return OperationResponse.Failed(); } } } }