不同的域名
您可能希望为您的应用支持的每种语言使用不同的域名。
实现方法如下:
- 将
differentDomains选项设置为true - 将
locales选项配置为对象数组,其中每个对象都有一个domain键,其值为您希望用于该语言环境的域名。您可以选择性地包含端口(如果不是标准端口)和/或协议。如果未提供协议,则会尝试自动检测,但在某些情况下可能无法正常工作,例如页面是静态生成时。 - 可选择将
detectBrowserLanguage设置为false。启用时(默认启用),首次访问会被重定向到提供浏览器检测到的语言环境的域名;而从您自己的某个域名访问的访客(通过语言切换器链接、跨域链接)则会停留在其选择的域名上。发送Accept-Language请求头的爬虫(Bingbot 会发送,Googlebot 通常不会)会被视为首次访问,并且对于不提供其语言的域名,会收到重定向而不是页面内容。如果您希望确保访问某个域名始终显示该域名自身语言环境的页面(包括爬虫),请将其设置为false。使用<SwitchLocalePathLink>构建跨域切换器——指向另一个域名的普通<NuxtLink>会携带rel="noreferrer",因此无法识别访问者是从您自己的域名到达的,并会再次被检测逻辑重定向。会移除来源地址的全站Referrer-Policy也会产生相同的效果——在这种情况下,只有覆盖这些域名的cookieDomain才能让切换保持生效。 - 当您的域名共享相同的后缀(例如同一站点的子域名)时,将
detectBrowserLanguage.cookieDomain设置为该后缀,以便访客的语言环境选择能够在不同域名之间传递。限定到单个域名的 Cookie 只会应用于设置它的域名,绝不会重定向到另一个域名——对于未覆盖所有已配置域名的cookieDomain,情况也是如此。
export default defineNuxtConfig({
i18n: {
locales: [
{
code: 'en',
domain: 'mydomain.com'
},
{
code: 'es',
domain: 'es.mydomain.com'
},
{
code: 'fr',
domain: 'fr.mydomain.com'
},
{
code: 'pl',
domain: 'http://pl.mydomain.com'
},
{
code: 'ua',
domain: 'https://ua.mydomain.com'
}
],
differentDomains: true
// 或仅在生产环境启用该选项
// differentDomains: (process.env.NODE_ENV === 'production')
}
})
使用不同的域名时,您的语言切换器链接会指向另一个源。建议使用 <SwitchLocalePathLink>,它还会写入语言环境 Cookie,因此当 detectBrowserLanguage.cookieDomain 覆盖您的域名时,切换后仍能保留该选择。普通的 <a> 标签同样可用——与 <NuxtLink> 不同,后者会为外部链接添加 rel="noreferrer",导致检测逻辑无法识别该访问是从您自己的域名到达的,并再次将其重定向:
<script setup>
const { locale, locales } = useI18n()
const switchLocalePath = useSwitchLocalePath()
const availableLocales = computed(() => {
return locales.value.filter(i => i.code !== locale.value)
})
</script>
<template>
...
<a v-for="locale in availableLocales" :href="switchLocalePath(locale.code)" :key="locale.code">
{{ locale.code }}
</a>
...
</template>
运行时环境变量
有时需要在不同环境中更改域名,例如预生产和生产环境。
由于 nuxt.config.ts 在构建时使用,因此需要为不同环境创建不同的构建版本。
export const localeDomains = {
uk: process.env.DOMAIN_UK,
fr: process.env.DOMAIN_FR
}
import { localeDomains } from './locale-domains.config'
export default defineNuxtConfig({
modules: ['@nuxtjs/i18n'],
i18n: {
differentDomains: process.env.NODE_ENV === 'production',
locales: [
{
code: 'uk',
domain: localeDomains.uk
},
{
code: 'fr',
domain: localeDomains.fr
}
]
}
})
根据以上配置,分别为预生产和生产环境运行构建时,需要使用不同的 .env 文件来指定 DOMAIN_UK 和 DOMAIN_FR。
或者,为了避免多次构建的需求,可以通过运行时环境变量来覆盖区域设置域。变量名称应遵循格式 NUXT_PUBLIC_I18N_DOMAIN_LOCALES_{code}_DOMAIN。
例如:
NUXT_PUBLIC_I18N_DOMAIN_LOCALES_UK_DOMAIN=uk.example.test
NUXT_PUBLIC_I18N_DOMAIN_LOCALES_FR_DOMAIN=fr.example.test
NUXT_PUBLIC_I18N_DOMAIN_LOCALES_UK_DOMAIN=uk.staging.example.test
NUXT_PUBLIC_I18N_DOMAIN_LOCALES_FR_DOMAIN=fr.staging.example.test
该覆盖设置会更改为某个区域设置提供服务的域名,但无法让某个区域设置成为它原本不是默认区域设置的域名的默认区域设置。域名以无前缀形式提供哪个区域设置,是由构建时生成的路由决定的,因此每个区域设置都需要在 nuxt.config.ts 中设置 domain(以及当一个域名为多个区域设置提供服务时设置 domainDefault),这样覆盖设置才能重新指向该区域设置。例如,如果构建时未设置 DOMAIN_FR,导致某个区域设置没有配置域名,那么它在被覆盖到的域名上仍会保留前缀,而该域名则会提供构建时实际解析为其默认区域设置的区域设置。'no_prefix' 策略不受影响,因为在该策略下,没有任何路由结构依赖域名。
仅为部分语言使用不同域名
如果一个或多个域名需要托管多种语言,则每个域的默认语言需要设置 domainDefault: true,以便针对该域有一个默认语言备用。
不过,differentDomains 选项仍需设置为 true。
export default defineNuxtConfig({
// ...
i18n: {
locales: [
{
code: 'en',
domain: 'mydomain.com',
domainDefault: true
},
{
code: 'pl',
domain: 'mydomain.com'
},
{
code: 'ua',
domain: 'mydomain.com'
},
{
code: 'es',
domain: 'es.mydomain.com',
domainDefault: true
},
{
code: 'fr',
domain: 'fr.mydomain.com',
domainDefault: true
}
],
strategy: 'prefix',
differentDomains: true
// 或仅在生产环境启用该选项
// differentDomains: (process.env.NODE_ENV === 'production')
},
// ...
})
基于上述配置和 '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://es.mydomain.com -> https://es.mydomain.com/es (西班牙语)
- https://fr.mydomain.com -> https://fr.mydomain.com/fr (法语)
使用 '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://es.mydomain.com -> https://es.mydomain.com (西班牙语)
- https://fr.mydomain.com -> https://fr.mydomain.com (法语)
不同域的缓存考虑事项
在使用不同域时,请确保正确配置缓存,以便每个域的响应能够正确分离。
因为同一路由可能在多个域名下提供服务(例如 en.mydomain.com 和 fr.mydomain.com),缓存需要根据请求主机进行变化。否则,为一个域生成的响应可能会在另一个域上被重用,导致错误的语言渲染,从而导致水合不匹配和客户端的可见闪烁。
推荐的设置是在您的路由规则中使用 cache.varies: ['host'],以便将 host 头包含在缓存键中:
export default defineNuxtConfig({
routeRules: {
- '/': { swr: 60 },
+ '/': { swr: 60, cache: { varies: ['host'] } },
},
// ...
})