未验证 提交 fd33c9f7 编写于 作者: J JJ Kasper 提交者: GitHub

Ensure href is updated for locale domain (#20631)

This ensures we render the locale domain on the `href` when using `next/link` previously the provided `href` was stilling being rendered which differed from the resulting `href` that was navigated to. 

Fixes: https://github.com/vercel/next.js/issues/20612
上级 9fc9a6e1
...@@ -3,6 +3,7 @@ import { UrlObject } from 'url' ...@@ -3,6 +3,7 @@ import { UrlObject } from 'url'
import { import {
addBasePath, addBasePath,
addLocale, addLocale,
getDomainLocale,
isLocalURL, isLocalURL,
NextRouter, NextRouter,
PrefetchOptions, PrefetchOptions,
...@@ -297,13 +298,19 @@ function Link(props: React.PropsWithChildren<LinkProps>) { ...@@ -297,13 +298,19 @@ function Link(props: React.PropsWithChildren<LinkProps>) {
// If child is an <a> tag and doesn't have a href attribute, or if the 'passHref' property is // If child is an <a> tag and doesn't have a href attribute, or if the 'passHref' property is
// defined, we specify the current 'href', so that repetition is not needed by the user // defined, we specify the current 'href', so that repetition is not needed by the user
if (props.passHref || (child.type === 'a' && !('href' in child.props))) { if (props.passHref || (child.type === 'a' && !('href' in child.props))) {
childProps.href = addBasePath( const curLocale =
addLocale( typeof locale !== 'undefined' ? locale : router && router.locale
as,
typeof locale !== 'undefined' ? locale : router && router.locale, const localeDomain = getDomainLocale(
router && router.defaultLocale as,
) curLocale,
router && router.locales,
router && router.domainLocales
) )
childProps.href =
localeDomain ||
addBasePath(addLocale(as, curLocale, router && router.defaultLocale))
} }
return React.cloneElement(child, childProps) return React.cloneElement(child, childProps)
......
...@@ -74,6 +74,28 @@ function addPathPrefix(path: string, prefix?: string) { ...@@ -74,6 +74,28 @@ function addPathPrefix(path: string, prefix?: string) {
: path : path
} }
export function getDomainLocale(
path: string,
locale?: string | false,
locales?: string[],
domainLocales?: DomainLocales
) {
if (process.env.__NEXT_I18N_SUPPORT) {
locale = locale || normalizeLocalePath(path, locales).detectedLocale
const detectedDomain = detectDomainLocale(domainLocales, undefined, locale)
if (detectedDomain) {
return `http${detectedDomain.http ? '' : 's'}://${detectedDomain.domain}${
basePath || ''
}${locale === detectedDomain.defaultLocale ? '' : `/${locale}`}${path}`
}
return false
}
return false
}
export function addLocale( export function addLocale(
path: string, path: string,
locale?: string | false, locale?: string | false,
...@@ -290,6 +312,7 @@ export type BaseRouter = { ...@@ -290,6 +312,7 @@ export type BaseRouter = {
locale?: string locale?: string
locales?: string[] locales?: string[]
defaultLocale?: string defaultLocale?: string
domainLocales?: DomainLocales
} }
export type NextRouter = BaseRouter & export type NextRouter = BaseRouter &
......
...@@ -74,6 +74,7 @@ class ServerRouter implements NextRouter { ...@@ -74,6 +74,7 @@ class ServerRouter implements NextRouter {
locale?: string locale?: string
locales?: string[] locales?: string[]
defaultLocale?: string defaultLocale?: string
domainLocales?: DomainLocales
// TODO: Remove in the next major version, as this would mean the user is adding event listeners in server-side `render` method // TODO: Remove in the next major version, as this would mean the user is adding event listeners in server-side `render` method
static events: MittEmitter = mitt() static events: MittEmitter = mitt()
...@@ -85,7 +86,8 @@ class ServerRouter implements NextRouter { ...@@ -85,7 +86,8 @@ class ServerRouter implements NextRouter {
basePath: string, basePath: string,
locale?: string, locale?: string,
locales?: string[], locales?: string[],
defaultLocale?: string defaultLocale?: string,
domainLocales?: DomainLocales
) { ) {
this.route = pathname.replace(/\/$/, '') || '/' this.route = pathname.replace(/\/$/, '') || '/'
this.pathname = pathname this.pathname = pathname
...@@ -96,6 +98,7 @@ class ServerRouter implements NextRouter { ...@@ -96,6 +98,7 @@ class ServerRouter implements NextRouter {
this.locale = locale this.locale = locale
this.locales = locales this.locales = locales
this.defaultLocale = defaultLocale this.defaultLocale = defaultLocale
this.domainLocales = domainLocales
} }
push(): any { push(): any {
noRouter() noRouter()
...@@ -533,7 +536,8 @@ export async function renderToHTML( ...@@ -533,7 +536,8 @@ export async function renderToHTML(
basePath, basePath,
renderOpts.locale, renderOpts.locale,
renderOpts.locales, renderOpts.locales,
renderOpts.defaultLocale renderOpts.defaultLocale,
renderOpts.domainLocales
) )
const ctx = { const ctx = {
err, err,
......
...@@ -74,6 +74,44 @@ export function runTests(ctx) { ...@@ -74,6 +74,44 @@ export function runTests(ctx) {
) )
}) })
it('should render the correct href for locale domain', async () => {
let browser = await webdriver(
ctx.appPort,
`${ctx.basePath || ''}/links?nextLocale=go`
)
for (const [element, pathname] of [
['#to-another', '/another'],
['#to-gsp', '/gsp'],
['#to-fallback-first', '/gsp/fallback/first'],
['#to-fallback-hello', '/gsp/fallback/hello'],
['#to-gssp', '/gssp'],
['#to-gssp-slug', '/gssp/first'],
]) {
const href = await browser.elementByCss(element).getAttribute('href')
expect(href).toBe(`https://example.com${ctx.basePath || ''}${pathname}`)
}
browser = await webdriver(
ctx.appPort,
`${ctx.basePath || ''}/links?nextLocale=go-BE`
)
for (const [element, pathname] of [
['#to-another', '/another'],
['#to-gsp', '/gsp'],
['#to-fallback-first', '/gsp/fallback/first'],
['#to-fallback-hello', '/gsp/fallback/hello'],
['#to-gssp', '/gssp'],
['#to-gssp-slug', '/gssp/first'],
]) {
const href = await browser.elementByCss(element).getAttribute('href')
expect(href).toBe(
`https://example.com${ctx.basePath || ''}/go-BE${pathname}`
)
}
})
it('should navigate through history with query correctly', async () => { it('should navigate through history with query correctly', async () => {
const browser = await webdriver(ctx.appPort, `${ctx.basePath || '/'}`) const browser = await webdriver(ctx.appPort, `${ctx.basePath || '/'}`)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册