Browse Source

Moved common language data into a new file

Ivan Savenko 2 years ago
parent
commit
320a44ca3c
4 changed files with 117 additions and 29 deletions
  1. 1 0
      cmake_modules/VCMI_lib.cmake
  2. 27 21
      lib/CGeneralTextHandler.cpp
  3. 8 8
      lib/CModHandler.cpp
  4. 81 0
      lib/Languages.h

+ 1 - 0
cmake_modules/VCMI_lib.cmake

@@ -434,6 +434,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
 		${MAIN_LIB_DIR}/Interprocess.h
 		${MAIN_LIB_DIR}/JsonDetail.h
 		${MAIN_LIB_DIR}/JsonNode.h
+		${MAIN_LIB_DIR}/Languages.h
 		${MAIN_LIB_DIR}/LoadProgress.h
 		${MAIN_LIB_DIR}/LogicalExpression.h
 		${MAIN_LIB_DIR}/NetPacksBase.h

+ 27 - 21
lib/CGeneralTextHandler.cpp

@@ -18,6 +18,7 @@
 #include "GameConstants.h"
 #include "mapObjects/CQuest.h"
 #include "VCMI_Lib.h"
+#include "Languages.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -106,22 +107,27 @@ bool Unicode::isValidString(const char * data, size_t size)
 /// Detects language and encoding of H3 text files based on matching against pregenerated footprints of H3 file
 void CGeneralTextHandler::detectInstallParameters()
 {
-	struct LanguageFootprint
-	{
-		std::string language;
-		std::string encoding;
-		std::array<double, 16> footprint;
-	};
-
-	static const std::vector<LanguageFootprint> knownFootprints =
-	{
-		{ "english",   "CP1252", { { 0.0559, 0.0000, 0.1983, 0.0051, 0.0222, 0.0183, 0.4596, 0.2405, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000 } } },
-		{ "french",    "CP1252", { { 0.0493, 0.0000, 0.1926, 0.0047, 0.0230, 0.0121, 0.4133, 0.2780, 0.0002, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0259, 0.0008 } } },
-		{ "german",    "CP1252", { { 0.0534, 0.0000, 0.1705, 0.0047, 0.0418, 0.0208, 0.4775, 0.2191, 0.0001, 0.0000, 0.0000, 0.0000, 0.0000, 0.0005, 0.0036, 0.0080 } } },
-		{ "polish",    "CP1250", { { 0.0534, 0.0000, 0.1701, 0.0067, 0.0157, 0.0133, 0.4328, 0.2540, 0.0001, 0.0043, 0.0000, 0.0244, 0.0000, 0.0000, 0.0181, 0.0071 } } },
-		{ "russian",   "CP1251", { { 0.0548, 0.0000, 0.1744, 0.0061, 0.0031, 0.0009, 0.0046, 0.0136, 0.0000, 0.0004, 0.0000, 0.0000, 0.0227, 0.0061, 0.4882, 0.2252 } } },
-		{ "ukrainian", "CP1251", { { 0.0559, 0.0000, 0.1807, 0.0059, 0.0036, 0.0013, 0.0046, 0.0134, 0.0000, 0.0004, 0.0000, 0.0487, 0.0209, 0.0060, 0.4615, 0.1972 } } },
-	};
+	using LanguageFootprint = std::array<double, 16>;
+
+	static const std::array<LanguageFootprint, 6> knownFootprints =
+	{ {
+		{ { 0.0559, 0.0000, 0.1983, 0.0051, 0.0222, 0.0183, 0.4596, 0.2405, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000 } },
+		{ { 0.0493, 0.0000, 0.1926, 0.0047, 0.0230, 0.0121, 0.4133, 0.2780, 0.0002, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0259, 0.0008 } },
+		{ { 0.0534, 0.0000, 0.1705, 0.0047, 0.0418, 0.0208, 0.4775, 0.2191, 0.0001, 0.0000, 0.0000, 0.0000, 0.0000, 0.0005, 0.0036, 0.0080 } },
+		{ { 0.0534, 0.0000, 0.1701, 0.0067, 0.0157, 0.0133, 0.4328, 0.2540, 0.0001, 0.0043, 0.0000, 0.0244, 0.0000, 0.0000, 0.0181, 0.0071 } },
+		{ { 0.0548, 0.0000, 0.1744, 0.0061, 0.0031, 0.0009, 0.0046, 0.0136, 0.0000, 0.0004, 0.0000, 0.0000, 0.0227, 0.0061, 0.4882, 0.2252 } },
+		{ { 0.0559, 0.0000, 0.1807, 0.0059, 0.0036, 0.0013, 0.0046, 0.0134, 0.0000, 0.0004, 0.0000, 0.0487, 0.0209, 0.0060, 0.4615, 0.1972 } },
+	} };
+
+	static const std::array<std::string, 6> knownLanguages =
+	{ {
+		"english",
+		"french",
+		"german",
+		"polish",
+		"russian",
+		"ukrainian"
+	} };
 
 	// load file that will be used for footprint generation
 	// this is one of the most text-heavy files in game and consists solely from translated texts
@@ -129,7 +135,7 @@ void CGeneralTextHandler::detectInstallParameters()
 
 	std::array<size_t, 256> charCount{};
 	std::array<double, 16> footprint{};
-	std::vector<double> deviations(knownFootprints.size(), 0.0);
+	std::array<double, 6> deviations{};
 
 	auto data = resource->readAll();
 
@@ -152,19 +158,19 @@ void CGeneralTextHandler::detectInstallParameters()
 	for (size_t i = 0; i < deviations.size(); ++i)
 	{
 		for (size_t j = 0; j < footprint.size(); ++j)
-			deviations[i] += std::abs((footprint[j] - knownFootprints[i].footprint[j]));
+			deviations[i] += std::abs((footprint[j] - knownFootprints[i][j]));
 	}
 
 	size_t bestIndex = boost::range::min_element(deviations) - deviations.begin();
 
 	for (size_t i = 0; i < deviations.size(); ++i)
-		logGlobal->debug("Comparing to %s: %f", knownFootprints[i].language, deviations[i]);
+		logGlobal->debug("Comparing to %s: %f", knownLanguages[i], deviations[i]);
 
 	Settings language = settings.write["session"]["language"];
-	language->String() = knownFootprints[bestIndex].language;
+	language->String() = knownLanguages[bestIndex];
 
 	Settings encoding = settings.write["session"]["encoding"];
-	encoding->String() = knownFootprints[bestIndex].encoding;
+	encoding->String() =  Languages::getLanguageOptions(knownLanguages[bestIndex]).encoding;
 }
 
 std::string Unicode::toUnicode(const std::string &text)

+ 8 - 8
lib/CModHandler.cpp

@@ -25,6 +25,7 @@
 #include "spells/CSpellHandler.h"
 #include "CSkillHandler.h"
 #include "CGeneralTextHandler.h"
+#include "Languages.h"
 #include "ScriptHandler.h"
 #include "RoadHandler.h"
 #include "RiverHandler.h"
@@ -1129,18 +1130,17 @@ bool CModHandler::validateTranslations(TModID modName) const
 		result |= VLC->generaltexth->validateTranslation(mod.baseLanguage, modName, json);
 	}
 
-	// TODO: unify language lists in mod handler, general text handler, launcher and json validation
-	static const std::vector<std::string> languagesList =
-	{ "english", "german", "polish", "russian", "ukrainian" };
-
-	for (auto const & language : languagesList)
+	for (auto const & language : Languages::getLanguageList())
 	{
-		if (mod.config[language].isNull())
+		if (!language.hasTranslation)
+			continue;
+
+		if (mod.config[language.identifier].isNull())
 			continue;
 
-		auto fileList = mod.config[language]["translations"].convertTo<std::vector<std::string> >();
+		auto fileList = mod.config[language.identifier]["translations"].convertTo<std::vector<std::string> >();
 		JsonNode json = JsonUtils::assembleFromFiles(fileList);
-		result |= VLC->generaltexth->validateTranslation(language, modName, json);
+		result |= VLC->generaltexth->validateTranslation(language.identifier, modName, json);
 	}
 
 	return result;

+ 81 - 0
lib/Languages.h

@@ -0,0 +1,81 @@
+/*
+ * 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 ELanguages
+{
+	ENGLISH,
+	FRENCH,
+	GERMAN,
+	POLISH,
+	RUSSIAN,
+	UKRAINIAN,
+
+	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;
+
+	/// VCMI is capable of detecting H3 install in this language
+	bool hasDetection = false;
+
+	/// VCMI supports translations into this language
+	bool hasTranslation = false;
+};
+
+inline auto const & getLanguageList( )
+{
+	static const std::array<Options, 6> languages
+	{ {
+		{ "english",   "English",   "English",    "CP1252", true,  true },
+		{ "french",    "French",    "Français",   "CP1252", true, false },
+		{ "german",    "German",    "Deutsch",    "CP1252", true,  true },
+		{ "polish",    "Polish",    "Polski",     "CP1250", true,  true },
+		{ "russian",   "Russian",   "Русский",    "CP1251", true,  true },
+		{ "ukrainian", "Ukrainian", "Українська", "CP1251", true,  true }
+	} };
+	static_assert (languages.size() == static_cast<size_t>(ELanguages::COUNT), "Languages array is missing a value!" );
+
+	return languages;
+}
+
+inline const Options & getLanguageOptions( ELanguages language )
+{
+	assert(language < ELanguages::COUNT);
+	return getLanguageList()[static_cast<size_t>(language)];
+}
+
+inline const Options & getLanguageOptions( std::string language )
+{
+	for (auto const & entry : getLanguageList())
+		if (entry.identifier == language)
+			return entry;
+
+	static const Options emptyValue;
+	assert(0);
+	return emptyValue;
+}
+
+}