1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
/*
* Languages.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
namespace Languages
{
enum class EPluralForms
{
NONE,
VI_1, // Single plural form, (Vietnamese)
EN_2, // Two forms, singular used for one only (English)
FR_2, // Two forms, singular used for zero and one (French)
UK_3, // Three forms, special cases for numbers ending in 1 and 2, 3, 4, except those ending in 1[1-4] (Ukrainian)
CZ_3, // Three forms, special cases for 1 and 2, 3, 4 (Czech)
PL_3, // Three forms, special case for one and some numbers ending in 2, 3, or 4 (Polish)
};
enum class ELanguages
{
CZECH,
CHINESE,
ENGLISH,
FINNISH,
FRENCH,
GERMAN,
HUNGARIAN,
ITALIAN,
KOREAN,
POLISH,
PORTUGUESE,
RUSSIAN,
SPANISH,
SWEDISH,
TURKISH,
UKRAINIAN,
VIETNAMESE,
COUNT
};
struct Options
{
/// string identifier (ascii, lower-case), e.g. "english"
std::string identifier;
/// human-readable name of language in English
std::string nameEnglish;
/// human-readable name of language in its own language
std::string nameNative;
/// encoding that is used by H3 for this language
std::string encoding;
/// primary IETF language tag
std::string tagIETF;
/// ISO 639-2 (B) language code
std::string tagISO2;
/// DateTime format
std::string dateTimeFormat;
/// Ruleset for plural forms in this language
EPluralForms pluralForms = EPluralForms::NONE;
};
inline const auto & getLanguageList()
{
static const std::array<Options, 17> languages
{ {
{ "czech", "Czech", "Čeština", "CP1250", "cs", "cze", "%d.%m.%Y %H:%M", EPluralForms::CZ_3 },
{ "chinese", "Chinese", "简体中文", "GBK", "zh", "chi", "%Y-%m-%d %H:%M", EPluralForms::VI_1 }, // Note: actually Simplified Chinese
{ "english", "English", "English", "CP1252", "en", "eng", "%Y-%m-%d %H:%M", EPluralForms::EN_2 }, // English uses international date/time format here
{ "finnish", "Finnish", "Suomi", "CP1252", "fi", "fin", "%d.%m.%Y %H:%M", EPluralForms::EN_2, },
{ "french", "French", "Français", "CP1252", "fr", "fre", "%d/%m/%Y %H:%M", EPluralForms::FR_2, },
{ "german", "German", "Deutsch", "CP1252", "de", "ger", "%d.%m.%Y %H:%M", EPluralForms::EN_2, },
{ "hungarian", "Hungarian", "Magyar", "CP1250", "hu", "hun", "%Y. %m. %d. %H:%M", EPluralForms::EN_2 },
{ "italian", "Italian", "Italiano", "CP1250", "it", "ita", "%d/%m/%Y %H:%M", EPluralForms::EN_2 },
{ "korean", "Korean", "한국어", "CP949", "ko", "kor", "%Y-%m-%d %H:%M", EPluralForms::VI_1 },
{ "polish", "Polish", "Polski", "CP1250", "pl", "pol", "%d.%m.%Y %H:%M", EPluralForms::PL_3 },
{ "portuguese", "Portuguese", "Português", "CP1252", "pt", "por", "%d/%m/%Y %H:%M", EPluralForms::EN_2 }, // Note: actually Brazilian Portuguese
{ "russian", "Russian", "Русский", "CP1251", "ru", "rus", "%d.%m.%Y %H:%M", EPluralForms::UK_3 },
{ "spanish", "Spanish", "Español", "CP1252", "es", "spa", "%d/%m/%Y %H:%M", EPluralForms::EN_2 },
{ "swedish", "Swedish", "Svenska", "CP1252", "sv", "swe", "%Y-%m-%d %H:%M", EPluralForms::EN_2 },
{ "turkish", "Turkish", "Türkçe", "CP1254", "tr", "tur", "%d.%m.%Y %H:%M", EPluralForms::EN_2 },
{ "ukrainian", "Ukrainian", "Українська", "CP1251", "uk", "ukr", "%d.%m.%Y %H:%M", EPluralForms::UK_3 },
{ "vietnamese", "Vietnamese", "Tiếng Việt", "UTF-8", "vi", "vie", "%d/%m/%Y %H:%M", EPluralForms::VI_1 }, // Fan translation uses special encoding
} };
static_assert(languages.size() == static_cast<size_t>(ELanguages::COUNT), "Languages array is missing a value!");
return languages;
}
inline const Options & getLanguageOptions(ELanguages language)
{
return getLanguageList().at(static_cast<size_t>(language));
}
inline const Options & getLanguageOptions(const std::string & language)
{
for(const auto & entry : getLanguageList())
if(entry.identifier == language)
return entry;
throw std::out_of_range("Language " + language + " does not exists!");
}
template<typename Numeric>
inline constexpr int getPluralFormIndex(EPluralForms form, Numeric value)
{
// Based on https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html
switch(form)
{
case EPluralForms::NONE:
case EPluralForms::VI_1:
return 0;
case EPluralForms::EN_2:
if (value == 1)
return 1;
return 2;
case EPluralForms::FR_2:
if (value == 1 || value == 0)
return 1;
return 2;
case EPluralForms::UK_3:
if (value % 10 == 1 && value % 100 != 11)
return 1;
if (value%10>=2 && value%10<=4 && (value%100<10 || value%100>=20))
return 2;
return 0;
case EPluralForms::CZ_3:
if (value == 1)
return 1;
if (value>=2 && value<=4)
return 2;
return 0;
case EPluralForms::PL_3:
if (value == 1)
return 1;
if (value%10>=2 && value%10<=4 && (value%100<10 || value%100>=20))
return 2;
return 0;
}
throw std::runtime_error("Invalid plural form enumeration received!");
}
template<typename Numeric>
inline std::string getPluralFormTextID(std::string languageName, Numeric value, std::string textID)
{
int formIndex = getPluralFormIndex(getLanguageOptions(languageName).pluralForms, value);
return textID + '.' + std::to_string(formIndex);
}
}
|