chore(task): archive 04-28-refactor-unify-language

This commit is contained in:
ZL-Q
2026-04-28 17:17:39 +08:00
parent 8de03314fd
commit c7a75a6445
2 changed files with 0 additions and 0 deletions
@@ -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. 所有测试通过