TranslationManager.cxx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #include "TranslationManager.hxx"
  2. #include <SDL.h>
  3. #include <fstream>
  4. #include <optional>
  5. #include <regex>
  6. namespace {
  7. std::optional<SupportedLanguage> language_from_string(std::string const& lang)
  8. {
  9. static std::unordered_map<std::string, SupportedLanguage> const MAPPING{
  10. {"en", SupportedLanguage::English},
  11. {"de", SupportedLanguage::German},
  12. };
  13. auto const it = MAPPING.find(lang);
  14. if (it==MAPPING.end())
  15. return {};
  16. return it->second;
  17. }
  18. SupportedLanguage get_preferred_language()
  19. {
  20. auto const locales = SDL_GetPreferredLocales();
  21. for (auto const* locale = locales; locale->language!=nullptr; ++locale) {
  22. auto const lang = language_from_string(locale->language);
  23. if (lang.has_value()) {
  24. SDL_free(locales);
  25. return lang.value();
  26. }
  27. }
  28. SDL_free(locales);
  29. return SupportedLanguage::English;
  30. }
  31. std::regex const KEY_REGEX = std::regex{R"(^\[([^\]]*)\]$)"};
  32. std::regex const VALUE_REGEX = std::regex{R"(^(en|de) = (.+)$)"};
  33. }
  34. TranslationManager::TranslationManager() noexcept
  35. :current_language_{::get_preferred_language()}
  36. {
  37. }
  38. TranslationManager& TranslationManager::instance()
  39. {
  40. static TranslationManager tm;
  41. return tm;
  42. }
  43. std::string TranslationManager::get_translation(std::string const& key) const
  44. {
  45. auto const it = translations_.find(key);
  46. if (it==translations_.end())
  47. return key;
  48. auto const lang_idx = static_cast<std::size_t>(current_language_);
  49. if (it->second[lang_idx].empty())
  50. return key;
  51. return it->second[lang_idx];
  52. }
  53. void TranslationManager::load(std::filesystem::path const& filename)
  54. {
  55. std::ifstream input{filename};
  56. std::string current_key{};
  57. for (std::string line; std::getline(input, line);) {
  58. if (std::smatch key_match; std::regex_match(line, key_match, ::KEY_REGEX)) {
  59. current_key = key_match.str(1);
  60. }
  61. else if (std::smatch value_match; std::regex_match(line, value_match, ::VALUE_REGEX)) {
  62. // hacky, but right now the regex already makes sure we alway get a language back
  63. auto const lang = ::language_from_string(value_match.str(1)).value();
  64. auto const value = value_match.str(2);
  65. if (current_key.empty()) {
  66. SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Translations without key not loaded! (%s)", value.c_str());
  67. }
  68. else {
  69. translations_[current_key][static_cast<std::size_t>(lang)] = value;
  70. }
  71. }
  72. else if (!line.empty()) {
  73. SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Translation line with unsupported format: %s", line.c_str());
  74. }
  75. }
  76. }