Skip to content

Commit 5b28e51

Browse files
feat: add bidirectional translation support (#17)
Enhanced translation functionality to support both Chinese-to-English and English-to-Chinese translation directions Added command-line options --to-english and --to-chinese for explicit direction control Implemented configurable default translation direction via config command Updated translation prompts for different directions with specific formatting rules Added text wrapping for Chinese content to maintain proper formatting Modified AI service interface to accept translation direction parameter Updated documentation with new features and examples Log: Added bidirectional translation support with configurable direction Influence: 1. Test Chinese-to-English translation with various Chinese text inputs 2. Test English-to-Chinese translation with different English content 3. Verify translation direction configuration persistence 4. Test command-line options for explicit translation direction control 5. Validate translation quality and format preservation 6. Test mixed content handling (Chinese and English in same text) 7. Verify configuration settings for default translation direction feat: 添加双向翻译支持 增强翻译功能,支持中译英和英译中双向翻译 添加命令行选项 --to-english 和 --to-chinese 用于显式控制翻译方向 实现可通过配置命令设置默认翻译方向 为不同翻译方向更新提示词,包含特定的格式规则 添加中文文本自动换行以保持格式规范 修改 AI 服务接口以接受翻译方向参数 更新文档,包含新功能和示例 Log: 新增双向翻译支持,可配置翻译方向 Influence: 1. 测试中译英功能,使用各种中文文本输入 2. 测试英译中功能,使用不同英文内容 3. 验证翻译方向配置的持久性 4. 测试命令行选项的显式翻译方向控制 5. 验证翻译质量和格式保持 6. 测试混合内容处理(中英文混合文本) 7. 验证默认翻译方向的配置设置 Fixes: #16
1 parent 795b902 commit 5b28e51

6 files changed

Lines changed: 179 additions & 35 deletions

File tree

README.md

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@
3838
- 自动审查代码变更
3939
- 性能和安全建议
4040
- 可通过参数禁用
41-
- 🌏 中英双语
42-
- 自动检测中文内容
41+
- 🌏 双向翻译
42+
- 支持中文翻译为英文(默认)
43+
- 支持英文翻译为中文
44+
- 可配置默认翻译方向
4345
- 智能中英互译
4446
- 保持格式规范
4547
- 📋 测试建议
@@ -173,6 +175,10 @@ a line exceeds the recommended value of git.
173175

174176
### 翻译命令
175177

178+
翻译命令支持双向翻译,可以进行中译英或英译中。
179+
180+
#### 基本用法
181+
176182
使用翻译命令有三种方式:
177183
```bash
178184
# 方式1:指定文件路径
@@ -188,11 +194,32 @@ git-commit-helper translate /path/to/existing/file # 文件路径
188194

189195
命令会自动判断参数内容:如果是一个存在的文件路径则读取文件内容进行翻译,否则将参数内容作为文本进行翻译。
190196

197+
#### 翻译方向控制
198+
199+
默认情况下,翻译命令使用配置文件中设置的默认翻译方向(默认为中译英)。你可以通过以下方式控制翻译方向:
200+
201+
```bash
202+
# 中译英(使用默认方向或显式指定)
203+
git-commit-helper translate "这是中文内容"
204+
git-commit-helper translate --to-english "这是中文内容"
205+
206+
# 英译中
207+
git-commit-helper translate --to-chinese "This is English content"
208+
209+
# 设置默认翻译方向
210+
git-commit-helper config --set-translate-direction to-english # 默认中译英
211+
git-commit-helper config --set-translate-direction to-chinese # 默认英译中
212+
```
213+
214+
支持的翻译方向值:
215+
- `to-english``chinese-to-english``中译英`:中文翻译为英文
216+
- `to-chinese``english-to-chinese``英译中`:英文翻译为中文
217+
191218
### 命令概览
192219

193220
| 命令 | 说明 | 示例 |
194221
|------|------|------|
195-
| config | 配置 AI 服务 | `git-commit-helper config [--set-only-chinese <true\|false>/--set-only-english <true\|false>]` |
222+
| config | 配置 AI 服务 | `git-commit-helper config [--set-only-chinese <true\|false>/--set-only-english <true\|false>/--set-translate-direction <to-english\|to-chinese>]` |
196223
| show | 显示当前配置 | `git-commit-helper show` |
197224
| install | 安装 Git Hook | `git-commit-helper install [-f]` |
198225
| ai add | 添加 AI 服务 | `git-commit-helper ai add` |
@@ -202,7 +229,7 @@ git-commit-helper translate /path/to/existing/file # 文件路径
202229
| ai set-timeout | 设置请求超时 | `git-commit-helper ai set-timeout -s 30` |
203230
| ai list | 列出所有服务 | `git-commit-helper ai list` |
204231
| ai test | 测试指定服务 | `git-commit-helper ai test [-t "测试文本"]` |
205-
| translate | 翻译内容 | `git-commit-helper translate [-f 文件] [-t 文本]` |
232+
| translate | 翻译内容 | `git-commit-helper translate [-f 文件] [-t 文本] [--to-english\|--to-chinese]` |
206233
| commit | 生成提交信息 | `git-commit-helper commit [-t 类型] [-m 描述] [-a] [--amend] [--no-review/--no-influence/--no-log/--only-chinese/--only-english] [--issues ISSUE...]` |
207234
| ai-review | 管理 AI 代码审查 | `git-commit-helper ai-review [--enable/--disable/--status]` |
208235

@@ -223,7 +250,18 @@ git-commit-helper translate /path/to/existing/file # 文件路径
223250
```bash
224251
# 配置
225252
git-commit-helper config [选项]
226-
--set-only-chinese <true|false> 设置默认是否只使用中文提交信息
253+
--set-only-chinese <true|false> 设置默认是否只使用中文提交信息
254+
--set-only-english <true|false> 设置默认是否只使用英文提交信息
255+
--set-translate-direction <DIRECTION> 设置默认翻译方向
256+
可选值: to-english(中译英), to-chinese(英译中)
257+
258+
# 翻译内容
259+
git-commit-helper translate [选项] [内容]
260+
-f, --file <FILE> 指定要翻译的文件路径
261+
-t, --text <TEXT> 指定要翻译的文本内容
262+
--to-english 翻译为英文(中译英)
263+
--to-chinese 翻译为中文(英译中)
264+
[内容] 直接提供要翻译的文本或文件路径(智能判断)
227265

228266
# 远程代码审查
229267
git-commit-helper <URL>
@@ -258,6 +296,22 @@ git-commit-helper commit [选项]
258296
示例:
259297

260298
```bash
299+
# 翻译示例
300+
# 使用默认翻译方向(默认为中译英)
301+
git-commit-helper translate "这是一段中文内容"
302+
303+
# 显式指定中译英
304+
git-commit-helper translate --to-english "这是一段中文内容"
305+
306+
# 英译中
307+
git-commit-helper translate --to-chinese "This is English content"
308+
309+
# 设置默认翻译方向为中译英
310+
git-commit-helper config --set-translate-direction to-english
311+
312+
# 设置默认翻译方向为英译中
313+
git-commit-helper config --set-translate-direction to-chinese
314+
261315
# 生成提交信息
262316
git-commit-helper commit
263317

src/ai_service.rs

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ use copilot_client::CopilotClient;
1313

1414
#[async_trait]
1515
pub trait AiService: Send + Sync {
16-
async fn translate(&self, text: &str) -> anyhow::Result<String> {
16+
async fn translate(&self, text: &str, direction: &crate::config::TranslateDirection) -> anyhow::Result<String> {
1717
// 使用翻译的 prompt
18-
let system_prompt = get_translation_prompt(text);
18+
let system_prompt = get_translation_prompt(text, direction);
1919
Ok(self.chat(&system_prompt, text).await?)
2020
}
2121

@@ -218,9 +218,12 @@ fn wrap_chinese_text(text: &str, max_width: usize) -> String {
218218
result
219219
}
220220

221-
fn get_translation_prompt(text: &str) -> String {
222-
let prompt = format!(
223-
r#"You are a professional translator. Please translate the following Chinese text to English.
221+
fn get_translation_prompt(text: &str, direction: &crate::config::TranslateDirection) -> String {
222+
use crate::config::TranslateDirection;
223+
224+
let prompt = match direction {
225+
TranslateDirection::ChineseToEnglish => format!(
226+
r#"You are a professional translator. Please translate the following Chinese text to English.
224227
Important rules:
225228
1. Keep all English content, numbers, and English punctuation unchanged
226229
2. Do not translate any content inside English double quotes
@@ -237,7 +240,30 @@ fn get_translation_prompt(text: &str) -> String {
237240
238241
Text to translate:
239242
{}"#,
240-
wrap_chinese_text(text, 72));
243+
wrap_chinese_text(text, 72)
244+
),
245+
TranslateDirection::EnglishToChinese => format!(
246+
r#"You are a professional translator. Please translate the following English text to Chinese.
247+
Important rules:
248+
1. Keep all Chinese content, numbers, and Chinese punctuation unchanged
249+
2. Do not translate any content inside quotes
250+
3. Maintain the original text structure and formatting
251+
4. Only return the Chinese translation, DO NOT include the original English text
252+
5. Keep simple and concise, no need to rewrite or expand the content
253+
6. Use appropriate Chinese punctuation marks
254+
255+
Example response format:
256+
feat: 添加外部插件支持
257+
258+
1. 实现插件加载机制
259+
2. 添加插件配置接口
260+
3. 设置插件发现路径: "/plugins"
261+
262+
Text to translate:
263+
{}"#,
264+
text
265+
),
266+
};
241267

242268
debug!("生成的提示词:\n{}", prompt);
243269
prompt
@@ -725,7 +751,7 @@ pub async fn create_translator(config: &Config) -> anyhow::Result<Box<dyn Transl
725751
create_translator_for_service(service_config).await
726752
}
727753

728-
pub async fn translate_with_fallback(config: &Config, text: &str) -> anyhow::Result<String> {
754+
pub async fn translate_with_fallback(config: &Config, text: &str, direction: &crate::config::TranslateDirection) -> anyhow::Result<String> {
729755
let mut tried_services = Vec::new();
730756

731757
// 如果已设置环境变量,直接返回原文
@@ -734,7 +760,7 @@ pub async fn translate_with_fallback(config: &Config, text: &str) -> anyhow::Res
734760
}
735761

736762
debug!("尝试使用默认服务 {:?}", config.default_service);
737-
if let Some(result) = try_translate(&config.default_service, config, text).await {
763+
if let Some(result) = try_translate(&config.default_service, config, text, direction).await {
738764
return result;
739765
}
740766
tried_services.push(config.default_service.clone());
@@ -745,15 +771,15 @@ pub async fn translate_with_fallback(config: &Config, text: &str) -> anyhow::Res
745771
}
746772

747773
debug!("尝试使用备选服务 {:?}", service_config.service);
748-
if let Some(result) = try_translate(&service_config.service, config, text).await {
774+
if let Some(result) = try_translate(&service_config.service, config, text, direction).await {
749775
return result;
750776
}
751777
tried_services.push(service_config.service.clone());
752778
}
753779

754780
while let Some(service) = select_retry_service(config, &tried_services)? {
755781
debug!("用户选择使用 {:?} 重试", service);
756-
if let Some(result) = try_translate(&service, config, text).await {
782+
if let Some(result) = try_translate(&service, config, text, direction).await {
757783
return result;
758784
}
759785
tried_services.push(service);
@@ -762,12 +788,12 @@ pub async fn translate_with_fallback(config: &Config, text: &str) -> anyhow::Res
762788
Err(anyhow::anyhow!("所有AI服务均失败"))
763789
}
764790

765-
async fn try_translate(service: &AIService, config: &Config, text: &str) -> Option<anyhow::Result<String>> {
791+
async fn try_translate(service: &AIService, config: &Config, text: &str, direction: &crate::config::TranslateDirection) -> Option<anyhow::Result<String>> {
766792
let service_config = config.services.iter()
767793
.find(|s| s.service == *service)?;
768794

769795
let translator = create_translator_for_service(service_config).await.ok()?;
770-
match translator.translate(text).await {
796+
match translator.translate(text, direction).await {
771797
Ok(result) => Some(Ok(result)),
772798
Err(e) => {
773799
warn!("{:?} 服务翻译失败: {}", service, e);

src/commit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,7 @@ pub async fn generate_commit_suggestion(commit_types: &[String], user_descriptio
959959
None => get_staged_diff()?
960960
};
961961

962-
let message = translator.translate(&prompt).await?.to_string();
962+
let message = translator.translate(&prompt, &config::TranslateDirection::ChineseToEnglish).await?.to_string();
963963

964964
// 移除各种 AI 返回的元信息标记
965965
let message = message

src/config.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ pub struct Config {
2626
pub only_chinese: bool, // 是否默认只使用中文
2727
#[serde(default = "default_only_english")]
2828
pub only_english: bool, // 是否默认只使用英文
29+
#[serde(default = "default_translate_direction")]
30+
pub translate_direction: TranslateDirection, // 默认翻译方向
2931
}
3032

3133
// 添加默认值函数
@@ -37,6 +39,16 @@ fn default_only_english() -> bool {
3739
false
3840
}
3941

42+
fn default_translate_direction() -> TranslateDirection {
43+
TranslateDirection::ChineseToEnglish
44+
}
45+
46+
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
47+
pub enum TranslateDirection {
48+
ChineseToEnglish, // 中译英(默认)
49+
EnglishToChinese, // 英译中
50+
}
51+
4052
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
4153
pub struct GerritConfig {
4254
pub username: Option<String>,
@@ -89,6 +101,7 @@ impl Config {
89101
gerrit: None,
90102
only_chinese: false, // 默认关闭
91103
only_english: false, // 默认关闭
104+
translate_direction: default_translate_direction(), // 默认中译英
92105
}
93106
}
94107

@@ -293,6 +306,7 @@ impl Config {
293306
gerrit: None,
294307
only_chinese: false, // 默认关闭
295308
only_english: false, // 默认关闭
309+
translate_direction: default_translate_direction(), // 默认中译英
296310
};
297311

298312
// 确保配置目录存在
@@ -322,9 +336,10 @@ impl Config {
322336
gerrit: None,
323337
only_chinese: false,
324338
only_english: false,
339+
translate_direction: default_translate_direction(),
325340
};
326341
let translator = ai_service::create_translator(&test_config).await?;
327-
match translator.translate("这是一个测试消息,用于验证翻译功能是否正常。").await {
342+
match translator.translate("这是一个测试消息,用于验证翻译功能是否正常。", &TranslateDirection::ChineseToEnglish).await {
328343
Ok(result) => {
329344
println!("\n测试结果:");
330345
println!("原文: 这是一个测试消息,用于验证翻译功能是否正常。");
@@ -496,11 +511,12 @@ impl Config {
496511
gerrit: None,
497512
only_chinese: false,
498513
only_english: false,
514+
translate_direction: default_translate_direction(),
499515
};
500516
let translator = ai_service::create_translator(&test_config).await?;
501517
let text = "这是一个测试消息,用于验证翻译功能是否正常。";
502518
debug!("开始发送翻译请求");
503-
match translator.translate(text).await {
519+
match translator.translate(text, &TranslateDirection::ChineseToEnglish).await {
504520
Ok(result) => {
505521
debug!("收到翻译响应");
506522
println!("\n测试结果:");

src/git.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::commit::CommitMessage;
22
use crate::ai_service;
33
use crate::review;
4+
use crate::config::{self, TranslateDirection};
45
use dialoguer::Confirm;
56
use log::{debug, info};
67
use std::path::Path;
@@ -57,14 +58,14 @@ pub async fn process_commit_msg(path: &Path, no_review: bool) -> anyhow::Result<
5758

5859
info!("开始翻译流程,默认使用 {:?} 服务", config.default_service);
5960

60-
// 翻译标题
61-
let en_title = ai_service::translate_with_fallback(&config, &msg.title).await?;
61+
// 翻译标题(中译英)
62+
let en_title = ai_service::translate_with_fallback(&config, &msg.title, &TranslateDirection::ChineseToEnglish).await?;
6263
let en_title = wrap_text(&en_title, MAX_LINE_LENGTH);
6364
let original_title = msg.title.clone();
6465

6566
// 翻译正文(如果有的话)
6667
let (en_body, cn_body) = if let Some(body) = &msg.body {
67-
let en_body = ai_service::translate_with_fallback(&config, body).await?;
68+
let en_body = ai_service::translate_with_fallback(&config, body, &TranslateDirection::ChineseToEnglish).await?;
6869
(Some(wrap_text(&en_body, MAX_LINE_LENGTH)), Some(body.clone()))
6970
} else {
7071
(None, None)

0 commit comments

Comments
 (0)