mirror of
https://github.com/ModOrganizer2/mob.git
synced 2026-07-27 14:07:05 -07:00
Compare commits
5
Commits
master
...
dev/extensions
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f97e0f1c7 | ||
|
|
b6d75fd1a3 | ||
|
|
c9882c7d99 | ||
|
|
41bb2a3032 | ||
|
|
0d6a130ef8 |
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
@@ -18,9 +18,13 @@ install_message = never
|
|||||||
host =
|
host =
|
||||||
|
|
||||||
[aliases]
|
[aliases]
|
||||||
super = cmake_common modorganizer* githubpp
|
super = cmake_common modorganizer*
|
||||||
plugins = check_fnis bsapacker bsa_extractor diagnose_basic installer_* plugin_python preview_base preview_bsa tool_* game_*
|
plugins = check_fnis bsapacker bsa_extractor diagnose_basic installer_* plugin_python preview_base preview_bsa tool_* game_*
|
||||||
|
|
||||||
|
[translations]
|
||||||
|
mo2-translations = organizer uibase plugin_python
|
||||||
|
mo2-game-bethesda = game_creation game_enderal game_enderalse game_fallout3 game_fallout4 game_fallout4vr game_falloutNV game_gamebryo game_morrowind game_nehrim game_oblivion game_skyrim game_skyrimse game_skyrimvr game_ttw
|
||||||
|
|
||||||
[task]
|
[task]
|
||||||
enabled = true
|
enabled = true
|
||||||
mo_org = ModOrganizer2
|
mo_org = ModOrganizer2
|
||||||
@@ -109,6 +113,7 @@ ss_fallout4_trosski = v1.11
|
|||||||
third_party =
|
third_party =
|
||||||
prefix =
|
prefix =
|
||||||
cache =
|
cache =
|
||||||
|
icons =
|
||||||
licenses =
|
licenses =
|
||||||
build =
|
build =
|
||||||
install =
|
install =
|
||||||
@@ -118,6 +123,7 @@ install_libs =
|
|||||||
install_pdbs =
|
install_pdbs =
|
||||||
install_dlls =
|
install_dlls =
|
||||||
install_plugins =
|
install_plugins =
|
||||||
|
install_extensions =
|
||||||
install_stylesheets =
|
install_stylesheets =
|
||||||
install_licenses =
|
install_licenses =
|
||||||
install_translations =
|
install_translations =
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ file(GLOB_RECURSE source_files *.cpp)
|
|||||||
file(GLOB_RECURSE header_files *.h)
|
file(GLOB_RECURSE header_files *.h)
|
||||||
|
|
||||||
add_executable(mob ${source_files} ${header_files})
|
add_executable(mob ${source_files} ${header_files})
|
||||||
set_target_properties(mob PROPERTIES CXX_STANDARD 20)
|
set_target_properties(mob PROPERTIES CXX_STANDARD 23)
|
||||||
|
|
||||||
target_compile_definitions(mob PUBLIC NOMINMAX)
|
target_compile_definitions(mob PUBLIC NOMINMAX)
|
||||||
target_compile_options(mob PUBLIC "/MT")
|
target_compile_options(mob PUBLIC "/MT")
|
||||||
|
|||||||
+28
-13
@@ -51,24 +51,32 @@ namespace mob::details {
|
|||||||
|
|
||||||
// returns a string from conf, bails out if it doesn't exist
|
// returns a string from conf, bails out if it doesn't exist
|
||||||
//
|
//
|
||||||
std::string get_string(std::string_view section, std::string_view key)
|
std::string get_string(std::string_view section, std::string_view key,
|
||||||
|
std::optional<std::string> default_)
|
||||||
{
|
{
|
||||||
auto sitor = g_conf.find(section);
|
auto sitor = g_conf.find(section);
|
||||||
if (sitor == g_conf.end())
|
if (sitor == g_conf.end())
|
||||||
gcx().bail_out(context::conf, "[{}] doesn't exist", section);
|
gcx().bail_out(context::conf, "[{}] doesn't exist", section);
|
||||||
|
|
||||||
auto kitor = sitor->second.find(key);
|
auto kitor = sitor->second.find(key);
|
||||||
if (kitor == sitor->second.end())
|
if (kitor == sitor->second.end()) {
|
||||||
gcx().bail_out(context::conf, "no key '{}' in [{}]", key, section);
|
if (!default_.has_value()) {
|
||||||
|
gcx().bail_out(context::conf, "no key '{}' in [{}]", key, section);
|
||||||
|
}
|
||||||
|
return *default_;
|
||||||
|
}
|
||||||
|
|
||||||
return kitor->second;
|
return kitor->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
// calls get_string(), converts to int
|
// calls get_string(), converts to int
|
||||||
//
|
//
|
||||||
int get_int(std::string_view section, std::string_view key)
|
int get_int(std::string_view section, std::string_view key,
|
||||||
|
std::optional<int> default_)
|
||||||
{
|
{
|
||||||
const auto s = get_string(section, key);
|
const auto s = get_string(section, key, default_.transform([](auto v) {
|
||||||
|
return std::to_string(v);
|
||||||
|
}));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return std::stoi(s);
|
return std::stoi(s);
|
||||||
@@ -80,9 +88,12 @@ namespace mob::details {
|
|||||||
|
|
||||||
// calls get_string(), converts to bool
|
// calls get_string(), converts to bool
|
||||||
//
|
//
|
||||||
bool get_bool(std::string_view section, std::string_view key)
|
bool get_bool(std::string_view section, std::string_view key,
|
||||||
|
std::optional<bool> default_)
|
||||||
{
|
{
|
||||||
const auto s = get_string(section, key);
|
const auto s = get_string(section, key, default_.transform([](auto v) {
|
||||||
|
return v ? "true" : "false";
|
||||||
|
}));
|
||||||
return bool_from_string(s);
|
return bool_from_string(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,13 +439,8 @@ namespace mob {
|
|||||||
|
|
||||||
MOB_ASSERT(!tasks.empty());
|
MOB_ASSERT(!tasks.empty());
|
||||||
|
|
||||||
for (auto& t : tasks) {
|
for (auto& t : tasks)
|
||||||
if (t->name() != task &&
|
|
||||||
details::find_string_for_task(t->name(), key)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
details::set_string_for_task(t->name(), key, value);
|
details::set_string_for_task(t->name(), key, value);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// global task option
|
// global task option
|
||||||
@@ -512,6 +518,7 @@ namespace mob {
|
|||||||
set_path_if_empty("vcpkg", find_vcpkg); // set after vs as it will use the VS
|
set_path_if_empty("vcpkg", find_vcpkg); // set after vs as it will use the VS
|
||||||
set_path_if_empty("qt_install", find_qt);
|
set_path_if_empty("qt_install", find_qt);
|
||||||
set_path_if_empty("temp_dir", find_temp_dir);
|
set_path_if_empty("temp_dir", find_temp_dir);
|
||||||
|
set_path_if_empty("icons", find_in_root("icons"));
|
||||||
set_path_if_empty("licenses", find_in_root("licenses"));
|
set_path_if_empty("licenses", find_in_root("licenses"));
|
||||||
set_path_if_empty("qt_bin", qt::installation_path() / "bin");
|
set_path_if_empty("qt_bin", qt::installation_path() / "bin");
|
||||||
set_path_if_empty("qt_translations", qt::installation_path() / "translations");
|
set_path_if_empty("qt_translations", qt::installation_path() / "translations");
|
||||||
@@ -537,6 +544,7 @@ namespace mob {
|
|||||||
resolve_path("install_licenses", p.install_bin(), "licenses");
|
resolve_path("install_licenses", p.install_bin(), "licenses");
|
||||||
resolve_path("install_stylesheets", p.install_bin(), "stylesheets");
|
resolve_path("install_stylesheets", p.install_bin(), "stylesheets");
|
||||||
resolve_path("install_translations", p.install_bin(), "translations");
|
resolve_path("install_translations", p.install_bin(), "translations");
|
||||||
|
resolve_path("install_extensions", p.install_bin(), "extensions");
|
||||||
|
|
||||||
// finally, resolve the tools that are unlikely to be in PATH; all the
|
// finally, resolve the tools that are unlikely to be in PATH; all the
|
||||||
// other tools (7z, jom, patch, etc.) are assumed to be in PATH (which
|
// other tools (7z, jom, patch, etc.) are assumed to be in PATH (which
|
||||||
@@ -682,6 +690,11 @@ namespace mob {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conf_translations conf::translation()
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
conf_versions conf::version()
|
conf_versions conf::version()
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
@@ -770,6 +783,8 @@ namespace mob {
|
|||||||
|
|
||||||
conf_build_types::conf_build_types() : conf_section("build-types") {}
|
conf_build_types::conf_build_types() : conf_section("build-types") {}
|
||||||
|
|
||||||
|
conf_translations::conf_translations() : conf_section("translations") {}
|
||||||
|
|
||||||
conf_prebuilt::conf_prebuilt() : conf_section("prebuilt") {}
|
conf_prebuilt::conf_prebuilt() : conf_section("prebuilt") {}
|
||||||
|
|
||||||
conf_paths::conf_paths() : conf_section("paths") {}
|
conf_paths::conf_paths() : conf_section("paths") {}
|
||||||
|
|||||||
+31
-11
@@ -9,7 +9,8 @@ namespace mob::details {
|
|||||||
|
|
||||||
// returns an option named `key` from the given `section`
|
// returns an option named `key` from the given `section`
|
||||||
//
|
//
|
||||||
std::string get_string(std::string_view section, std::string_view key);
|
std::string get_string(std::string_view section, std::string_view key,
|
||||||
|
std::optional<std::string> default_ = {});
|
||||||
|
|
||||||
// convert a string to the given type
|
// convert a string to the given type
|
||||||
template <class T>
|
template <class T>
|
||||||
@@ -25,11 +26,13 @@ namespace mob::details {
|
|||||||
|
|
||||||
// calls get_string(), converts to bool
|
// calls get_string(), converts to bool
|
||||||
//
|
//
|
||||||
bool get_bool(std::string_view section, std::string_view key);
|
bool get_bool(std::string_view section, std::string_view key,
|
||||||
|
std::optional<bool> default_ = {});
|
||||||
|
|
||||||
// calls get_string(), converts to in
|
// calls get_string(), converts to in
|
||||||
//
|
//
|
||||||
int get_int(std::string_view section, std::string_view key);
|
int get_int(std::string_view section, std::string_view key,
|
||||||
|
std::optional<int> default_ = {});
|
||||||
|
|
||||||
// sets the given option, bails out if the option doesn't exist
|
// sets the given option, bails out if the option doesn't exist
|
||||||
//
|
//
|
||||||
@@ -60,9 +63,17 @@ namespace mob {
|
|||||||
template <class DefaultType>
|
template <class DefaultType>
|
||||||
class conf_section {
|
class conf_section {
|
||||||
public:
|
public:
|
||||||
DefaultType get(std::string_view key) const
|
DefaultType get(std::string_view key,
|
||||||
|
std::optional<DefaultType> default_ = {}) const
|
||||||
{
|
{
|
||||||
const auto value = details::get_string(name_, key);
|
const auto value = [=] {
|
||||||
|
if constexpr (std::is_same_v<DefaultType, std::string>) {
|
||||||
|
return details::get_string(name_, key, default_);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return details::get_string(name_, key);
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
if constexpr (std::is_convertible_v<std::string, DefaultType>) {
|
if constexpr (std::is_convertible_v<std::string, DefaultType>) {
|
||||||
return value;
|
return value;
|
||||||
@@ -74,18 +85,18 @@ namespace mob {
|
|||||||
|
|
||||||
// undefined
|
// undefined
|
||||||
template <class T>
|
template <class T>
|
||||||
T get(std::string_view key) const;
|
T get(std::string_view key, std::optional<T> default_ = {}) const;
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
bool get<bool>(std::string_view key) const
|
bool get<bool>(std::string_view key, std::optional<bool> default_) const
|
||||||
{
|
{
|
||||||
return details::get_bool(name_, key);
|
return details::get_bool(name_, key, default_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
int get<int>(std::string_view key) const
|
int get<int>(std::string_view key, std::optional<int> default_) const
|
||||||
{
|
{
|
||||||
return details::get_int(name_, key);
|
return details::get_int(name_, key, default_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(std::string_view key, std::string_view value)
|
void set(std::string_view key, std::string_view value)
|
||||||
@@ -223,6 +234,13 @@ namespace mob {
|
|||||||
conf_build_types();
|
conf_build_types();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// options in [translations]
|
||||||
|
//
|
||||||
|
class conf_translations : public conf_section<std::string> {
|
||||||
|
public:
|
||||||
|
conf_translations();
|
||||||
|
};
|
||||||
|
|
||||||
// options in [prebuilt]
|
// options in [prebuilt]
|
||||||
//
|
//
|
||||||
class conf_prebuilt : public conf_section<std::string> {
|
class conf_prebuilt : public conf_section<std::string> {
|
||||||
@@ -245,6 +263,7 @@ namespace mob {
|
|||||||
VALUE(third_party);
|
VALUE(third_party);
|
||||||
VALUE(prefix);
|
VALUE(prefix);
|
||||||
VALUE(cache);
|
VALUE(cache);
|
||||||
|
VALUE(icons);
|
||||||
VALUE(licenses);
|
VALUE(licenses);
|
||||||
VALUE(build);
|
VALUE(build);
|
||||||
|
|
||||||
@@ -255,7 +274,7 @@ namespace mob {
|
|||||||
VALUE(install_pdbs);
|
VALUE(install_pdbs);
|
||||||
|
|
||||||
VALUE(install_dlls);
|
VALUE(install_dlls);
|
||||||
VALUE(install_plugins);
|
VALUE(install_extensions);
|
||||||
VALUE(install_stylesheets);
|
VALUE(install_stylesheets);
|
||||||
VALUE(install_licenses);
|
VALUE(install_licenses);
|
||||||
VALUE(install_translations);
|
VALUE(install_translations);
|
||||||
@@ -283,6 +302,7 @@ namespace mob {
|
|||||||
conf_cmake cmake();
|
conf_cmake cmake();
|
||||||
conf_tools tool();
|
conf_tools tool();
|
||||||
conf_transifex transifex();
|
conf_transifex transifex();
|
||||||
|
conf_translations translation();
|
||||||
conf_prebuilt prebuilt();
|
conf_prebuilt prebuilt();
|
||||||
conf_versions version();
|
conf_versions version();
|
||||||
conf_build_types build_types();
|
conf_build_types build_types();
|
||||||
|
|||||||
@@ -116,6 +116,30 @@ namespace mob::op {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void delete_file_glob_recurse(const context& cx, const fs::path& directory,
|
||||||
|
const fs::path& glob, flags f)
|
||||||
|
{
|
||||||
|
cx.trace(context::fs, "deleting glob {}", glob);
|
||||||
|
|
||||||
|
const auto native = glob.native();
|
||||||
|
|
||||||
|
if (!fs::exists(directory))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (auto&& e : fs::recursive_directory_iterator(directory)) {
|
||||||
|
const auto p = e.path();
|
||||||
|
const auto name = p.filename().native();
|
||||||
|
|
||||||
|
if (!PathMatchSpecW(name.c_str(), native.c_str())) {
|
||||||
|
cx.trace(context::fs, "{} did not match {}; skipping", name, glob);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_file(cx, p, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void remove_readonly(const context& cx, const fs::path& dir, flags f)
|
void remove_readonly(const context& cx, const fs::path& dir, flags f)
|
||||||
{
|
{
|
||||||
cx.trace(context::fs, "removing read-only from {}", dir);
|
cx.trace(context::fs, "removing read-only from {}", dir);
|
||||||
|
|||||||
@@ -65,6 +65,11 @@ namespace mob::op {
|
|||||||
//
|
//
|
||||||
void delete_file_glob(const context& cx, const fs::path& glob, flags f = noflags);
|
void delete_file_glob(const context& cx, const fs::path& glob, flags f = noflags);
|
||||||
|
|
||||||
|
// deletes all files matching the glob in the given directory and its subdirectories
|
||||||
|
//
|
||||||
|
void delete_file_glob_recurse(const context& cx, const fs::path& directory,
|
||||||
|
const fs::path& glob, flags f = noflags);
|
||||||
|
|
||||||
// removes the readonly flag for all files in `dir`, recursive
|
// removes the readonly flag for all files in `dir`, recursive
|
||||||
//
|
//
|
||||||
void remove_readonly(const context& cx, const fs::path& dir, flags f = noflags);
|
void remove_readonly(const context& cx, const fs::path& dir, flags f = noflags);
|
||||||
|
|||||||
+2
-4
@@ -23,7 +23,6 @@ namespace mob {
|
|||||||
//
|
//
|
||||||
// mob doesn't have a concept of task dependencies, just task ordering, so
|
// mob doesn't have a concept of task dependencies, just task ordering, so
|
||||||
// if a task depends on another, it has to be earlier in the order
|
// if a task depends on another, it has to be earlier in the order
|
||||||
|
|
||||||
// super tasks
|
// super tasks
|
||||||
|
|
||||||
using mo = modorganizer;
|
using mo = modorganizer;
|
||||||
@@ -42,13 +41,12 @@ namespace mob {
|
|||||||
.add_task<mo>("modorganizer-bsatk")
|
.add_task<mo>("modorganizer-bsatk")
|
||||||
.add_task<mo>("modorganizer-nxmhandler")
|
.add_task<mo>("modorganizer-nxmhandler")
|
||||||
.add_task<mo>("modorganizer-helper")
|
.add_task<mo>("modorganizer-helper")
|
||||||
|
.add_task<mo>({"modorganizer-bsapacker", "bsa_packer"})
|
||||||
|
.add_task<mo>("modorganizer-preview_bsa")
|
||||||
.add_task<mo>("modorganizer-game_bethesda");
|
.add_task<mo>("modorganizer-game_bethesda");
|
||||||
|
|
||||||
add_task<parallel_tasks>()
|
add_task<parallel_tasks>()
|
||||||
.add_task<mo>({"modorganizer-bsapacker", "bsa_packer"})
|
|
||||||
.add_task<mo>({"modorganizer-tool_inieditor", "inieditor"})
|
.add_task<mo>({"modorganizer-tool_inieditor", "inieditor"})
|
||||||
.add_task<mo>({"modorganizer-tool_inibakery", "inibakery"})
|
|
||||||
.add_task<mo>("modorganizer-preview_bsa")
|
|
||||||
.add_task<mo>("modorganizer-preview_base")
|
.add_task<mo>("modorganizer-preview_base")
|
||||||
.add_task<mo>("modorganizer-diagnose_basic")
|
.add_task<mo>("modorganizer-diagnose_basic")
|
||||||
.add_task<mo>("modorganizer-check_fnis")
|
.add_task<mo>("modorganizer-check_fnis")
|
||||||
|
|||||||
+111
-15
@@ -1,6 +1,8 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "../core/env.h"
|
#include "../core/env.h"
|
||||||
|
#include "../utility/string.h"
|
||||||
#include "../utility/threading.h"
|
#include "../utility/threading.h"
|
||||||
|
#include "nlohmann/json.hpp"
|
||||||
#include "task_manager.h"
|
#include "task_manager.h"
|
||||||
#include "tasks.h"
|
#include "tasks.h"
|
||||||
|
|
||||||
@@ -197,8 +199,8 @@ namespace mob::tasks {
|
|||||||
|
|
||||||
// remove the .qm files in the translations/ directory
|
// remove the .qm files in the translations/ directory
|
||||||
if (is_set(c, clean::rebuild)) {
|
if (is_set(c, clean::rebuild)) {
|
||||||
op::delete_file_glob(cx(), conf().path().install_translations() / "*.qm",
|
op::delete_file_glob_recurse(cx(), conf().path().install_extensions(),
|
||||||
op::optional);
|
"*.qm", op::optional);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,46 +253,139 @@ namespace mob::tasks {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generate_translations_metadata(
|
||||||
|
std::filesystem::path const& path,
|
||||||
|
std::vector<mob::tasks::translations::projects::lang> const& languages)
|
||||||
|
{
|
||||||
|
using json = nlohmann::ordered_json;
|
||||||
|
|
||||||
|
json metadata = json::parse(R"(
|
||||||
|
{
|
||||||
|
"id": "mo2-translations",
|
||||||
|
"name": "Translations for ModOrganizer2",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Multi-language translations for ModOrganizer2 itself.",
|
||||||
|
"author": {
|
||||||
|
"name": "Mod Organizer 2",
|
||||||
|
"homepage": "https://www.modorganizer.org/"
|
||||||
|
},
|
||||||
|
"icon": "translations.png",
|
||||||
|
"type": "translation",
|
||||||
|
"content": {
|
||||||
|
"translations": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
|
||||||
|
// fix version
|
||||||
|
json translations;
|
||||||
|
for (auto&& lang : languages) {
|
||||||
|
std::vector<std::string> files;
|
||||||
|
files.push_back("translations/" + lang.name + "/*.qm");
|
||||||
|
json jsonlang;
|
||||||
|
jsonlang["files"] = files;
|
||||||
|
translations[lang.name] = jsonlang;
|
||||||
|
}
|
||||||
|
metadata["content"]["translations"] = translations;
|
||||||
|
|
||||||
|
std::ofstream ofs(path);
|
||||||
|
ofs << metadata.dump(2);
|
||||||
|
}
|
||||||
|
|
||||||
void translations::do_build_and_install()
|
void translations::do_build_and_install()
|
||||||
{
|
{
|
||||||
// 1) build the list of projects, languages and .ts files
|
// 1) build the list of projects, languages and .ts files
|
||||||
// 2) run `lrelease` for every language in every project
|
// 2) run `lrelease` for every language in every project
|
||||||
// 3) copy builtin qt translations
|
// 3) copy builtin qt translations
|
||||||
|
|
||||||
const auto root = source_path() / "translations";
|
const auto root = source_path() / "translations";
|
||||||
const auto dest = conf().path().install_translations();
|
const auto extensions = conf().path().install_extensions();
|
||||||
const projects ps(root);
|
const projects ps(root);
|
||||||
|
|
||||||
op::create_directories(cx(), dest);
|
op::create_directories(cx(), extensions / "mo2-translations");
|
||||||
|
|
||||||
// log all the warnings added while walking the projects
|
// log all the warnings added while walking the projects
|
||||||
for (auto&& w : ps.warnings())
|
for (auto&& w : ps.warnings())
|
||||||
cx().warning(context::generic, "{}", w);
|
cx().warning(context::generic, "{}", w);
|
||||||
|
|
||||||
|
std::map<std::string, fs::path::string_type> project_to_extension;
|
||||||
|
|
||||||
|
// go through the list of extensions and find the matching projects
|
||||||
|
for (auto& p : fs::directory_iterator(extensions)) {
|
||||||
|
if (!fs::is_directory(p))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto name =
|
||||||
|
mob::replace_all(p.path().filename().string(), "mo2-", "");
|
||||||
|
|
||||||
|
project_to_extension[name] = p.path().filename();
|
||||||
|
project_to_extension[mob::replace_all(name, "-", "_")] =
|
||||||
|
p.path().filename();
|
||||||
|
|
||||||
|
const auto s_projects =
|
||||||
|
conf().translation().get(p.path().filename().string(), "");
|
||||||
|
if (!s_projects.empty()) {
|
||||||
|
const auto extension_projects = mob::split(s_projects, " ");
|
||||||
|
for (const auto& project : extension_projects) {
|
||||||
|
project_to_extension[project] = p.path().filename();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// run `lrelease` in a thread pool
|
// run `lrelease` in a thread pool
|
||||||
parallel_functions v;
|
parallel_functions v;
|
||||||
|
|
||||||
// for each project
|
// for each project
|
||||||
for (auto& p : ps.get()) {
|
for (auto& p : ps.get()) {
|
||||||
|
if (!project_to_extension.contains(p.name)) {
|
||||||
|
cx().warning(context::generic,
|
||||||
|
"found project {} but no matching extension", p.name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto base = extensions / project_to_extension[p.name];
|
||||||
|
|
||||||
|
if (!fs::exists(base)) {
|
||||||
|
cx().warning(
|
||||||
|
context::generic,
|
||||||
|
"found project {} for extension {} but extension is not built",
|
||||||
|
p.name, project_to_extension[p.name]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto dest = base / "translations";
|
||||||
|
op::create_directories(cx(), dest);
|
||||||
|
|
||||||
// for each language
|
// for each language
|
||||||
for (auto& lg : p.langs) {
|
for (auto& lg : p.langs) {
|
||||||
|
op::create_directories(cx(), dest / lg.name);
|
||||||
// add a functor that will run lrelease
|
// add a functor that will run lrelease
|
||||||
v.push_back(
|
v.push_back({lg.name + "." + p.name, [=] {
|
||||||
{lg.name + "." + p.name, [&] {
|
// run release for the given project name and list of
|
||||||
// run release for the given project name and list of .ts files
|
// .ts files
|
||||||
run_tool(
|
run_tool(lrelease()
|
||||||
lrelease().project(p.name).sources(lg.ts_files).out(dest));
|
.project(p.name)
|
||||||
}});
|
.sources(lg.ts_files)
|
||||||
|
.out(dest / lg.name));
|
||||||
|
}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// run all the functors in parallel
|
// run all the functors in parallel
|
||||||
parallel(v);
|
parallel(v);
|
||||||
|
|
||||||
if (auto p = ps.find("organizer"))
|
if (auto p = ps.find("organizer")) {
|
||||||
copy_builtin_qt_translations(*p, dest);
|
// copy Qt builting translation, icon and generate metadata
|
||||||
|
copy_builtin_qt_translations(*p, extensions / "mo2-translations" /
|
||||||
|
"translations");
|
||||||
|
op::copy_file_to_file_if_better(
|
||||||
|
cx(), conf().path().icons() / "translations.png",
|
||||||
|
extensions / "mo2-translations" / "translations.png", op::unsafe);
|
||||||
|
generate_translations_metadata(
|
||||||
|
extensions / "mo2-translations" / "metadata.json", p->langs);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
cx().bail_out(context::generic, "organizer project not found");
|
cx().warning(context::generic, "organizer project not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
void translations::copy_builtin_qt_translations(const projects::project& p,
|
void translations::copy_builtin_qt_translations(const projects::project& p,
|
||||||
@@ -307,7 +402,8 @@ namespace mob::tasks {
|
|||||||
if (!fs::exists(src))
|
if (!fs::exists(src))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
op::copy_file_to_dir_if_better(cx(), src, dest, op::unsafe);
|
op::create_directories(cx(), dest / lang);
|
||||||
|
op::copy_file_to_dir_if_better(cx(), src, dest / lang, op::unsafe);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user