Files
life-echo/api/app/features/user/models.py
Kevin ccdc4e4277 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>
2026-05-11 16:16:49 +08:00

42 lines
1.6 KiB
Python

from sqlalchemy import Column, DateTime, Integer, String
from sqlalchemy.orm import relationship
from app.core.db import Base, utc_now
class User(Base):
__tablename__ = "users"
id = Column(String, primary_key=True)
phone = Column(String, unique=True, nullable=False, index=True)
password_hash = Column(String, nullable=False)
email = Column(String, unique=True, nullable=True)
openid = Column(String, unique=True, nullable=True)
nickname = Column(String, nullable=False)
avatar_url = Column(String, nullable=True)
subscription_type = Column(String, default="free")
subscription_expires_at = Column(DateTime(timezone=True), nullable=True)
created_at = Column(DateTime(timezone=True), default=utc_now)
birth_year = Column(Integer, nullable=True)
birth_place = Column(String, nullable=True)
grew_up_place = Column(String, nullable=True)
occupation = Column(String, nullable=True)
language_preference = Column(
String(8), nullable=False, default="zh", server_default="zh"
)
conversations = relationship("Conversation", back_populates="user")
chapters = relationship("Chapter", back_populates="user")
stories = relationship("Story", back_populates="user")
books = relationship("Book", back_populates="user")
orders = relationship("Order", back_populates="user", cascade="all, delete-orphan")
memoir_state = relationship(
"MemoirState",
back_populates="user",
uselist=False,
cascade="all, delete-orphan",
)
refresh_tokens = relationship(
"RefreshToken", back_populates="user", cascade="all, delete-orphan"
)