Add i18n debug stuff
This commit is contained in:
parent
bf05a14ef5
commit
131accb5ac
@ -70,6 +70,7 @@ AddSconsOption('opengl', False, False, "Build with OpenGL interface support.")
|
|||||||
AddSconsOption('opengl-renderer', False, False, "Build with OpenGL renderer support (turns on --opengl).") #Note: this has nothing to do with --renderer, only tells the game to render particles with opengl
|
AddSconsOption('opengl-renderer', False, False, "Build with OpenGL renderer support (turns on --opengl).") #Note: this has nothing to do with --renderer, only tells the game to render particles with opengl
|
||||||
AddSconsOption('renderer', False, False, "Build the save renderer.")
|
AddSconsOption('renderer', False, False, "Build the save renderer.")
|
||||||
AddSconsOption('font', False, False, "Build the font editor.")
|
AddSconsOption('font', False, False, "Build the font editor.")
|
||||||
|
AddSconsOption('i18n-debug', False, False, "Instrument the binary for debugging internationalization")
|
||||||
|
|
||||||
AddSconsOption('wall', False, False, "Error on all warnings.")
|
AddSconsOption('wall', False, False, "Error on all warnings.")
|
||||||
AddSconsOption('no-warnings', False, False, "Disable all compiler warnings.")
|
AddSconsOption('no-warnings', False, False, "Disable all compiler warnings.")
|
||||||
@ -404,7 +405,8 @@ elif not GetOption('help'):
|
|||||||
env = conf.Finish()
|
env = conf.Finish()
|
||||||
|
|
||||||
if not msvc:
|
if not msvc:
|
||||||
env.Append(CXXFLAGS=['-std=c++11', '-U__STRICT_ANSI__'])
|
env.Append(CXXFLAGS=['-std=c++11' if not GetOption('i18n-debug') else '-std=c++14'])
|
||||||
|
env.Append(CXXFLAGS=['-U__STRICT_ANSI__'])
|
||||||
env.Append(CXXFLAGS=['-Wno-invalid-offsetof'])
|
env.Append(CXXFLAGS=['-Wno-invalid-offsetof'])
|
||||||
if platform == "Linux":
|
if platform == "Linux":
|
||||||
env.Append(CXXFLAGS=['-Wno-unused-result'])
|
env.Append(CXXFLAGS=['-Wno-unused-result'])
|
||||||
@ -519,6 +521,9 @@ if GetOption('renderer'):
|
|||||||
if GetOption('font'):
|
if GetOption('font'):
|
||||||
env.Append(CPPDEFINES=['FONTEDITOR'])
|
env.Append(CPPDEFINES=['FONTEDITOR'])
|
||||||
|
|
||||||
|
if GetOption('i18n-debug'):
|
||||||
|
env.Append(CPPDEFINES=['I18N_DEBUG'])
|
||||||
|
|
||||||
if GetOption("wall"):
|
if GetOption("wall"):
|
||||||
if msvc:
|
if msvc:
|
||||||
env.Append(CCFLAGS=['/WX'])
|
env.Append(CCFLAGS=['/WX'])
|
||||||
|
@ -673,6 +673,16 @@ int main(int argc, char * argv[])
|
|||||||
else
|
else
|
||||||
ChdirToDataDirectory();
|
ChdirToDataDirectory();
|
||||||
|
|
||||||
|
#ifdef I18N_DEBUG
|
||||||
|
for(auto const &key : i18n::activeKeys())
|
||||||
|
{
|
||||||
|
std::cout << "{";
|
||||||
|
for(auto const &s : key)
|
||||||
|
std::cout << "\"" << s << "\",";
|
||||||
|
std::cout << "}" << std::endl;
|
||||||
|
}
|
||||||
|
#endif // I18N_DEBUG
|
||||||
|
|
||||||
String localeName = Client::Ref().GetPrefString("Locale", "");
|
String localeName = Client::Ref().GetPrefString("Locale", "");
|
||||||
for(Locale *locale : locales)
|
for(Locale *locale : locales)
|
||||||
if(locale->GetName() == localeName)
|
if(locale->GetName() == localeName)
|
||||||
|
@ -28,4 +28,15 @@ namespace i18n
|
|||||||
else
|
else
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef I18N_DEBUG
|
||||||
|
|
||||||
|
std::set<std::vector<ByteString> > &activeKeys()
|
||||||
|
{
|
||||||
|
static std::set<std::vector<ByteString> > activeKeys;
|
||||||
|
return activeKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // I18N_DEBUG
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "String.h"
|
#include "String.h"
|
||||||
|
|
||||||
@ -31,7 +33,7 @@
|
|||||||
Sometimes several pieces of strings are assembled into a larger string,
|
Sometimes several pieces of strings are assembled into a larger string,
|
||||||
possibly with data inbetween, e.g.:
|
possibly with data inbetween, e.g.:
|
||||||
String::Build("Page ", page, " of ", total)
|
String::Build("Page ", page, " of ", total)
|
||||||
In the C world we could've gotten away with using a key with placeholders
|
In the C world we could've gotten away with using a key with placeholders
|
||||||
such as "Page %d of %d" and then the translation would include the format
|
such as "Page %d of %d" and then the translation would include the format
|
||||||
specifiers as well and it would all work out. Note that it is a bad idea to
|
specifiers as well and it would all work out. Note that it is a bad idea to
|
||||||
introduce "Page" and "of" as separate keys as they don't make much sense on
|
introduce "Page" and "of" as separate keys as they don't make much sense on
|
||||||
@ -62,6 +64,29 @@ namespace i18n
|
|||||||
|
|
||||||
CanonicalPtr Canonicalize(LiteralPtr str);
|
CanonicalPtr Canonicalize(LiteralPtr str);
|
||||||
|
|
||||||
|
#ifdef I18N_DEBUG
|
||||||
|
std::set<std::vector<ByteString> > &activeKeys();
|
||||||
|
|
||||||
|
template<char... cs> struct Chars
|
||||||
|
{
|
||||||
|
static char const chars[];
|
||||||
|
};
|
||||||
|
template<char... cs> char const Chars<cs...>::chars[] = {cs..., 0};
|
||||||
|
|
||||||
|
template<char... cs> struct KeyUsage
|
||||||
|
{
|
||||||
|
KeyUsage() { activeKeys().insert({ByteString({cs..., 0})}); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Ts> struct MultiKeyUsage
|
||||||
|
{
|
||||||
|
MultiKeyUsage() { activeKeys().insert({Ts::chars...}); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<char... cs> KeyUsage<cs...> keyUsage;
|
||||||
|
template<typename... Ts> MultiKeyUsage<Ts...> multiKeyUsage;
|
||||||
|
#endif
|
||||||
|
|
||||||
template<size_t n> struct TranslationMap
|
template<size_t n> struct TranslationMap
|
||||||
{
|
{
|
||||||
// This is not just a static field so that it is possible to use it
|
// This is not just a static field so that it is possible to use it
|
||||||
@ -77,7 +102,7 @@ namespace i18n
|
|||||||
{
|
{
|
||||||
return TranslationMap<1>::Map()[{Canonicalize(str)}][0];
|
return TranslationMap<1>::Map()[{Canonicalize(str)}][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t n> inline std::array<String, n> &multiTranslation(std::array<CanonicalPtr, n> &cans, size_t)
|
template<size_t n> inline std::array<String, n> &multiTranslation(std::array<CanonicalPtr, n> &cans, size_t)
|
||||||
{
|
{
|
||||||
return TranslationMap<n>::Map()[cans];
|
return TranslationMap<n>::Map()[cans];
|
||||||
@ -121,6 +146,8 @@ namespace i18n
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef I18N_DEBUG
|
||||||
|
|
||||||
inline String operator""_i18n(char const *str, size_t)
|
inline String operator""_i18n(char const *str, size_t)
|
||||||
{
|
{
|
||||||
return i18n::getTranslation<1>({str})[0];
|
return i18n::getTranslation<1>({str})[0];
|
||||||
@ -131,3 +158,42 @@ template<typename... Ts> std::array<String, sizeof...(Ts)> i18nMulti(Ts&&... arg
|
|||||||
std::array<i18n::LiteralPtr, sizeof...(Ts)> strs;
|
std::array<i18n::LiteralPtr, sizeof...(Ts)> strs;
|
||||||
return i18n::getMultiTranslation(strs, 0, std::forward<Ts>(args)...);
|
return i18n::getMultiTranslation(strs, 0, std::forward<Ts>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else // I18N_DEBUG
|
||||||
|
|
||||||
|
template<typename T, T... cs> inline i18n::Chars<cs...> operator""_chars()
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, T... cs> inline String operator""_i18n()
|
||||||
|
{
|
||||||
|
(void)i18n::keyUsage<cs...>;
|
||||||
|
return i18n::getTranslation<1>({i18n::Chars<cs...>::chars})[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Macros are hard
|
||||||
|
// Expand i18nMulti("a", "b") into i18nMultiImpl<decltype("a"_chars), decltype("b"_chars)>()
|
||||||
|
#define NARG_SELECT(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N
|
||||||
|
#define NARG(...) NARG_SELECT(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1)
|
||||||
|
#define i18nMultiNargH(N, ...) i18nMultiNarg(N, __VA_ARGS__)
|
||||||
|
#define i18nMultiNarg(N, ...) i18nMulti_##N(__VA_ARGS__)
|
||||||
|
#define i18nMulti(...) i18nMultiNargH(NARG(__VA_ARGS__), __VA_ARGS__)
|
||||||
|
#define i18nMulti_1(s1) i18nMultiImpl<decltype(s1##_chars)>()
|
||||||
|
#define i18nMulti_2(s1, s2) i18nMultiImpl<decltype(s1##_chars), decltype(s2##_chars)>()
|
||||||
|
#define i18nMulti_3(s1, s2, s3) i18nMultiImpl<decltype(s1##_chars), decltype(s2##_chars), decltype(s3##_chars)>()
|
||||||
|
#define i18nMulti_4(s1, s2, s3, s4) i18nMultiImpl<decltype(s1##_chars), decltype(s2##_chars), decltype(s3##_chars), decltype(s4##_chars)>()
|
||||||
|
#define i18nMulti_5(s1, s2, s3, s4, s5) i18nMultiImpl<decltype(s1##_chars), decltype(s2##_chars), decltype(s3##_chars), decltype(s4##_chars), decltype(s5##_chars)>()
|
||||||
|
#define i18nMulti_6(s1, s2, s3, s4, s5, s6) i18nMultiImpl<decltype(s1##_chars), decltype(s2##_chars), decltype(s3##_chars), decltype(s4##_chars), decltype(s5##_chars), decltype(s6##_chars)>()
|
||||||
|
#define i18nMulti_7(s1, s2, s3, s4, s5, s6, s7) i18nMultiImpl<decltype(s1##_chars), decltype(s2##_chars), decltype(s3##_chars), decltype(s4##_chars), decltype(s5##_chars), decltype(s6##_chars), decltype(s7##_chars)>()
|
||||||
|
#define i18nMulti_8(s1, s2, s3, s4, s5, s6, s7, s8) i18nMultiImpl<decltype(s1##_chars), decltype(s2##_chars), decltype(s3##_chars), decltype(s4##_chars), decltype(s5##_chars), decltype(s6##_chars), decltype(s7##_chars), decltype(s8##_chars)>()
|
||||||
|
#define i18nMulti_9(s1, s2, s3, s4, s5, s6, s7, s8, s9) i18nMultiImpl<decltype(s1##_chars), decltype(s2##_chars), decltype(s3##_chars), decltype(s4##_chars), decltype(s5##_chars), decltype(s6##_chars), decltype(s7##_chars), decltype(s8##_chars), decltype(s9##_chars)>()
|
||||||
|
|
||||||
|
template<typename... Ts> std::array<String, sizeof...(Ts)> i18nMultiImpl()
|
||||||
|
{
|
||||||
|
(void)i18n::multiKeyUsage<Ts...>;
|
||||||
|
std::array<i18n::LiteralPtr, sizeof...(Ts)> strs;
|
||||||
|
return i18n::getMultiTranslation(strs, 0, Ts::chars...);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // I18N_DEBUG
|
||||||
|
Reference in New Issue
Block a user