Skip to content

Commit

Permalink
support nextConfig.basePath with i18n + tests (#1123)
Browse files Browse the repository at this point in the history
  • Loading branch information
dimaMachina committed Dec 26, 2022
1 parent f35e724 commit cc1cb5f
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 107 deletions.
5 changes: 5 additions & 0 deletions .changeset/thirty-papayas-do.md
@@ -0,0 +1,5 @@
---
'nextra': patch
---

support `nextConfig.basePath` with i18n
97 changes: 48 additions & 49 deletions examples/swr-site/next.config.js
Expand Up @@ -13,55 +13,54 @@ module.exports = withNextra({
locales: ["en-US", "es-ES", "ja", "ko", "ru", "zh-CN"],
defaultLocale: "en-US",
},
// basePath: "/some-base-path",
distDir: "./.next", // Nextra supports custom `nextConfig.distDir`
redirects: () => {
return [
// {
// source: "/docs.([a-zA-Z-]+)",
// destination: "/docs/getting-started",
// statusCode: 301,
// },
// {
// source: "/advanced/performance",
// destination: "/docs/advanced/performance",
// statusCode: 301,
// },
// {
// source: "/advanced/cache",
// destination: "/docs/advanced/cache",
// statusCode: 301,
// },
// {
// source: "/docs/cache",
// destination: "/docs/advanced/cache",
// statusCode: 301,
// },
{
source: "/change-log",
destination: "/docs/change-log",
statusCode: 301,
},
{
source: "/blog/swr-1",
destination: "/blog/swr-v1",
statusCode: 301,
},
{
source: "/docs.([a-zA-Z-]+)",
destination: "/docs/getting-started",
statusCode: 302,
},
{
source: "/docs",
destination: "/docs/getting-started",
statusCode: 302,
},
{
source: "/examples",
destination: "/examples/basic",
statusCode: 302,
},
];
},
redirects: () => [
// {
// source: "/docs.([a-zA-Z-]+)",
// destination: "/docs/getting-started",
// statusCode: 301,
// },
// {
// source: "/advanced/performance",
// destination: "/docs/advanced/performance",
// statusCode: 301,
// },
// {
// source: "/advanced/cache",
// destination: "/docs/advanced/cache",
// statusCode: 301,
// },
// {
// source: "/docs/cache",
// destination: "/docs/advanced/cache",
// statusCode: 301,
// },
{
source: "/change-log",
destination: "/docs/change-log",
statusCode: 301,
},
{
source: "/blog/swr-1",
destination: "/blog/swr-v1",
statusCode: 301,
},
{
source: "/docs.([a-zA-Z-]+)",
destination: "/docs/getting-started",
statusCode: 302,
},
{
source: "/docs",
destination: "/docs/getting-started",
statusCode: 302,
},
{
source: "/examples",
destination: "/examples/basic",
statusCode: 302,
},
],
reactStrictMode: true,
});
61 changes: 61 additions & 0 deletions packages/nextra/__test__/locale-with-base-path.test.ts
@@ -0,0 +1,61 @@
// Next.js' `addBasePath`, `hasBasePath` and `removeBasePath` functions depend
// on `__NEXT_ROUTER_BASEPATH` environment variable that must be set before
// importing middleware
process.env.__NEXT_ROUTER_BASEPATH = '/testBasePath'
import { locales as originalLocales } from '../src/locales'
import { describe, expect, it, vi } from 'vitest'
import { NextRequest } from 'next/server'

vi.mock('next/server', async () => {
const mod = await vi.importActual<typeof import('next/server')>('next/server')
return {
...mod,
NextResponse: {
redirect: (url: string) => ({ url, type: 'redirect' }),
rewrite: (url: string) => ({ url, type: 'rewrite' })
}
}
})

const locales = originalLocales as unknown as (req: NextRequest) => {
type: string
url: URL
}

const createRequest = (url: string, localeCookie = '') => {
return new NextRequest(url, {
headers: { cookie: localeCookie },
nextConfig: {
i18n: {
locales: ['en-US', 'zh-CN'],
defaultLocale: 'en-US'
}
}
})
}

/**
* @vitest-environment edge-runtime
*/
describe('basePath', () => {
// Next.js' `addLocale` and `removeLocale` functions depend on `__NEXT_I18N_SUPPORT`
process.env.__NEXT_I18N_SUPPORT = 'true'

it('should rewrite basePath', () => {
const request = createRequest(
'http://localhost:3000/zh-CN/docs/getting-started'
)
const result = locales(request)
expect(result.type).toBe('rewrite')
expect(result.url.href).toBe(
'http://localhost:3000/testBasePath/zh-CN/docs/getting-started.zh-CN'
)
})

it('should redirect with basePath', () => {
const request = createRequest('http://localhost:3000', 'NEXT_LOCALE=zh-CN')
const result = locales(request)
expect(result.type).toBe('redirect')
expect(result.url.href).toBe('http://localhost:3000/testBasePath/zh-CN')
})
})
73 changes: 33 additions & 40 deletions packages/nextra/__test__/locale.test.ts
Expand Up @@ -2,28 +2,13 @@ import { describe, it, expect, vi } from 'vitest'
import { NextRequest } from 'next/server'
import { locales as originalLocales } from '../src/locales'

const i18n = {
locales: ['en-US', 'zh-CN'],
defaultLocale: 'en-US'
}

vi.mock('next/server', async () => {
const mod = await vi.importActual('next/server')
const mod = await vi.importActual<typeof import('next/server')>('next/server')
return {
...(mod as any),
...mod,
NextResponse: {
redirect(url: string) {
return {
type: 'redirect',
url
}
},
rewrite(url: string) {
return {
type: 'rewrite',
url
}
}
redirect: (url: string) => ({ url, type: 'redirect' }),
rewrite: (url: string) => ({ url, type: 'rewrite' })
}
}
})
Expand All @@ -36,81 +21,89 @@ const locales = originalLocales as unknown as (req: NextRequest) => {
const createRequest = (url: string, localeCookie = '') => {
return new NextRequest(url, {
headers: { cookie: localeCookie },
nextConfig: { i18n }
nextConfig: {
i18n: {
locales: ['en-US', 'zh-CN'],
defaultLocale: 'en-US'
}
}
})
}

/**
* @vitest-environment edge-runtime
*/
describe('locale process', () => {
// Next.js' `addLocale` and `removeLocale` functions depend on `__NEXT_I18N_SUPPORT`
process.env.__NEXT_I18N_SUPPORT = 'true'

it('root url without locale', () => {
const request = createRequest('http://localhost:3000')
const result = locales(request)
expect(result.type).toBe('rewrite')
expect(result.url?.href).toBe('http://localhost:3000/en-US/index.en-US')
expect(result.url.href).toBe('http://localhost:3000/index.en-US')
})
it('slash root url without locale', () => {
const request = createRequest('http://localhost:3000/')
const result = locales(request)
expect(result.type).toBe('rewrite')
expect(result.url?.href).toBe('http://localhost:3000/en-US/index.en-US')
expect(result.url.href).toBe('http://localhost:3000/index.en-US')
})
it('root url with locale cookie', () => {
const request = createRequest('http://localhost:3000', 'NEXT_LOCALE=zh-CN')
const result = locales(request)
expect(result.type).toBe('redirect')
expect(result.url?.href).toBe('http://localhost:3000/zh-CN/')
expect(result.url.href).toBe('http://localhost:3000/zh-CN')
})
it('slash root url with locale cookie', () => {
const request = createRequest('http://localhost:3000/', 'NEXT_LOCALE=zh-CN')
const result = locales(request)
expect(result.type).toBe('redirect')
expect(result.url?.href).toBe('http://localhost:3000/zh-CN/')
expect(result.url.href).toBe('http://localhost:3000/zh-CN')
})
it('root url with locale', () => {
const request = createRequest('http://localhost:3000/zh-CN')
const result = locales(request)
expect(result.type).toBe('rewrite')
expect(result?.url?.href).toBe('http://localhost:3000/zh-CN/index.zh-CN')
expect(result?.url.href).toBe('http://localhost:3000/zh-CN/index.zh-CN')
})
it('slash root url with locale', () => {
const request = createRequest('http://localhost:3000/zh-CN/')
const result = locales(request)
expect(result?.type).toBe('rewrite')
expect(result?.url?.href).toBe('http://localhost:3000/zh-CN/index.zh-CN')
expect(result.type).toBe('rewrite')
expect(result.url.href).toBe('http://localhost:3000/zh-CN/index.zh-CN')
})
it('url without locale', () => {
const request = createRequest('http://localhost:3000/docs/getting-started')
const result = locales(request)
expect(result?.type).toBe('rewrite')
expect(result?.url?.href).toBe(
'http://localhost:3000/en-US/docs/getting-started.en-US'
expect(result.type).toBe('rewrite')
expect(result.url.href).toBe(
'http://localhost:3000/docs/getting-started.en-US'
)
})
it('slash url without locale', () => {
const request = createRequest('http://localhost:3000/docs/getting-started/')
const result = locales(request)
expect(result?.type).toBe('rewrite')
expect(result?.url?.href).toBe(
'http://localhost:3000/en-US/docs/getting-started.en-US'
expect(result.type).toBe('rewrite')
expect(result.url.href).toBe(
'http://localhost:3000/docs/getting-started.en-US'
)
})
it('url with locale cookie', () => {
const request = createRequest('http://localhost:3000', 'NEXT_LOCALE=zh-CN')
const result = locales(request)
expect(result?.type).toBe('redirect')
expect(result?.url?.href).toBe('http://localhost:3000/zh-CN/')
expect(result.type).toBe('redirect')
expect(result.url.href).toBe('http://localhost:3000/zh-CN')
})
it('slash url with locale cookie', () => {
const request = createRequest(
'http://localhost:3000/docs/getting-started/',
'NEXT_LOCALE=zh-CN'
)
const result = locales(request)
expect(result?.type).toBe('redirect')
expect(result?.url?.href).toBe(
'http://localhost:3000/zh-CN/docs/getting-started/'
expect(result.type).toBe('redirect')
expect(result.url.href).toBe(
'http://localhost:3000/zh-CN/docs/getting-started'
)
})
it('url with locale', () => {
Expand All @@ -119,7 +112,7 @@ describe('locale process', () => {
)
const result = locales(request)
expect(result.type).toBe('rewrite')
expect(result.url?.href).toBe(
expect(result.url.href).toBe(
'http://localhost:3000/zh-CN/docs/getting-started.zh-CN'
)
})
Expand All @@ -129,7 +122,7 @@ describe('locale process', () => {
)
const result = locales(request)
expect(result.type).toBe('rewrite')
expect(result.url?.href).toBe(
expect(result.url.href).toBe(
'http://localhost:3000/zh-CN/docs/getting-started.zh-CN'
)
})
Expand Down

1 comment on commit cc1cb5f

@vercel
Copy link

@vercel vercel bot commented on cc1cb5f Dec 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.