Scribe

配置

scribe.config.ts 中的所有选项:项目设置、内容类型、字段标记与多语言路由。

View as Markdown

所有配置都集中在一个文件里:scribe.config.ts,并通过 defineConfig({...}) 导出。无论是在运行时(通过 createScribe)还是在 CLI 环境中(自动在工作目录中查找 scribe.config.ts),读取的都是这份相同的配置文件。

项目选项

export default defineConfig({
  rootDir: ".",
  contentDir: "content",             // 默认值
  store: ".scribe/store.sqlite",     // 默认值
  assetsDir: "public",               // 选填
  locales: ["en", "fr", "de"],
  defaultLocale: "en",               // 默认值
  localeRouting: { strategy: "path-prefix", prefixDefaultLocale: false },
  localeFallbacks: true,             // 默认值
  localePresets: { active: ["fr"] },
  translate: { /* 详见翻译页面 */ },
  types: [ /* defineContentType(...) */ ],
});
选项默认值说明
rootDir— (必填)项目根目录。请保持相对路径(通常是 "."):CLI 会相对于配置文件的所在目录进行解析,而 createScribe 则相对于 process.cwd() 解析。不要通过 import.meta.url 动态构建:打包工具会在构建时将该路径内联,这会导致在 Vercel 等 Serverless 托管平台上运行失败。
contentDir"content"存放内容的目录,每种内容类型对应一个子文件夹。
store".scribe/store.sqlite"SQLite 翻译存储库。请务必将其提交到代码库,不要在 .gitignore 中忽略 .scribe/
assetsDir静态资产的根目录(例如 "public")。设置后,若前置数据或正文中引用的图片路径在磁盘上不存在,scribe validate 将发出警告。
locales— (必填)包含默认语言在内的所有语言区域(Locale)。
defaultLocale"en"权威源语言。必须包含在 locales 列表中。
localeRoutingpath-prefix,默认语言无前缀语言标记在生成 URL 中的呈现方式。path-prefix 会在路径前添加语言前缀(除非开启了 prefixDefaultLocale,否则默认语言会省略前缀)。search-param 会通过 ?param=locale 的形式为非默认语言追加查询参数。
localeFallbackstrue根据语言标签推导降级链:如果某个文档没有特定区域变体(如 pt-BR)的翻译,系统会在回退到默认语言之前,先提供最接近的基础语言版本(如 pt)。设置为 false 可禁用此功能。详见多语言降级链
localePresetsscribe translate --preset name 命令定义的语言分组预设。
translate项目级的全局翻译默认配置(翻译)。
types— (必填)内容类型定义。

配置会在第一时间进行校验:如果出现未知的 defaultLocale、重复的类型 id 或是格式错误的 path 模板,系统会立刻抛出异常并给出清晰的提示信息。

内容类型选项

defineContentType({
  id: "blog",
  schema: blogSchema,
  path: "/blog/{slug}",
  contentDir: "blog",          // 默认值:同 id
  slugStrategy: "localized",   // 默认值:"fixed"
  indexFallback: "en",         // 默认值:若设置了 path 则为 "en",否则为 "none"
  orderBy: "-publishedAt",     // 默认值:"slug"
  label: "Blog",               // 默认值:首字母大写的 id(仅用于 Studio UI)
  crossValidate: (data, ctx) => [],
  translate: { /* 针对该类型的覆盖配置 */ },
})
选项说明
id唯一标识符。将作为类型化访问器(如 scribe.blog)及默认的 contentDir
schema前置数据(Frontmatter)的 Zod 对象模式,包含下文提到的字段标记。
path包含且仅包含一个 {slug} 的 URL 模板(例如 /blog/{slug})。对于没有独立页面、仅供引用的内容类型(如作者、分类),请省略此项。
contentDir位于项目 contentDir 下的子文件夹,存放该类型的 .mdx 文件。
slugStrategy"fixed" 表示所有语言都使用英文 slug。"localized" 表示翻译人员会为不同语言生成专属的 slug(例如 /fr/blog/bonjour-le-monde)。
indexFallback当某种语言缺乏对应的翻译时,resolve() 的返回策略:"en" 会提供英文文档(并标注 actualLocale: "en"),"none" 则不返回任何内容。
orderBylist() 的默认排序方式:可选用 "slug""publishedAt""-publishedAt""updatedAt""-updatedAt",或者传入一个对强类型文档进行比较的 (a, b) => number 函数。
crossValidatescribe validate 执行的额外验证规则,接收解析后的强类型前置数据。需返回 { field, message, level }[]
translate特定类型的翻译提示、规则或模型配置(翻译)。

字段标记

每一个模式(schema)字段必属于以下三种类型之一。未标注的字段默认视为**结构化(structural)**字段。

import { field } from "scribe-cms";

const schema = z.object({
  // 发送给翻译人员,按语言区域分别存储:
  title: field.translatable(z.string().min(1)),

  // 仅限英文,从英文文档直接复制到所有其他语言版本中:
  heroImage: field.structural(z.string().optional()),

  // 指向其他内容类型的英文 slug 引用:
  author: field.relation("author"),
  relatedPosts: field.relation("blog", { multiple: true, max: 4, optional: true }),
});

可翻译标记同样适用于普通数组或对象内嵌套的字段(例如 sections.*.title)。需要注意的是,千万不要用 field.structural 去包裹外层数组,否则整个子树都会变成仅限英文。

field.relation(typeId, options?)

选项默认值说明
multiplefalse该字段包含的是 slug 数组。
optionalfalse该字段可省略。省略时,单值引用的 related() 会返回 null,而多值引用会跳过缺失的项目。
min / max限制项目数量(仅在 multiple: true 时有效)。

所有的约束条件都应当写在 options 对象里,不要使用 Zod 的链式调用。诸如 .max(8).optional() 的链式调用会克隆模式结构,从而导致关系元数据丢失。

关系字段始终存储英文 slugscribe validate 会对它们进行检查(如果是必填项出现悬空引用,将引发阻断构建的错误,而选填项则会触发警告)。在运行时可以通过 related() 解引用,具体请参阅 运行时 API

多语言降级链

默认情况下,当某篇文档缺少特定区域版本的翻译时,系统会先尝试提供它的基础语言,然后再回退到默认语言。每个区域设置都会在 locales 列表中依次寻找自身语言标签较短的前缀,例如 fr-CA 会降级到 fr,而 zh-Hant-TW 则会先找 zh-Hant,再找 zh。若要禁用该行为,可设置 localeFallbacks: false。默认语言永远不会出现在降级链中,它始终是最终的兜底选项,并受类型的 indexFallback 设置控制。

降级策略适用于 resolve()(系统会在 actualLocale 中说明实际采用的语言,且 slug 重定向也会使用降级语言的 slug)以及 staticParams()(预渲染的 slug 与 resolve() 提供的结果保持一致)。而对于 get()list()translation()alternates() 或是站点地图(sitemap),则刻意应用降级策略,而是坚持精确匹配规则。

强类型客户端类型

在应用端使用类型别名时,您可以直接基于配置推导所有内容:

import type { ScribeClient, ScribeDocs } from "scribe-cms/runtime";
import config from "./scribe.config";

type MyScribe = ScribeClient<typeof config>;
type BlogDoc = ScribeDocs<typeof config>["blog"];
配置 · Scribe