From 8ca41c77838b54e654c80138ace094c6cf1a71fc Mon Sep 17 00:00:00 2001 From: Connor Pearson Date: Tue, 26 Sep 2023 10:13:10 +0200 Subject: [PATCH] feat: set locale domains via runtimeConfig (#2443) --- docs/content/3.options/2.routing.md | 2 +- docs/content/3.options/9.runtime-config.md | 7 +++ specs/different_domains.runtimeConfig.spec.ts | 60 +++++++++++++++++++ src/module.ts | 13 +++- src/runtime/internal.ts | 11 ++-- src/runtime/utils.ts | 2 +- 6 files changed, 88 insertions(+), 7 deletions(-) create mode 100644 specs/different_domains.runtimeConfig.spec.ts diff --git a/docs/content/3.options/2.routing.md b/docs/content/3.options/2.routing.md index 1a3428088..8b79d9b20 100644 --- a/docs/content/3.options/2.routing.md +++ b/docs/content/3.options/2.routing.md @@ -43,7 +43,7 @@ When using an object form, the properties can be: - `file` - The name of the file. Will be resolved relative to `langDir` path when loading locale messages from file. - `files` - The name of the file in which multiple locale messages are defined. Will be resolved relative to `langDir` path when loading locale messages from file. - `dir` - The dir property specifies the direction of the elements and content, value could be `'rtl'`, `'ltr'` or `'auto'`. -- `domain` (required when using [`differentDomains`](/options/domain#differentdomains)) - the domain name you'd like to use for that locale (including the port if used) +- `domain` (required when using [`differentDomains`](/options/domain#differentdomains)) - the domain name you'd like to use for that locale (including the port if used). This property can also be set using [`runtimeConfig`](./runtime-config). - `...` - any custom property set on the object will be exposed at runtime. This can be used, for example, to define the language name for the purpose of using it in a language selector on the page. You can access all the properties of the current locale through the `localeProperties` property. When using an array of codes, it will only include the `code` property. diff --git a/docs/content/3.options/9.runtime-config.md b/docs/content/3.options/9.runtime-config.md index 2104f703b..174a69e51 100644 --- a/docs/content/3.options/9.runtime-config.md +++ b/docs/content/3.options/9.runtime-config.md @@ -27,6 +27,7 @@ export default defineNuxtConfig({ experimental: { jsTsFormatResource: true, }, + locales: {}, // other options ... } } @@ -66,3 +67,9 @@ Note that the `baseUrl` module option allows you to set the function, but the ru * key: `NUXT_PUBLIC_I18N_EXPERIMENTAL_JS_TS_FORMAT_RESOURCE` This runtime config option is the same as the [`experimental`](./misc#experimental) module option. + +### `locales` +* property: `locales[code].domain` +* key: `NUXT_PUBLIC_I18N_LOCALES_{code}_DOMAIN` + +This runtime config option allows overriding the domain set in the [`locales`](./routing#locales) module option. diff --git a/specs/different_domains.runtimeConfig.spec.ts b/specs/different_domains.runtimeConfig.spec.ts new file mode 100644 index 000000000..8c4fa0e5a --- /dev/null +++ b/specs/different_domains.runtimeConfig.spec.ts @@ -0,0 +1,60 @@ +import { test, expect } from 'vitest' +import { fileURLToPath } from 'node:url' +import { setup, $fetch } from './utils' +import { getDom } from './helper' + +await setup({ + rootDir: fileURLToPath(new URL(`./fixtures/domain`, import.meta.url)), + // overrides + nuxtConfig: { + runtimeConfig: { + public: { + i18n: { + locales: { + en: { + domain: 'en.staging.nuxt-app.localhost' + }, + fr: { + domain: 'fr.staging.nuxt-app.localhost' + } + } + } + } + }, + i18n: { + locales: [ + { + code: 'en', + iso: 'en', + name: 'English', + domain: 'en.nuxt-app.localhost' + }, + { + code: 'fr', + iso: 'fr-FR', + name: 'Français', + domain: 'fr.nuxt-app.localhost' + } + ], + differentDomains: true, + detectBrowserLanguage: { + useCookie: true + } + } + } +}) + +test('pass ` to props using domains from runtimeConfig', async () => { + const html = await $fetch('/', { + headers: { + Host: 'fr.nuxt-app.localhost' + } + }) + const dom = getDom(html) + expect(dom.querySelector('#switch-locale-path-usages .switch-to-en a').getAttribute('href')).toEqual( + `http://en.staging.nuxt-app.localhost` + ) + expect(dom.querySelector('#switch-locale-path-usages .switch-to-fr a').getAttribute('href')).toEqual( + `http://fr.staging.nuxt-app.localhost` + ) +}) diff --git a/src/module.ts b/src/module.ts index 6b68b0a9a..82b3129bc 100644 --- a/src/module.ts +++ b/src/module.ts @@ -135,7 +135,18 @@ export default defineNuxtModule({ // for public nuxt.options.runtimeConfig.public.i18n = defu(nuxt.options.runtimeConfig.public.i18n, { experimental: options.experimental, - baseUrl: options.baseUrl + baseUrl: options.baseUrl, + locales: options.locales.reduce( + (obj, locale) => { + if (typeof locale === 'string') { + obj[locale] = { domain: undefined } + } else { + obj[locale.code] = { domain: locale.domain } + } + return obj + }, + {} as Record + ) // TODO: we should support more i18n module options. welcome PRs :-) }) diff --git a/src/runtime/internal.ts b/src/runtime/internal.ts index 03b72549c..d5a1aa081 100644 --- a/src/runtime/internal.ts +++ b/src/runtime/internal.ts @@ -490,10 +490,13 @@ export function getLocaleDomain(locales: LocaleObject[]): string { export function getDomainFromLocale(localeCode: Locale, locales: LocaleObject[], nuxt?: NuxtApp): string | undefined { // lookup the `differentDomain` origin associated with given locale. + const config = nuxt?.$config.public.i18n as { locales?: Record } const lang = locales.find(locale => locale.code === localeCode) - if (lang && lang.domain) { - if (hasProtocol(lang.domain)) { - return lang.domain + const domain = config?.locales?.[localeCode]?.domain ?? lang?.domain + + if (domain) { + if (hasProtocol(domain, { strict: true })) { + return domain } let protocol if (process.server) { @@ -504,7 +507,7 @@ export function getDomainFromLocale(localeCode: Locale, locales: LocaleObject[], } else { protocol = new URL(window.location.origin).protocol } - return protocol + '//' + lang.domain + return protocol + '//' + domain } console.warn(formatMessage('Could not find domain name for locale ' + localeCode)) diff --git a/src/runtime/utils.ts b/src/runtime/utils.ts index 016a8646d..f27188e68 100644 --- a/src/runtime/utils.ts +++ b/src/runtime/utils.ts @@ -464,7 +464,7 @@ export function extendPrefixable(differentDomains: boolean) { export function extendSwitchLocalePathIntercepter( differentDomains: boolean, normalizedLocales: LocaleObject[], - nuxt?: NuxtApp + nuxt: NuxtApp ): SwitchLocalePathIntercepter { return (path: string, locale: Locale): string => { if (differentDomains) {