Merge submodule contents for Editor/locale/master

This commit is contained in:
Luke Street 2021-04-06 13:58:09 -04:00
commit 3c2dd5b95a
7 changed files with 275 additions and 0 deletions

View File

@ -0,0 +1,15 @@
add_executable(genlocales genlocales.cpp)
target_link_libraries(genlocales fmt athena-core)
set(LOCALES_IN en_US.yaml en_GB.yaml ja_JP.yaml)
set(LOCALES_OUT ${CMAKE_CURRENT_BINARY_DIR}/locales-inl.hpp)
add_custom_command(OUTPUT ${LOCALES_OUT} COMMAND $<TARGET_FILE:genlocales>
ARGS ${LOCALES_OUT} ${LOCALES_IN}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS genlocales ${LOCALES_IN})
add_library(UrdeLocales ${LOCALES_OUT} locale.hpp locale.cpp)
target_link_libraries(UrdeLocales fmt)
target_include_directories(UrdeLocales PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(specter PUBLIC UrdeLocales)

3
Editor/locale/en_GB.yaml Normal file
View File

@ -0,0 +1,3 @@
name: "British English"
en_GB:
color: "Colour"

42
Editor/locale/en_US.yaml Normal file
View File

@ -0,0 +1,42 @@
name: "US English"
en_US:
color: "Color"
branch: "Branch"
commit: "Commit"
release: "Release"
date: "Date"
new_project: "New Project"
open_project: "Open Project"
extract_game: "Extract Game"
name: "Name"
type: "Type"
size: "Size"
directory: "Directory"
file: "File"
file_name: "File Name"
cancel: "Cancel"
system_locations: "System Locations"
recent_projects: "Recent Projects"
recent_files: "Recent Files"
scroll_left: "Scroll Left"
scroll_right: "Scroll Right"
ok: "OK"
cancel: "Cancel"
boundary_action: "Boundary Action"
split: "Split"
join: "Join"
hecl_project: "HECL Project"
no_access_as_dir: "Unable to access '{}' as directory"
file_field_empty: "Unable to save empty file"
overwrite_confirm: "Overwrite '{}'?"
directory_field_empty: "Unable to make empty-named directory"
no_overwrite_file: "Unable to make directory over file"
no_overwrite_project: "Unable to make project within existing project"
no_access_as_file: "Unable to access '{}' as file"
space_types: "Space Types"
resource_browser: "Resource Browser"
effect_editor: "Effect Editor"
model_viewer: "Model Viewer"
information_center: "Information Center"
game_mode: "Game Mode"
version: "Version"

View File

@ -0,0 +1,115 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <unordered_set>
#include "athena/FileReader.hpp"
#include "athena/YAMLDocReader.hpp"
#define FMT_STRING_ALIAS 1
#define FMT_ENFORCE_COMPILE_STRING 1
#include <fmt/format.h>
#include <fmt/ostream.h>
int main(int argc, char** argv) {
if (argc < 3) {
fmt::print(FMT_STRING("{} <out-header> <in-yamls>...\n"), argv[0]);
return 1;
}
std::ofstream out(argv[1]);
if (!out.is_open()) {
fmt::print(FMT_STRING("Unable to open {} for writing\n"), argv[1]);
return 1;
}
std::unordered_set<std::string> seenLocales;
std::stringstream enumLocales;
std::stringstream declLocales;
std::unordered_set<std::string> seenKeys;
std::stringstream keys;
std::stringstream lookups;
std::stringstream dos;
for (int i = 2; i < argc; ++i) {
athena::io::FileReader fr(argv[i]);
if (!fr.isOpen()) {
fmt::print(FMT_STRING("Unable to open {} for reading\n"), argv[i]);
return 1;
}
athena::io::YAMLDocReader r;
if (!r.parse(&fr)) {
fmt::print(FMT_STRING("Unable to parse {}\n"), argv[i]);
return 1;
}
std::string name;
std::string fullName;
athena::io::YAMLNode* listNode = nullptr;
for (const auto& c : r.getRootNode()->m_mapChildren) {
if (c.first == "name") {
fullName = c.second->m_scalarString;
} else {
name = c.first;
listNode = c.second.get();
}
}
if (fullName.empty()) {
fmt::print(FMT_STRING("Unable to find 'name' node in {}\n"), argv[i]);
return 1;
}
if (!listNode) {
fmt::print(FMT_STRING("Unable to find list node in {}\n"), argv[i]);
return 1;
}
if (seenLocales.find(name) == seenLocales.end()) {
seenLocales.insert(name);
fmt::print(enumLocales, FMT_STRING(" {},\n"), name);
fmt::print(declLocales,
FMT_STRING("struct {0} {{ static constexpr auto Name = \"{0}\"sv; static constexpr auto FullName = \"{1}\"sv; }};\n"),
name, fullName);
fmt::print(dos,
FMT_STRING(" case ELocale::{0}:\n"
" return act.template Do<{0}>(std::forward<Args>(args)...);\n"), name);
fmt::print(lookups, FMT_STRING("/* {} */\n"), name);
for (const auto& k : listNode->m_mapChildren) {
if (seenKeys.find(k.first) == seenKeys.end()) {
seenKeys.insert(k.first);
fmt::print(keys, FMT_STRING("struct {} {{}};\n"), k.first);
}
fmt::print(lookups,
FMT_STRING("template<> struct Lookup<{}, {}> {{ static constexpr auto Value() {{ return FMT_STRING(\"{}\"); }} }};\n"),
name, k.first, k.second->m_scalarString);
}
}
lookups << '\n';
}
out << "/* Locales */\n"
"enum class ELocale {\n"
" Invalid = -1,\n";
out << enumLocales.str();
out << " MAXLocale\n"
"};\n";
out << declLocales.str();
out << "\n"
"using DefaultLocale = en_US;\n"
"template<typename L, typename K> struct Lookup {\n"
" static_assert(!std::is_same_v<L, DefaultLocale>, \"The default locale must translate all keys\");\n"
" static constexpr auto Value() { return Lookup<DefaultLocale, K>::Value(); }\n"
"};\n"
"\n"
"/* Keys */\n";
out << keys.str();
out << "\n";
out << lookups.str();
out << "template <typename Action, typename... Args>\n"
"constexpr auto Do(ELocale l, Action act, Args&&... args) {\n"
" switch (l) {\n"
" default:\n";
out << dos.str();
out << " }\n"
"}\n";
return 0;
}

19
Editor/locale/ja_JP.yaml Normal file
View File

@ -0,0 +1,19 @@
name: "日本語"
ja_JP:
color: "色"
branch: "分派"
commit: "預ける"
date: "年月日"
new_project: "新しいプロジェクト"
open_project: "プロジェクトを開きます"
extract_game: "ビデオゲームを抽出"
name: "名"
type: "タイプ"
size: "サイズ"
directory: "ディレクトリ"
file: "ファイル"
file_name: "ファイル名"
cancel: "キャンセル"
system_locations: "システムの場所"
recent_projects: "最近使ったプロジェクト"
recent_files: "最近使用したファイル"

37
Editor/locale/locale.cpp Normal file
View File

@ -0,0 +1,37 @@
#include "locale.hpp"
#include <cstring>
#include <clocale>
#include <algorithm>
#undef min
#undef max
namespace locale {
std::vector<std::pair<std::string_view, std::string_view>> ListLocales() {
std::vector<std::pair<std::string_view, std::string_view>> ret;
ret.reserve(std::size_t(ELocale::MAXLocale));
for (ELocale l = ELocale(0); l < ELocale::MAXLocale; l = ELocale(int(l) + 1))
ret.emplace_back(GetName(l), GetFullName(l));
return ret;
}
ELocale LookupLocale(std::string_view name) {
for (ELocale l = ELocale(0); l < ELocale::MAXLocale; l = ELocale(int(l) + 1))
if (name == GetName(l))
return l;
return ELocale::Invalid;
}
ELocale SystemLocaleOrEnglish() {
const char* sysLocale = std::setlocale(LC_ALL, nullptr);
size_t sysLocaleLen = std::strlen(sysLocale);
for (ELocale l = ELocale(0); l < ELocale::MAXLocale; l = ELocale(int(l) + 1)) {
auto name = GetName(l);
if (!name.compare(0, std::min(name.size(), sysLocaleLen), sysLocale))
return l;
}
return ELocale::en_US;
}
} // namespace locale

44
Editor/locale/locale.hpp Normal file
View File

@ -0,0 +1,44 @@
#pragma once
#include <type_traits>
#include <string_view>
#include <vector>
#define FMT_STRING_ALIAS 1
#define FMT_ENFORCE_COMPILE_STRING 1
#include <fmt/format.h>
namespace locale {
using namespace std::literals;
#include <locales-inl.hpp>
struct DoGetName {
template <typename L>
constexpr auto Do() { return L::Name; }
};
constexpr auto GetName(ELocale l) {
return Do(l, DoGetName());
}
struct DoGetFullName {
template <typename L>
constexpr auto Do() { return L::FullName; }
};
constexpr auto GetFullName(ELocale l) {
return Do(l, DoGetFullName());
}
template <typename Key>
struct DoTranslate {
template <typename L, typename... Args>
constexpr auto Do(Args&&... args) { return fmt::format(Lookup<L, Key>::Value(), std::forward<Args>(args)...); }
};
template <typename Key, typename... Args>
constexpr auto Translate(ELocale l, Args&&... args) {
return Do(l, DoTranslate<Key>(), std::forward<Args>(args)...);
}
std::vector<std::pair<std::string_view, std::string_view>> ListLocales();
ELocale LookupLocale(std::string_view name);
ELocale SystemLocaleOrEnglish();
} // namespace locale