大猫OPC

21 张表怎么切

阅读 0 更新于 2026-10-27

先说结论

多语言 CMS 的表结构,难点不在"字段多",在"翻译放哪"。放错地方,后面每一个查询都要打补丁。

五组表

组 表 职责
内容 products / cases / solutions / news / pages 五类内容,结构相近
组织 categories / tags / relations 分类树、标签、关联
语言 languages / translations 语种开关、译文
配置 configs / settings / menus 站点配置、导航
系统 users / audit_logs / tokens 账号、审计、API

翻译放哪:两种方案

方案 A:同表加字段(title_en / title_ja …)

  • 优点:一次查询拿全
  • 缺点:33 个语种就是 33 组字段,表结构爆炸,加语种要改表

方案 B:独立译文表(content_id + lang + field + value)

  • 优点:加语种不改表,翻译状态好管
  • 缺点:查询要 join 或二次聚合

我选 B 的变体:译文按语种存 JSON 字段(translations 存 {"ja": {...}, "ru": {...}}),兼顾灵活与查询效率。

关键设计:翻译状态与版本

每条内容带三个字段:

  • translation_status:pending / translating / done / failed
  • translation_version:v1:<sha1>,原文的哈希
  • translated_at:最后回写时间

改稿时版本号变化,旧译文自动作废——这是整个系统最重要的一个设计。

索引怎么建

  • (category_id, status, published_at) 列表页
  • (slug) 详情页(唯一)
  • (translation_status) 翻译队列扫描
  • (lang, status) 语言维度查询

迁移策略

首发用一份 baseline 迁移建全表,后续每个版本一个增量迁移。好处是:新客户装完就是最新结构,老客户跑增量即可。

踩过两个坑:一是把 33 个语种塞进一个 JSON 字段,列表页整列读出,内存直接翻倍——后来改成列表只取当前语种;二是分类树用递归查询,层级一深就 N+1,改成物化路径(path 字段)后一次查询搞定。

本页内容对你有帮助吗? 感谢反馈(演示按钮,暂未接入后端)