Skip to content

Commit

Permalink
Improve exports and docs
Browse files Browse the repository at this point in the history
  • Loading branch information
cvolant committed Aug 17, 2022
1 parent e1f8443 commit 8bfee0f
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 35 deletions.
85 changes: 68 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ Translated routing and more for Next using Next regular file-base routing system
- [Basic usage](#basic-usage)
1. [Wrap you next config with the next-translate-routes plugin](#1-wrap-you-next-config-with-the-next-translate-routes-plugin)
2. [Define your routes](#2-define-your-routes)
3. [Wrap your \_app component with the withTranslateRoutes hoc](#3-wrap-you-app-component-with-the-withtranslateroutes-hoc)
4. [Use next-translate-routes/link instead of next/link](#4-use-next-translate-routeslink-instead-of-nextlink)
3. [Wrap your `\_app` component with the `withTranslateRoutes` hoc](#3-wrap-you-app-component-with-the-withtranslateroutes-hoc)
4. [Use `next-translate-routes/link` instead of `next/link`](#4-use-next-translate-routeslink-instead-of-nextlink)
5. [Use `next-translate-routes/router instead` of `next/router` for singleton router (default export)](#5-use-next-translate-routesrouter-instead-of-nextrouter-for-singleton-router-default-export)
- [Advanced usage](#advanced-usage)
- [Configuration](#configuration)
- [Constrained dynamic paths segments](#constrained-dynamic-paths-segments)
Expand Down Expand Up @@ -142,7 +143,7 @@ for each language or only some language, like "blog" in `pt` here:
- page1 will in fact be accessible at `/blog/section/article` in `pt`,
- page2 will in fact be accessible at `/blog/section/definition` in `pt`.

#### 3. Wrap you \_app component with the withTranslateRoutes hoc
#### 3. Wrap you `\_app` component with the `withTranslateRoutes` hoc

```js
// `/pages/_app.js`
Expand All @@ -167,7 +168,7 @@ const App = ({ Component, pageProps }) => {
export default withTranslateRoutes(App)
```

#### 4. Use next-translate-routes/link instead of next/link
#### 4. Use `next-translate-routes/link` instead of `next/link`

next-translate-routes extends Next Link to translate routes automatically: import it from 'next-translate-routes/link' instead of 'next/link' and use as you ever did.

Expand Down Expand Up @@ -195,16 +196,14 @@ const MyLinks = (props) => {
}
```

#### 5. Use next-translate-routes/router instead of next/router for SingletonRouter (default export)
#### 5. Use `next-translate-routes/router instead` of `next/router` for singleton router (default export)

You can use `next-translate-routes/router` everywhere instead of `next/router` but it is only necessary for the SingletonRouter (which is rarely used).
You can use `next-translate-routes/router` everywhere instead of `next/router` but it is only necessary for the singleton router (which is rarely used).

```typescript
import SingletonRouter from 'next-translate-routes/router'
// Or:
import { SingletonRouter } from 'next-translate-routes/router'
import singletonRouter from 'next-translate-routes/router'
// Indead of:
import SingletonRouter from 'next/router'
import singletonRouter from 'next/router'
```

### Advanced usage
Expand Down Expand Up @@ -358,12 +357,12 @@ type TRouteBranch<Locale extends string> = {

#### Outside Next

One might need to mock next-translate-routes outside Next, for example for testing or in [Storybook](https://storybook.js.org/).
You might need to mock next-translate-routes outside Next, for example for testing or in [Storybook](https://storybook.js.org/).

First, you need to create next-translate-routes data. You can do it using the `createNtrData` helper. It takes the next config as first parameter. The second parameter is optional and allows to use a custom pages folder: if omitted, `createNtrData` will look for you next `pages` folder.
First, you need to create next-translate-routes data. You can do it using the `createNtrData` helper, but it only works in node environment. It takes the next config as first parameter. The second parameter is optional and allows to use a custom pages folder: if omitted, `createNtrData` will look for you next `pages` folder.

```typescript
import { createNtrData } from 'next-translate-routes/plugin/createNtrData`
import { createNtrData } from 'next-translate-routes/plugin`
import nextConfig from '../next.config.js'

const ntrData = createNtrData(
Expand All @@ -372,24 +371,31 @@ const ntrData = createNtrData(
)
```
Then, if you want to render you app, you need to inject the router context, then (and only then) inject next-translate-routes.
Then, if you want to render you app, you need to inject the router context, then (and only then) inject next-translate-routes. You can do it manually, or using `next-tranlate-routes/loader` with Webpack.
##### Manually
You will have to execute createNtrData in a node script and store the result somewhere that can be imported.
```typescript
// nextRouterMock.ts

import { RouterContext } from 'next/dist/shared/lib/router-context'
import withTranslateRoutes from 'next-translate-routes'
import ntrData from 'path/to/your/ntrData'

//[...]

const TranslateRoutes = withTranslateRoutes(
const RouteTranslationsProvider = withTranslateRoutes(
ntrData,
({ children }) => <>{children}</>,
)

const TranslatedRoutesProvider = ({ children }) => (
<RouterContext.Provider value={routerMock}>
<TranslateRoutes router={routerMock}>
<RouteTranslationsProvider router={routerMock}>
{children}
</TranslateRoutes>
</RouteTranslationsProvider>
</RouterContext.Provider>
)

Expand All @@ -406,6 +412,51 @@ export const WithNextRouter: DecoratorFn = (Story, context): JSX.Element => (
)
```
##### With `next-translate-routes/loader` for Webpack
`next-translate-routes/loader` allows to create next-translate-routes data at build time. So you can do exactly the same as described in the [Manually](#manually) paragraph above, but you don't need to create and add `ntrData` as an argument to `withTranslateRoutes`.
```typescript
// nextRouterMock.ts

import { RouterContext } from 'next/dist/shared/lib/router-context'
import withTranslateRoutes from 'next-translate-routes'

//[...]

const RouteTranslationsProvider = withTranslateRoutes(({ children }) => <>{children}</>)

// TranslatedRoutesProvider is the same as in the manually paragraph above

// [...]
```
Then all you have to do is to add this rule in your webpack config:
```js
// storybook/config/webpack.config.js for exemple

const { createNtrData } = require('next-translate-routes/plugin')
const nextConfig = require('../../next.config') // Your project nextConfig

module.exports = ({ config }) => {
// [...]

config.module.rules.push({
test: /path\/to\/nextRouterMock/, // /!\ Warning! This test should only match the file where withTranslateRoutes is used! If you cannot, set the mustMatch option to false.
use: {
loader: 'next-translate-routes/loader',
options: { data: createNtrData(nextConfig) },
},
})

return config
}

```
> ⚠️ Warning! The rule `test` should only match the file where `withTranslateRoutes` is used! If you cannot, then set the `mustMatch` loader option to `false`.
## Known issue: middleware with Next >=12.2.0
Unfortunately, Next new middleware synthax (stable) is not supported yet, because of what seems to be a Next issue.
Expand Down
4 changes: 2 additions & 2 deletions example/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import withTranslateRoutes, { translateUrl } from 'next-translate-routes'
import { SingletonRouter } from 'next-translate-routes/router'
import singletonRouter from 'next-translate-routes/router'
import { AppProps } from 'next/app'
import { useRouter } from 'next/router'
import React, { useEffect } from 'react'

const App: React.FC<AppProps> = ({ Component, pageProps, router: baseRouter }) => {
const router = useRouter()

useEffect(() => console.log('From _app.', { translateUrl, baseRouter, SingletonRouter }), [baseRouter])
useEffect(() => console.log('From _app.', { translateUrl, baseRouter, singletonRouter }), [baseRouter])

useEffect(() => console.log('From _app. useRouter router:', router), [router])

Expand Down
5 changes: 4 additions & 1 deletion src/plugin/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { createNtrData } from './createNtrData'
import { withTranslateRoutes } from './withTranslateRoutes'

module.exports = withTranslateRoutes
module.exports = Object.assign(withTranslateRoutes, { withTranslateRoutes, createNtrData })

export { withTranslateRoutes, createNtrData }

export default withTranslateRoutes
22 changes: 11 additions & 11 deletions src/plugin/loader.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import type { TNtrData } from '../types'

export function loader(this: { query: { pagesPath: string; data: TNtrData }; resourcePath: string }, rawCode: string) {
// Normalize slashes in a file path to be posix/unix-like forward slashes
const normalizedPagesPath = this.query.pagesPath.replace(/\\/g, '/')
const normalizedResourcePath = this.resourcePath.replace(/\\/g, '/')

// Skip if current resource is not _app file
if (!normalizedResourcePath.startsWith(`${normalizedPagesPath}_app.`)) {
return rawCode
}

export function loader(
this: { query: { mustMatch?: boolean; data: TNtrData }; resourcePath: string },
rawCode: string,
) {
const uncommentedCode = rawCode.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '')

const defaultExportHocMatch = uncommentedCode.match(/^\s*import (\w+).* from ["']next-translate-routes["']/m)
Expand All @@ -21,7 +15,13 @@ export function loader(this: { query: { pagesPath: string; data: TNtrData }; res
const namedExportHocName = namedExportHocMatch ? namedExportHocMatch[1] || 'withTranslateRoutes' : null

if (!defaultExportHocName && !namedExportHocName) {
throw new Error('[next-translate-routes] - No withTranslateRoutes high order component found in _app.')
if (this.query.mustMatch ?? true) {
throw new Error(
`[next-translate-routes] - No withTranslateRoutes high order component found in ${this.resourcePath}.`,
)
} else {
return rawCode
}
}

let result = rawCode
Expand Down
3 changes: 1 addition & 2 deletions src/plugin/withTranslateRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,10 @@ export const withTranslateRoutes = (userNextConfig: NextConfigWithNTR): NextConf
config.module.rules = []
}
config.module.rules.push({
test: new RegExp(`_app\\.(${context.config.pageExtensions.join('|')})$`),
test: new RegExp(`${pagesPath}_app\\.(${context.config.pageExtensions.join('|')})$`),
use: {
loader: 'next-translate-routes/loader',
options: {
pagesPath,
data: ntrData,
},
},
Expand Down
2 changes: 1 addition & 1 deletion src/react/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ import { enhanceNextRouter } from './enhanceNextRouter'

export * from 'next/dist/client/router'

export const SingletonRouter = enhanceNextRouter(NextSingletonRouter)
export default enhanceNextRouter(NextSingletonRouter)
2 changes: 1 addition & 1 deletion src/router.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from './react/router'
export { SingletonRouter as default } from './react/router'
export { default } from './react/router'

0 comments on commit 8bfee0f

Please sign in to comment.