本地化
本地化是现代 CMS 最重要的功能之一。它允许你管理多种语言的内容,然后根据用户请求的语言向其提供内容。这与 I18n 类似,但不是管理应用程序界面的翻译,而是管理数据本身的翻译。
通过本地化功能,你可以根据用户特定的语言偏好(例如多语言网站或多站点应用程序)开始向其提供个性化内容。你的 Payload 项目可以添加的语言环境数量没有限制。
要配置本地化功能,请在 Payload Config 中使用 localization
键:
import { buildConfig } from 'payload'
export default buildConfig({
// ...
localization: {
// highlight-line
// ...
},
})
配置选项
在 Payload Config 中添加 localization
属性以启用项目范围的本地化功能。你需要提供所有需要支持的语言环境列表,并设置一些其他选项。
要配置语言环境,请在 Payload Config 中使用 localization.locales
属性:
import { buildConfig } from 'payload'
export default buildConfig({
// ...
localization: {
locales: ['en', 'es', 'de'], // 必填
defaultLocale: 'en', // 必填
},
})
你也可以使用 完整配置对象 来定义语言环境:
import { buildConfig } from 'payload'
export default buildConfig({
collections: [
// 集合配置放在这里
],
localization: {
locales: [
{
label: 'English',
code: 'en',
},
{
label: 'Arabic',
code: 'ar',
// 当当前语言环境是rtl时,选择将Input字段的默认文本对齐方式设置为rtl(从右到左)
rtl: true,
},
],
defaultLocale: 'en', // 必填
fallback: true, // 默认为true
},
})
提示: 本地化功能与 I18n 配合使用效果非常好。
以下是可用的配置选项:
选项 | 描述 |
---|---|
locales | 包含所有需要支持的语言环境的数组。更多详情 |
defaultLocale | 必填字符串,必须与提供的数组中的某个语言环境代码匹配。默认情况下,如果未指定语言环境,文档将返回此语言环境的内容。 |
fallback | 布尔值,启用"回退"语言环境功能。如果请求某个语言环境的文档,但某个字段没有对应请求语言环境的本地化值,那么如果启用此属性,文档将自动回退到回退语言环境的值。如果未启用此属性,除非在请求中明确提供了回退值,否则该值将不会被填充。默认为true。 |
filterAvailableLocales | 一个函数,接收 locales 数组和 req 作为参数,应返回要在管理界面选择器中显示的语言环境。查看更多。 |
多语言配置
locales 数组列出了你想要支持的所有语言。可以是简单的语言代码字符串,也可以是完整的配置对象以实现更高级的选项。
语言代码不需要遵循特定格式。你可以自由定义如何表示你的语言环境。常见的模式是使用两位字母的 ISO 639 语言代码,或四位字母的语言和国家代码(ISO 3166‑1),例如 en-US
、en-UK
、es-MX
等。
语言对象配置
选项 | 描述 |
---|---|
code * | 用于在 API 中通过 locale 和 fallbackLocale 标识语言的唯一代码 |
label | 用于语言选择器显示的字符串,或一个以 i18n 键为键的对象,用于支持不同语言的显示。 |
rtl | 布尔值,设为 true 时将使管理界面以从右到左的方式显示。 |
fallbackLocale | 当文档属性不存在时,该语言将回退使用的语言代码。 |
* 星号表示该属性为必填项。
过滤可用选项
在某些项目中,你可能需要过滤管理界面选择器中显示的可用语种。这可以通过在 Payload 配置中提供 filterAvailableLocales
函数来实现。该函数在服务器端调用,并接收语种数组作为参数。这意味着你可以决定哪些语种会显示在管理面板顶部的本地化选择菜单中。你可以按用户进行过滤,或者实现一个按租户范围过滤的函数。以下是一个在多租户应用中使用请求头的示例:
// ... Payload 配置的其他部分
localization: {
defaultLocale: 'en',
locales: ['en', 'es'],
filterAvailableLocales: async ({ req, locales }) => {
if (getTenantFromCookie(req.headers, 'text')) {
const fullTenant = await req.payload.findByID({
id: getTenantFromCookie(req.headers, 'text') as string,
collection: 'tenants',
req,
})
if (fullTenant && fullTenant.supportedLocales?.length) {
return locales.filter((locale) => {
return fullTenant.supportedLocales?.includes(locale.code as 'en' | 'es')
})
}
}
return locales
},
}
由于过滤发生在应用的根级别,且结果不会在每次导航到新页面时重新计算,你可能需要在自定义组件中调用 router.refresh
,该组件会监视影响结果的值变化。在上面的示例中,当租户文档的 supportedLocales
发生变化时,你就需要这样做。
字段本地化
Payload 的本地化功能工作在字段级别,而非文档级别。除了在基础 Payload 配置中支持本地化外,你还需要为每个需要本地化的字段单独指定。
以下是如何为字段启用本地化(Localization)的示例:
{
name: 'title',
type: 'text',
// highlight-start
localized: true,
// highlight-end
}
通过上述配置,title
字段现在会以所有语言环境的对象形式保存在数据库中,而不是单个字符串。
所有带有 name
属性的字段类型都支持 localized
属性——即使是更复杂的字段类型如 array
和 block
也是如此。
注意: 对支持嵌套字段的字段类型启用本地化时,会自动为该字段包含的所有子字段创建本地化"集合"。例如,如果你使用 blocks 字段类型构建页面布局,你可以选择通过在最顶层的 blocks 字段上启用本地化来对整个布局进行本地化,或者只对布局中的特定字段进行本地化。
重要: 当将现有字段从 localized: true
转换或转换为非本地化时,该字段在文档中的数据结构会发生变化,因此该字段的现有数据将会丢失。在更改已有数据的字段的本地化设置前,你可能需要考虑字段迁移策略。
获取本地化文档
获取文档时,你可以指定希望接收的语言环境以及应该使用的备用语言环境。
REST API
REST API 的语言环境功能依赖于 URL 查询参数。
?locale=
通过在端点 URL 中直接提供 locale
查询参数来指定你需要的语言环境。
?fallback-locale=
通过提供 fallback-locale
查询参数来指定要使用的备用语言环境。可以将其设置为你的基础 Payload 配置中提供的有效语言环境,或者设置为 'null'
、'false'
或 'none'
来禁用回退功能。
示例:
fetch('https://localhost:3000/api/pages?locale=es&fallback-locale=none');
GraphQL API
在 GraphQL API 中,你可以为所有相关查询和变更指定 locale
和 fallbackLocale
参数。
locale
参数只接受有效的 locales,但 locales 会自动格式化为有效的 GraphQL 枚举值(破折号或特殊字符会被转换为下划线,空格会被移除等)。如果你想了解 locales 是如何自动格式化的,可以使用 GraphQL playground。
fallbackLocale
参数接受有效的 locales,也可以设置为 none
来禁用回退功能。
示例:
query {
Posts(locale: de, fallbackLocale: none) {
docs {
title
}
}
}
在 GraphQL 中,在查询的顶层指定 locale 会自动应用于所有嵌套的关系字段。你可以通过在嵌套的相关文档查询中重新指定 locale 参数来覆盖这一行为。
Local API
你也可以在 Local API 中通过 options
参数指定 locale
和 fallbackLocale
属性。locale
属性接受任何有效的 locale,而 fallbackLocale
属性接受任何有效的 locale,以及 'null'
、'false'
、false
和 'none'
。
示例:
const posts = await payload.find({
collection: 'posts',
locale: 'es',
fallbackLocale: false,
})
提示: REST 和 Local API 可以通过传递 'all' 或 '*' 作为 locale 参数,在一次请求中返回所有本地化数据。响应结构会将字段值作为完整的对象返回,按每个 locale 作为键,而不是单一的翻译值。