From ee92185124c0d704cf40b5bebdea76333f95b242 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 24 Feb 2021 04:17:23 -0500 Subject: [PATCH] error handling for missing translations directory copy builtin qt translations --- mob.ini | 1 + src/core/conf.cpp | 17 +++--- src/core/conf.h | 1 + src/tasks/tasks.h | 14 +++++ src/tasks/translations.cpp | 105 ++++++++++++++++++++++++++++++++++--- 5 files changed, 122 insertions(+), 16 deletions(-) diff --git a/mob.ini b/mob.ini index e133cf8..d3230e5 100644 --- a/mob.ini +++ b/mob.ini @@ -143,6 +143,7 @@ install_translations = vs = qt_install = qt_bin = +qt_translations = pf_x86 = pf_x64 = temp_dir = diff --git a/src/core/conf.cpp b/src/core/conf.cpp index e21bf43..6c92fdf 100644 --- a/src/core/conf.cpp +++ b/src/core/conf.cpp @@ -488,14 +488,15 @@ void resolve_paths() set_path_if_empty("third_party", find_third_party_directory); this_env::prepend_to_path(conf().path().third_party() / "bin"); - set_path_if_empty("pf_x86", find_program_files_x86); - set_path_if_empty("pf_x64", find_program_files_x64); - set_path_if_empty("vs", find_vs); - set_path_if_empty("qt_install", find_qt); - set_path_if_empty("temp_dir", find_temp_dir); - set_path_if_empty("patches", find_in_root("patches")); - set_path_if_empty("licenses", find_in_root("licenses")); - set_path_if_empty("qt_bin", qt::installation_path() / "bin"); + set_path_if_empty("pf_x86", find_program_files_x86); + set_path_if_empty("pf_x64", find_program_files_x64); + set_path_if_empty("vs", find_vs); + set_path_if_empty("qt_install", find_qt); + set_path_if_empty("temp_dir", find_temp_dir); + set_path_if_empty("patches", find_in_root("patches")); + set_path_if_empty("licenses", find_in_root("licenses")); + set_path_if_empty("qt_bin", qt::installation_path() / "bin"); + set_path_if_empty("qt_translations", qt::installation_path() / "translations"); // second, if any of these paths are relative, they use the second argument // as the root; if they're empty, they combine the second and third diff --git a/src/core/conf.h b/src/core/conf.h index 2bd1e0e..5b8d4bc 100644 --- a/src/core/conf.h +++ b/src/core/conf.h @@ -220,6 +220,7 @@ public: VALUE(vs); VALUE(qt_install); VALUE(qt_bin); + VALUE(qt_translations); VALUE(pf_x86); VALUE(pf_x64); diff --git a/src/tasks/tasks.h b/src/tasks/tasks.h index c8686f8..f8cff68 100644 --- a/src/tasks/tasks.h +++ b/src/tasks/tasks.h @@ -627,6 +627,11 @@ public: std::vector ts_files; lang(std::string n); + + // if `name` has an underscore, returns the part before and after + // it; if there is no underscore, first is `name`, second is empty + // + std::pair split() const; }; // a project that contains languages @@ -654,6 +659,10 @@ public: // const std::vector& warnings() const; + // return a project by name + // + std::optional find(std::string_view name) const; + private: // translations directory const fs::path root_; @@ -696,6 +705,11 @@ protected: void do_clean(clean c) override; void do_fetch() override; void do_build_and_install() override; + +private: + // copy builtin qt .qm files + void copy_builtin_qt_translations( + const projects::project& organizer_project, const fs::path& dest); }; diff --git a/src/tasks/translations.cpp b/src/tasks/translations.cpp index c7321d7..a6528cc 100644 --- a/src/tasks/translations.cpp +++ b/src/tasks/translations.cpp @@ -69,6 +69,17 @@ translations::projects::lang::lang(std::string n) { } +std::pair translations::projects::lang::split() const +{ + const auto p = name.find('_'); + + if (p == std::string::npos) + return {{}, name}; + + return {name.substr(0, p), name.substr(p + 1)}; +} + + translations::projects::project::project(std::string n) : name(std::move(n)) { @@ -78,16 +89,24 @@ translations::projects::project::project(std::string n) translations::projects::projects(fs::path root) : root_(std::move(root)) { - // walk all directories in the root, each one is a project directory that - // contains .ts files - for (auto e : fs::directory_iterator(root_)) + try { - if (!e.is_directory()) - continue; + // walk all directories in the root, each one is a project directory that + // contains .ts files + for (auto e : fs::directory_iterator(root_)) + { + if (!e.is_directory()) + continue; - auto p = create_project(e.path()); - if (!p.name.empty()) - projects_.push_back(p); + auto p = create_project(e.path()); + if (!p.name.empty()) + projects_.push_back(p); + } + } + catch(std::exception& e) + { + gcx().bail_out(context::generic, + "can't walk {} for projects, {}", root_, e.what()); } } @@ -102,6 +121,18 @@ const std::vector& translations::projects::warnings() const return warnings_; } +std::optional +translations::projects::find(std::string_view name) const +{ + for (auto&& p : projects_) + { + if (p.name == name) + return p; + } + + return {}; +} + translations::projects::project translations::projects::create_project(const fs::path& dir) { @@ -327,6 +358,7 @@ void translations::do_build_and_install() { // 1) build the list of projects, languages and .ts files // 2) run `lrelease` for every language in every project + // 3) copy builtin qt translations const auto root = source_path() / "translations"; const auto dest = conf().path().install_translations(); @@ -361,6 +393,63 @@ void translations::do_build_and_install() // run all the functors in parallel parallel(v); + + if (auto p=ps.find("organizer")) + copy_builtin_qt_translations(*p, dest); + else + cx().bail_out(context::generic, "organizer project not found"); +} + +void translations::copy_builtin_qt_translations( + const projects::project& p, const fs::path& dest) +{ + // list of prefixes in the qt translations directory + const std::vector prefixes = + { + "qt", "qtbase" + }; + + + // tries to copy the .qm file, returns false if the file doesn't exist + auto try_copy = [&](auto&& prefix, auto&& lang) + { + const std::string file = prefix + "_" + lang + ".qm"; + const fs::path src = conf().path().qt_translations() / file; + + if (!fs::exists(src)) + return false; + + op::copy_file_to_dir_if_better(cx(), src, dest, op::unsafe); + return true; + }; + + + for (auto&& prefix : prefixes) + { + cx().debug(context::generic, + "copying builtin qt translations '{}'", prefix); + + for (auto&& lg : p.langs) + { + // some source files use 'country_lang', others are just 'lang', + // such as "qt_pl.qm" and "qt_zh_CN.qm", so try both + + if (try_copy(prefix, lg.name)) + continue; + + const auto [language, country] = lg.split(); + + if (!country.empty()) + { + if (try_copy(prefix, language)) + continue; + } + + cx().warning(context::generic, + "missing builtin qt translation '{}' for lang {} from {}", + prefix, lg.name, conf().path().qt_translations()); + } + } } } // namespace