Sanity Studio多语言场景下如何实现当前Locale无文档时的回退查询
问题根因
当前的GROQ查询使用了无优先级的OR逻辑,只要文档满足「匹配目标语言」或「匹配默认语言」任意一个条件就会被返回,没有对同一内容的多语言版本做去重和优先级判断。当某份内容同时存在目标语言、默认语言两个版本时,两个版本都会被查出,前端如果没有做二次筛选,就会出现重复条目、错误渲染默认语言内容的问题。
正确的回退实现
基于sanity-plugin-intl-input的文档元数据特性:同一内容的所有语言版本,都会通过固定的关联ID做绑定。可以通过分组排序实现「优先匹配目标语言,目标语言无对应内容时自动回退到默认语言」的逻辑,从查询层面就避免返回重复的多语言条目,具体实现思路:
- 先过滤掉非目标语言、非默认语言的无效文档,减少查询计算量
- 按照同一内容的i18n关联ID对文档做分组
- 组内按优先级排序:目标语言条目的优先级高于默认语言条目,每组只保留优先级最高的那一条
适配常用的老版本插件(元数据为顶级__i18n_lang字段)的查询语句如下:
*[_type == "cardPage" && !(_id in path('drafts.**'))] [__i18n_lang in [$locale, $defaultLocale]] { "validDoc": @[]{ // 计算优先级:目标语言排序更靠前,优先级更高 "priority": select( __i18n_lang == $locale => 0, __i18n_lang == $defaultLocale => 1 ), ...this } | order(priority asc)[0] }.validDoc
如果是单详情页的查询,只需在最外层的过滤条件里补充对应路由参数(比如匹配slug值)即可,后续的分组优先级逻辑保持不变。
注意事项
- 如果使用的是新版本的sanity-plugin-intl-input,i18n元数据会嵌套在
__i18n对象下,只需把查询里的__i18n_lang替换为__i18n.lang,对应调整关联分组的字段名即可 - 单文档查询场景下,不要直接使用
目标语言 || 默认语言的无优先级条件,这类逻辑只会返回所有满足条件的文档,无法实现回退需要的优先级判断 - 前端拿到查询结果后不需要额外做语言过滤,返回的每一条文档都已经是对应内容下优先级最高的语言版本
内容的提问来源于stack exchange,提问作者Mahabubur Rahman
相关产品推荐
相关产品推荐

