feat(i18n): persist language preference and thread through chat, memoir, TTS
- Add users.language_preference (Alembic 0018, default zh); capture at signup/SMS only; expose on auth and profile APIs - Lite English prompts for chat and memoir; localized stage labels and agent names (Life Echo / 岁月知己) - Tencent TTS: language-aware synthesis, ModelType=1 for 501004, English chunking - WebSocket pipeline: emit all AGENT_RESPONSE segments when TTS cancels; INFO logs for tts_this_turn and TTS decisions; on-demand TTS logging - Expo: device language on auth, i18n tiers/agent name, [SPLIT] streaming UX fixes - Tests for migration, prompts, pipeline, router tts_this_turn, reply segments Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
from typing import Optional
|
||||
from typing import Literal, Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
LanguagePreference = Literal["zh", "en"]
|
||||
|
||||
|
||||
class RegisterRequest(BaseModel):
|
||||
phone: str = Field(..., min_length=11, max_length=11, description="手机号(11位)")
|
||||
@@ -9,6 +11,10 @@ class RegisterRequest(BaseModel):
|
||||
nickname: str = Field(..., min_length=1, max_length=50, description="昵称")
|
||||
email: Optional[str] = Field(None, description="邮箱(可选)")
|
||||
agreed_to_terms: bool = Field(..., description="是否同意用户协议和隐私政策")
|
||||
language: Optional[LanguagePreference] = Field(
|
||||
None,
|
||||
description="device language at signup; only used when creating a new user",
|
||||
)
|
||||
|
||||
|
||||
class LoginRequest(BaseModel):
|
||||
@@ -35,6 +41,7 @@ class UserResponse(BaseModel):
|
||||
avatar_url: Optional[str] = None
|
||||
subscription_type: str
|
||||
created_at: str
|
||||
language_preference: LanguagePreference = "zh"
|
||||
|
||||
|
||||
class SendSmsRequest(BaseModel):
|
||||
@@ -57,6 +64,10 @@ class SmsLoginRequest(BaseModel):
|
||||
nickname: Optional[str] = Field(
|
||||
None, max_length=50, description="昵称(注册时必填,登录时可选)"
|
||||
)
|
||||
language: Optional[LanguagePreference] = Field(
|
||||
None,
|
||||
description="device language at signup; only used when creating a new user",
|
||||
)
|
||||
|
||||
|
||||
class MockSmsLoginRequest(BaseModel):
|
||||
@@ -67,6 +78,10 @@ class MockSmsLoginRequest(BaseModel):
|
||||
nickname: Optional[str] = Field(
|
||||
None, max_length=50, description="新用户昵称(可选)"
|
||||
)
|
||||
language: Optional[LanguagePreference] = Field(
|
||||
None,
|
||||
description="device language at signup; only used when creating a new user",
|
||||
)
|
||||
|
||||
|
||||
class SmsRegisterRequest(BaseModel):
|
||||
@@ -76,6 +91,10 @@ class SmsRegisterRequest(BaseModel):
|
||||
nickname: str = Field(..., min_length=1, max_length=50, description="昵称")
|
||||
email: Optional[str] = Field(None, description="邮箱(可选)")
|
||||
agreed_to_terms: bool = Field(..., description="是否同意用户协议和隐私政策")
|
||||
language: Optional[LanguagePreference] = Field(
|
||||
None,
|
||||
description="device language at signup; only used when creating a new user",
|
||||
)
|
||||
|
||||
|
||||
class ResetPasswordRequest(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user