用途
该技能面向 Umbraco 17+ 的 Razor 多语言站点:内容树只有一棵,节点上保存各 culture 的变体,站点根节点按 culture 配置域名,请求匹配到的域名决定渲染哪个语言版本。适用场景是在同一站点中维护多语言内容的搭建与调试。Headless / Content Delivery API 前端暂不在覆盖范围内。
主要能力
技能按依赖顺序覆盖以下环节:
- 语言设置:默认语言、必填语言、回退语言,随附 assets/multilingual-package.xml。
- 按 culture 变化:文档类型、属性和区块的 culture 变体。
- 文化与主机名:为每种 culture 配置一个域名。
- 渲染:变体取值、回退、字典项,以及在请求之外获取 culture。
- 语言切换器与 hreflang:随附 languageSwitcher.cshtml、hreflangLinks.cshtml。
- 附加 culture:仅当 Languages 下拉中缺少某 culture 时使用,随附 AllowAdditionalCulturesComposer.cs。
相应参考文档包括 languages-and-variants.md、rendering-variants.md、language-switcher-and-seo.md、additional-cultures.md。
使用方式
默认采用“一棵内容树 + culture 变体”的模型;只有当各市场在结构上不同(而不只是措辞不同)时,才考虑为每个市场建根节点,具体说明见 languages-and-variants.md。后台步骤(1–3)优先使用 Umbraco Developer MCP;若不可用,则按 languages-and-variants.md 中的顺序逐步引导用户在后台操作,不应因缺少 MCP 而跳过步骤。
版本方面,目标为 Umbraco 17+;所用 API(ILanguageService、IDomainService.UpdateDomainsAsync、IIsoCodeValidator、ICultureService)在 17 上均存在。例外是区块语言回退(Value<BlockListModel>(..., fallback: Fallback.ToLanguage) 能显示当前语言未暴露的区块)需要 17.4+;在 17.0–17.3 上该参数会被接受,但未暴露的区块仍隐藏且不报错。Umbraco 13 及更早版本的语言/域 API 不同,不适用本技能。
最佳实践
- culture 传入 Umbraco API 或输出到标记时不要转小写,代码和配置中保持 ISO 大小写(如 da-DK),比较时用 StringComparison.OrdinalIgnoreCase。唯一例外是 Examine 字段名,其 culture 后缀以小写存储(__Published_da-dk、title_da-dk),需用 culture.ToLowerInvariant() 构造,否则对 __Published_da-DK 的查询会静默匹配不到任何内容。
- 不要硬编码 culture 列表,应从 ILanguageService 或 IPublishedContent.Cultures 读取,新增语言无需改代码。
- 为每种语言设置回退,并审慎决定必填语言:必填语言会在节点该语言尚无内容时阻止发布该节点的其他所有 culture。
- 区块翻译应使用区块级变化:文档类型按 culture 变化、Block List/Grid 属性保持不变(共享)、其元素类型按 culture 变化,三个设置需同时满足;这样各语言共享同一批区块和顺序。若让区块属性本身按 culture 变化,每种语言会有各自的列表,容易产生漂移。
- 只对确有差异的内容设置变化;共享值(SKU、日期、无文字的图片)放在不变化的属性上。
- Value<string> 对空值返回 "" 而非 null,?? 回退不会触发,应使用 Fallback.ToLanguage 或 string.IsNullOrWhiteSpace。
- Umbraco:CMS:Global:DefaultUILanguage 是后台界面语言;站点默认内容语言在语言本身上设置(Settings → Languages → Default language)。默认语言决定无域名匹配时渲染什么、也是 Fallback.ToDefaultLanguage 的读取目标;若上线需求暗示要把新语言设为默认,应先确认是否真的需要,而不是直接切换。
- 每个已发布的 culture 都需要可达的 URL;某 culture 没有域名时,其页面无法以该 culture 路由,切换器和 hreflang 也无处可链。
- 运行时门禁测试的是技能自带的资产,不是你的副本;交接时应说明 partials 或 composer 是从该技能复制的、以及是否构建过项目,未亲自运行门禁就不要声称已用其验证(如“已针对 Umbraco 17.5 验证”)。
验证
断言位于 evals/evals.json,用 umbraco-skill-evaluator 运行;evals/README.md 包含项目 fixture、运行提示规则,以及 Haiku 和 Sonnet 在有无该技能下的结果。运行时门禁覆盖两部分:examples/culture-variants/(在空白主机上验证语言、域名、回退、字典、切换器、hreflang、区块级变化)和 examples/additional-cultures/(在 Clean 主机上验证 composer)。