# 发布扩展 ## 功能 BT 官网扩展注册表把可安装扩展的元数据存放在 `db/ext///`。本页规定 `info.json` 的本地化模型、README 文件名、 语言标签规范、回退行为,以及浏览器语言偏好与明确语言 URL 之间的区别。 注册表元数据 schema 2 不规定无后缀默认字段使用哪种语言,由发布者自行选择。 其他翻译在字段名后添加点号和官网规范化后的语言标签,例如 `summary.en` 或 `summary.zh-hans`。机器可读标识不能翻译。 ## 语言标签规范 语言标识遵循 **BCP 47**。BCP 47 是总规范: [RFC 5646](https://www.rfc-editor.org/rfc/rfc5646) 定义语言标签的结构和注册表, [RFC 4647](https://www.rfc-editor.org/rfc/rfc4647) 定义语言范围匹配。两者互相补充, 不是两套二选一的命名规范。 [HTML 语言偏好标准](https://html.spec.whatwg.org/multipage/system-state.html#language-preferences) 要求 `navigator.language` 以及 `navigator.languages` 中的每一项都是有效的 BCP 47 语言标签, 后者按用户偏好排序。HTTP `Accept-Language` 由 [RFC 9110 第 12.5.4 节](https://www.rfc-editor.org/rfc/rfc9110.html#section-12.5.4) 定义,它是带可选 `q` 权重的语言范围优先列表。HTML 标准建议浏览器让 Navigator API 和 HTTP 请求头使用相同的偏好列表;但浏览器可能出于隐私保护减少信息,服务器不能假定 两者的字节内容始终完全相同。 BT 官网按以下规则保存语言标签: - BCP 47 规定语言标签比较时不区分大小写;官网比较后统一转换为小写,用于 URL、 JSON 字段后缀和文件名。 - 子标签之间使用 ASCII 连字符 `-`,不得使用下划线:应写 `pt-br`,不能写 `pt_BR`。 - 合法示例包括 `en`、`zh-hans`、`zh-hant`、`pt-br`、`sr-latn-rs`。 - `zh-cn` 是带地区的中文标签,`zh-hans` 是带书写体系的中文标签,两者通常不能视为 完全等价。官网把历史 `/zh-cn/...` 地址重定向到 `/zh-hans/...`,这是本站兼容规则, 不是通用的 BCP 47 等价关系。 - 当前公开官网只支持 `en` 和 `zh-hans` 两种明确 URL 语言。扩展可以提前准备其他有效 标签的翻译,但只有该语言加入官网路由白名单后才会展示。 强制统一大小写是因为生产服务器文件系统可能区分大小写。在 Linux 上, `readme.zh-Hans.md`、`readme.ZH-HANS.md` 和 `readme.zh-hans.md` 可能是三个文件。 注册表只接受一种规范存储形式:`readme.zh-hans.md`。 ## 官网如何选择语言 访问 `/en/ext/sqlite` 或 `/zh-hans/ext/sqlite` 这类带语言标识的 URL 时,URL 始终决定 页面语言,不会被 JavaScript、Cookie 或请求头改写。 只有访问根地址 `/` 时才进行语言协商,顺序如下: 1. 存在受支持的 `bt_locale` Cookie 时优先使用它。 2. 否则由服务器读取 HTTP `Accept-Language`,处理有效的 `q` 权重;权重相同则保留请求头 中的先后顺序,再选择官网支持的语言。 3. 没有匹配语言时使用 `en`。 官网不会执行 `navigator.language` 来决定首次跳转。浏览器通常根据自己的语言偏好生成 `Accept-Language` 并随 HTTP 请求发送,因此服务器可以在 HTML 和 JavaScript 加载前完成 跳转。目前中文语言范围映射到本站已有的 `zh-hans`,英文语言范围和 `*` 映射到 `en`; `q=0` 表示该范围不可接受。明确语言页面的响应会设置对应的 `Content-Language`。 ## 语法 ```json { "schema_version": 2, "name": "sqlite", "summary": "SQLite 文件数据库扩展", "summary.en": "SQLite file database extension", "description": "为 BT 项目提供 SQLite 访问能力。", "description.en": "Provides SQLite access for BT projects.", "author": "BT Team", "developer": { "id": "bt_official", "name": "BT 官方", "name.en": "BT Official", "homepage": "https://btlang.org" }, "repository": "https://github.com/bt-lang/bt/tree/main/extension/sqlite", "license": "MIT OR Apache-2.0", "latest": "1.0.0", "versions": [] } ``` 本地化 JSON 属性名中的点号是键名的一部分。读取时必须使用 `info['summary.' + locale]` 这类动态下标;`info.summary.zh-hans` 不是同一个含义。 ## `info.json` 字段 | 字段 | 类型 | 必填 | 默认值 | 有效值 | 含义 | | ------ | ------ | ------ | ------ | ------ | ------ | | `schema_version` | Int | 是 | 无 | `2` | 注册表元数据版本。 | | `name` | String | 是 | 无 | 小写扩展标识 | 稳定机器名称,不本地化。 | | `summary` | String | 是 | 无 | 发布者自选默认语言的非空文本 | 默认简述。 | | `summary.` | String | 否 | `summary` | 非空文本;locale 为规范化 BCP 47 | 精确语言的本地化简述。 | | `description` | String | 是 | 无 | 发布者自选默认语言的非空文本 | 默认完整说明。 | | `description.` | String | 否 | `description` | 非空文本;locale 为规范化 BCP 47 | 精确语言的本地化完整说明。 | | `author` | String | 是 | 无 | 非空文本 | 扩展作者回退值,不按语言选择。 | | `developer` | Object | 是 | 无 | 字段见下表 | 发布者身份。 | | `repository` | String | 是 | 无 | 公开 HTTPS URL | 当前版本源码仓库。 | | `license` | String | 是 | 无 | SPDX 表达式 | 扩展许可证。 | | `latest` | String | 是 | 无 | 已发布 SemVer | 最新未撤回版本。 | | `versions` | Array[Object] | 是 | 无 | 至少一个已发布版本 | 版本与扩展包记录。 | ### `developer` 字段 | 字段 | 类型 | 必填 | 默认值 | 有效值 | 含义 | | ------ | ------ | ------ | ------ | ------ | ------ | | `id` | String | 是 | 无 | 稳定发布者标识 | 机器身份,不本地化。 | | `name` | String | 是 | 无 | 发布者自选默认语言的非空文本 | 默认发布者显示名。 | | `name.` | String | 否 | `name` | 非空文本;规范化 BCP 47 后缀 | 精确语言的显示名。 | | `homepage` | String | 是 | 无 | 公开 HTTPS URL | 发布者主页。 | ### `versions` 项字段 | 字段 | 类型 | 必填 | 默认值 | 有效值 | 含义 | | ------ | ------ | ------ | ------ | ------ | ------ | | `version` | String | 是 | 无 | 三段式 SemVer | 已发布扩展版本。 | | `file` | String | 是 | 无 | `-.bts` | 下载文件名。 | | `download_url` | String | 是 | 无 | 注册表 HTTPS API URL | 规范下载入口。 | | `sha256` | String | 是 | 无 | 64 位小写十六进制 | 扩展包精确摘要。 | | `size` | Int | 是 | 无 | 正整数,单位字节 | 扩展包精确大小。 | | `bt_min_version` | String | 是 | 无 | 三段式 SemVer | 最低兼容 BT 运行时。 | | `kind` | String | 是 | 无 | `bt` 或 `wasm` | 扩展后端。 | | `abi` | String | 是 | 无 | 与 kind 对应的 ABI | 运行时调用协议。 | | `created_at` | String | 是 | 无 | 注册表发布时间 | 发布时间。 | | `yanked` | Bool | 是 | `false` | `true` 或 `false` | 是否不再建议新安装。 | | `downloads` | Int | 是 | `0` | 非负整数 | 已记录安装次数。 | | `permissions` | Array[String] | 是 | `[]` | manifest 权限标识 | 安装前显示的能力。 | | `exports` | Array[Object] | 是 | `[]` | 每项包含 `name`、`returns` | 全局入口;标识不本地化。 | | `objects` | Array[Object] | 是 | `[]` | 每项包含 `name`、`methods` | 对象 API 摘要;标识不本地化。 | ## README 本地化 `readme.md` 使用哪种语言由发布者自行决定。本地化文件添加规范化的点号后缀: ```text readme.md readme.en.md readme.zh-hans.md readme.zh-hant.md readme.ja.md readme.pt-br.md ``` 访问 `/en/ext/` 时,渲染器先查找 `readme.en.md`,不存在时读取 `readme.md`; 访问 `/zh-hans/ext/` 时,则先查找 `readme.zh-hans.md`,不存在时读取 `readme.md`。 规则是“规范化标签精确匹配,然后回退发布者定义的默认文件”;不会把 `pt-br` 自动截断为 `pt`。`summary.`、`description.` 和 `developer.name.` 使用同一规则。 官网注册表中的小写 `readme.md` 与 `.bts` 扩展包内的大写 `README.md` 是两个独立文件。 生产注册表文件名必须小写并精确一致。迁移期间仍可读取 schema 1 的 `summary_en`、 `description_en` 和 `name_en`,但新增元数据必须使用 schema 2 点号字段与规范化文件名。 ## 返回值与回退 本地化 HTML 页面优先显示精确语言字段,缺失时显示无后缀、由发布者定义的默认字段。 注册表 JSON API 返回包含全部翻译的原始元数据,由 API 使用者执行同样的选择。 缺少翻译不是错误,也不会让页面出现空白区块。 ## 注意事项 - 不得本地化 `name`、API 标识、配置字段、事件名、版本、摘要、权限、ABI、文件名或下载 URL。 - 翻译后缀必须与官网规范化后的 URL 语言标识完全一致。 - 语言标签比较不区分大小写;文件名和 JSON 键统一小写,确保大小写敏感与不敏感系统结果一致。 - 根地址语言偏好只用于第一次跳转。可收藏、可分享的规范链接始终包含明确语言段。