From 77c1b4f51aa164d546f743d01b3ef1332dc73fd2 Mon Sep 17 00:00:00 2001 From: xkeyC <3334969096@qq.com> Date: Sun, 16 Nov 2025 15:09:56 +0800 Subject: [PATCH] feat: use Opus-MT-StarCitizen-zh-en model --- lib/common/conf/conf.dart | 4 +- lib/common/utils/multi_window_manager.dart | 2 +- .../input_method/input_method_dialog_ui.dart | 238 +++++++++--------- .../input_method_dialog_ui_model.dart | 2 +- rust/src/ort_models/opus_mt.rs | 4 +- 5 files changed, 126 insertions(+), 124 deletions(-) diff --git a/lib/common/conf/conf.dart b/lib/common/conf/conf.dart index 6e00eb3..cdb807c 100644 --- a/lib/common/conf/conf.dart +++ b/lib/common/conf/conf.dart @@ -1,7 +1,7 @@ class ConstConf { - static const String appVersion = "2.15.1 Beta"; + static const String appVersion = "2.15.1 Beta2"; static const int appVersionCode = 71; - static const String appVersionDate = "2025-11-15"; + static const String appVersionDate = "2025-11-16"; static const _gameChannels = [ "LIVE", "4.0_PREVIEW", diff --git a/lib/common/utils/multi_window_manager.dart b/lib/common/utils/multi_window_manager.dart index 9a70968..74742de 100644 --- a/lib/common/utils/multi_window_manager.dart +++ b/lib/common/utils/multi_window_manager.dart @@ -77,7 +77,7 @@ class MultiWindowManager { ), ); await Future.delayed(Duration(milliseconds: 500)).then((_) async { - await controller.setFrame(const Rect.fromLTWH(0, 0, 800, 1200)); + await controller.setFrame(const Rect.fromLTWH(0, 0, 720, 800)); await controller.setTitle(title); await controller.center(); await controller.show(); diff --git a/lib/ui/home/input_method/input_method_dialog_ui.dart b/lib/ui/home/input_method/input_method_dialog_ui.dart index 630b47e..e52976b 100644 --- a/lib/ui/home/input_method/input_method_dialog_ui.dart +++ b/lib/ui/home/input_method/input_method_dialog_ui.dart @@ -29,133 +29,135 @@ class InputMethodDialogUI extends HookConsumerWidget { }, const []); return ContentDialog( - constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * .8), + constraints: BoxConstraints(maxWidth: MediaQuery + .of(context) + .size + .width * .8), title: makeTitle(context, state, model, destTextCtrl), content: state.keyMaps == null ? makeLoading(context) : Column( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox(height: 12), - InfoBar( - title: Text(S.current.input_method_usage_instructions), - content: Text(S.current.input_method_input_text_instructions), - ), - SizedBox(height: 12), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - GestureDetector( - child: Padding( - padding: const EdgeInsets.all(3), - child: Text( - S.current.input_method_online_version_prompt, - style: TextStyle(color: Color(0xff4ca0e0), fontSize: 12), - ), - ), - onTap: () { - launchUrlString("https://ime.citizenwiki.cn/"); - }, - ), - ], - ), - SizedBox(height: 12), - TextFormBox( - placeholder: state.isEnableAutoTranslate - ? "${S.current.input_method_input_placeholder}\n\n本地翻译模型对中英混合处理能力较差,如有需要,建议分开发送。" - : S.current.input_method_input_placeholder, - controller: srcTextCtrl, - maxLines: 5, - placeholderStyle: TextStyle(color: Colors.white.withValues(alpha: .6)), - style: TextStyle(fontSize: 16, color: Colors.white), - onChanged: (str) async { - final text = model.onTextChange("src", str); - destTextCtrl.text = text ?? ""; - if (text != null) { - model.checkAutoTranslate(); - } - }, - ), - SizedBox(height: 16), - Center( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (state.isAutoTranslateWorking) - SizedBox(width: 24, height: 24, child: ProgressRing()) - else - SizedBox(width: 24, height: 24, child: Icon(FluentIcons.down)), - ], + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox(height: 12), + InfoBar( + title: Text(S.current.input_method_usage_instructions), + content: Text(S.current.input_method_input_text_instructions), + ), + SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + GestureDetector( + child: Padding( + padding: const EdgeInsets.all(3), + child: Text( + S.current.input_method_online_version_prompt, + style: TextStyle(color: Color(0xff4ca0e0), fontSize: 12), ), ), - SizedBox(height: 16), - TextFormBox( - placeholder: S.current.input_method_encoded_text_placeholder, - controller: destTextCtrl, - maxLines: 5, - placeholderStyle: TextStyle(color: Colors.white.withValues(alpha: .6)), - style: TextStyle(fontSize: 16, color: Colors.white), - enabled: true, - onChanged: (str) {}, - ), - SizedBox(height: 24), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Row( - children: [ - Text(S.current.input_method_auto_translate), - SizedBox(width: 6), - ToggleSwitch( - checked: state.isEnableAutoTranslate, - onChanged: (b) => _onSwitchAutoTranslate(context, model, b), - ), - ], - ), - SizedBox(width: 24), - Row( - children: [ - Text(S.current.input_method_remote_input_service), - SizedBox(width: 6), - if (serverState.isServerStartup) - Button( - onPressed: () { - showDialog(context: context, builder: (BuildContext context) => ServerQrDialogUI()); - }, - child: Text(serverState.serverAddressText ?? "...", style: TextStyle(fontSize: 14)), - ), - SizedBox(width: 14), - ToggleSwitch( - checked: serverState.isServerStartup, - onChanged: (b) => _onSwitchServer(context, b, serverModel), - ), - ], - ), - ], - ), - SizedBox(height: 24), - Row( - children: [ - Expanded( - child: Text( - textAlign: TextAlign.end, - S.current.input_method_disclaimer, - style: TextStyle(fontSize: 13, color: Colors.white.withValues(alpha: .6)), - ), - ), - ], - ), + onTap: () { + launchUrlString("https://ime.citizenwiki.cn/"); + }, + ), + ], + ), + SizedBox(height: 12), + TextFormBox( + placeholder: state.isEnableAutoTranslate + ? "${S.current + .input_method_input_placeholder}\n\n本地翻译模型对中英混合处理能力较差,如有需要,建议分开发送。" + : S.current.input_method_input_placeholder, + controller: srcTextCtrl, + maxLines: 5, + placeholderStyle: TextStyle(color: Colors.white.withValues(alpha: .6)), + style: TextStyle(fontSize: 16, color: Colors.white), + onChanged: (str) async { + final text = model.onTextChange("src", str); + destTextCtrl.text = text ?? ""; + if (text != null) { + model.checkAutoTranslate(); + } + }, + ), + SizedBox(height: 16), + Center( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (state.isAutoTranslateWorking) + SizedBox(width: 24, height: 24, child: ProgressRing()) + else + SizedBox(width: 24, height: 24, child: Icon(FluentIcons.down)), ], ), + ), + SizedBox(height: 16), + TextFormBox( + placeholder: S.current.input_method_encoded_text_placeholder, + controller: destTextCtrl, + maxLines: 5, + placeholderStyle: TextStyle(color: Colors.white.withValues(alpha: .6)), + style: TextStyle(fontSize: 16, color: Colors.white), + enabled: true, + onChanged: (str) {}, + ), + SizedBox(height: 24), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Row( + children: [ + Text(S.current.input_method_auto_translate), + SizedBox(width: 6), + ToggleSwitch( + checked: state.isEnableAutoTranslate, + onChanged: (b) => _onSwitchAutoTranslate(context, model, b), + ), + ], + ), + SizedBox(width: 24), + Row( + children: [ + Text(S.current.input_method_remote_input_service), + SizedBox(width: 6), + if (serverState.isServerStartup) + Button( + onPressed: () { + showDialog(context: context, builder: (BuildContext context) => ServerQrDialogUI()); + }, + child: Text(serverState.serverAddressText ?? "...", style: TextStyle(fontSize: 14)), + ), + SizedBox(width: 14), + ToggleSwitch( + checked: serverState.isServerStartup, + onChanged: (b) => _onSwitchServer(context, b, serverModel), + ), + ], + ), + ], + ), + SizedBox(height: 24), + Row( + children: [ + Expanded( + child: Text( + textAlign: TextAlign.end, + S.current.input_method_disclaimer, + style: TextStyle(fontSize: 13, color: Colors.white.withValues(alpha: .6)), + ), + ), + ], + ), + ], + ), ); } - Widget makeTitle( - BuildContext context, - InputMethodDialogUIState state, - InputMethodDialogUIModel model, - TextEditingController destTextCtrl, - ) { + Widget makeTitle(BuildContext context, + InputMethodDialogUIState state, + InputMethodDialogUIModel model, + TextEditingController destTextCtrl,) { return Row( children: [ IconButton( @@ -223,8 +225,8 @@ class InputMethodDialogUI extends HookConsumerWidget { "是否下载 AI 模型以使用翻译功能?", Text( "大约需要 200MB 的本地空间。" - "\n\n我们使用本地模型进行翻译,您的翻译数据不会发送给任何第三方。" - "\n\n模型未对游戏术语优化,请自行判断使用。", + "\n\n我们使用本地模型进行翻译,您的翻译数据不会发送给任何第三方。" + "\n\nOpus-MT-StarCitizen-zh-en 是汉化盒子团队基于 Opus-MT 模型微调得到的模型,对游戏术语进行了优化。", ), ); if (userOK) { diff --git a/lib/ui/home/input_method/input_method_dialog_ui_model.dart b/lib/ui/home/input_method/input_method_dialog_ui_model.dart index f5320db..52d8485 100644 --- a/lib/ui/home/input_method/input_method_dialog_ui_model.dart +++ b/lib/ui/home/input_method/input_method_dialog_ui_model.dart @@ -195,7 +195,7 @@ class InputMethodDialogUIModel extends _$InputMethodDialogUIModel { } } - String get _localTranslateModelName => "opus-mt-zh-en_onnx"; + String get _localTranslateModelName => "Opus-MT-StarCitizen-zh-en"; String get _localTranslateModelDir => "${appGlobalState.applicationSupportDir}/onnx_models"; diff --git a/rust/src/ort_models/opus_mt.rs b/rust/src/ort_models/opus_mt.rs index ef274d9..c637267 100644 --- a/rust/src/ort_models/opus_mt.rs +++ b/rust/src/ort_models/opus_mt.rs @@ -393,11 +393,11 @@ mod tests { #[test] fn test_translation() { let model = OpusMtModel::new( - "C:\\Users\\xkeyc\\Downloads\\onnx_models\\opus-mt-zh-en", + "E:\\Project\\StarCtizen\\Opus-MT-StarCitizen\\results\\final_model", "_q4f16", ) .unwrap(); - let result = model.translate("你好世界").unwrap(); + let result = model.translate("北极星要炸了,快撤!").unwrap(); println!("Translation: {}", result); } }