From ca319a5b55538f786b81d6ede7cfc98cf0f737d9 Mon Sep 17 00:00:00 2001 From: Mentalflow <312902918@qq.com> Date: Sun, 18 May 2025 16:02:01 +0800 Subject: [PATCH] Project: Add multilingual support. --- 3rdparty/Qt5QMLPlugin | 2 +- example/CMakeLists.txt | 30 +- example/i18n/RibbonUIAPP_en_US.ts | 495 ++++++++++++++++++ example/i18n/RibbonUIAPP_zh_CN.ts | 495 ++++++++++++++++++ example/qml/Qt5/example.qml | 19 +- example/qml/Qt5/pages/SettingsMenuPage.qml | 38 ++ example/qml/Qt6/example.qml | 18 +- example/qml/Qt6/pages/SettingsMenuPage.qml | 38 ++ lib_source/CMakeLists.txt | 41 +- lib_source/i18n/RibbonUI_en_US.ts | 376 +++++++++++++ lib_source/i18n/RibbonUI_zh_CN.ts | 377 +++++++++++++ lib_source/{ => include}/definitions.h | 24 +- lib_source/{ => include}/platformsupport.h | 0 lib_source/include/ribbonlocalization.h | 46 ++ lib_source/{ => include}/ribbontheme.h | 2 +- lib_source/{ => include}/ribbonui.h | 12 + .../qml/Qt5/RibbonBackStageMenuItem.qml | 1 + lib_source/qml/Qt5/RibbonBackStageView.qml | 11 + lib_source/qml/Qt5/RibbonTabBar.qml | 3 +- lib_source/qml/Qt5/RibbonTour.qml | 12 +- lib_source/qml/Qt5/RibbonTourItem.qml | 1 + lib_source/qml/Qt5/RibbonWindow.qml | 2 + .../qml/Qt6/RibbonBackStageMenuItem.qml | 1 + lib_source/qml/Qt6/RibbonBackStageView.qml | 11 + lib_source/qml/Qt6/RibbonTabBar.qml | 3 +- lib_source/qml/Qt6/RibbonTour.qml | 12 +- lib_source/qml/Qt6/RibbonTourItem.qml | 1 + lib_source/qml/Qt6/RibbonWindow.qml | 2 + lib_source/{ => source}/platformsupport.mm | 0 lib_source/source/ribbonlocalization.cpp | 106 ++++ lib_source/{ => source}/ribbontheme.cpp | 0 lib_source/{ => source}/ribbonui.cpp | 40 ++ 32 files changed, 2181 insertions(+), 38 deletions(-) create mode 100644 example/i18n/RibbonUIAPP_en_US.ts create mode 100644 example/i18n/RibbonUIAPP_zh_CN.ts create mode 100644 lib_source/i18n/RibbonUI_en_US.ts create mode 100644 lib_source/i18n/RibbonUI_zh_CN.ts rename lib_source/{ => include}/definitions.h (99%) rename lib_source/{ => include}/platformsupport.h (100%) create mode 100644 lib_source/include/ribbonlocalization.h rename lib_source/{ => include}/ribbontheme.h (91%) rename lib_source/{ => include}/ribbonui.h (58%) rename lib_source/{ => source}/platformsupport.mm (100%) create mode 100644 lib_source/source/ribbonlocalization.cpp rename lib_source/{ => source}/ribbontheme.cpp (100%) rename lib_source/{ => source}/ribbonui.cpp (52%) diff --git a/3rdparty/Qt5QMLPlugin b/3rdparty/Qt5QMLPlugin index eeefdd7..fd7734e 160000 --- a/3rdparty/Qt5QMLPlugin +++ b/3rdparty/Qt5QMLPlugin @@ -1 +1 @@ -Subproject commit eeefdd757e64fae21449d4de3706072385e66b12 +Subproject commit fd7734e79071d0acc1286004dc53db8c9b8c5a1a diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 4a96338..73e9a56 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -31,7 +31,10 @@ endif() # Find Qt package find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core) -find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Quick REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Quick LinguistTools REQUIRED) + +# List all ts files to be used in the project +set(ts_files i18n/${PROJECT_NAME}_zh_CN.ts i18n/${PROJECT_NAME}_en_US.ts) # Source and QML files set(sources_files example.cpp) @@ -56,6 +59,31 @@ list(APPEND source_files ${CMAKE_CURRENT_BINARY_DIR}/${__example_project_version qt_add_executable(${PROJECT_NAME} ${sources_files}) +# Add i18n files +set_source_files_properties(${ts_files} PROPERTIES OUTPUT_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/i18n) + +if(QT_VERSION VERSION_LESS 6.0) + qt5_create_translation_plus(qm_files ${CMAKE_CURRENT_SOURCE_DIR} ${ts_files}) + foreach(qm_file ${qm_files}) + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" r_qm_file ${qm_file}) + list(APPEND r_qm_files ${r_qm_file}) + endforeach() + qt5_add_resources_plus(${PROJECT_NAME} "${PROJECT_NAME}-translations" + PREFIX "/" + FILES ${r_qm_files} + ) +else() + qt6_create_translation(qm_files ${CMAKE_CURRENT_SOURCE_DIR} ${ts_files}) + foreach(qm_file ${qm_files}) + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" r_qm_file ${qm_file}) + list(APPEND r_qm_files ${r_qm_file}) + endforeach() + qt6_add_resources(${PROJECT_NAME} "${PROJECT_NAME}-translations" + PREFIX "/" + FILES ${r_qm_files} + ) +endif() + # Windows-specific settings if (WIN32) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../.cmake/win_app.rc.in ${CMAKE_BINARY_DIR}/win_app.rc) diff --git a/example/i18n/RibbonUIAPP_en_US.ts b/example/i18n/RibbonUIAPP_en_US.ts new file mode 100644 index 0000000..25d70b7 --- /dev/null +++ b/example/i18n/RibbonUIAPP_en_US.ts @@ -0,0 +1,495 @@ + + + + + RibbonMessageListViewExample + + + + Message List View Example + + + + + + Add Message + + + + + + Clear Message + + + + + SettingsMenuPage + + + + Settings + + + + + + Theme + + + + + + Current Theme: + + + + + + Current Style: + + + + + + Style + + + + + + Modern + + + + + + Classic + + + + + + Text Render + + + + + + Current Text Render: + + + + + + TitleBar + + + + + + Show TitleBar Icon: + + + + + + Language + + + + + + Current Language: + + + + + TabBar + + + + Basic + + + + + + Slider + + + + + + Switch Button + + + + + + CheckBox + + + + + + Button + + + + + + Push Button + + + + + + + + No Menu + + + + + + + + + + Menu + + + + + + Radio Button + + + + + + Input + + + + + + Line Edit + + + + + + Text Edit + + + + + + Combo Box + + + + + + Spin Box + + + + + + Progress + + + + + + ProgressBar + + + + + + ProgressRing + + + + + + Indicator + + + + + + BusyRing + + + + + + BusyBar + + + + + + PageIndicator + + + + + + Views + + + + + + MessageListView + + + + + + Open Message List View + + + + + + Others + + + + + + Text + + + + + + Open Menu + + + + + + Popup + + + + + + Open Popup + + + + + + Open Popup Dialog (Double Choices) + + + + + + Open Popup Dialog (Triple Choices) + + + + + + MessageBar + + + + + + Generate One Message + + + + + + Clear All Messages + + + + + about + + + + About + + + + + example + + + + RibbonUI APP + + + + + + Tab Bar + + + + + + A tab bar for window, let user choose the controllers. + + + + + + Tab Bar Buttons + + + + + + Tool buttons at the top of tab bar. + + + + + + Sliders + + + + + + Vertical/Horizental sliders with/without buttons. + + + + + + Switch Buttons + + + + + + Switch buttons with/without background color or grabber text. + + + + + + CheckBoxs + + + + + + CheckBoxs with colorful background or with/without label text. + + + + + + Buttons + + + + + + Buttons with/without background or label text. + + + + + + Push Buttons + + + + + + Push buttons with/without sub menu. + + + + + + Line Edits + + + + + + Line edits with/without icon. + + + + + + Bottom Bar + + + + + + A bottom bar for window. + + + + + + + About + + + + + + Tour + + + + + + Test Item 2 + + + + + + Test Item 3 + + + + + Home + + + + + File + + + + + Search + + + + + Account + + + + + Settings + + + + diff --git a/example/i18n/RibbonUIAPP_zh_CN.ts b/example/i18n/RibbonUIAPP_zh_CN.ts new file mode 100644 index 0000000..f9e5c1d --- /dev/null +++ b/example/i18n/RibbonUIAPP_zh_CN.ts @@ -0,0 +1,495 @@ + + + + + RibbonMessageListViewExample + + + + Message List View Example + Message List View 示例 + + + + + Add Message + 添加信息 + + + + + Clear Message + 清除信息 + + + + SettingsMenuPage + + + + Settings + 设置 + + + + + Theme + 主题 + + + + + Current Theme: + 当前主题: + + + + + Current Style: + 当前风格: + + + + + Style + 风格 + + + + + Modern + 现代化 + + + + + Classic + 经典 + + + + + Text Render + 文本渲染器 + + + + + Current Text Render: + 当前文本渲染器: + + + + + TitleBar + 标题栏 + + + + + Show TitleBar Icon: + 显示标题栏图标: + + + + + Language + 语言 + + + + + Current Language: + 当前语言: + + + + TabBar + + + + Basic + 基本 + + + + + Slider + 滑动条 + + + + + Switch Button + 开关 + + + + + CheckBox + 复选框 + + + + + Button + 按钮 + + + + + Push Button + 按压按钮 + + + + + + + No Menu + 无菜单 + + + + + + + + + Menu + 菜单 + + + + + Radio Button + 单选按钮 + + + + + Input + 输入 + + + + + Line Edit + 行编辑 + + + + + Text Edit + 文本编辑 + + + + + Combo Box + 组合框 + + + + + Spin Box + 调整框 + + + + + Progress + 进度 + + + + + ProgressBar + 进度条 + + + + + ProgressRing + 进度环 + + + + + Indicator + 指示器 + + + + + BusyRing + 加载环 + + + + + BusyBar + 加载条 + + + + + PageIndicator + 页面指示器 + + + + + Views + 视图 + + + + + MessageListView + 消息列表视图 + + + + + Open Message List View + 打开消息列表视图 + + + + + Others + 其他 + + + + + Text + 文本 + + + + + Open Menu + 打开菜单 + + + + + Popup + 弹出窗口 + + + + + Open Popup + 打开弹出窗口 + + + + + Open Popup Dialog (Double Choices) + 打开弹出窗口(双选择) + + + + + Open Popup Dialog (Triple Choices) + 打开弹出窗口(三选择) + + + + + MessageBar + 信息栏 + + + + + Generate One Message + 生成一条信息 + + + + + Clear All Messages + 清除所有信息 + + + + about + + + + About + 关于 + + + + example + + + + RibbonUI APP + RibbonUI 应用 + + + + + Tab Bar + 标签栏 + + + + + A tab bar for window, let user choose the controllers. + 一个让用户选择工具使用的标签栏。 + + + + + Tab Bar Buttons + 标签栏按钮 + + + + + Tool buttons at the top of tab bar. + 在标签栏顶端的工具按钮。 + + + + + Sliders + 滑动条 + + + + + Vertical/Horizental sliders with/without buttons. + 含/不含按钮的垂直/水平滑动条。 + + + + + Switch Buttons + 开关 + + + + + Switch buttons with/without background color or grabber text. + 有/没有背景颜色或者抓握指示器文本的开关。 + + + + + CheckBoxs + 复选框 + + + + + CheckBoxs with colorful background or with/without label text. + 具有多彩背景色彩或标签文本的复选框。 + + + + + Buttons + 按钮 + + + + + Buttons with/without background or label text. + 具有/不具有背景或标签文本的按钮。 + + + + + Push Buttons + 下压按钮 + + + + + Push buttons with/without sub menu. + 有/没有带菜单的下压按钮。 + + + + + Line Edits + 行编辑 + + + + + Line edits with/without icon. + 带/不带图标的行编辑器。 + + + + + Bottom Bar + 底层工具栏 + + + + + A bottom bar for window. + 窗口的底层工具栏。 + + + + + + About + 关于 + + + + + Tour + 导览 + + + + + Test Item 2 + 测试项目 1 + + + + + Test Item 3 + 测试项目 1 + + + + Home + 主页 + + + + File + 文件 + + + + Search + 搜索 + + + + Account + 账户 + + + + Settings + 设置 + + + diff --git a/example/qml/Qt5/example.qml b/example/qml/Qt5/example.qml index 7de2706..abce5be 100644 --- a/example/qml/Qt5/example.qml +++ b/example/qml/Qt5/example.qml @@ -12,6 +12,7 @@ RibbonWindow { title: qsTr("RibbonUI APP") comfirmedQuit: true property bool modernStyle: RibbonTheme.modernStyle + RibbonMessageBarGroup{ id: msg_bar implicitWidth: windowItems.width @@ -142,7 +143,10 @@ RibbonWindow { blurEnabled: true targetRect: Qt.rect(windowItems.x + x, windowItems.y + y, width, height) } - Component.onCompleted: tour.open() + Component.onCompleted: { + RibbonUI.autoLoadLanguage = true + tour.open() + } TabBar{ id: tab_bar @@ -157,6 +161,7 @@ RibbonWindow { pageWidth: (page_slider.value / 100.0) * width spacing: 0 isMainView: true + ColumnLayout{ Layout.alignment: Qt.AlignCenter Layout.topMargin: 30 @@ -368,42 +373,42 @@ RibbonWindow { blurTarget: root.windowItems radius: borderRadius RibbonBackStageMenuItem{ - menuText: "Home" + menuText: qsTr("Home") menuIcon: RibbonIcons.Home type: RibbonBackStageView.MenuItemLocation.Head sourceComponent: t_content sourceArgs:{'pageName':"Home"} } RibbonBackStageMenuItem{ - menuText: "File" + menuText: qsTr("File") menuIcon: RibbonIcons.Document type: RibbonBackStageView.MenuItemLocation.Head sourceComponent: t_content sourceArgs:{'pageName':"File"} } RibbonBackStageMenuItem{ - menuText: "Search" + menuText: qsTr("Search") menuIcon: RibbonIcons.Search type: RibbonBackStageView.MenuItemLocation.Body sourceComponent: t_content sourceArgs:{'pageName':"Search"} } RibbonBackStageMenuItem{ - menuText: "Account" + menuText: qsTr("Account") menuIcon: RibbonIcons.PersonAccounts type: RibbonBackStageView.MenuItemLocation.Tail clickOnly: true clickFunc: ()=>console.log("Menu Account clicked") } RibbonBackStageMenuItem{ - menuText: "About" + menuText: qsTr("About") menuIcon: RibbonIcons.Info type: RibbonBackStageView.MenuItemLocation.Tail clickOnly: true clickFunc: ()=>root.showWindow(Qt.resolvedUrl("about.qml")) } RibbonBackStageMenuItem{ - menuText: "Settings" + menuText: qsTr("Settings") menuIcon: RibbonIcons.Settings type: RibbonBackStageView.MenuItemLocation.Tail sourceUrl: Qt.resolvedUrl("pages/SettingsMenuPage.qml") diff --git a/example/qml/Qt5/pages/SettingsMenuPage.qml b/example/qml/Qt5/pages/SettingsMenuPage.qml index 809f47a..2783520 100644 --- a/example/qml/Qt5/pages/SettingsMenuPage.qml +++ b/example/qml/Qt5/pages/SettingsMenuPage.qml @@ -108,5 +108,43 @@ RibbonBackStagePage{ } } } + RibbonBackStageGroup{ + Layout.alignment: Qt.AlignTop + Layout.preferredHeight: lang_combo.height + 40 + Layout.fillWidth: true + groupName: qsTr("Language") + ColumnLayout{ + RowLayout{ + RibbonText{ + text: qsTr("Current Language: ") + } + RibbonComboBox{ + id: lang_combo + model: ListModel { + id: model_lang + } + iconSource: RibbonIcons.LocalLanguage + Component.onCompleted: update_state() + onActivated: { + RibbonLocalization.currentLanguage = currentText + } + Connections{ + target: RibbonLocalization + function onCurrentLanguageChanged(){ + lang_combo.update_state() + } + } + function update_state(){ + model_lang.clear() + let langs = RibbonLocalization.languageList() + for(let i = 0; i < langs.length; i++){ + model_lang.append({text:langs[i]}) + } + currentIndex = find(RibbonLocalization.currentLanguage) + } + } + } + } + } } } diff --git a/example/qml/Qt6/example.qml b/example/qml/Qt6/example.qml index 8dc7a90..3b850b2 100644 --- a/example/qml/Qt6/example.qml +++ b/example/qml/Qt6/example.qml @@ -12,6 +12,7 @@ RibbonWindow { title: qsTr("RibbonUI APP") comfirmedQuit: true property bool modernStyle: RibbonTheme.modernStyle + RibbonMessageBarGroup{ id: msg_bar implicitWidth: windowItems.width @@ -142,7 +143,10 @@ RibbonWindow { blurEnabled: true targetRect: Qt.rect(windowItems.x + x, windowItems.y + y, width, height) } - Component.onCompleted: tour.open() + Component.onCompleted: { + RibbonUI.autoLoadLanguage = true + tour.open() + } TabBar{ id: tab_bar @@ -369,42 +373,42 @@ RibbonWindow { blurTarget: root.windowItems radius: borderRadius RibbonBackStageMenuItem{ - menuText: "Home" + menuText: qsTr("Home") menuIcon: RibbonIcons.Home type: RibbonBackStageView.MenuItemLocation.Head sourceComponent: t_content sourceArgs:{'pageName':"Home"} } RibbonBackStageMenuItem{ - menuText: "File" + menuText: qsTr("File") menuIcon: RibbonIcons.Document type: RibbonBackStageView.MenuItemLocation.Head sourceComponent: t_content sourceArgs:{'pageName':"File"} } RibbonBackStageMenuItem{ - menuText: "Search" + menuText: qsTr("Search") menuIcon: RibbonIcons.Search type: RibbonBackStageView.MenuItemLocation.Body sourceComponent: t_content sourceArgs:{'pageName':"Search"} } RibbonBackStageMenuItem{ - menuText: "Account" + menuText: qsTr("Account") menuIcon: RibbonIcons.PersonAccounts type: RibbonBackStageView.MenuItemLocation.Tail clickOnly: true clickFunc: ()=>console.log("Menu Account clicked") } RibbonBackStageMenuItem{ - menuText: "About" + menuText: qsTr("About") menuIcon: RibbonIcons.Info type: RibbonBackStageView.MenuItemLocation.Tail clickOnly: true clickFunc: ()=>root.showWindow(Qt.resolvedUrl("about.qml")) } RibbonBackStageMenuItem{ - menuText: "Settings" + menuText: qsTr("Settings") menuIcon: RibbonIcons.Settings type: RibbonBackStageView.MenuItemLocation.Tail sourceUrl: Qt.resolvedUrl("pages/SettingsMenuPage.qml") diff --git a/example/qml/Qt6/pages/SettingsMenuPage.qml b/example/qml/Qt6/pages/SettingsMenuPage.qml index ed330d0..ab273e2 100644 --- a/example/qml/Qt6/pages/SettingsMenuPage.qml +++ b/example/qml/Qt6/pages/SettingsMenuPage.qml @@ -108,5 +108,43 @@ RibbonBackStagePage{ } } } + RibbonBackStageGroup{ + Layout.alignment: Qt.AlignTop + Layout.preferredHeight: lang_combo.height + 40 + Layout.fillWidth: true + groupName: qsTr("Language") + ColumnLayout{ + RowLayout{ + RibbonText{ + text: qsTr("Current Language: ") + } + RibbonComboBox{ + id: lang_combo + model: ListModel { + id: model_lang + } + iconSource: RibbonIcons.LocalLanguage + Component.onCompleted: update_state() + onActivated: { + RibbonLocalization.currentLanguage = currentText + } + Connections{ + target: RibbonLocalization + function onCurrentLanguageChanged(){ + lang_combo.update_state() + } + } + function update_state(){ + model_lang.clear() + let langs = RibbonLocalization.languageList() + for(let i = 0; i < langs.length; i++){ + model_lang.append({text:langs[i]}) + } + currentIndex = find(RibbonLocalization.currentLanguage) + } + } + } + } + } } } diff --git a/lib_source/CMakeLists.txt b/lib_source/CMakeLists.txt index 938aa1f..6d1fe9a 100644 --- a/lib_source/CMakeLists.txt +++ b/lib_source/CMakeLists.txt @@ -18,7 +18,7 @@ endif() # Find Qt package find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core) -find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Quick Qml REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Quick Qml LinguistTools REQUIRED) # Determine library type and plugin target name based on build type if (RIBBONUI_BUILD_STATIC_LIB) @@ -30,6 +30,9 @@ else() set(PLUGIN_TARGET_NAME ${PROJECT_NAME}) endif() +# List all ts files to be used in the project +set(ts_files i18n/${PROJECT_NAME}_zh_CN.ts i18n/${PROJECT_NAME}_en_US.ts) + # List of QML files to be included in the project set(qml_files RibbonTabBar.qml RibbonTabButton.qml RibbonView.qml @@ -58,8 +61,11 @@ list(TRANSFORM qml_files PREPEND ${qml_prefix}) # List of source files to be included in the project set (source_files - ribbonui.cpp ribbonui.h definitions.h ribbontheme.h ribbontheme.cpp - platformsupport.h) + include/ribbonui.h source/ribbonui.cpp + include/definitions.h + include/ribbontheme.h source/ribbontheme.cpp + include/platformsupport.h + include/ribbonlocalization.h source/ribbonlocalization.cpp) # Configure version header set(__ribbonui_project_version "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") @@ -70,7 +76,7 @@ list(APPEND source_files ${CMAKE_CURRENT_BINARY_DIR}/${__ribbonui_project_name_l # Add platform-specific source files for Apple if(APPLE) - list(APPEND source_files platformsupport.mm) + list(APPEND source_files source/platformsupport.mm) endif() # Set properties for QML files @@ -89,6 +95,31 @@ endif() # Define the RibbonUI library qt_add_library(${PROJECT_NAME} ${LIB_TYPE}) +# Add i18n files +set_source_files_properties(${ts_files} PROPERTIES OUTPUT_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/i18n) + +if(QT_VERSION VERSION_LESS 6.0) + qt5_create_translation_plus(qm_files ${CMAKE_CURRENT_SOURCE_DIR} ${ts_files}) + foreach(qm_file ${qm_files}) + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" r_qm_file ${qm_file}) + list(APPEND r_qm_files ${r_qm_file}) + endforeach() + qt5_add_resources_plus(${PROJECT_NAME} "${PROJECT_NAME}-translations" + PREFIX "/" + FILES ${r_qm_files} + ) +else() + qt6_create_translation(qm_files ${CMAKE_CURRENT_SOURCE_DIR} ${ts_files}) + foreach(qm_file ${qm_files}) + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" r_qm_file ${qm_file}) + list(APPEND r_qm_files ${r_qm_file}) + endforeach() + qt6_add_resources(${PROJECT_NAME} "${PROJECT_NAME}-translations" + PREFIX "/" + FILES ${r_qm_files} + ) +endif() + # Define the QML module for the library qt_add_qml_module(${PROJECT_NAME} PLUGIN_TARGET ${PLUGIN_TARGET_NAME} @@ -130,7 +161,7 @@ target_link_libraries(${PROJECT_NAME} PUBLIC # Include directories target_include_directories(${PROJECT_NAME} PUBLIC - ${PROJECT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/3rdparty/qwindowkit/include ) diff --git a/lib_source/i18n/RibbonUI_en_US.ts b/lib_source/i18n/RibbonUI_en_US.ts new file mode 100644 index 0000000..3bea03c --- /dev/null +++ b/lib_source/i18n/RibbonUI_en_US.ts @@ -0,0 +1,376 @@ + + + + + RibbonBackStageGroup + + + + Title + + + + + RibbonBackStagePage + + + + Name + + + + + RibbonBackStageView + + + + Back + + + + + + Close + + + + + + Minimize + + + + + + Restore + + + + + + Maximize + + + + + RibbonLineEdit + + + + Please input: + + + + + + Clear + + + + + RibbonMessageBar + + + + Link + + + + + + Close + + + + + + See More + + + + + + ActionA + + + + + + ActionB + + + + + + ActionA Clicked + + + + + + ActionB Clicked + + + + + RibbonMessageBarGroup + + + + Clear All + + + + + + Show all messages + + + + + + Hide all messages + + + + + RibbonPageIndicator + + + + Previous + + + + + + Next + + + + + RibbonProgressBar + + + + Loading + + + + + RibbonSwitchButton + + + + Open + + + + + + Close + + + + + RibbonTabBar + + + + Settings + + + + + + Show + + + + + + Hide + + + + + + RibbonTabBar: Error loading component: + + + + + RibbonTabGroup + + + + Open + + + + + + 's external + + + + + RibbonTextBoxMenu + + + + Cut + + + + + + Copy + + + + + + Paste + + + + + + Select All + + + + + RibbonTextEdit + + + + Please input: + + + + + + Clear + + + + + RibbonTitleBar + + + + Close + + + + + + Minimize + + + + + + Restore + + + + + + Maximize + + + + + + Style + + + + + + Modern + + + + + + Classic + + + + + + Dark Mode + + + + + + Stay on Top + + + + + RibbonTour + + + + Don't auto pop up + + + + + + Previous + + + + + + Finish + + + + + + Next + + + + + RibbonWindow + + + + Quit + + + + + + Minimize + + + + + + Cancel + + + + + + Do you want to close this window? + + + + + + Please note + + + + diff --git a/lib_source/i18n/RibbonUI_zh_CN.ts b/lib_source/i18n/RibbonUI_zh_CN.ts new file mode 100644 index 0000000..5b14fc2 --- /dev/null +++ b/lib_source/i18n/RibbonUI_zh_CN.ts @@ -0,0 +1,377 @@ + + + + + RibbonBackStageGroup + + + + Title + 标题 + + + + RibbonBackStagePage + + + + Name + 页面名称 + + + + RibbonBackStageView + + + + Back + 返回 + + + + + Close + 关闭 + + + + + Minimize + 最小化 + + + + + Restore + 还原 + + + + + Maximize + 最大化 + + + + RibbonLineEdit + + + + Please input: + 请输入: + + + + + Clear + 清除 + + + + RibbonMessageBar + + + + Link + 外部链接 + + + + + Close + 关闭 + + + + + See More + 查看更多 + + + + + ActionA + 按钮A + + + + + ActionB + 按钮B + + + + + ActionA Clicked + 按钮A被点击 + + + + + ActionB Clicked + 按钮B被点击 + + + + RibbonMessageBarGroup + + + + Clear All + 清除全部 + + + + + Show all messages + 显示全部消息 + + + + + Hide all messages + 隐藏全部消息 + + + + RibbonPageIndicator + + + + Previous + 上一个 + + + + + Next + 下一个 + + + + RibbonProgressBar + + + + Loading + 加载中 + + + + RibbonSwitchButton + + + + Open + 打开 + + + + + Close + 关闭 + + + + RibbonTabBar + + + + Settings + 设置 + + + + + Show + 显示 + + + + + Hide + 隐藏 + + + + + RibbonTabBar: Error loading component: + RibbonTabBar:加载组件失败: + + + + RibbonTabGroup + + + + Open + 打开 + + + + + 's external + 的外部链接 + + + + RibbonTextBoxMenu + + + + Cut + 剪切 + + + + + Copy + 拷贝 + + + + + Paste + 粘贴 + + + + + Select All + 全选 + + + + + RibbonTextEdit + + + + Please input: + 请输入: + + + + + Clear + 清除 + + + + RibbonTitleBar + + + + Close + 关闭 + + + + + Minimize + 最小化 + + + + + Restore + 还原 + + + + + Maximize + 最大化 + + + + + Style + 风格 + + + + + Modern + 现代化 + + + + + Classic + 经典 + + + + + Dark Mode + 暗色模式 + + + + + Stay on Top + 总是显示在顶层 + + + + RibbonTour + + + + Don't auto pop up + 不要自动弹出 + + + + + Previous + 上一个 + + + + + Finish + 完成 + + + + + Next + 下一个 + + + + RibbonWindow + + + + Quit + 退出 + + + + + Minimize + 最小化 + + + + + Cancel + 取消 + + + + + Do you want to close this window? + 需要关闭窗口吗? + + + + + Please note + 请注意 + + + diff --git a/lib_source/definitions.h b/lib_source/include/definitions.h similarity index 99% rename from lib_source/definitions.h rename to lib_source/include/definitions.h index abaa789..07f4c52 100644 --- a/lib_source/definitions.h +++ b/lib_source/include/definitions.h @@ -2355,8 +2355,8 @@ enum class RibbonIcons_Filled{ Q_ENUM_NS(RibbonIcons_Filled) QML_NAMED_ELEMENT(RibbonIcons_Filled) #if (QT_VERSION > QT_VERSION_CHECK(6, 3, 0)) - Q_CLASSINFO("QML.Creatable", "false") - Q_CLASSINFO("QML.UncreatableReason", "This type is right-valued only.") +Q_CLASSINFO("QML.Creatable", "false") +Q_CLASSINFO("QML.UncreatableReason", "This type is right-valued only.") #elif (QT_VERSION <= QT_VERSION_CHECK(6, 3, 0)) QML_UNCREATABLE("This type is right-valued only.") #endif @@ -4718,30 +4718,30 @@ QML_UNCREATABLE("This type is right-valued only.") #define Q_PROPERTY_RW(TYPE, M) \ Q_PROPERTY(TYPE M MEMBER _##M NOTIFY M##Changed FINAL) \ -public: \ + public: \ Q_SIGNAL void M##Changed(); \ void M(TYPE in_##M) \ - { \ +{ \ _##M = in_##M; \ Q_EMIT M##Changed(); \ - } \ +} \ TYPE M() \ - { \ +{ \ return _##M; \ - } \ +} \ \ -private: \ + private: \ TYPE _##M; #define Q_PROPERTY_R(TYPE, M) \ Q_PROPERTY(TYPE M READ M NOTIFY M##Changed FINAL) \ -public: \ + public: \ Q_SIGNAL void M##Changed(); \ TYPE M() \ - { \ +{ \ return _##M; \ - } \ -private: \ +} \ + private: \ TYPE _##M; namespace RibbonPopupDialogType { diff --git a/lib_source/platformsupport.h b/lib_source/include/platformsupport.h similarity index 100% rename from lib_source/platformsupport.h rename to lib_source/include/platformsupport.h diff --git a/lib_source/include/ribbonlocalization.h b/lib_source/include/ribbonlocalization.h new file mode 100644 index 0000000..94e0025 --- /dev/null +++ b/lib_source/include/ribbonlocalization.h @@ -0,0 +1,46 @@ +#ifndef RIBBONLOCALIZATION_H +#define RIBBONLOCALIZATION_H + +#include +#include +#include + +class RibbonLocalization : public QQuickItem +{ + Q_OBJECT + QML_ELEMENT + QML_SINGLETON + QML_NAMED_ELEMENT(RibbonLocalization) + Q_PROPERTY(QString currentLanguage READ currentLanguage WRITE setCurrentLanguage NOTIFY currentLanguageChanged FINAL) +public: + typedef QPair LangItem; // example: <"zh_CN", "qrc://i18n/xxx_zh_CN.qm"> + typedef QMap> Translator; // example: <"main", mainTranslator> + typedef QMap ModuleTranslator; // example: + static RibbonLocalization* create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return instance();} + static RibbonLocalization* instance(); + Q_INVOKABLE bool registerLanguage(QString langName, QString path, QString moduleName); + Q_INVOKABLE bool removeLanguage(QString langName, QString path); + Q_INVOKABLE void bindEngine(); + Q_INVOKABLE QList languageList(); + QString currentLanguage(); + bool setCurrentLanguage(QString langName); + // Use if you need to directly save/load language from config files + Q_INVOKABLE virtual void loadCurrentLanguage(){}; + virtual bool saveCurrentLanguage(const QString &language){return false;}; +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) +public: +#else +private: + Q_DISABLE_COPY_MOVE(RibbonLocalization) +#endif + RibbonLocalization(); + ~RibbonLocalization(); +private: + ModuleTranslator moduleLangList; + Translator transList; + QString _currentLang; +signals: + void currentLanguageChanged(); +}; + +#endif // RIBBONLOCALIZATION_H diff --git a/lib_source/ribbontheme.h b/lib_source/include/ribbontheme.h similarity index 91% rename from lib_source/ribbontheme.h rename to lib_source/include/ribbontheme.h index 6f847d1..6bdae6b 100644 --- a/lib_source/ribbontheme.h +++ b/lib_source/include/ribbontheme.h @@ -11,7 +11,7 @@ class RibbonTheme : public QQuickItem QML_SINGLETON QML_NAMED_ELEMENT(RibbonTheme) - Q_PROPERTY(bool isDarkMode READ isDarkMode() NOTIFY isDarkModeChanged FINAL) + Q_PROPERTY(bool isDarkMode READ isDarkMode NOTIFY isDarkModeChanged FINAL) Q_PROPERTY_RW(RibbonThemeType::ThemeMode,themeMode) Q_PROPERTY_RW(bool,modernStyle) Q_PROPERTY_RW(bool,nativeText) diff --git a/lib_source/ribbonui.h b/lib_source/include/ribbonui.h similarity index 58% rename from lib_source/ribbonui.h rename to lib_source/include/ribbonui.h index 21525f9..099f039 100644 --- a/lib_source/ribbonui.h +++ b/lib_source/include/ribbonui.h @@ -3,6 +3,7 @@ #include #include "definitions.h" +#include "ribbonlocalization.h" class RibbonUI : public QQuickItem { @@ -14,11 +15,16 @@ class RibbonUI : public QQuickItem Q_PROPERTY_R(int, qtVersion) Q_PROPERTY_R(int, isWin11) Q_PROPERTY_RW(QVariantMap, windowsSet) + Q_PROPERTY(bool autoLoadLanguage READ autoLoadLanguage WRITE setAutoLoadLanguage NOTIFY autoLoadLanguageChanged FINAL) public: static RibbonUI* instance(); static RibbonUI* create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return instance();} RIBBONUI_API static void init(); RIBBONUI_API static void registerTypes(const char *uri); + RIBBONUI_API Q_INVOKABLE void setTranslator(RibbonLocalization *translator = RibbonLocalization::instance()); + Q_INVOKABLE void initTranslator(); + bool autoLoadLanguage(){return _autoLoadLanguage;}; + void setAutoLoadLanguage(bool value); #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) public: #else @@ -26,6 +32,12 @@ private: Q_DISABLE_COPY_MOVE(RibbonUI) #endif explicit RibbonUI(QQuickItem *parent = nullptr); +private: + RibbonLocalization* _translator; + bool _autoLoadLanguage = false; + +signals: + void autoLoadLanguageChanged(); }; #endif // RIBBONUI_H diff --git a/lib_source/qml/Qt5/RibbonBackStageMenuItem.qml b/lib_source/qml/Qt5/RibbonBackStageMenuItem.qml index b4411fa..4cc985d 100644 --- a/lib_source/qml/Qt5/RibbonBackStageMenuItem.qml +++ b/lib_source/qml/Qt5/RibbonBackStageMenuItem.qml @@ -4,6 +4,7 @@ import RibbonUI 1.1 RibbonObject { id: control required property string menuText + property int id property var menuIcon property var menuIconFilled required property var type diff --git a/lib_source/qml/Qt5/RibbonBackStageView.qml b/lib_source/qml/Qt5/RibbonBackStageView.qml index 54cc7e2..cf34cb6 100644 --- a/lib_source/qml/Qt5/RibbonBackStageView.qml +++ b/lib_source/qml/Qt5/RibbonBackStageView.qml @@ -44,6 +44,12 @@ Popup { if(data_container.resources[index] instanceof RibbonBackStageMenuItem) { let item = data_container.resources[index] + item.menuTextChanged.connect(function(){ + item.getPropertiesReady() + pageModel[item.id] = item.properties + refreshModel() + }) + item.id = pageModel.length item.getPropertiesReady() pageModel.push(item.properties) } @@ -555,6 +561,11 @@ Popup { body_menu_list.model.append(item) } } + menu_bg.currentMenu = 0 + head_menu_list.currentIndex = 0 + body_menu_list.currentIndex = 0 + tail_menu_list.currentIndex = 0 + content_view.currentIndex = 0 } function alphaTohex(color, alpha) diff --git a/lib_source/qml/Qt5/RibbonTabBar.qml b/lib_source/qml/Qt5/RibbonTabBar.qml index b2f3f3b..3f427fe 100644 --- a/lib_source/qml/Qt5/RibbonTabBar.qml +++ b/lib_source/qml/Qt5/RibbonTabBar.qml @@ -225,7 +225,8 @@ Item{ { let item = stack.contentData[i] if(item instanceof RibbonTabPage){ - let btn = ribbonTabButton.createObject(bar,{text:qsTr(item.title),index:sign}) + let btn = ribbonTabButton.createObject(bar,{text:item.title,index:sign}) + item.titleChanged.connect(function(){btn.text=item.title}) if (sign===0) { btn.checked = true diff --git a/lib_source/qml/Qt5/RibbonTour.qml b/lib_source/qml/Qt5/RibbonTour.qml index d578016..cf0a7b3 100644 --- a/lib_source/qml/Qt5/RibbonTour.qml +++ b/lib_source/qml/Qt5/RibbonTour.qml @@ -154,6 +154,16 @@ Popup { if(data_container.resources[index] instanceof RibbonTourItem) { let item = data_container.resources[index] + item.titleChanged.connect(function(){ + item.getPropertiesReady() + targetList[item.id] = item.properties + }) + if(item.text){ + item.textChanged.connect(function(){ + targetList[item.id].text = item.text + }) + } + item.id = targetList.length item.getPropertiesReady() targetList.push(item.properties) } @@ -164,7 +174,7 @@ Popup { Popup{ id: rec - parent: Overlay.overlay + parent: popup.parent margins: 0 padding: 0 topInset: 0 diff --git a/lib_source/qml/Qt5/RibbonTourItem.qml b/lib_source/qml/Qt5/RibbonTourItem.qml index df947b0..b5d2c3b 100644 --- a/lib_source/qml/Qt5/RibbonTourItem.qml +++ b/lib_source/qml/Qt5/RibbonTourItem.qml @@ -4,6 +4,7 @@ import RibbonUI 1.1 RibbonObject { id: control required property string title + property int id property string text property var target property var enterFunc diff --git a/lib_source/qml/Qt5/RibbonWindow.qml b/lib_source/qml/Qt5/RibbonWindow.qml index 5f4c99b..b071f90 100644 --- a/lib_source/qml/Qt5/RibbonWindow.qml +++ b/lib_source/qml/Qt5/RibbonWindow.qml @@ -73,6 +73,8 @@ Window { { windowAgent.setWindowAttribute("blur-effect", blurBehindWindow ? RibbonTheme.isDarkMode ? "dark" : "light" : "none") } + RibbonLocalization.bindEngine(); + RibbonUI.setTranslator(RibbonLocalization) } Item{ id: windowItems diff --git a/lib_source/qml/Qt6/RibbonBackStageMenuItem.qml b/lib_source/qml/Qt6/RibbonBackStageMenuItem.qml index d19f086..ac50d9f 100644 --- a/lib_source/qml/Qt6/RibbonBackStageMenuItem.qml +++ b/lib_source/qml/Qt6/RibbonBackStageMenuItem.qml @@ -4,6 +4,7 @@ import RibbonUI RibbonObject { id: control required property string menuText + property int id property var menuIcon property var menuIconFilled required property var type diff --git a/lib_source/qml/Qt6/RibbonBackStageView.qml b/lib_source/qml/Qt6/RibbonBackStageView.qml index ae937e8..b829e04 100644 --- a/lib_source/qml/Qt6/RibbonBackStageView.qml +++ b/lib_source/qml/Qt6/RibbonBackStageView.qml @@ -44,6 +44,12 @@ Popup { if(data_container.resources[index] instanceof RibbonBackStageMenuItem) { let item = data_container.resources[index] + item.menuTextChanged.connect(function(){ + item.getPropertiesReady() + pageModel[item.id] = item.properties + refreshModel() + }) + item.id = pageModel.length item.getPropertiesReady() pageModel.push(item.properties) } @@ -555,5 +561,10 @@ Popup { body_menu_list.model.append(item) } } + menu_bg.currentMenu = 0 + head_menu_list.currentIndex = 0 + body_menu_list.currentIndex = 0 + tail_menu_list.currentIndex = 0 + content_view.currentIndex = 0 } } diff --git a/lib_source/qml/Qt6/RibbonTabBar.qml b/lib_source/qml/Qt6/RibbonTabBar.qml index 49a75d2..2322910 100644 --- a/lib_source/qml/Qt6/RibbonTabBar.qml +++ b/lib_source/qml/Qt6/RibbonTabBar.qml @@ -225,7 +225,8 @@ Item{ { let item = stack.contentData[i] if(item instanceof RibbonTabPage){ - let btn = ribbonTabButton.createObject(bar,{text:qsTr(item.title),index:sign}) + let btn = ribbonTabButton.createObject(bar,{text:item.title,index:sign}) + item.titleChanged.connect(function(){btn.text=item.title}) if (sign===0) { btn.checked = true diff --git a/lib_source/qml/Qt6/RibbonTour.qml b/lib_source/qml/Qt6/RibbonTour.qml index 37bf484..5311f45 100644 --- a/lib_source/qml/Qt6/RibbonTour.qml +++ b/lib_source/qml/Qt6/RibbonTour.qml @@ -57,7 +57,7 @@ Popup { radius: 7 maskOpacity: blurEnabled ? 0.9 : 1 maskBorderColor: RibbonTheme.modernStyle ? - RibbonTheme.isDarkMode ? "#7A7A7A" : "#2C59B7" : + RibbonTheme.isDarkMode ? "#7A7A7A" : "#2C59B7" : RibbonTheme.isDarkMode ? "#5C5D5D" : "#B5B4B5" maskBorderWidth: 1 } @@ -155,6 +155,16 @@ Popup { if(data_container.resources[index] instanceof RibbonTourItem) { let item = data_container.resources[index] + item.titleChanged.connect(function(){ + item.getPropertiesReady() + targetList[item.id] = item.properties + }) + if(item.text){ + item.textChanged.connect(function(){ + targetList[item.id].text = item.text + }) + } + item.id = targetList.length item.getPropertiesReady() targetList.push(item.properties) } diff --git a/lib_source/qml/Qt6/RibbonTourItem.qml b/lib_source/qml/Qt6/RibbonTourItem.qml index 0c92027..10f172f 100644 --- a/lib_source/qml/Qt6/RibbonTourItem.qml +++ b/lib_source/qml/Qt6/RibbonTourItem.qml @@ -4,6 +4,7 @@ import RibbonUI RibbonObject { id: control required property string title + property int id property string text property var target property var enterFunc diff --git a/lib_source/qml/Qt6/RibbonWindow.qml b/lib_source/qml/Qt6/RibbonWindow.qml index a9a115b..6da3a0c 100644 --- a/lib_source/qml/Qt6/RibbonWindow.qml +++ b/lib_source/qml/Qt6/RibbonWindow.qml @@ -73,6 +73,8 @@ Window { { windowAgent.setWindowAttribute("blur-effect", blurBehindWindow ? RibbonTheme.isDarkMode ? "dark" : "light" : "none") } + RibbonLocalization.bindEngine(); + RibbonUI.setTranslator(RibbonLocalization) } Item{ id: windowItems diff --git a/lib_source/platformsupport.mm b/lib_source/source/platformsupport.mm similarity index 100% rename from lib_source/platformsupport.mm rename to lib_source/source/platformsupport.mm diff --git a/lib_source/source/ribbonlocalization.cpp b/lib_source/source/ribbonlocalization.cpp new file mode 100644 index 0000000..c294483 --- /dev/null +++ b/lib_source/source/ribbonlocalization.cpp @@ -0,0 +1,106 @@ +#include "ribbonlocalization.h" +#include +#include +#include + +RibbonLocalization::RibbonLocalization() { + _currentLang = "en_US"; +} + +RibbonLocalization::~RibbonLocalization() { + for (auto item : transList) + item.clear(); +} + +RibbonLocalization* RibbonLocalization::instance(){ + static QMutex mutex; + QMutexLocker locker(&mutex); + + static RibbonLocalization *singleton = nullptr; + if (!singleton) { + singleton = new RibbonLocalization(); + } + return singleton; +} + +bool RibbonLocalization::registerLanguage(QString langName, QString path, QString moduleName){ + LangItem temp(langName, path); + if(!moduleLangList.contains(temp)){ + if(!transList.contains(moduleName)){ + transList.insert(moduleName, QSharedPointer(new QTranslator)); + if(langName == _currentLang){ + Q_UNUSED(transList[moduleName].get()->load(path)); + qApp->installTranslator(transList[moduleName].get()); + } + } + moduleLangList.insert(temp, moduleName); + return true; + } + return false; +} + +bool RibbonLocalization::removeLanguage(QString langName, QString path){ + LangItem temp(langName, path); + if(moduleLangList.contains(temp)){ + if(langName == _currentLang){ + qApp->removeTranslator(transList[moduleLangList[temp]].get()); + _currentLang = "en_US"; + emit currentLanguageChanged(); + } + transList[moduleLangList[temp]].clear(); + transList.remove(moduleLangList[temp]); + moduleLangList.remove(temp); + return true; + } + return false; +} + +QString RibbonLocalization::currentLanguage(){ + return _currentLang; +} + +bool RibbonLocalization::setCurrentLanguage(QString langName){ + bool hasChanged = false; + QMap isNeeded; + for(auto langItem : moduleLangList.keys()){ + if(langItem.first == langName){ + isNeeded[moduleLangList[langItem]] = true; + Q_UNUSED(transList[moduleLangList[langItem]].get()->load(langItem.second)); + _currentLang = langName; + qApp->installTranslator(transList[moduleLangList[langItem]].get());; + hasChanged = true; + } + else{ + if(!isNeeded[moduleLangList[langItem]]){ + qApp->removeTranslator(transList[moduleLangList[langItem]].get()); + } + } + } + if(hasChanged){ + saveCurrentLanguage(langName); + emit currentLanguageChanged(); + } + return hasChanged; +} + +void RibbonLocalization::bindEngine(){ + QQmlApplicationEngine * engine = dynamic_cast(qmlEngine(this)); + Q_ASSERT(engine); + if (!engine) + return; + QObject::connect(this, &RibbonLocalization::currentLanguageChanged, engine, [engine]() -> void { + engine->retranslate(); + }); +} + +QList RibbonLocalization::languageList(){ + QList list; + QSet set; + for(auto langItem : moduleLangList.keys()){ + set.insert(langItem.first); + } + for(auto setItem : set){ + list.append(setItem); + } + return list; +} diff --git a/lib_source/ribbontheme.cpp b/lib_source/source/ribbontheme.cpp similarity index 100% rename from lib_source/ribbontheme.cpp rename to lib_source/source/ribbontheme.cpp diff --git a/lib_source/ribbonui.cpp b/lib_source/source/ribbonui.cpp similarity index 52% rename from lib_source/ribbonui.cpp rename to lib_source/source/ribbonui.cpp index 74b2d7d..a59103a 100644 --- a/lib_source/ribbonui.cpp +++ b/lib_source/source/ribbonui.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "ribbonui_version.h" RibbonUI::RibbonUI(QQuickItem *parent) @@ -12,6 +13,7 @@ RibbonUI::RibbonUI(QQuickItem *parent) _version = RIBBONUI_VERSION; _qtVersion = QString(qVersion()).replace('.',"").toInt(); _isWin11 = QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 22000); + _translator = RibbonLocalization::instance(); } RibbonUI* RibbonUI::instance(){ @@ -45,3 +47,41 @@ void RibbonUI::registerTypes(const char *uri) Q_UNUSED(uri); QWK::registerTypes(nullptr); } + +void RibbonUI::setTranslator(RibbonLocalization *translator){ + _translator = translator; + initTranslator(); +} + +void RibbonUI::initTranslator(){ + QDir dir(":/i18n"); + QStringList filters; + filters<<"*.qm"; + dir.setNameFilters(filters); + QStringList matchedFiles = dir.entryList(); + for(auto file : matchedFiles){ + QString project, lang; + int start = 0; + int end = file.indexOf('_'); + + if (end > start) + project = file.mid(start, end - start); + + start = file.indexOf('_') + 1; + end = file.lastIndexOf('.'); + if (start > 0 && end > start) + lang = file.mid(start, end - start); + + if(!lang.isEmpty() && !project.isEmpty()){ + if(_autoLoadLanguage || (!_autoLoadLanguage && project == "RibbonUI")){ + _translator->registerLanguage(lang, ":/i18n/" + file, project); + continue; + } + } + } +} + +void RibbonUI::setAutoLoadLanguage(bool value){ + _autoLoadLanguage = value; + initTranslator(); +}