Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass locales to getStaticPaths for i18n #18077

Merged
merged 1 commit into from Oct 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/next/build/utils.ts
Expand Up @@ -544,7 +544,7 @@ export async function buildStaticPaths(
// Get the default list of allowed params.
const _validParamKeys = Object.keys(_routeMatcher(page))

const staticPathsResult = await getStaticPaths()
const staticPathsResult = await getStaticPaths({ locales })

const expectedReturnVal =
`Expected: { paths: [], fallback: boolean }\n` +
Expand Down
40 changes: 26 additions & 14 deletions packages/next/build/webpack/loaders/next-serverless-loader.ts
Expand Up @@ -264,28 +264,40 @@ const nextServerlessLoader: loader.Loader = function () {

// check if the locale prefix matches a domain's defaultLocale
// and we're on a locale specific domain if so redirect to that domain
if (detectedDomain) {
const matchedDomain = detectDomainLocale(
i18n.domains,
undefined,
detectedLocale
)
// if (detectedDomain) {
// const matchedDomain = detectDomainLocale(
// i18n.domains,
// undefined,
// detectedLocale
// )

// if (matchedDomain) {
// localeDomainRedirect = \`http\${
// matchedDomain.http ? '' : 's'
// }://\${matchedDomain.domain}\`
// }
// }
} else if (detectedDomain) {
const matchedDomain = detectDomainLocale(
i18n.domains,
undefined,
acceptPreferredLocale
)

if (matchedDomain) {
localeDomainRedirect = \`http\${
matchedDomain.http ? '' : 's'
}://\${matchedDomain.domain}\`
}
if (matchedDomain && matchedDomain.domain !== detectedDomain.domain) {
localeDomainRedirect = \`http\${matchedDomain.http ? '' : 's'}://\${
matchedDomain.domain
}\`
}
}

const denormalizedPagePath = denormalizePagePath(parsedUrl.pathname || '/')
const detectedDefaultLocale =
!detectedLocale ||
detectedLocale.toLowerCase() === defaultLocale.toLowerCase()
const shouldStripDefaultLocale =
detectedDefaultLocale &&
denormalizedPagePath.toLowerCase() === \`/\${i18n.defaultLocale.toLowerCase()}\`
const shouldStripDefaultLocale = false
// detectedDefaultLocale &&
// denormalizedPagePath.toLowerCase() === \`/\${i18n.defaultLocale.toLowerCase()}\`

const shouldAddLocalePrefix =
!detectedDefaultLocale && denormalizedPagePath === '/'
Expand Down
42 changes: 27 additions & 15 deletions packages/next/next-server/server/next-server.ts
Expand Up @@ -345,29 +345,41 @@ export default class Server {

// check if the locale prefix matches a domain's defaultLocale
// and we're on a locale specific domain if so redirect to that domain
if (detectedDomain) {
const matchedDomain = detectDomainLocale(
i18n.domains,
undefined,
detectedLocale
)
// if (detectedDomain) {
// const matchedDomain = detectDomainLocale(
// i18n.domains,
// undefined,
// detectedLocale
// )

// if (matchedDomain) {
// localeDomainRedirect = `http${matchedDomain.http ? '' : 's'}://${
// matchedDomain?.domain
// }`
// }
// }
} else if (detectedDomain) {
const matchedDomain = detectDomainLocale(
i18n.domains,
undefined,
acceptPreferredLocale
)

if (matchedDomain) {
localeDomainRedirect = `http${matchedDomain.http ? '' : 's'}://${
matchedDomain?.domain
}`
}
if (matchedDomain && matchedDomain.domain !== detectedDomain.domain) {
localeDomainRedirect = `http${matchedDomain.http ? '' : 's'}://${
matchedDomain.domain
}`
}
}

const denormalizedPagePath = denormalizePagePath(pathname || '/')
const detectedDefaultLocale =
!detectedLocale ||
detectedLocale.toLowerCase() === defaultLocale.toLowerCase()
const shouldStripDefaultLocale =
detectedDefaultLocale &&
denormalizedPagePath.toLowerCase() ===
`/${i18n.defaultLocale.toLowerCase()}`
const shouldStripDefaultLocale = false
// detectedDefaultLocale &&
// denormalizedPagePath.toLowerCase() ===
// `/${i18n.defaultLocale.toLowerCase()}`

const shouldAddLocalePrefix =
!detectedDefaultLocale && denormalizedPagePath === '/'
Expand Down
10 changes: 7 additions & 3 deletions packages/next/types/index.d.ts
Expand Up @@ -105,14 +105,18 @@ export type InferGetStaticPropsType<T> = T extends GetStaticProps<infer P, any>
? P
: never

export type GetStaticPathsContext = {
locales?: string[]
}

export type GetStaticPathsResult<P extends ParsedUrlQuery = ParsedUrlQuery> = {
paths: Array<string | { params: P; locale?: string }>
fallback: boolean | 'unstable_blocking'
}

export type GetStaticPaths<
P extends ParsedUrlQuery = ParsedUrlQuery
> = () => Promise<GetStaticPathsResult<P>>
export type GetStaticPaths<P extends ParsedUrlQuery = ParsedUrlQuery> = (
context: GetStaticPathsContext
) => Promise<GetStaticPathsResult<P>>

export type GetServerSidePropsContext<
Q extends ParsedUrlQuery = ParsedUrlQuery
Expand Down
Expand Up @@ -33,7 +33,14 @@ export const getStaticProps = ({ params, locale, locales }) => {
}
}

export const getStaticPaths = () => {
export const getStaticPaths = ({ locales }) => {
// make sure locales were provided correctly
if (!locales || locales.length !== 7) {
throw new Error(
'locales missing in getStaticPaths!! got: ' + JSON.stringify(locales)
)
}

return {
// the default locale will be used since one isn't defined here
paths: ['first', 'second'].map((slug) => ({
Expand Down
71 changes: 36 additions & 35 deletions test/integration/i18n-support/test/index.test.js
Expand Up @@ -397,19 +397,19 @@ function runTests(isDev) {
expect(JSON.parse($2('#router-locales').text())).toEqual(locales)
})

it('should strip locale prefix for default locale with locale domains', async () => {
it('should not strip locale prefix for default locale with locale domains', async () => {
const res = await fetchViaHTTP(appPort, '/fr', undefined, {
headers: {
host: 'example.fr',
},
redirect: 'manual',
})

expect(res.status).toBe(307)
expect(res.status).toBe(200)

const result = url.parse(res.headers.get('location'), true)
expect(result.pathname).toBe('/')
expect(result.query).toEqual({})
// const result = url.parse(res.headers.get('location'), true)
// expect(result.pathname).toBe('/')
// expect(result.query).toEqual({})

const res2 = await fetchViaHTTP(appPort, '/nl-BE', undefined, {
headers: {
Expand All @@ -418,28 +418,28 @@ function runTests(isDev) {
redirect: 'manual',
})

expect(res2.status).toBe(307)
expect(res2.status).toBe(200)

const result2 = url.parse(res2.headers.get('location'), true)
expect(result2.pathname).toBe('/')
expect(result2.query).toEqual({})
// const result2 = url.parse(res2.headers.get('location'), true)
// expect(result2.pathname).toBe('/')
// expect(result2.query).toEqual({})
})

it('should set locale cookie when removing default locale and accept-lang doesnt match', async () => {
const res = await fetchViaHTTP(appPort, '/en-US', undefined, {
headers: {
'accept-language': 'nl',
},
redirect: 'manual',
})
// ('should set locale cookie when removing default locale and accept-lang doesnt match', async () => {
// const res = await fetchViaHTTP(appPort, '/en-US', undefined, {
// headers: {
// 'accept-language': 'nl',
// },
// redirect: 'manual',
// })

expect(res.status).toBe(307)
// expect(res.status).toBe(307)

const parsedUrl = url.parse(res.headers.get('location'), true)
expect(parsedUrl.pathname).toBe('/')
expect(parsedUrl.query).toEqual({})
expect(res.headers.get('set-cookie')).toContain('NEXT_LOCALE=en-US')
})
// const parsedUrl = url.parse(res.headers.get('location'), true)
// expect(parsedUrl.pathname).toBe('/')
// expect(parsedUrl.query).toEqual({})
// expect(res.headers.get('set-cookie')).toContain('NEXT_LOCALE=en-US')
// })

it('should not redirect to accept-lang preferred locale with locale cookie', async () => {
const res = await fetchViaHTTP(appPort, '/', undefined, {
Expand All @@ -465,18 +465,19 @@ function runTests(isDev) {
it('should redirect to correct locale domain', async () => {
const checks = [
// test domain, locale prefix, redirect result
['example.be', 'nl-BE', 'http://example.be/'],
// ['example.be', 'nl-BE', 'http://example.be/'],
['example.be', 'fr', 'http://example.fr/'],
['example.fr', 'nl-BE', 'http://example.be/'],
['example.fr', 'fr', 'http://example.fr/'],
// ['example.fr', 'fr', 'http://example.fr/'],
]

for (const check of checks) {
const [domain, localePath, location] = check
const [domain, locale, location] = check

const res = await fetchViaHTTP(appPort, `/${localePath}`, undefined, {
const res = await fetchViaHTTP(appPort, `/`, undefined, {
headers: {
host: domain,
'accept-language': locale,
},
redirect: 'manual',
})
Expand Down Expand Up @@ -705,20 +706,20 @@ function runTests(isDev) {
expect(await browser.eval('window.beforeNav')).toBe(1)
})

it('should remove un-necessary locale prefix for default locale', async () => {
it('should not remove locale prefix for default locale', async () => {
const res = await fetchViaHTTP(appPort, '/en-US', undefined, {
redirect: 'manual',
headers: {
'Accept-Language': 'en-US;q=0.9',
},
})

expect(res.status).toBe(307)
expect(res.status).toBe(200)

const parsedUrl = url.parse(res.headers.get('location'), true)
// const parsedUrl = url.parse(res.headers.get('location'), true)

expect(parsedUrl.pathname).toBe('/')
expect(parsedUrl.query).toEqual({})
// expect(parsedUrl.pathname).toBe('/')
// expect(parsedUrl.query).toEqual({})

// make sure locale is case-insensitive
const res2 = await fetchViaHTTP(appPort, '/eN-Us', undefined, {
Expand All @@ -728,12 +729,12 @@ function runTests(isDev) {
},
})

expect(res2.status).toBe(307)
expect(res2.status).toBe(200)

const parsedUrl2 = url.parse(res.headers.get('location'), true)
// const parsedUrl2 = url.parse(res.headers.get('location'), true)

expect(parsedUrl2.pathname).toBe('/')
expect(parsedUrl2.query).toEqual({})
// expect(parsedUrl2.pathname).toBe('/')
// expect(parsedUrl2.query).toEqual({})
})

it('should load getStaticProps page correctly SSR (default locale no prefix)', async () => {
Expand Down