Collapsed translated text struct and array.

This commit is contained in:
Muzychenko Andrey 2022-08-29 11:01:19 +03:00
parent dae4b1bf20
commit 9f17e0dd0a
2 changed files with 84 additions and 67 deletions

View File

@ -14,7 +14,7 @@ const languageInfo* translations::get_languages(size_t* languages_number) {
void translations::set_current_language(const char* short_name) void translations::set_current_language(const char* short_name)
{ {
for(int i = 0; i < (int)lang::NUMBER; i++) { for(int i = 0; i < (int)lang::Max; i++) {
if(!strcmp(short_name, languages[(lang)i].short_name)) { if(!strcmp(short_name, languages[(lang)i].short_name)) {
current_language = (lang) i; current_language = (lang) i;
return; return;
@ -25,7 +25,7 @@ void translations::set_current_language(const char* short_name)
const languageInfo* translations::get_current_language() const languageInfo* translations::get_current_language()
{ {
if(!languages.contains(current_language)) if(!TextArray::contains(current_language))
{ {
current_language = lang::English; current_language = lang::English;
} }
@ -34,36 +34,26 @@ const languageInfo* translations::get_current_language()
const char* translations::get_translation(Msg id) const char* translations::get_translation(Msg id)
{ {
if(!translated_strings.contains(id)) if(!TextArray::contains(id))
{ return "!Missing MsgId!";
return "";
} // Current language assumed in bounds at this point
auto text = Translations.Get(id, current_language);
const auto& translation = translated_strings[id]; // Fallback to english if available
if (text == nullptr)
text = Translations.Get(id, lang::English);
if (text == nullptr)
text = "!Missing English text!";
if(!translation.contains(current_language)) return text;
{
// fallback to english if available
if(translation.contains(lang::English))
{
return translation[lang::English];
}
else
{
return "";
}
}
else
{
return translation[current_language];
}
} }
void translations::get_glyph_range(ImVector<ImWchar>* ranges) void translations::get_glyph_range(ImVector<ImWchar>* ranges)
{ {
ImFontGlyphRangesBuilder builder; ImFontGlyphRangesBuilder builder;
for(int i = 0; i < (int)Msg::NUMBER; i++) { for(int i = 0; i < (int)Msg::Max; i++) {
const char* translation = get_translation((Msg)i); const char* translation = get_translation((Msg)i);
if(translation) if(translation)
{ {
@ -78,7 +68,7 @@ void translations::get_glyph_range(ImVector<ImWchar>* ranges)
const InitializedArray< const InitializedArray<
lang, lang,
languageInfo, languageInfo,
(int)lang::NUMBER (int)lang::Max
> translations::languages = > translations::languages =
{ {
{ lang::Arabic, {"ar", "Arabic" } }, { lang::Arabic, {"ar", "Arabic" } },
@ -107,15 +97,7 @@ const InitializedArray<
{ lang::TraditionalChinese, {"zh_TW", "Traditional Chinese" } }, { lang::TraditionalChinese, {"zh_TW", "Traditional Chinese" } },
}; };
const InitializedArray< const TextArray translations::Translations =
Msg,
InitializedArray<
lang,
const char*,
(int)lang::NUMBER
>,
(int)Msg::NUMBER
> translations::translated_strings =
{ {
{ {
Msg::STRING101, Msg::STRING101,

View File

@ -1,8 +1,9 @@
#pragma once #pragma once
enum class Msg enum class Msg : int
{ {
STRING101, Min = 0,
STRING101 = 0,
STRING102, STRING102,
STRING103, STRING103,
STRING104, STRING104,
@ -254,12 +255,13 @@ enum class Msg
Menu1_UseMaxResolution_800x600, Menu1_UseMaxResolution_800x600,
Menu1_UseMaxResolution_1024x768, Menu1_UseMaxResolution_1024x768,
NUMBER, Max,
}; };
enum class lang enum class lang : int
{ {
Arabic, Min = 0,
Arabic = 0,
Czech, Czech,
Danish, Danish,
German, German,
@ -283,35 +285,24 @@ enum class lang
Turkish, Turkish,
SimplifiedChinese, SimplifiedChinese,
TraditionalChinese, TraditionalChinese,
NUMBER Max
}; };
template <typename Key, typename Value, int N> template <typename Key, typename Value, int N>
struct InitializedArray struct InitializedArray
{ {
static_assert(std::is_enum<Key>::value, "Key is not an enum"); static_assert(std::is_enum_v<Key>, "Key is not an enum");
InitializedArray() : Store{}
{
}
InitializedArray(const std::initializer_list<std::pair<Key, Value>>& iList) InitializedArray(const std::initializer_list<std::pair<Key, Value>>& iList)
{ {
Store.reserve(iList.size());
for (const auto& pair : iList) for (const auto& pair : iList)
{ {
size_t index = static_cast<int>(pair.first); auto index = static_cast<int>(pair.first);
if (Store.size() <= index)
Store.resize(index + 1);
Store[index] = pair.second; Store[index] = pair.second;
} }
} }
bool contains(Key index) const
{
return Store.size() > static_cast<int>(index);
}
const Value& operator[](Key index) const const Value& operator[](Key index) const
{ {
return Store[static_cast<int>(index)]; return Store[static_cast<int>(index)];
@ -319,16 +310,68 @@ struct InitializedArray
const Value* data() const const Value* data() const
{ {
return Store.data(); return Store;
} }
size_t size() const static bool contains(Key index)
{ {
return Store.size(); return N >= 0 && N > static_cast<int>(index);
}
static size_t size()
{
return N;
} }
private: private:
std::vector<Value> Store; Value Store[N]{};
};
struct TextArray
{
TextArray(const std::initializer_list<std::pair<Msg, std::initializer_list<std::pair<lang, LPCSTR>>>>& iList)
{
for (const auto& msgPair : iList)
{
for (const auto& languagePair : msgPair.second)
{
assertm(!contains(msgPair.first, languagePair.first), "Key redefinition");
Set(msgPair.first, languagePair.first, languagePair.second);
}
}
}
LPCSTR Get(Msg msgId, lang langId) const
{
assertm(TextArray::contains(msgId), "Message Id out of bounds");
assertm(TextArray::contains(langId), "Language Id out of bounds");
return Store[static_cast<int>(msgId)][static_cast<int>(langId)];
}
bool contains(Msg msgId, lang langId) const
{
return contains(msgId) && Get(msgId, langId) != nullptr;
}
static bool contains(Msg msgId)
{
return msgId >= Msg::Min && msgId < Msg::Max;
}
static bool contains(lang langId)
{
return langId >= lang::Min && langId < lang::Max;
}
private:
LPCSTR Store[static_cast<int>(Msg::Max )][static_cast<int>(lang::Max)]{ nullptr };
void Set(Msg msgId, lang langId, LPCSTR value)
{
assertm(TextArray::contains(msgId), "Message Id out of bounds");
assertm(TextArray::contains(langId), "Language Id out of bounds");
Store[static_cast<int>(msgId)][static_cast<int>(langId)] = value;
}
}; };
struct languageInfo struct languageInfo
@ -347,19 +390,11 @@ public:
static void get_glyph_range(ImVector<ImWchar>* ranges); static void get_glyph_range(ImVector<ImWchar>* ranges);
private: private:
static const InitializedArray< static const TextArray Translations;
Msg,
InitializedArray<
lang,
const char*,
static_cast<int>(lang::NUMBER)
>,
static_cast<int>(Msg::NUMBER)
> translated_strings;
static const InitializedArray< static const InitializedArray<
lang, lang,
languageInfo, languageInfo,
(int)lang::NUMBER static_cast<int>(lang::Max)
> languages; > languages;
static lang current_language; static lang current_language;
}; };