Skip to content

Commit

Permalink
Make sure default locale isn't prefixed on the client
Browse files Browse the repository at this point in the history
  • Loading branch information
ijjk committed Oct 8, 2020
1 parent 2f4f40e commit 552fc6d
Show file tree
Hide file tree
Showing 13 changed files with 190 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ const nextServerlessLoader: loader.Loader = function () {
isDataReq: _nextData,
locale: detectedLocale,
locales: i18n.locales,
defaultLocale: i18n.defaultLocale,
},
options,
)
Expand Down
2 changes: 2 additions & 0 deletions packages/next/client/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const {
isFallback,
head: initialHeadData,
locales,
defaultLocale,
} = data

let { locale } = data
Expand Down Expand Up @@ -317,6 +318,7 @@ export default async (opts: { webpackHMR?: any } = {}) => {
render({ App, Component, styleSheets, props, err }),
locale,
locales,
defaultLocale,
})

// call init-client middleware
Expand Down
4 changes: 3 additions & 1 deletion packages/next/client/link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,9 @@ 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
// 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))) {
childProps.href = addBasePath(addLocale(as, router && router.locale))
childProps.href = addBasePath(
addLocale(as, router && router.locale, router && router.defaultLocale)
)
}

return React.cloneElement(child, childProps)
Expand Down
29 changes: 25 additions & 4 deletions packages/next/client/page-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,23 @@ export default class PageLoader {
* @param {string} href the route href (file-system path)
* @param {string} asPath the URL as shown in browser (virtual path); used for dynamic routes
*/
getDataHref(href: string, asPath: string, ssg: boolean, locale?: string) {
getDataHref(
href: string,
asPath: string,
ssg: boolean,
locale?: string,
defaultLocale?: string
) {
const { pathname: hrefPathname, query, search } = parseRelativeUrl(href)
const { pathname: asPathname } = parseRelativeUrl(asPath)
const route = normalizeRoute(hrefPathname)

const getHrefForSlug = (path: string) => {
const dataRoute = addLocale(getAssetPathFromRoute(path, '.json'), locale)
const dataRoute = addLocale(
getAssetPathFromRoute(path, '.json'),
locale,
defaultLocale
)
return addBasePath(
`/_next/data/${this.buildId}${dataRoute}${ssg ? '' : search}`
)
Expand All @@ -229,15 +239,26 @@ export default class PageLoader {
* @param {string} href the route href (file-system path)
* @param {string} asPath the URL as shown in browser (virtual path); used for dynamic routes
*/
prefetchData(href: string, asPath: string) {
prefetchData(
href: string,
asPath: string,
locale?: string,
defaultLocale?: string
) {
const { pathname: hrefPathname } = parseRelativeUrl(href)
const route = normalizeRoute(hrefPathname)
return this.promisedSsgManifest!.then(
(s: ClientSsgManifest, _dataHref?: string) =>
// Check if the route requires a data file
s.has(route) &&
// Try to generate data href, noop when falsy
(_dataHref = this.getDataHref(href, asPath, true)) &&
(_dataHref = this.getDataHref(
href,
asPath,
true,
locale,
defaultLocale
)) &&
// noop when data has already been prefetched (dedupe)
!document.querySelector(
`link[rel="${relPrefetch}"][href^="${_dataHref}"]`
Expand Down
1 change: 1 addition & 0 deletions packages/next/client/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const urlPropertyFields = [
'basePath',
'locale',
'locales',
'defaultLocale',
]
const routerEvents = [
'routeChangeStart',
Expand Down
7 changes: 5 additions & 2 deletions packages/next/export/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ export default async function exportApp(
}
}

const { i18n } = nextConfig.experimental

// Start the rendering process
const renderOpts = {
dir,
Expand All @@ -298,8 +300,9 @@ export default async function exportApp(
ampValidatorPath: nextConfig.experimental.amp?.validator || undefined,
ampSkipValidation: nextConfig.experimental.amp?.skipValidation || false,
ampOptimizerConfig: nextConfig.experimental.amp?.optimizer || undefined,
locales: nextConfig.experimental.i18n?.locales,
locale: nextConfig.experimental.i18n?.defaultLocale,
locales: i18n?.locales,
locale: i18n.defaultLocale,
defaultLocale: i18n.defaultLocale,
}

const { serverRuntimeConfig, publicRuntimeConfig } = nextConfig
Expand Down
32 changes: 26 additions & 6 deletions packages/next/next-server/lib/router/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,13 @@ function addPathPrefix(path: string, prefix?: string) {
: path
}

export function addLocale(path: string, locale?: string) {
export function addLocale(
path: string,
locale?: string,
defaultLocale?: string
) {
if (process.env.__NEXT_i18n_SUPPORT) {
return locale && !path.startsWith('/' + locale)
return locale && locale !== defaultLocale && !path.startsWith('/' + locale)
? addPathPrefix(path, '/' + locale)
: path
}
Expand Down Expand Up @@ -246,6 +250,7 @@ export type BaseRouter = {
basePath: string
locale?: string
locales?: string[]
defaultLocale?: string
}

export type NextRouter = BaseRouter &
Expand Down Expand Up @@ -356,6 +361,7 @@ export default class Router implements BaseRouter {
_shallow?: boolean
locale?: string
locales?: string[]
defaultLocale?: string

static events: MittEmitter = mitt()

Expand All @@ -375,6 +381,7 @@ export default class Router implements BaseRouter {
isFallback,
locale,
locales,
defaultLocale,
}: {
subscription: Subscription
initialProps: any
Expand All @@ -387,6 +394,7 @@ export default class Router implements BaseRouter {
isFallback: boolean
locale?: string
locales?: string[]
defaultLocale?: string
}
) {
// represents the current component key
Expand Down Expand Up @@ -440,6 +448,7 @@ export default class Router implements BaseRouter {
if (process.env.__NEXT_i18n_SUPPORT) {
this.locale = locale
this.locales = locales
this.defaultLocale = defaultLocale
}

if (typeof window !== 'undefined') {
Expand Down Expand Up @@ -596,7 +605,7 @@ export default class Router implements BaseRouter {
this.abortComponentLoad(this._inFlightRoute)
}

as = addLocale(as, this.locale)
as = addLocale(as, this.locale, this.defaultLocale)
const cleanedAs = delLocale(
hasBasePath(as) ? delBasePath(as) : as,
this.locale
Expand Down Expand Up @@ -790,7 +799,12 @@ export default class Router implements BaseRouter {
}

Router.events.emit('beforeHistoryChange', as)
this.changeState(method, url, addLocale(as, this.locale), options)
this.changeState(
method,
url,
addLocale(as, this.locale, this.defaultLocale),
options
)

if (process.env.NODE_ENV !== 'production') {
const appComp: any = this.components['/_app'].Component
Expand Down Expand Up @@ -960,7 +974,8 @@ export default class Router implements BaseRouter {
formatWithValidation({ pathname, query }),
delBasePath(as),
__N_SSG,
this.locale
this.locale,
this.defaultLocale
)
}

Expand Down Expand Up @@ -1117,7 +1132,12 @@ export default class Router implements BaseRouter {

const route = removePathTrailingSlash(pathname)
await Promise.all([
this.pageLoader.prefetchData(url, asPath),
this.pageLoader.prefetchData(
url,
asPath,
this.locale,
this.defaultLocale
),
this.pageLoader[options.priority ? 'loadPage' : 'prefetch'](route),
])
}
Expand Down
1 change: 1 addition & 0 deletions packages/next/next-server/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export type NEXT_DATA = {
head: HeadEntry[]
locale?: string
locales?: string[]
defaultLocale?: string
}

/**
Expand Down
2 changes: 2 additions & 0 deletions packages/next/next-server/server/next-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ export default class Server {
optimizeImages: boolean
locale?: string
locales?: string[]
defaultLocale?: string
}
private compression?: Middleware
private onErrorMiddleware?: ({ err }: { err: Error }) => Promise<void>
Expand Down Expand Up @@ -193,6 +194,7 @@ export default class Server {
: null,
optimizeImages: this.nextConfig.experimental.optimizeImages,
locales: this.nextConfig.experimental.i18n?.locales,
defaultLocale: this.nextConfig.experimental.i18n?.defaultLocale,
}

// Only the `publicRuntimeConfig` key is exposed to the client side
Expand Down
11 changes: 9 additions & 2 deletions packages/next/next-server/server/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class ServerRouter implements NextRouter {
isFallback: boolean
locale?: string
locales?: string[]
defaultLocale?: string
// 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()

Expand All @@ -79,7 +80,8 @@ class ServerRouter implements NextRouter {
{ isFallback }: { isFallback: boolean },
basePath: string,
locale?: string,
locales?: string[]
locales?: string[],
defaultLocale?: string
) {
this.route = pathname.replace(/\/$/, '') || '/'
this.pathname = pathname
Expand All @@ -89,6 +91,7 @@ class ServerRouter implements NextRouter {
this.basePath = basePath
this.locale = locale
this.locales = locales
this.defaultLocale = defaultLocale
}
push(): any {
noRouter()
Expand Down Expand Up @@ -164,6 +167,7 @@ export type RenderOptsPartial = {
resolvedAsPath?: string
locale?: string
locales?: string[]
defaultLocale?: string
}

export type RenderOpts = LoadComponentsReturnType & RenderOptsPartial
Expand Down Expand Up @@ -203,6 +207,7 @@ function renderDocument(
devOnlyCacheBusterQueryString,
locale,
locales,
defaultLocale,
}: RenderOpts & {
props: any
docComponentsRendered: DocumentProps['docComponentsRendered']
Expand Down Expand Up @@ -251,6 +256,7 @@ function renderDocument(
appGip, // whether the _app has getInitialProps
locale,
locales,
defaultLocale,
head: React.Children.toArray(docProps.head || [])
.map((elem) => {
const { children } = elem?.props
Expand Down Expand Up @@ -517,7 +523,8 @@ export async function renderToHTML(
},
basePath,
renderOpts.locale,
renderOpts.locales
renderOpts.locales,
renderOpts.defaultLocale
)
const ctx = {
err,
Expand Down
2 changes: 1 addition & 1 deletion test/integration/i18n-support/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module.exports = {
experimental: {
i18n: {
locales: ['nl-NL', 'nl-BE', 'nl', 'en-US', 'en'],
defaultLocale: 'en',
defaultLocale: 'en-US',
},
},
}
Loading

0 comments on commit 552fc6d

Please sign in to comment.