多域名多语言区域设置
如何设置多域名多语言区域:
- 将
multiDomainLocales选项设置为true - 将
locales选项配置为对象数组:- 每个对象都有一个
domains键,其值是一个包含您希望用于该区域设置的域名的数组。可选地包含端口(如果不是标准端口)和/或协议。如果未提供协议,则会尝试自动检测,但在某些情况下可能无法正常工作,例如页面是静态生成时。 - 可选地为每个对象设置
defaultForDomains键,其值是一个包含您希望用于该区域设置的默认域名的数组。可选地包含端口(如果不是标准端口)和/或协议。如果未提供协议,则会尝试自动检测,但在某些情况下可能无法正常工作,例如页面是静态生成时。
- 每个对象都有一个
- 可选地设置
defaultLocale。每个域名都会根据defaultForDomains解析自身未添加前缀的区域设置,此项为整个集群指定回退区域设置——请参阅defaultLocale和x-default。 - 可选地将
detectBrowserLanguage设置为false。启用时(默认启用),首次访问会被重定向到提供浏览器检测到的区域设置的域名,而从您自己的某个域名(区域设置切换器链接、跨域链接)访问的访客会停留在其选择的域名上。发送Accept-Language标头的爬虫(Bingbot 会发送,Googlebot 大多不会)会被视为首次访问,并且在不提供其语言的域名上会收到重定向,而不是页面内容。如果您希望确保访问给定域名时始终显示该域名自身区域设置的页面(包括爬虫),请将其设置为false。使用<SwitchLocalePathLink>构建跨域切换器——指向其他域名的普通<NuxtLink>会携带rel="noreferrer",因此无法识别访问者是您自己的访客,并会再次被检测逻辑重定向。全站范围的Referrer-Policy(会移除 referer)也会产生相同效果——在这种情况下,只有覆盖这些域名的cookieDomain才能让切换保持有效。 - 当您的域名共享一个后缀时(例如同一站点的子域名),将
detectBrowserLanguage.cookieDomain设置为该后缀,以便访客的区域设置选择可以在域名之间传递。作用域限定为单个域名的 Cookie 只会应用于设置它的域名,绝不会重定向到其他域名——不覆盖所有已配置域名的cookieDomain也是如此。
const i18nDomains = ['mydomain.com', 'es.mydomain.com', 'fr.mydomain.com', 'http://pl.mydomain.com', 'https://ua.mydomain.com']
export default defineNuxtConfig({
i18n: {
locales: [
{
code: 'en',
domains: i18nDomains,
defaultForDomains: ['mydomain.com']
},
{
code: 'es',
domains: i18nDomains,
defaultForDomains: ['es.mydomain.com']
},
{
code: 'fr',
domains: i18nDomains,
defaultForDomains: ['fr.mydomain.com']
},
{
code: 'pl',
domains: i18nDomains,
defaultForDomains: ['http://pl.mydomain.com']
},
{
code: 'ua',
domains: i18nDomains,
defaultForDomains: ['https://ua.mydomain.com']
},
{
code: 'nl',
domains: i18nDomains
},
{
code: 'de',
domains: i18nDomains
},
],
defaultLocale: 'en',
multiDomainLocales: true
}
})
运行时环境变量
有时需要在不同环境中更改域名,例如预发布和生产环境。
由于 nuxt.config.ts 在构建时使用,因此需要为不同环境创建不同的构建。
export const localeDomains = {
uk: process.env.DOMAIN_UK,
fr: process.env.DOMAIN_FR
}
import { localeDomains } from './locale-domains.config'
const i18nDomains = [localeDomains.uk, localeDomains.fr]
export default defineNuxtConfig({
modules: ['@nuxtjs/i18n'],
i18n: {
multiDomainLocales: true,
locales: [
{
code: 'uk',
domains: i18nDomains,
defaultForDomains: [localeDomains.uk]
},
{
code: 'fr',
domains: i18nDomains,
defaultForDomains: [localeDomains.fr]
}
]
}
})
借助上述配置,预发布和生产环境需要分别用不同的 .env 文件运行构建,这些文件指定了 DOMAIN_UK 和 DOMAIN_FR。
通过在运行时使用 NUXT_PUBLIC_I18N_DOMAIN_LOCALES_{code}_DOMAIN 覆盖域名,单个构建也可以服务于不同的域名——请参阅 differentDomains 指南中的运行时环境变量,其中还包括该覆盖无法更改的内容。
仅为部分语言使用不同的域名
如果多个域共享相同的默认语言,可以使用支持多个域名的 defaultForDomains 来全部指定它们。
const i18nDomains = ['mydomain.com', 'en.mydomain.com', 'es.mydomain.com', 'fr.mydomain.com', 'http://pl.mydomain.com', 'https://ua.mydomain.com']
export default defineNuxtConfig({
// ...
i18n: {
locales: [
{
code: 'en',
domains: i18nDomains,
defaultForDomains: ['mydomain.com', 'en.mydomain.com']
},
{
code: 'es',
domains: i18nDomains,
defaultForDomains: ['es.mydomain.com']
},
{
code: 'fr',
domains: i18nDomains,
defaultForDomains: ['fr.mydomain.com']
},
{
code: 'pl',
domains: i18nDomains,
defaultForDomains: ['http://pl.mydomain.com']
},
{
code: 'ua',
domains: i18nDomains,
defaultForDomains: ['https://ua.mydomain.com']
},
{
code: 'nl',
domains: i18nDomains
},
{
code: 'de',
domains: i18nDomains
},
],
strategy: 'prefix',
multiDomainLocales: true
},
// ...
})
上述配置配合 'prefix' 策略,请求如下:
- https://mydomain.com -> https://mydomain.com/en (英文)
- https://mydomain.com/pl -> https://mydomain.com/pl (波兰语)
- https://mydomain.com/ua -> https://mydomain.com/ua (乌克兰语)
- https://mydomain.com/nl -> https://mydomain.com/nl (荷兰语)
- https://en.mydomain.com -> https://en.mydomain.com/en (英文)
- https://es.mydomain.com -> https://es.mydomain.com/es (西班牙语)
- https://fr.mydomain.com -> https://fr.mydomain.com/fr (法语)
- https://fr.mydomain.com/de -> https://fr.mydomain.com/de (德语)
使用 'prefix_except_default' 策略时,相同的请求将变为:
- https://mydomain.com -> https://mydomain.com (英文)
- https://mydomain.com/pl -> https://mydomain.com/pl (波兰语)
- https://mydomain.com/ua -> https://mydomain.com/ua (乌克兰语)
- https://mydomain.com/nl -> https://mydomain.com/nl (荷兰语)
- https://en.mydomain.com -> https://en.mydomain.com (英文)
- https://es.mydomain.com -> https://es.mydomain.com (西班牙语)
- https://fr.mydomain.com -> https://fr.mydomain.com (法语)
- https://fr.mydomain.com/de -> https://fr.mydomain.com/de (德语)
- https://fr.mydomain.com/en -> https://fr.mydomain.com/en (英文)
某个语言仅在将其设为默认语言的域名上不带前缀,在其他所有域名上都会保留其前缀。这也包括设置为 defaultLocale 的语言。
将语言环境限制到特定域名
语言环境的 domains 不必列出每个域名,只需列出应该提供该语言环境的域名即可。未配置 domains 的语言环境会在所有域名上提供。
限制语言环境可以确保每个页面都能通过单一地址访问:列在某个域名上的语言环境会在该域名上提供,并从其他域名重定向到该域名。在多个域名上列出同一个语言环境,会使其在每个域名上都可用,因此同一个页面可以通过多个 URL 访问——关于这些 URL 如何标注,请参阅 defaultLocale 和 x-default。
将每个语言环境限制到各自独立的域名上,也是使 strategy: 'no_prefix' 在此处可用的条件:路径中没有前缀时,域名是标识语言环境的唯一依据,因此每个域名必须恰好提供一个语言环境。在 'no_prefix' 下让两个语言环境共用一个域名,会导致路由未本地化,并在构建时报告错误。
export default defineNuxtConfig({
i18n: {
locales: [
{
code: 'en',
domains: ['mydomain.com'],
defaultForDomains: ['mydomain.com']
},
{
// 在两个域名之间共享
code: 'fr',
domains: ['mydomain.com', 'es.mydomain.com']
},
{
code: 'es',
domains: ['es.mydomain.com'],
defaultForDomains: ['es.mydomain.com']
}
],
defaultLocale: 'en',
strategy: 'prefix_except_default',
multiDomainLocales: true
}
})
根据上述配置,以下请求将会:
- https://mydomain.com -> https://mydomain.com(英语)
- https://mydomain.com/fr -> https://mydomain.com/fr(法语)
- https://mydomain.com/es -> https://es.mydomain.com(西班牙语,重定向到提供该语言的域名)
- https://es.mydomain.com -> https://es.mydomain.com(西班牙语)
- https://es.mydomain.com/fr -> https://es.mydomain.com/fr(法语)
- https://es.mydomain.com/en -> https://mydomain.com(英语,重定向到提供该语言的域名)
在其他域名上提供的语言环境仍会在 locales 和语言环境切换器中可用,switchLocalePath 会将它们链接到提供该语言的域名。浏览器语言检测遵循相同的规则:如果首次访问时检测到的语言环境由其他域名提供,则会重定向到该域名。从某个已配置域名进入的访问者已经选择了目标地址,并会保留该域名自身的语言环境;只有当 detectBrowserLanguage.cookieDomain 使语言环境 Cookie 在另一个域名上可见时,才会根据该 Cookie 重定向到另一个域名。
对不匹配任何已配置域名的主机发起的请求(例如暂存域名或通过 IP 进行的健康检查)不受限制。所有语言环境都会在该主机上提供,并使用 defaultLocale 作为无前缀的默认语言环境,因此即使每个域名都通过 defaultForDomains 设置了自己的默认语言环境,也值得设置 defaultLocale。此类主机上的重定向会保持相对路径,不会将访问者发送到任何一个已配置的域名。
defaultLocale 和 x-default
这些域名被标注为一个集群,每个页面都会链接到其他域名上的替代页面。一个集群针对不匹配的语言只有一个回退选项,因此 x-default 替代页面取自 defaultLocale,而不是取自某个域名恰好默认使用的语言环境——否则每个域名都会指定不同的一个页面。
在多个域名上提供的语言环境会在其中一个域名上进行标注:优先使用其 defaultForDomains 中的第一个条目;如果没有,则使用 domains 中的第一个条目。提供该语言环境的每个域名都会为它输出相同的 URL,从而保持集群的相互对应关系——如果改为标注当前域名,那么每个域名都会声称该语言属于自己。未配置任何域名的语言环境会在所有域名上提供,但没有属于自己的域名可供标注,因此会采用提供 defaultLocale 的域名。
规范链接遵循相同的规则,因此在多个域名上可访问的页面会指向其语言所标注的 URL,而不是将自身作为目标。仅在单个域名上提供的语言环境,其规范链接会指向该域名,与之前相同。
这意味着,你在多个域名上列出的语言环境会在其中一个域名上进行宣传,同时仍可通过其他域名访问,因此除非你确实希望某个语言环境在多个位置提供,否则应将其限制在所属的域名上。
这里的 defaultLocale 是可选的,因为每个域名都会通过 defaultForDomains 解析自身未加前缀的语言环境。不设置它意味着完全不会标注 x-default,这虽然是允许的,但会失去向语言与任何语言环境都不匹配的访问者传递的一项信号。未设置时会记录一条警告。