初始化 fanyi 翻译 CLI 项目
- 项目从 fyy 更名为 fanyi - 添加 clap 命令行参数解析 - 实现语言检测功能 - 配置异步运行时和 HTTP 客户端依赖 - 创建 TUTORIAL.md 教学计划文档
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/target
|
||||
2008
Cargo.lock
generated
Normal file
2008
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "fanyi"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.59", features = ["derive"] }
|
||||
reqwest = { version = "0.13", features = ["json"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
112
TUTORIAL.md
Normal file
112
TUTORIAL.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# fanyi 翻译 CLI 教学计划
|
||||
|
||||
## 项目简介
|
||||
`fanyi` 是一个 Rust 编写的命令行翻译工具,支持中英文互译。
|
||||
|
||||
**使用方法:**
|
||||
```bash
|
||||
fanyi hello # 输出中文翻译
|
||||
fanyi 你好 # 输出英文翻译
|
||||
```
|
||||
|
||||
## 项目状态
|
||||
|
||||
### 已完成 ✓
|
||||
1. **命令行参数解析** (clap)
|
||||
- 使用 derive 宏定义 CLI 接口
|
||||
- 支持接收单个字符串参数
|
||||
|
||||
2. **语言检测**
|
||||
- 检测输入文本的第一个字符
|
||||
- 判断是否为中文 (Unicode 范围: `\u{4e00}` - `\u{9fff}`)
|
||||
- 决定翻译方向(中文→英文 / 英文→中文)
|
||||
|
||||
3. **依赖配置**
|
||||
- `clap`: 命令行参数解析
|
||||
- `reqwest`: HTTP 客户端(异步)
|
||||
- `tokio`: 异步运行时
|
||||
- `serde`: 序列化/反序列化
|
||||
- `serde_json`: JSON 处理
|
||||
|
||||
4. **API 响应结构定义**
|
||||
- `ApiResponse`: 顶层响应
|
||||
- `Choice`: 选择列表
|
||||
- `Message`: 消息内容
|
||||
|
||||
5. **异步主函数**
|
||||
- 使用 `#[tokio::main]`
|
||||
- 返回 `Result` 类型处理错误
|
||||
|
||||
### 待完成 ⏳
|
||||
1. **实现 translate 函数**
|
||||
- 从环境变量读取 `DEEPSEEK_API_KEY`
|
||||
- 根据语言检测结果构建 system prompt
|
||||
- 发送 HTTP POST 请求到 DeepSeek API
|
||||
- 解析 JSON 响应并返回翻译结果
|
||||
|
||||
2. **错误处理**
|
||||
- API 调用失败
|
||||
- 网络错误
|
||||
- 无效 API Key
|
||||
|
||||
3. **测试与优化**
|
||||
- 实际调用 API 测试
|
||||
- 处理边界情况(空字符串、特殊字符等)
|
||||
|
||||
## 技术要点
|
||||
|
||||
### 核心概念
|
||||
- **clap derive macro**: 声明式 CLI 定义
|
||||
- **Rust 异步编程**: async/await + tokio 运行时
|
||||
- **HTTP 请求**: reqwest 发送 POST 请求
|
||||
- **JSON 处理**: serde 序列化/反序列化
|
||||
- **环境变量**: 安全存储 API Key
|
||||
|
||||
### 关键代码片段
|
||||
|
||||
```rust
|
||||
// 语言检测
|
||||
fn is_chinese(text: &str) -> bool {
|
||||
text.chars().next()
|
||||
.map(|c| c >= '\u{4e00}' && c <= '\u{9fff}')
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
// 异步主函数
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## 下一步行动
|
||||
|
||||
### 任务:实现 translate 函数
|
||||
|
||||
**步骤:**
|
||||
1. 获取 API Key: `std::env::var("DEEPSEEK_API_KEY")?`
|
||||
2. 构建 system prompt(根据输入语言决定目标语言)
|
||||
3. 创建 HTTP 客户端: `reqwest::Client::new()`
|
||||
4. 构建请求体(JSON)
|
||||
5. 发送 POST 请求
|
||||
6. 解析响应并提取翻译文本
|
||||
|
||||
**API Endpoint:**
|
||||
```
|
||||
POST https://api.deepseek.com/chat/completions
|
||||
```
|
||||
|
||||
**请求示例:**
|
||||
```json
|
||||
{
|
||||
"model": "deepseek-chat",
|
||||
"messages": [
|
||||
{"role": "system", "content": "将用户输入翻译成中文。只输出翻译结果。"},
|
||||
{"role": "user", "content": "hello"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**最后更新:** 2026-02-19
|
||||
46
src/main.rs
Normal file
46
src/main.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
use clap::Parser;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "fyy")]
|
||||
struct Args {
|
||||
input: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ApiResponse {
|
||||
choices: Vec<Choice>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Choice {
|
||||
message: Message,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Message {
|
||||
content: String,
|
||||
}
|
||||
|
||||
fn is_chinese(text: &str) -> bool {
|
||||
let first = text.chars().next();
|
||||
match first {
|
||||
Some(c) => {
|
||||
if c >= '\u{4e00}' && c <= '\u{9fff}' {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let args = Args::parse();
|
||||
println!("input: {}", args.input);
|
||||
println!("is_chinese: {}", is_chinese(&args.input));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user