Skip to content

Commit 5f56bba

Browse files
ap-artoapavlovskyBobbieGoede
authored
fix: respect detectBrowserLanguage: false in SSG plugin (#3410)
--------- Co-authored-by: apavlovsky <apavlovsky@greengeeks.com> Co-authored-by: Bobbie Goede <bobbiegoede@gmail.com>
1 parent 2a4d88c commit 5f56bba

12 files changed

Lines changed: 122 additions & 18 deletions

File tree

specs/fixtures/issues/3407/app.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<template>
2+
<div>
3+
<NuxtRouteAnnouncer />
4+
<NuxtPage />
5+
</div>
6+
</template>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"heading": "i18n SSG issue",
3+
"text": "This is a test case of the nuxt/i18n SSG issue"
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"heading": "Problema de i18n SSG",
3+
"text": "Este es un caso de prueba del problema de nuxt/i18n SSG"
4+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// https://nuxt.com/docs/api/configuration/nuxt-config
2+
export default defineNuxtConfig({
3+
modules: ['@nuxtjs/i18n'],
4+
i18n: {
5+
// some of the options are taken from the runtimeConfig
6+
strategy: 'no_prefix',
7+
differentDomains: true,
8+
lazy: false,
9+
locales: [
10+
{
11+
code: 'en',
12+
language: 'en-US',
13+
isCatchallLocale: true,
14+
domain: '127.0.0.1:7776',
15+
// domain: 'en.localhost',
16+
name: 'English',
17+
files: ['en.json']
18+
},
19+
{
20+
code: 'es',
21+
language: 'es-ES',
22+
domain: '127.0.0.1:7777',
23+
// domain: 'es.localhost',
24+
name: 'Español',
25+
files: ['es.json']
26+
}
27+
],
28+
detectBrowserLanguage: false
29+
}
30+
})
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "fixture-3407",
3+
"private": true,
4+
"scripts": {
5+
"build": "nuxt build",
6+
"dev": "nuxt dev",
7+
"generate": "nuxt generate",
8+
"preview": "nuxt preview"
9+
},
10+
"devDependencies": {
11+
"@nuxtjs/i18n": "latest",
12+
"nuxt": "latest"
13+
}
14+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<template>
2+
<div>
3+
<h1 id="translated-heading">{{ $t('heading') }}</h1>
4+
</div>
5+
</template>

specs/helper.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export async function renderPage(path = '/', options?: BrowserContextOptions) {
109109

110110
if (path) {
111111
/**
112-
* Nuxt uses `gotoPath` here, ths would throw errors as the given `path` can differ
112+
* Nuxt uses `gotoPath` here, this would throw errors as the given `path` can differ
113113
* from the final path due to language detection and redirects.
114114
*/
115115
// gotoPath(page, path)

specs/issues/3407.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { test, expect } from 'vitest'
2+
import { fileURLToPath } from 'node:url'
3+
import { createPage, setup, url } from '../utils'
4+
import { getText } from '../helper'
5+
6+
// this is an SSG test
7+
await setup({
8+
rootDir: fileURLToPath(new URL(`../fixtures/issues/3407`, import.meta.url)),
9+
browser: true,
10+
prerender: true,
11+
port: [7777, 7776]
12+
})
13+
14+
test('does not reset cookie no refresh', async () => {
15+
const page = await createPage('/')
16+
const heading = await getText(page, '#translated-heading')
17+
expect(heading).toEqual(`Problema de i18n SSG`)
18+
19+
await page.goto(url('/', 7776))
20+
const heading2 = await getText(page, '#translated-heading')
21+
expect(heading2).toEqual(`i18n SSG issue`)
22+
})

specs/utils/browser.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export async function waitForHydration(page: Page, url: string, waitUntil?: Goto
4949
}
5050
}
5151

52-
export async function createPage(path?: string, options?: BrowserContextOptions) {
52+
export async function createPage(path?: string, options?: BrowserContextOptions, port?: number) {
5353
const browser = await getBrowser()
5454
const page = await browser.newPage(options)
5555

@@ -59,13 +59,14 @@ export async function createPage(path?: string, options?: BrowserContextOptions)
5959
if (waitUntil && ['hydration', 'route'].includes(waitUntil)) {
6060
delete options.waitUntil
6161
}
62+
6263
const res = await _goto(url, options as Parameters<Page['goto']>[1])
6364
await waitForHydration(page, url, waitUntil)
6465
return res
6566
}
6667

6768
if (path) {
68-
await page.goto(url(path), { waitUntil: 'hydration' })
69+
await page.goto(url(path, port), { waitUntil: 'hydration' })
6970
}
7071

7172
return page

specs/utils/server.ts

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ import { resolve } from 'pathe'
99
import { useTestContext } from './context'
1010
import { request } from 'undici'
1111

12+
function toArray<T>(value: T | T[]): T[] {
13+
return Array.isArray(value) ? value : [value]
14+
}
15+
1216
// @ts-expect-error type cast
1317
// eslint-disable-next-line
1418
const kit: typeof _kit = _kit.default || _kit
@@ -17,8 +21,8 @@ export async function startServer(env: Record<string, unknown> = {}) {
1721
const ctx = useTestContext()
1822
await stopServer()
1923
const host = '127.0.0.1'
20-
const port = ctx.options.port || (await getRandomPort(host))
21-
ctx.url = `http://${host}:${port}`
24+
const ports = ctx.options.port ? toArray(ctx.options.port) : [await getRandomPort(host)]
25+
ctx.url = `http://${host}:${ports[0]}`
2226
if (ctx.options.dev) {
2327
const nuxiCLI = await kit.resolvePath('nuxi/cli')
2428
ctx.serverProcess = exec(nuxiCLI, ['_dev'], {
@@ -27,15 +31,15 @@ export async function startServer(env: Record<string, unknown> = {}) {
2731
stdio: 'inherit',
2832
env: {
2933
...process.env,
30-
_PORT: String(port), // Used by internal _dev command
31-
PORT: String(port),
34+
_PORT: String(ports[0]), // Used by internal _dev command
35+
PORT: String(ports[0]),
3236
HOST: host,
3337
NODE_ENV: 'development',
3438
...env
3539
}
3640
}
3741
})
38-
await waitForPort(port, { retries: 32, host }).catch(() => {})
42+
await waitForPort(ports[0], { retries: 32, host }).catch(() => {})
3943
let lastError
4044
for (let i = 0; i < 150; i++) {
4145
await new Promise(resolve => setTimeout(resolve, 100))
@@ -51,35 +55,36 @@ export async function startServer(env: Record<string, unknown> = {}) {
5155
ctx.serverProcess.kill()
5256
throw lastError || new Error('Timeout waiting for dev server!')
5357
} else if (ctx.options.prerender) {
54-
const command = `pnpx serve ${ctx.nuxt!.options.nitro!.output?.publicDir} -l tcp://${host}:${port} --no-port-switching`
55-
// ; (await import('consola')).consola.restoreConsole()
58+
const listenTo = ports.map(port => `-l tcp://${host}:${port}`).join(' ')
59+
const command = `pnpx serve ${ctx.nuxt!.options.nitro!.output?.publicDir} ${listenTo} --no-port-switching`
60+
// ;(await import('consola')).consola.restoreConsole()
5661
const [_command, ...commandArgs] = command.split(' ')
5762

5863
ctx.serverProcess = exec(_command, commandArgs, {
5964
nodeOptions: {
6065
env: {
6166
...process.env,
62-
PORT: String(port),
67+
PORT: String(ports[0]),
6368
HOST: host,
6469
...env
6570
}
6671
}
6772
})
6873

69-
await waitForPort(port, { retries: 32, host, delay: 1000 })
74+
await waitForPort(ports[0], { retries: 32, host, delay: 1000 })
7075
} else {
7176
ctx.serverProcess = exec('node', [resolve(ctx.nuxt!.options.nitro.output!.dir!, 'server/index.mjs')], {
7277
nodeOptions: {
7378
stdio: 'inherit',
7479
env: {
7580
...process.env,
76-
PORT: String(port),
81+
PORT: String(ports[0]),
7782
HOST: host,
7883
...env
7984
}
8085
}
8186
})
82-
await waitForPort(port, { retries: 20, host })
87+
await waitForPort(ports[0], { retries: 20, host })
8388
}
8489
}
8590

@@ -102,14 +107,21 @@ export function undiciRequest(path: string, options?: Parameters<typeof request>
102107
return request(url(path), options)
103108
}
104109

105-
export function url(path: string) {
110+
export function url(path: string, port?: number) {
106111
const ctx = useTestContext()
107112
if (!ctx.url) {
108113
throw new Error('url is not available (is server option enabled?)')
109114
}
115+
110116
if (path.startsWith(ctx.url)) {
111117
return path
112118
}
119+
120+
// replace port in url
121+
if (port != null) {
122+
return ctx.url.slice(0, ctx.url.lastIndexOf(':')) + `:${port}/` + path
123+
}
124+
113125
return ctx.url + path
114126
}
115127

0 commit comments

Comments
 (0)