chore(task): archive 04-28-refactor-unify-language
This commit is contained in:
@@ -0,0 +1,294 @@
|
||||
# IMPLEMENTATION_PLAN:统一语言设置
|
||||
|
||||
## 前置条件
|
||||
|
||||
| 条件 | 状态 |
|
||||
|------|------|
|
||||
| 后端 Schema 定义清晰 | ✅ |
|
||||
| 前端 Model 定义清晰 | ✅ |
|
||||
| AI 运行时使用 `ai_language` | ✅ |
|
||||
| 协议文档存在 | ✅ |
|
||||
|
||||
## 实现步骤
|
||||
|
||||
### Step 1: 更新协议文档
|
||||
|
||||
**文件**: `docs/protocols/profile/profile-protocol.md`
|
||||
|
||||
- 将 `interface_language` 和 `ai_language` 合并为 `language`
|
||||
- 更新示例 JSON
|
||||
|
||||
---
|
||||
|
||||
### Step 2: 后端 Schema
|
||||
|
||||
**文件**: `backend/src/schemas/shared/user.py`
|
||||
|
||||
```python
|
||||
class PreferenceSettings(BaseModel):
|
||||
language: str = "zh-CN"
|
||||
timezone: str = "Asia/Shanghai"
|
||||
country: str = "US"
|
||||
|
||||
@field_validator("language")
|
||||
@classmethod
|
||||
def validate_language(cls, value: str) -> str:
|
||||
if not _BCP47_PATTERN.fullmatch(value):
|
||||
raise ValueError("language must be a valid BCP-47 tag")
|
||||
return value
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 3: 后端 AI 运行时
|
||||
|
||||
**文件**: `backend/src/core/agentscope/runtime/runner.py`
|
||||
|
||||
```python
|
||||
# 第 268-276 行
|
||||
language = "zh-CN"
|
||||
if user_context.settings is not None:
|
||||
prefs = getattr(user_context.settings, "preferences", None)
|
||||
if prefs is not None:
|
||||
language = getattr(prefs, "language", "zh-CN") or "zh-CN"
|
||||
|
||||
system_prompt = build_system_prompt(
|
||||
agent_type=stage_config.agent_type,
|
||||
language=language,
|
||||
llm_config=stage_config.llm_config,
|
||||
tools=None,
|
||||
now_utc=datetime.now(timezone.utc),
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 4: 后端 Prompt 构建
|
||||
|
||||
**文件**: `backend/src/core/agentscope/prompts/system_prompt.py`
|
||||
|
||||
```python
|
||||
def _build_output_rules(*, language: str) -> str:
|
||||
lang_label = _get_language_label(language)
|
||||
...
|
||||
|
||||
def build_system_prompt(
|
||||
*,
|
||||
agent_type: AgentType,
|
||||
language: str,
|
||||
llm_config: LlmConfig,
|
||||
tools: list[ToolSchema] | None,
|
||||
now_utc: datetime,
|
||||
) -> str:
|
||||
...
|
||||
_build_output_rules(language=language),
|
||||
```
|
||||
|
||||
**文件**: `backend/src/core/agentscope/prompts/worker_rules.py`
|
||||
|
||||
```python
|
||||
def get_worker_role_playing(language: str) -> str:
|
||||
_ = language
|
||||
...
|
||||
|
||||
def get_worker_output_rules(language: str) -> str:
|
||||
if language.startswith("en"):
|
||||
...
|
||||
```
|
||||
|
||||
**文件**: `backend/src/core/agentscope/prompts/agent_prompt.py`
|
||||
|
||||
```python
|
||||
def build_agent_prompt(
|
||||
*,
|
||||
language: str = "zh-CN",
|
||||
) -> str:
|
||||
role_playing = get_worker_role_playing(language)
|
||||
output_rules = get_worker_output_rules(language)
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 5: 后端测试
|
||||
|
||||
**文件**: `backend/tests/unit/test_parse_profile_settings.py`
|
||||
|
||||
- 字段名 `ai_language` → `language`
|
||||
- 字段名 `interface_language` → `language`
|
||||
|
||||
**文件**: `backend/tests/unit/test_agentscope_prompts.py`
|
||||
|
||||
- 参数名 `ai_language` → `language`
|
||||
|
||||
---
|
||||
|
||||
### Step 6: 数据库数据更新
|
||||
|
||||
直接用 Supabase MCP 执行 SQL(无需迁移脚本):
|
||||
|
||||
```sql
|
||||
UPDATE profiles
|
||||
SET settings = jsonb_set(
|
||||
settings - 'interface_language' - 'ai_language',
|
||||
'{preferences,language}',
|
||||
COALESCE(
|
||||
settings->'preferences'->>'interface_language',
|
||||
settings->'preferences'->>'ai_language',
|
||||
'"zh-CN"'
|
||||
)::jsonb
|
||||
)
|
||||
WHERE settings->'preferences' ?| array['interface_language', 'ai_language'];
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 7: 前端 Model
|
||||
|
||||
**文件**: `apps/lib/features/settings/data/models/profile_settings.dart`
|
||||
|
||||
```dart
|
||||
class PreferenceSettings {
|
||||
const PreferenceSettings({
|
||||
this.language = 'zh-CN',
|
||||
this.timezone = 'Asia/Shanghai',
|
||||
this.country = 'US',
|
||||
});
|
||||
|
||||
final String language;
|
||||
final String timezone;
|
||||
final String country;
|
||||
|
||||
PreferenceSettings copyWith({
|
||||
String? language,
|
||||
String? timezone,
|
||||
String? country,
|
||||
}) {
|
||||
return PreferenceSettings(
|
||||
language: language ?? this.language,
|
||||
timezone: timezone ?? this.timezone,
|
||||
country: country ?? this.country,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新 defaultsForLocale
|
||||
factory ProfileSettingsV1.defaultsForLocale(Locale locale) {
|
||||
final tag = languageTagFromLocale(locale);
|
||||
return ProfileSettingsV1(
|
||||
preferences: PreferenceSettings(language: tag),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 8: 前端 API
|
||||
|
||||
**文件**: `apps/lib/features/settings/data/apis/profile_api.dart`
|
||||
|
||||
```dart
|
||||
// 序列化 (第 45 行)
|
||||
'language': settings.preferences.language,
|
||||
|
||||
// 反序列化 (第 114 行)
|
||||
language: (preferencesRaw['language'] as String?) ?? 'zh-CN',
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 9: 前端设置界面
|
||||
|
||||
**文件**: `apps/lib/features/settings/presentation/screens/general_settings_screen.dart`
|
||||
|
||||
移除第 75-95 行的 AI 语言 `SettingsMenuTile`,修改剩余的语言选项:
|
||||
|
||||
```dart
|
||||
SettingsMenuTile(
|
||||
icon: Icons.language_rounded,
|
||||
title: l10n.settingsLanguage,
|
||||
subtitle: displayLanguageLabel(
|
||||
l10n,
|
||||
_settings.preferences.language,
|
||||
),
|
||||
tint: colors.primary,
|
||||
background: colors.surfaceContainerHighest,
|
||||
showDivider: false,
|
||||
onTap: () => _selectLanguage(
|
||||
_settings.preferences.language,
|
||||
(lang) => setState(() {
|
||||
_settings = _settings.copyWith(
|
||||
preferences: _settings.preferences.copyWith(
|
||||
language: lang,
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 10: 前端 i18n
|
||||
|
||||
**文件**: `apps/lib/l10n/app_zh.arb`
|
||||
|
||||
```diff
|
||||
- "settingsInterfaceLanguage": "界面语言",
|
||||
- "settingsAiLanguage": "AI回复语言",
|
||||
- "settingsAiLanguageHint": "该字段将对齐..."
|
||||
+ "settingsLanguage": "语言",
|
||||
```
|
||||
|
||||
**文件**: `apps/lib/l10n/app_en.arb`
|
||||
|
||||
```diff
|
||||
- "settingsInterfaceLanguage": "Interface Language",
|
||||
- "settingsAiLanguage": "AI Response Language",
|
||||
- "settingsAiLanguageHint": "This field will align..."
|
||||
+ "settingsLanguage": "Language",
|
||||
```
|
||||
|
||||
**文件**: `apps/lib/l10n/app_zh_hant.arb`
|
||||
|
||||
```diff
|
||||
- "settingsInterfaceLanguage": "介面語言",
|
||||
- "settingsAiLanguage": "AI 回覆語言",
|
||||
+ "settingsLanguage": "語言",
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 11: 重新生成 l10n
|
||||
|
||||
```bash
|
||||
cd apps && flutter gen-l10n
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 12: 更新其他协议文档
|
||||
|
||||
**文件**: `docs/protocols/divination/divination-run-protocol.md`
|
||||
|
||||
第 240 行:
|
||||
```diff
|
||||
- - Language rule: `conclusion`, `focus_points`, `advice`, `keywords`, `answer` should follow user `ai_language` preference unless user explicitly requests otherwise.
|
||||
+ - Language rule: `conclusion`, `focus_points`, `advice`, `keywords`, `answer` should follow user `language` preference unless user explicitly requests otherwise.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 验证
|
||||
|
||||
```bash
|
||||
# 后端
|
||||
cd backend
|
||||
uv run pytest tests/unit/test_parse_profile_settings.py tests/unit/test_agentscope_prompts.py -v
|
||||
./infra/scripts/dev-migrate.sh migrate
|
||||
|
||||
# 前端
|
||||
cd apps
|
||||
flutter gen-l10n
|
||||
flutter analyze
|
||||
```
|
||||
@@ -0,0 +1,93 @@
|
||||
# PRD:统一语言设置
|
||||
|
||||
## 1. 背景
|
||||
|
||||
当前存在两个独立语言设置:`interface_language`(界面语言)和 `ai_language`(AI 回复语言),用户需分别设置。本任务将其统一为单一 `language` 字段。
|
||||
|
||||
## 2. 目标
|
||||
|
||||
1. 合并 `interface_language` + `ai_language` → `language`
|
||||
2. 后端 AI 统一使用 `language` 作为回复语言
|
||||
3. 前端移除 AI 语言 UI,设置界面只保留一个"语言"选项
|
||||
4. 文案从"界面语言"改为"语言"
|
||||
|
||||
## 3. 变更内容
|
||||
|
||||
### 3.1 Schema 变更
|
||||
|
||||
**变更前**:
|
||||
```json
|
||||
{
|
||||
"preferences": {
|
||||
"interface_language": "zh-CN",
|
||||
"ai_language": "zh-CN"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**变更后**:
|
||||
```json
|
||||
{
|
||||
"preferences": {
|
||||
"language": "zh-CN"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 UI 变更
|
||||
|
||||
**变更前**: 两个独立选项
|
||||
```
|
||||
界面语言 简体中文 >
|
||||
AI回复语言 简体中文 >
|
||||
```
|
||||
|
||||
**变更后**: 一个选项
|
||||
```
|
||||
语言 简体中文 >
|
||||
```
|
||||
|
||||
## 4. 文件变更清单
|
||||
|
||||
### 后端 (7 文件)
|
||||
|
||||
| 文件 | 变更 |
|
||||
|------|------|
|
||||
| `backend/src/schemas/shared/user.py` | 字段重命名 |
|
||||
| `backend/src/core/agentscope/runtime/runner.py` | 读取 `language` |
|
||||
| `backend/src/core/agentscope/prompts/system_prompt.py` | 参数重命名 |
|
||||
| `backend/src/core/agentscope/prompts/worker_rules.py` | 参数重命名 |
|
||||
| `backend/src/core/agentscope/prompts/agent_prompt.py` | 参数重命名 |
|
||||
| `backend/tests/unit/test_parse_profile_settings.py` | 测试更新 |
|
||||
| `backend/tests/unit/test_agentscope_prompts.py` | 测试更新 |
|
||||
|
||||
### 数据库 (SQL 直接执行)
|
||||
|
||||
| 操作 | 说明 |
|
||||
|------|------|
|
||||
| Supabase MCP SQL | 更新现有 profiles.settings JSON 结构 |
|
||||
|
||||
### 前端 (6 文件)
|
||||
|
||||
| 文件 | 变更 |
|
||||
|------|------|
|
||||
| `apps/lib/features/settings/data/models/profile_settings.dart` | 字段重命名 |
|
||||
| `apps/lib/features/settings/data/apis/profile_api.dart` | 序列化字段 |
|
||||
| `apps/lib/features/settings/presentation/screens/general_settings_screen.dart` | 移除 AI 语言 UI |
|
||||
| `apps/lib/l10n/app_zh.arb` | 删除旧文案,添加新文案 |
|
||||
| `apps/lib/l10n/app_en.arb` | 删除旧文案,添加新文案 |
|
||||
| `apps/lib/l10n/app_zh_hant.arb` | 删除旧文案,添加新文案 |
|
||||
|
||||
### 协议文档 (2 文件)
|
||||
|
||||
| 文件 | 变更 |
|
||||
|------|------|
|
||||
| `docs/protocols/profile/profile-protocol.md` | 更新字段定义 |
|
||||
| `docs/protocols/divination/divination-run-protocol.md` | 更新语言规则 |
|
||||
|
||||
## 5. 验收标准
|
||||
|
||||
1. 后端 API 只返回 `language` 字段
|
||||
2. 前端设置界面只有一个语言选项
|
||||
3. AI 回复语言跟随 `language` 设置
|
||||
4. 所有测试通过
|
||||
Reference in New Issue
Block a user