From d96f75105f95c3a71710f877a9d00b57d8027630 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 23 Aug 2021 16:26:47 +0200 Subject: [PATCH] Parse hints.ini for translatable text as part of gettext_make_pot --- CMakeLists.txt | 3 ++ src/CMakeLists.txt | 1 + src/hints/CMakeLists.txt | 12 +++++ src/hints/HintsToPot.cpp | 84 +++++++++++++++++++++++++++++ src/slic3r/GUI/HintNotification.cpp | 21 ++++++++ 5 files changed, 121 insertions(+) create mode 100644 src/hints/CMakeLists.txt create mode 100644 src/hints/HintsToPot.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6002091b6..d771a730a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -481,6 +481,7 @@ add_custom_target(gettext_make_pot COMMAND xgettext --keyword=L --keyword=_L --keyword=_u8L --keyword=L_CONTEXT:1,2c --keyword=_L_PLURAL:1,2 --add-comments=TRN --from-code=UTF-8 --debug -f "${L10N_DIR}/list.txt" -o "${L10N_DIR}/PrusaSlicer.pot" + COMMAND hintsToPot ${SLIC3R_RESOURCES_DIR} ${L10N_DIR} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMENT "Generate pot file from strings in the source tree" ) @@ -553,6 +554,8 @@ endfunction() add_subdirectory(src) set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT PrusaSlicer_app_console) +add_dependencies(gettext_make_pot hintsToPot) + # Perl bindings, currently only used for the unit / integration tests of libslic3r. # Also runs the unit / integration tests. #FIXME Port the tests into C++ to finally get rid of the Perl! diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bbade8a97..9e89e82f6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,6 +13,7 @@ add_subdirectory(qhull) add_subdirectory(Shiny) add_subdirectory(semver) add_subdirectory(libigl) +add_subdirectory(hints) # Adding libnest2d project for bin packing... add_subdirectory(libnest2d) diff --git a/src/hints/CMakeLists.txt b/src/hints/CMakeLists.txt new file mode 100644 index 000000000..66550c786 --- /dev/null +++ b/src/hints/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.13) +project(HintsToPot) + +add_executable(hintsToPot + HintsToPot.cpp) + +target_link_libraries(hintsToPot PRIVATE boost_libs) + +#encoding_check(HintsToPot) + + + diff --git a/src/hints/HintsToPot.cpp b/src/hints/HintsToPot.cpp new file mode 100644 index 000000000..7c8029cde --- /dev/null +++ b/src/hints/HintsToPot.cpp @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +bool write_to_pot(boost::filesystem::path path, const std::vector>& data) +{ + boost::filesystem::ofstream file(std::move(path), std::ios_base::app); + for (const auto& element : data) + { + //Example of .pot element + //#: src/slic3r/GUI/GUI_App.cpp:1647 src/slic3r/GUI/wxExtensions.cpp:687 + //msgctxt "Mode" + //msgid "Advanced" + //msgstr "" + file << "\n#: resources/data/hints.ini: ["<< element.first << "]\nmsgid \"" << element.second << "\"\nmsgstr \"\"\n"; + } + file.close(); + return true; +} +bool read_hints_ini(boost::filesystem::path path, std::vector>& pot_elements) +{ + namespace pt = boost::property_tree; + pt::ptree tree; + boost::nowide::ifstream ifs(path.string()); + try { + pt::read_ini(ifs, tree); + } + catch (const boost::property_tree::ini_parser::ini_parser_error& err) { + std::cout << err.what() << std::endl; + return false; + } + for (const auto& section : tree) { + if (boost::starts_with(section.first, "hint:")) { + for (const auto& data : section.second) { + if (data.first == "text") + { + pot_elements.emplace_back(section.first, data.second.data()); + break; + } + } + } + } + return true; +} + +int main(int argc, char* argv[]) +{ + std::vector> data; + boost::filesystem::path path_to_ini; + boost::filesystem::path path_to_pot; + if (argc != 3) + { + std::cout << "HINTS_TO_POT FAILED: WRONG NUM OF ARGS" << std::endl; + return -1; + } + try { + path_to_ini = boost::filesystem::canonical(boost::filesystem::path(argv[1])).parent_path() / "resources" / "data" / "hints.ini"; + path_to_pot = boost::filesystem::canonical(boost::filesystem::path(argv[2])).parent_path() / "localization" /"PrusaSlicer.pot"; + } catch (std::exception&) { + std::cout << "HINTS_TO_POT FAILED: BOOST CANNONICAL" << std::endl; + return -1; + } + + if (!boost::filesystem::exists(path_to_ini)){ + std::cout << "HINTS_TO_POT FAILED: PATH TO INI DOES NOT EXISTS" << std::endl; + std::cout << path_to_ini.string() << std::endl; + return -1; + } + if (!read_hints_ini(std::move(path_to_ini), data)) { + std::cout << "HINTS_TO_POT FAILED TO READ HINTS INI" << std::endl; + return -1; + } + if (!write_to_pot(std::move(path_to_pot), data)) { + std::cout << "HINTS_TO_POT FAILED TO WRITE POT FILE" << std::endl; + return -1; + } + std::cout << "HINTS_TO_POT SUCCESS" << std::endl; + return 0; +} diff --git a/src/slic3r/GUI/HintNotification.cpp b/src/slic3r/GUI/HintNotification.cpp index 2b079b6ff..42039fa70 100644 --- a/src/slic3r/GUI/HintNotification.cpp +++ b/src/slic3r/GUI/HintNotification.cpp @@ -179,6 +179,21 @@ void launch_browser_if_allowed(const std::string& url) if (wxGetApp().app_config->get("suppress_hyperlinks") != "1") wxLaunchDefaultBrowser(url); } +bool pot_exists() +{ + return true; +// return boost::filesystem::exists(std::move(boost::filesystem::path(resources_dir()) / "data" / "hints.pot")); +} +void write_pot(const std::vector& elements) +{ + boost::filesystem::ofstream file(std::move(boost::filesystem::path(resources_dir()) / "data" / "hints.pot")); + + for ( const auto &element : elements) + { + file << "msgid \"" << escape_string_cstyle(element) << "\"\nmsgstr \"\"\n\n"; + } + file.close(); +} } //namespace void HintDatabase::init() @@ -195,6 +210,8 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path) { namespace pt = boost::property_tree; pt::ptree tree; + bool create_pot = !pot_exists(); + std::vector pot_elements; boost::nowide::ifstream ifs(path.string()); try { pt::read_ini(ifs, tree); @@ -221,6 +238,8 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path) std::string documentation_link; //unescape text1 unescape_string_cstyle(_utf8(dict["text"]), fulltext); + if (create_pot) + pot_elements.emplace_back(fulltext); // replace and for imgui markers std::string marker_s(1, ImGui::ColorMarkerStart); std::string marker_e(1, ImGui::ColorMarkerEnd); @@ -319,6 +338,8 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path) } } } + if (create_pot) + write_pot(pot_elements); } HintData* HintDatabase::get_hint(bool up) {