address4cj服务端实战:如何用FormatDistributor快速搭建多语言地址格式JSON API
【免费下载链接】address4cj处理地址表示、验证和格式化。项目地址: https://gitcode.com/Cangjie-SIG/address4cj
address4cj 是一个面向仓颉(Cangjie)语言的地址处理库,负责全球地址的表示、验证与格式化,内置约 200 个国家的地址格式与行政区划数据(基于 CLDR v47)。本文带你用其中的 FormatDistributor 组件,快速搭建一个多语言地址格式 JSON API 服务:前端一次 GET 请求,即可按用户语言拿到各国的地址布局模板、必填字段与邮编校验规则。
🌐 为什么需要多语言地址格式 JSON API
做国际化表单(电商下单、注册、物流)时,每个国家的地址习惯都不同:
- 书写顺序不同:日本习惯「邮编→都道府县→城市→街门牌」,美国则是「街道→城市/州→邮编」;
- 邮编规则不同:中国是 6 位纯数字,美国是 5 位数字(可扩展 9 位),爱尔兰用 Eircode;
- 行政区划名称不同:同一地区需要本地语言名称(例如 Okinawa / 沖縄県)。
手动维护这些规则是噩梦。address4cj 已经内置了这些规则,而FormatDistributor能把它们以 RESTful JSON 接口的形式暴露出去,前端不再需要自己硬编码任何国家规则。
🧩 FormatDistributor:请求分发器工作原理
FormatDistributor实现了HttpRequestDistributor接口,内部维护一张「路径 → 处理器」的映射表,负责把 HTTP 请求路由到对应的处理器(见 src/http.cj):
| 请求路径 | 分发结果 |
|---|---|
/address-formats | FormatHandler(返回地址格式 JSON) |
| 其他任意路径 | NotFoundHandler(404) |
它还提供了register(path, handler)方法,你可以在官方/address-formats之外,按需注册自己的扩展路由,接口说明见 doc/feature_api.md。
⚙️ FormatHandler:一次请求生成全部国家的本地化格式
FormatHandler.handle的处理流程非常直接(src/http.cj):
- 解析语言:按优先级确定本次请求使用的 Locale;
- 逐国选择模板:遍历内置的全部国家格式,调用
selectLayout(locale)与selectRegions(locale),为每个国家挑出适合该语言的布局与行政区划名称; - 序列化为 JSON:写入响应体,并设置
Content-Type: application/json与Content-Language: <locale>两个响应头。
一个细节值得一提:服务端在响应前预先选择好布局与区域名称,相比让客户端自行全量下发再挑选,响应体积可减少约 20%(源码注释见 src/http.cj),对移动网络非常友好。
🔍 三种方式指定语言:locale 参数优先级
getLocale方法(src/http.cj)按以下优先级解析语言:
| 优先级 | 方式 | 示例 |
|---|---|---|
| 1(最高) | URL 查询参数 | GET /address-formats?locale=zh |
| 2 | 请求头 | Accept-Language: zh-Hant, zh, en;q=0.8 |
| 3(兜底) | 默认英语 | 返回Content-Language: en |
两点注意事项:
- 请求头只取第一个值:服务端会按
,或;拆分Accept-Language并取第一项,所以zh-Hant, zh实际生效的是zh-Hant; - 语言标识会自动标准化为 BCP 47:例如
sr_rs_latn会被规范化为sr-Latn-RS,语言处理逻辑见 src/locale.cj。
📦 JSON 响应字段速览
响应体是一个以「国家代码」为键的对象,每个国家包含以下字段(空值字段会自动省略,进一步压缩体积):
| 字段 | 说明 | 示例 |
|---|---|---|
locale | 本次响应的语言区域 | zh |
layout | 地址布局模板(%P邮编、%L城市、%R区域、%1行1…) | 〒%P\n%R%L\n%1 |
required | 必填字段列表 | ["1","L","P"] |
defaults | 字段默认值 | — |
region_type | 行政层级类型(省/州/都道府县…) | province |
postal_code_pattern | 邮编校验正则 | ^\d{6}$ |
show_region_id | 是否展示行政区划代码 | false |
regions | 行政代码 → 本地语言名称(约 50 个国家提供) | {"SN": "陕西省"} |
以?locale=zh请求时,CN条目的示意如下(实际字段以接口返回为准):
{ "CN": { "locale": "zh", "layout": "%P\n%R%L\n%1\n%2\n%3", "required": ["1", "L", "P"], "region_type": "province", "postal_code_pattern": "^\\d{6}$", "show_region_id": false, "regions": { "SN": "陕西省" } } }前端拿到后:layout决定表单字段顺序,required控制必填校验,postal_code_pattern直接用于邮编格式校验——一套数据,三种用途。
🚀 5 分钟启动:最简服务端代码
搭建服务器只需一个FormatDistributor实例(参考测试用例中的搭建方式,src/test/http_test.cj):
import address4cj.* import stdx.net.http.* main() { let server = ServerBuilder() .addr("127.0.0.1") .port(8080) .distributor(FormatDistributor()) .build() server.serve() }启动后,用三条命令验证三种语言指定方式:
# ① 不带参数:默认返回英语格式 curl -i http://127.0.0.1:8080/address-formats # ② 查询参数指定中文 curl -i "http://127.0.0.1:8080/address-formats?locale=zh" # ③ 请求头指定繁体中文(注意只取第一个值) curl -i -H "Accept-Language: zh-Hant, zh, en;q=0.8" http://127.0.0.1:8080/address-formats预期结果:状态码 200,响应头Content-Type: application/json,Content-Language分别对应en、zh、zh-Hant;响应体中TW等国家的layout与regions也会随语言切换为对应模板与本地名称(完整断言逻辑可参考 src/test/http_test.cj)。
💡 前端接入的 3 个实用建议
- 按语言缓存:响应包含全部约 200 个国家的数据,适合在浏览器内按
Content-Language分键缓存,用户切换语言再拉取一次即可; - 用响应头做联调:前端 i18n 切到某语言后,检查
Content-Language是否一致,能快速定位「语言协商失败」问题; - 配合 Formatter 做服务端渲染:如果你在后端直接生成地址 HTML,同一库还提供 HTML 格式化器,示例见 README.md,与 JSON API 互补。
❓ 常见问题排查
| 现象 | 原因与处理 |
|---|---|
| 返回 404 | 路径必须是精确的/address-formats,其他路径由NotFoundHandler处理 |
| 语言不生效 | 确认 locale 写法(如zh、zh-Hant);请求头方式下只会采用第一个候选语言 |
某国没有regions字段 | 正常现象,约 50 个国家提供行政区划本地名称,其余国家该字段被省略 |
| 想扩展接口 | 通过FormatDistributor.register()注册自定义路径与处理器 |
📚 总结与延伸阅读
一句话回顾:FormatDistributor 负责路由,FormatHandler 负责按 locale 生成全国家地址格式 JSON,语言优先级为「查询参数 > Accept-Language > 英语」。基于 address4cj 搭建多语言地址格式 API 的核心工作就是三行ServerBuilder代码,剩下的交给内置的 CLDR 数据。
想继续深入,推荐阅读:
- 完整接口文档:doc/feature_api.md
- 服务实现源码:src/http.cj
- 语言标识标准化:src/locale.cj
- 国家级格式规则库:src/format.cj
- 基于 CLDR v47 的国家列表数据:src/countries.cj
- 端到端测试用例:src/test/http_test.cj
- 变更日志:CHANGELOG.md
【免费下载链接】address4cj处理地址表示、验证和格式化。项目地址: https://gitcode.com/Cangjie-SIG/address4cj
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考