Giter VIP home page Giter VIP logo

next-translate-routes's Introduction

Next-translate-routes

Translated routing and more for Next /pages router using Next regular file-base routing system

Features

  • Translated paths segments
    Ex: /contact-us and /fr/contactez-nous.
  • Complex paths segments (path-to-regexp syntax)
    Ex: /:id{-:slug}?/
  • Constrained dynamic paths segments (path-to-regexp syntax)
    Ex: /:id(\\d+)/
  • No duplicated content (SEO)
    Simple rewrites would make a page accessible with 2 different urls which is bad for SEO.
  • Auto-redirection to correct translated path
    Ex: /fr/english/path redirects to /fr/french/path
  • No custom server needed!
    Next automatic static optimization remains available.

See it in action: https://codesandbox.io/s/github/hozana/next-translate-routes/tree/master

Unsupported features

  • /app router is not supported: with /app router, you can use next-roots.
  • Html static export is not and will never be supported by next-translate-routes, since internationalized routing is among static html export unsupported features.
  • Domain routing is not supported yet but could be in the future. Any help would be appreciated, see here.

Motivation

To build a fully internationalized website, one need to translate url segments: it is important for UX and SEO. For now, Next only ship with locale prefixes (see Next.js internationalized routing doc).

The next-routes package allow fully internationalized routing but it is no longer maintained, and it is designed without the latest Next api, such as internationalized routing, new data fetching methods, automatic static optimization.
To be able to use theses, a new approach is needed. Next.js provides it with Redirects and Rewrites, but:

  • the main problem is that writing the rewrites and redirects to translate all the routes by hand is long, boring, error-prone, and hard to maintain.
  • an other problem is that by default, the file path works with all the locale prefixes: it creates 2 urls for the same content, which is not good for SEO. This problem can be worked around by creating redirects from /${localePrefix}/$(filePath) to /${localePrefix}/$(localePath), but it creates a lot more complexity to write by hand and maintain.

How to

Basic usage

Check the example folder to see next-translate-routes in action. Some advanced techniques are shown there too: they may seem complicated but those 4 steps should cover most of the cases.

1. Wrap you next config with the next-translate-routes plugin

Import the withTranslateRoutes from next-translate-routes/plugin.

// next.config.js
const withTranslateRoutes = require('next-translate-routes/plugin')

module.exports = withTranslateRoutes({
  // Next i18n config (mandatory): https://nextjs.org/docs/advanced-features/i18n-routing
  i18n: {
    locales: ['en', 'fr', 'es', 'pl'],
    defaultLocale: 'pl',
  },

  // ...Remaining next config
})

2. Define your routes

You can add a _routes.json, or a _routes.yaml, file in the pages folder, and in the every subfolder where you want to define routes.

Given a folder structure like so, you can add a _routes.json in /pages/ and in /pages/section/.

/pages/
 ├ section/
 | ├ page1.tsx
 | ├ page2.tsx
 | └ _routes.json
 ├ somewhere/
 | └ else.json
 ├ _app.tsx
 ├ about.tsx
 ├ contact.tsx
 └ _routes.json

In /pages/section/, the _routes.json file could look like this.

// `/pages/section/_routes.json`
{
  "/": {
    "es": "seccion" // Folder path in es
  },
  "page1": {
    "default": "article", // Overwrite the default page path (fallback)
    "es": "articulo"
  },
  "page2": "definition" // Overwrite the page path for all language
}

The "/": { ... } part define the folder paths, each other section define the paths of a page file in this folder:

  • page1 will be accessible at /seccion/articulo in es, and at /section/article in other languages,
  • page2 will be accessible at /seccion/definition in es, and at /section/definition in other languages.

You don't need a _routes.json file in folder where you don't customize anything. If it is empty, then delete it. Here, the /somewhere/ subfolder does not have any _routes.json file.

Then, in /pages/, the _routes.json file could look like this.

// `/pages/_routes.json`
{
  "/": {
    "pt": "blog" // As we are in the root pages folder, this will add a "blog" path prefix for all pages in pt
  },
  "contact": {
    "es": "contactar",
    "pt": "contatar"
  }
}

In the root pages folder, the "/": { ... } part of the root _routes.json allows to add a different basePath for each language or only some language, like "blog" in pt here:

  • about will be accessible at /blog/about in pt and at /about in other languages,
  • contact will be accessible at /blog/contatar in pt, at /contactar in es and at /contact in other languages,
  • 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

// `/pages/_app.js`
import { withTranslateRoutes } from 'next-translate-routes'
import { App } from 'next/app'

export default withTranslateRoutes(App)

Or:

// `/pages/_app.js`
import { withTranslateRoutes } from 'next-translate-routes'

const App = ({ Component, pageProps }) => {
  // Custom code...

  return <Component {...pageProps} />
}

export default withTranslateRoutes(App)

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.

import Link from 'next-translate-routes/link'
import React, { useEffect, useState } from 'react'

const MyLinks = (props) => {
  const { locales } = useRouter()

  return (
    <>
      <Link href="/file/path/to/page">Current locale</Link>
      {locales.map((locale) => (
        <Link
          href={{ pathname: '/file/path/to/[dynamic]/page', query: { dynamic: props.param, otherQueryParam: 'foo' } }}
          locale={locale}
          key={locale}
        >
          {locale}
        </Link>
      ))}
    </>
  )
}

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 singleton router (which is rarely used).

import singletonRouter from 'next-translate-routes/router'
// Indead of:
import singletonRouter from 'next/router'

6. Use a middleware to redirect from urls with the default locale prefix

If en is the default locale for example, you probably will want to:

  • either redirect /en to / and /en/anywhere to /anywhere,
  • or redirect from / to /en and /anywhere to /en/anywhere.

This is complex: next-translate-routes cannot handle this without creating a looping redirect. The only way to do this seems to be using the middleware, as stated here.

Advanced usage

Check the example folder to see some advanced techniques in action.

Configuration

Next-translate-routes is configurable by adding a translateRoutes key in Next config that accept an object of the following NTRConfig type.

type NTRConfig = {
  debug?: boolean
  routesDataFileName?: string
  routesTree?: TRouteBranch<L>
  pagesDirectory?: string
}
See more about TRouteBranch

If i18n.locales is set to ['en', 'fr'], then the TRouteBranch generic L prop would be 'en' | 'fr'. A non-generic equivalent of TRouteBranch<'en' | 'fr'> would be the following.

/** Non generic version of the TRouteBranch type for better readability, where the generi L prop is set to `'en' | 'fr'` */
type TRouteBranchEnFr = {
  name: string
  en: string
  fr: string
  children: TRouteBranchEnFr[]
}
  translateRoutes: {
    debug: true,
    routesDataFileName: 'routesData',
  }

When debug is set to true, you will get some logs, both in the server terminal and in the browser console. By default, you will get some logs for each router.push and router.replace, but not router.prefetch. To enable logs for router.prefetch too, you can set debug to withPrefetch.

If routesDataFileName is defined, to 'routesData' for example, next-translate-routes will look in the pages folder for files named routesData.json or routesData.yaml instead of the default _routes.json or _routes.yaml.

If routesTree is defined, next-translate-routes won't parse the pages folder and will use the given object as the routes tree. If you uses it, beware of building correctly the routes tree to avoid bugs.

You can see and edit these while your app is running to debug things, using __NEXT_TRANSLATE_ROUTES_DATA in the browser console. For exemple, executing __NEXT_TRANSLATE_ROUTES_DATA.debug = true will activate the logs on router.push and router.replace.

Translate/untranslate urls

Two helpers are exposed to translate/untranslate urls:

  • fileUrlToUrl transforms a file url into a translated url
  • urlToFileUrl transforms a translated url into a file url

Both of them take 2 arguments: an url and a locale. fileUrlToUrl can take an extra option argument to prevent it to throw and return undefined instead if the file url is not found: { throwOnError: false }.

Alternate pages (SEO)

You will probably want to indicate alternate pages for SEO optimization. Here is how you can do that:

  const { pathname, query, locale, locale } = useRouter()

  return (
    <Head>
      {locales.map((l) => l !== locale && <link rel="alternate" hrefLang={l} href={fileUrlToUrl({ pathname, query }, l)} />)}
    </Head>
  )

You can do it in the _app component if you are sure to do that for all your pages. You can also use a dedicated package, like next-seo.

See this article about alternate and canonical pages

Sitemap

See @JacbSoderblom's suggestion

Constrained dynamic paths segments

// `/pages/blog/[id]/_routes.json`
{
  "/": ":id(\\d+)", // Constrain a dynamic folder segment (to be a number here)
  "[slug]": ":slug(\\w+)", // Constrain a dynamic page segment (to be letters here)
}

For a catch all route: "[...path]": ":path*".

You can use a constrained dynamic path segment in the root of your application too.

/pages/
 ├ [side]/
 | ├ index.tsx
 | └ _routes.yml
 ├ somewhere.tsx
 └ _app.tsx

# /pages/[side]/_routes.yml
---
"/":
  default: :side(heads|tails) # Important!
  en: :side(heads|tails)
  fr: :side(pile|face)
  es: :side(cara|cruz)

Ignoring a path part

This will ignore the blog path segment:

// `/pages/blog/_routes.json`
{
  "/": "."
}

It can be done for some lang only and not others.

// `/pages/blog/_routes.json`
{
  "/": {
    fr: "."
  }
}

⚠️ Ignoring a path segment can cause troubles with the redirections.

Ex: given the /a/[b]/[c] and /a/[b]/[c]/d file paths where [b] is ignored and the b param is merged with the c param: :b-:c. /a/:b/:c => /a/:b-:c and /a/:b/:c/d => /a/:b-:c/d Then /a/bb/11 will be redirected to /a/bb-11 and /a/bb/11/d to /a/bb-11/d and that is fine. But then /a/bb-11/d will match /a/:b-:c and be redirected to /a/bb-11-d and that is not fine!

To handle this case, one can add a path-to-regex pattern to the default ignore token: .(\\d+), or .(\[\^-\]+), or .(what|ever). This path-to-regex pattern will be added after the segment name in the redirect. /a/:b(\[\^-\]+)/:c => /a/:b-:c and /a/:b(\[\^-\]+)/:c/d => /a/:b-:c/d Then /a/bb-11/d will no more match /a/[b]/[c] (/a/:b(\[\^-\]+)/:c). #ignorePattern

⚠️ This is only handled in default paths (i.e. "/": ".(\\d+)" or "/": { "default": ".(\\d+)" }), not in lang-specific paths.

Complex paths segments

// `/pages/blog/[id]/_routes.json`
{
  "/": "article{-:id}?-view", // Add prefix, optional prefix, suffix
}

It is also possible to create a path segment with 2 dynamic parameters. Ex: /articles/:id{-:slug}?.
First, create a path segment for each dynamic parameter: `/articles/[id]/[slug]. Then:

// `/articles/[id]/_routes.json`
{
  "/": ".", // Ignore the [id] segment
  "[slug]": ":id{-:slug}?" // Give the 2 params to the 2nd segment
}

Custom route tree

If you want to avoid seeding _routes.json files in your /pages folder, you can directly create a routesTree object, and inject it in the next config as follow.

// next.config.js
const withTranslateRoutes = require('next-translate-routes')
const getRoutesTree = require('./getRoutesTree')

const routesTree = getRoutesTree()

module.exports = withTranslateRoutes({
  // Next i18n config (mandatory): https://nextjs.org/docs/advanced-features/i18n-routing
  i18n: {
    locales: ['en', 'fr', 'es', 'pl'],
    defaultLocale: 'pl',
  },

  translateRoutes: {
    routesTree,
  },

  // ...Remaining next config
})

routesTree must be of type TRouteBranch:

type TRouteBranch<Locale extends string> = {
  name: string
  paths: { default: string } & Partial<Record<Locale, string>>
  children?: TRouteBranch[]
}

Outside Next

You might need to mock next-translate-routes outside Next, for example for testing or in Storybook.

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.

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

const ntrData = createNtrData(
  nextConfig,
  path.resolve(process.cwd(), './fixtures/pages'),
)

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.

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

//[...]

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

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

// [...]

For Storybook, this piece of code can be used to create a decorator function:

export const WithNextRouter: DecoratorFn = (Story, context): JSX.Element => (
  <TranslatedRoutesProvider routerMock={createRouterFromContext(context)}>
    <Story />
  </TranslatedRoutesProvider>
)
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 paragraph above, but you don't need to create and add ntrData as an argument to withTranslateRoutes.

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

//[...]

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:

// 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.

Fallback languages

You can define fallback languages in next-translate-routes config as you would in i18next, using fallbackLng, that can take either a string (ex: 'fr'), an array (ex: ['fr', 'en']), or an object (ex: { default: ['en'], 'de-CH': ['fr'] }), but unlike i18next, fallbackLng cannot be a function.

// next.config.js
const withTranslateRoutes = require('next-translate-routes')

module.exports = withTranslateRoutes({
  // Next i18n config (mandatory): https://nextjs.org/docs/advanced-features/i18n-routing
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'fr', 'de', 'de-AT', 'de-DE', 'de-CH'],
  },

  translateRoutes: {
    fallbackLng: {
      default: ['en'],
      'de-AT': ['de'],
      'de-DE': ['de'],
      'de-CH': ['de', 'fr'],
    },
  },

  // ...Remaining next config
})

It can avoid having routes.json files looking like:

{
  "/": {
    "de": "produkt",
    "de-AT": "produkt",
    "de-DE": "produkt",
    "de-CH": "produkt"
  }
}

Known issues

Middleware with watcher (Next >=12.2.0)

Unfortunately, Next new middleware syntax (stable) has a bug when using a "matcher" and rewrites. You can keep track of this issue:

So if you want to use a middleware with Next >= 12.2.0, you need to remove any watcher option and filter from within the middleware using conditional statements.

Optional catch-all with rewrites

Another issue in Next.js messed some optional catch all routes when they are rewritten: it has been fixed starting from 13.0.4.

With @sentry/nextjs

@sentry/nextjs inject a webpack loader that replaces all pages content with a proxy, including _app. If it does it before next-translate-routes loader execution, the latter won't be able to do its job.

So the wrapping order in next.config.js is important!

Works:

module.exports = withTranslateRoutes(withSentryConfig(nextConfig, sentryWebpackPluginOptions))

Does NOT work:

module.exports = withSentryConfig(withTranslateRoutes(nextConfig), sentryWebpackPluginOptions)

How does it work

  • Next-translate-routes plugin parses the page folder and builds a routes tree object that contains the path tree and the information in the _routes.json files.
  • The plugin then uses this information to build optimized redirects and rewrites, then add them to the next config object.
  • Rewrites take care of displaying the right page for the translates urls, redirects take care of the urls that would give an unwanted access to the pages (and would create duplicated content).
  • The plugin adds a webpack loader for the pages/_app file. This loader adds a data object (containing the routes tree object along with other config) as first argument of the withTranslateRoutes high order component that wrap the app.
  • withTranslateRoutes makes this data available as a global variable, __NEXT_TRANSLATE_ROUTES_DATA.
  • The translateUrl function uses this data to translate routes.
  • The next-translate-routes/link leverages the translateUrl function to set the as prop of next/link to the translated url so that the link is aware of the true url destination (which is then available on hover, or on right-click - copy link for example).
  • The withTranslateRoutes enhance the router by overriding the router context, to give translation skills to the router.push (which is used on click on a next/link), router.replace, and router.prefetch functions, using the translateUrl function too.

next-translate-routes's People

Contributors

cvolant avatar michalpulpan avatar peacecwz avatar ristomatti avatar semantic-release-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

next-translate-routes's Issues

Add Next 13 support

At the moment I get the following error when I update to NextJS 13.0.3:

TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string or an instance of Buffer or URL. Received undefined
at Object.readdirSync (node:fs:1446:10)
at getAllRoutesFiles (/Users/.../node_modules/next-translate-routes/plugin/routesFiles.js:46:39)

Does this plugin support locale format en-US, es-MX, etc?

So far I'm not able to make this plugin work in my app which has the locale configured in 5 characters as en-US, fr-CA, es-MX, etc.
Is this plugin intended with this format? Thanks

Here is my next.config.js i18n setup:

image

Here is how I have set up the _routes.json:

image

Route using translated locale/.json file

Hi,

Looks like the next-translate-routes affects the next-i18n translation file logic.
The 18n file (namespace) that is requested is translated.

Example folder structure:

\public
    ....
     \locales
          en\
               about.json
               ...
          fr\ 
              about.json
              ...

For some reason, locally everything works fine for both language. The correct about.json file is fetched.
But once deployed to Vercel, the .json file that is request is not about.json but notre-histoire.json ?

In the browser, I see the file being fetched as https://..../_next/data/UhEhAsJqgcuNptbGTt7v2/fr/notre-histoire.json
When it should be https://..../_next/data/UhEhAsJqgcuNptbGTt7v2/fr/about.json

image
Looks like a redirect made by next-translate-route?
I would prefer not having to change the file names (i18n namespaces)

NextJS Automatic Static Optimization not supported

It seems that at the moment wrapping the entire App disables automatic static optimization for some pages. Any idea why this happens and how we can fix this?

Warning: You have opted-out of Automatic Static Optimization due to `getInitialProps` in `pages/_app`. This does not opt-out pages with `getStaticProps`
Read more: https://nextjs.org/docs/messages/opt-out-auto-static-optimization

Can someone add more documentation on routes.json ?

I am having hard time understanding these and how to define route? Is there anyone that can help me?

  1. Define your routes

In the pages folder, and in each of its subfolders, add a routes.json file with the following:

// `/pages/section/routes.json`
{
  "/": {
    "es": "seccion" // Folder path in es
  },
  "page1": {
    "default": "article", // Overwrite the default page path (fallback)
    "es": "articulo"
  },
  "page2": "definition", // Overwrite the page path for all language
}

The "/" section define the folder paths, each other section define the paths of a page file in this folder.

Is there a way to translate dynamic pages?

image
image

Hey, is there a way how to translate specific named dynamic pages (like in the picture above with "hello")? The documentation/readme only explains how to restrict dynamic pages and how to append pre- and suffixes.

Thanks

Without Lang Prefix

My site is multi-domain
( next config like: )

...
  i18n: {
    locales: ['en-US', 'fr-FR', 'de-DE'],
    defaultLocale: 'en-US',
    domains: [
      {
        domain: 'dev.site.com',
        defaultLocale: 'en-US',
        http: true,
      },
      {
        domain: 'dev.site.fr',
        defaultLocale: 'fr-FR',
        http: true,
      },
    ],
...

But my links now have are like : "dev.site.fr/fr-FR/example"
How to remove the language sufix since I already do it by domain ?
I managed to do like that

  <Link
      href={href}
      as={translateUrl(href, router.locale, {
        withoutLangPrefix: true,
        format: 'string',
      })}
    >

is this the proper way ? Can I remove all the language prefix everywhere ?
Also how to make the url "site.fr/sell" redirect to "site.fr/vendre" instead of redirecting with the lang prefix "site.fr/fr-FR/vendre/"

PS. THANKS FOR YOUR WORK ON THIS !

Existing routes not updating when _routes.json updates

After updating previously existing routes in the _routes.json file and changing languages, it will still redirect to the old route and will give a 404. I was able to recreate with the example project, I downloaded it and ran it, then changed the french redirect from "blog" to "blo" and re-ran the project, I was still redirected to "blog" when switching languages. If there is something I have to do after updating the file let me know.

yarn install does not work on windows

image

When I run yarn install, it says that "rm" is not recognized. However, when I type it alone (bottom of the image), it works. Have anyone seen this before? Thank you very much for your help!

Incorrect translation of external links

Some version between 1.8.0-1 and 1.9.1 now causes external links to be translated incorrectly:
I'm passing a href like
https://www.dhl.com/de-de/home/tracking/tracking-express.html
and the lib parses it to
/de-de/home/tracking/tracking-express.html

My current workaround is something like
const Link = href.toString().startsWith("http") ? NextLink : NextTranslateRoutesLink;
which I then render in a custom component.

But it would be better if the next-translate-routes wouldn't translate external links.

translate-routes and language change

Hey there,

I'm using next-translate-routes and it works fine so far. But when I change the language, the paths were not redirected, but the site-content is correct.
My code for languageChange is like this:

function changeLanguage(language) {
    i18n
      .changeLanguage(language === 'EN' ? 'en' : 'de')
      .then((t) => {
        t('key');
      })
      .catch((err) => {
        console.log('something went wrong loading', err);
      });
    router.push({ pathname, query }, asPath, { locale: language });
  }

my i18 config:

i18n: {
    defaultLocale: 'en',
    locales: ['en', 'de'],
  },

and my _routes.json:

{
  "contact": {
    "en": "contact",
    "de": "kontakt"
  }
}

eg.:
I am on page /de/kontakt and use the languageSwitcher. The url changed to /kontakt. The component "contact" is correctly loaded and its translated content too. But the url is false. If I refresh the page in browser, the re-direrection to/contact is done correctly.

How can I change my changeLanguage-Function to make this work?

Dynamic pages without index.js not translating trough translatePath

Example folder structure:

pages(folder)
       destinations(folder)
              [id].js

_routes.json looks like this:

{
    "/": {
        "en": "destinations",
        "hr": "destinationsHr",
        "de": "destinationsDe"
    }
}

translatePath usage:
translatepath('/destinations', 'de')

In this case, translatePath returns the original page name instead of the translation. This only happens to dynamic routes without an index.js page.

Edit:
On folder structure with catch all routes works flawlessly.

pages(folder)
       destinations(folder)
              [[...id]].js

support for router.push

Hi, managing all links with "next-translate-routes / link" is very easy but in some cases I have to change routes through router.push which does not support translated route names. Any solution to this?

Wrong sitemap

The package next-sitemap is not getting the translations

How to generate a sitemap with the translated paths ?
I would able to do it manually but translateUrl and translatePath ( methods ) don't seems to work well when the first parameter is a URL in another language that is not the default one,

ex : translateUrl('/home','fr-FR') == gets the path for French
But how to get the English path given a French one ? Or a third language given the french path ?
Thanks

[storybook] - No wrapped App component in withTranslateRoutes

Can't hadnle this error in storybook.

anyone know whats wrong?

export const WithNextRouter = (Story, context) => withTranslateRoutes(
  <TranslatedRoutesProvider routerMock={createRouterFromContext(context)}>
    <Story />
  </TranslatedRoutesProvider>
)

export const decorators = [WithNextRouter]

Cache issue upon changing the route name causes 404

First of all: your library rocks, it allowed me to rather easily translate my routes. Many thanks for this!

My issue: I made a change in my _routes.json for the "en" key, renamed it from "trade" to "sell" (see below). The route keeps being translated through (from next-translate-routes/link) as "trade"... only upon rm -rf .next/cache/* this starts to work as expected. Unfortunately this cache clearing is not possible or happening on Vercel, there might be something else going on?

"sell": { "de": "kaufen", "fr": "vendre", "en": "sell" },

Any thoughts?

Link to dynamic route results in ERR_ABORTED 404 (Not Found), then redirects correctly

Since I've updated from 1.8.0-1 to 1.9.1, some links to dynamic routes show a weird behavior. At first they log the following error to the console ...
image
... and then they redirect to the page successfully. Refreshing the page works fine, too, so the issue is most likely related to the link component, not any routes setup.

Here's the folder structure:

pages
   products
       [slug].page.tsx

routes.json inside the products folder:

{
  "/": {
    "de": "produkte"
  }
}

The link looks like this:
<Link href={`/products/${product.slug}`}>...</Link>

The debug-mode logs the following object when clicking the link:

image

Workaround
After some experimenting, I've found a solution which seems to work. If I built the link like this, the 404 doesn't show up any more:
<Link href={{ pathname: "/products/[slug]", query: { slug: product.slug }}}>...</Link>

The debugged objects looks a bit different then:

image

Am I missing something, or is my workaround maybe even the intended way of using links to dynamic routes?
However, the initially described code worked perfectly fine before the update.

Error with unit tests

There is page 404.tsx and unit test for the same page

import { act, render } from "test/utils";

import FourOFourPage from "../../src/pages/404";

describe.skip("<FourOFourPage>", () => {
  it("should render", () =>
    act(async () => {
      const { getByText } = render(<FourOFourPage />);

      expect(getByText("404")).toBeInTheDocument();
    }));
});

But when I try to run tests...

● Test suite failed to run

[next-translate-routes] - No translate routes data found. next-translate-routes plugin is probably missing from next.config.js

  325 | }
  326 |
> 327 | export default withTranslateRoutes(App);
      |                ^
  328 |

Note that there is skip but it still failes and there is next-translate-routes added in the config because some tests not related do pages are ok

Versions:

"next": "12.0.4"
"next-translate-routes": "^1.7.1"

Trans component doesn't seem to work in this example

So this is the code that I have

{
  "sign-up-modal-message": "or <0><1>Sign Up</1></0> if you do not have an account."
}
<Trans
  i18nKey='common:sign-up-modal-message'
  components={[<Link href='/auth/sign-up' />, <a className='font-medium text-primary hover:text-primary-focus' />]}
/>

This is the error thrown at me: Error: Multiple children were passed to <Link> with hrefof/auth/sign-up but only one child is supported https://nextjs.org/docs/messages/link-multiple-children

I've tried this as well but same error is thrown.

{
  "sign-up-modal-message": "or <link><a>Sign Up</a></link> if you do not have an account."
}
<Trans
  i18nKey='common:sign-up-modal-message'
  components={{ link: <Link href='/auth/sign-up' />, a: <a className='font-medium text-primary hover:text-primary-focus' />}}
/>

It works fine as a link if I only pass <Link /> in the components prop but obviously I cannot style my link.

Typescript support for Link properties

The following code is not valid on typescript 4.8.4:

import Link from "next-translate-routes/link";

export default function Sample() {
    return (
        <Link href="/some/url" target="_blank">Some link</Link>
    )
}

It generate the error:

Type '{ children: Element[]; href: string; target: HTMLAttributeAnchorTarget; }' is not assignable to type 'IntrinsicAttributes & InternalLinkProps & { children?: ReactNode; }'.
  Property 'target' does not exist on type 'IntrinsicAttributes & InternalLinkProps & { children?: ReactNode; }'.ts(2322)

target="_blank" causes the error.

It might be because of the declaration of next-translate-routes/link:

import { LinkProps } from 'next/link';
import React from 'react';
/**
 * Link component that handle route translations
 */
export declare const Link: React.FC<React.PropsWithChildren<LinkProps>>;
export default Link;

as LinkProps seems to only be the internal props for next/link and those does not includes React.AnchorHTMLAttributes<HTMLAnchorElement>:


export declare type LinkProps = InternalLinkProps;
/**
 * React Component that enables client-side transitions between routes.
 */
declare const Link: React.ForwardRefExoticComponent<Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof InternalLinkProps> & InternalLinkProps & {
    children?: React.ReactNode;
} & React.RefAttributes<HTMLAnchorElement>>;
export default Link;

I might be all wrong, but I think the declaration should include

Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof InternalLinkProps> & InternalLinkProps & {
    children?: React.ReactNode;
} & React.RefAttributes<HTMLAnchorElement>

and not only LinkProps .

Yarn install fails

I installed yarn and ran yarn install but it fails with the following error (the same thing happens with npm install)

Oops! Something went wrong! :(

ESLint 7.32.0

ESLint couldn't find the config "next" to extend from. Please check that the name of the config is correct.

The config "next" was referenced from the config file in "C:\Users\USER\next-translate-routes\example".

Support for fallback / substituable language (nonExplicitSupportedLngs)

Hello!

First of all, thank you very much for maintaining this project.
I wanted to ask whether there's (or is planned) support for a feature nonExplicitSupportedLngs / fallbackLng of next-i18next that is quite common in NextJS world.
See: i18next/next-i18next#1930

I'm running e-commerce site on NextJS and it's necessary for me to store both locale and country in the URL (as, for example, de-AT or de-CH). So I might have two urls example.org/de-DE/produkt/1 and example.org/de-CH/produkt/1. Both routes share the same locale but they might present different prices ( vs. CHF).
The rewrite itself can be handled by middleware (I can share code later if anyone is interested, but it's fairly simple).

With this feature, next-i18next allows to define "substituable" locale de-CH --> de and de-AT --> de so folder public/locales doesn't have to look like:

.
└── public/
    └── locales/
        ├── de
        ├── de-CH
        └── de-AT

but

.
└── public/
    └── locales/
        ├── de

is sufficient.

It would be nice if this feature is also supported by next-translate-routes so that routes.json doesn't have to look like 😊 :

{
  "/": {
    "de": "produkt",
    "de-CH": "produkt",
    "de-AT": "produkt",
    }
}

but only

{
  "/": {
    "de": "produkt",
    }
}

and generate page only once (for de).

If it would not be possible to implement, is there a chance to at least to introduce substitutable pages into build process?
NextJS will now generate the same page 3x (de, de-CH, de-AT) and it heavily slows down build time (due to large amount of pages).

Thank you in advance ☺️ .

Implement a Service Worker integration?

I know this is probably out of the scope of this project, but there's one feature I think would be sweet which is service worker integration. Currently I am using next-pwa, but it doesn't really fulfill my needs. Here's basically the service worker I need (I am considering just coding my own custom worker, but it would be cool to see an integration here):

The worker needs to cache the entire website when I press the download button (kind of like next-offline, but I couldn't get it to work properly). The reason I am doing this is because I am deploying my site as a progressive web application, so that people with limited internet connectivity can get reliable access to the site. The problem is that if I deploy the website in a large number of languages that's going to skyrocket the download size, hence the need to download the entire site, but only in the language selected by the user. This is why I think there's a need for integration between service workers and next translation solutions.

I'm not sure if this would mean implementing an entirely custom service worker for this library, or potentially providing an integration with an existing solution like next-pwa. Either way this is just an idea and you're welcome to decide whether this falls inside of the scope you have for this project or not.

Error when following the doc: No withTranslateRoutes high order component found in _app

Hello, your component is exactly what I was looking for. I really hope I can make it work, from what I've read you exactly addressed my need (which is interestingly not a out-of-the-box thing from Next).

What happened?

  1. I successfully installed the package with yarn add next-translate-routes
  2. I imported withTranslateRoutes on line 1 of next.config.js as follows: const withTranslateRoutes = require('next-translate-routes/plugin');
  3. I wrapped, as indicated, the config in next.config.js with withTranslateRoutes instead of nextTranslate
  4. I obtain the following error:

error - ./pages/_app.js
Error: [next-translate-routes] - No withTranslateRoutes high order component found in _app.

What am I missing, what am I doing wrong? Looking forward to hearing from you :)

P.S. I created one _routes.json at my pages root level, and added one single page to test.

Bug - translateUrl

Hello,
I've found a bug when trying a catch-all route (https://nextjs.org/docs/routing/dynamic-routes#catch-all-routes).

For a page represented by file in next /pages/destination/[...destinationSlugs], when trying to use <Link href="/destination/europe" />, I receive replaced link /destination/[...destinationSlugs]?destinationSlugs=europe instead of /destination/europe.

The only problem is when the [...destinationSlugs] variable should be replaced with only one level of slug. If there are more of them, it works OK (e.g. /destination/europe/prague).

Could you please have a look at it?

Automatically make link rel=alternate for SEO?

Can we use this plugin to automatically add this on each page based on _route.json :

<Head>
  <link rel="alternate" hrefLang="en" href="/en/about" />
  <link rel="alternate" hrefLang="fr" href="/fr/a-propos" />
</Head>

Maybe we can make a hook that takes the current page, search all rewrite for each language and return the Head tag with all alternate pages inside

TranslatePath does not respect ignored segment

Hi,

I have the following route configuration in pages/landing/_routes.json:
{ "/": { "default": "." }, "print": { "hu": "foto", "en": "prints" } }

I call translatePath like this:
translatePath('landing/print')

I would expect the function to return /foto (or /prints). However, it does return landing/foto. Note that the page urls are working fine, so my page loades at /foto and not at /landing/foto, the issue is only with the links.

Next 12 crash

Hi all,
i try to use your plugin with next 12.
But after update i received this error:

TypeError: Cannot read property 'push' of null
at enhanceNextRouter (/node_modules/next-translate-routes/index.js:231:19)

Breaks jsxImportSource in Nextjs

First of all, thank you for the time you put into this!

When running with this package in development mode I get Module not found: Can't resolve for the package I'm using as jsxImportSource. I have followed the guide presented on the README, is there anything I'm doing wrong? Or is it just not meant to work with development mode?

I'm running 1.9.0-2

Query parameter is added to the URL within the address bar.

Everything has been working fine so far. Love your work. However I noticed a problem where the query parameter for dynamic pages is added to the URL within the address bar. I setup a simple example here to reproduce the problem:
codesandbox example

Even when I check some of my older branches of 4 weeks ago, where I used version 1.7.2, I get the same issue. So it is probably not related to next-translate-routes, but maybe something else changed. A dependency of a dependency or something. Using different versions of nextjs doesnt help either.

Anyway, not using pathname and query to define the url within the "href" property still works, but I am pretty sure the aforementioned behaviour is not intended.

So in short:

<Link href={{ pathname: "/blog/[slug]", query: { slug: "derp" } }}>
          Link to dynamic page
        </Link>

Results in this URL:
/blog/derp?slug=derp

Instead of:
/blog/derp

TypeError: withTranslateRoutes is not a function

Hi

i was so happy to find this package because it matches 100% of the needs and i could not agree more with the motivation. However, i made a fresh Next.js install then just npm install next-translate-routes so my package looks like this
{ "name": "next-poc", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "next": "11.0.1", "next-translate-routes": "^1.1.0", "react": "17.0.2", "react-dom": "17.0.2" }, "devDependencies": { "eslint": "7.32.0", "eslint-config-next": "11.0.1" } }
edited next.config.js as describe
`const withTranslateRoutes = require('next-translate-routes/plugin')

module.exports = withTranslateRoutes({
reactStrictMode: true,
// Next i18n config (mandatory): https://nextjs.org/docs/advanced-features/i18n-routing
i18n: {
locales: ['en', 'fr', 'es', 'pl'],
defaultLocale: 'pl',
},

// ...Remaining next config
})
`

nothing else and i got the following when running
ready - started server on 0.0.0.0:3000, url: http://localhost:3000 TypeError: withTranslateRoutes is not a function at Object.<anonymous> (/[mypath]/next-poc/next.config.js:3:18) at Module._compile (internal/modules/cjs/loader.js:1137:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10) at Module.load (internal/modules/cjs/loader.js:985:32) at Function.Module._load (internal/modules/cjs/loader.js:878:14) at Module.require (internal/modules/cjs/loader.js:1025:19)

what is wrong?
tx

1.9.0-3 - navigation to wrong translation reloads the app

Since I can not use 1.8.0 due to this issue I am using the 1.9.0-3

I have this structure:

/author
--[slug].tsx
--_routes.json
[...catchAll].tsx
index.tsx

in routes.json is defined:

{
  "/": {
    "cz": "autori",
    "en": "authors"
  }
}

The issue

When navigating with useRouter or Link from next-translate-routes/link and trying to navigate to the 'incorrectly' translated path the part of path that should be translated stays the same

router.push('cz/author/name-of-author', 'cz/author/name-of-author', { locale: 'cz' })

or

<Link href={'cz/author/name-of-author'} locale={ 'cz' } >

Both route to __domain__/cz/author/name-of-author instead of __domain__/cz/autori/name-of-author. Link also generates the URLs with wrong translation in html.

On full reload, the URLs is properly translated.

Duplication with routesTree

I have crated routesTree and I have 2 urls
/user - just user data
/user/cards - user cards

So inside routesTree.json

{
      "name": "user",
      "paths": {
        "default": "user",
        "de": "benutzer",
      },
      "children": [
        {
          "name": "cards",
          "paths": {
            "default": "cards",
            "de": "karten"
          }
        }
      ]
    }

Now when I use link component and have link to user/cards translation is working fine but just for user is not working, only when I add new object for user without this children array

"No translate routes data found. next-translate-routes plugin is probably missing from next.config.js"

I keep getting this error although I followed all the basic steps. I can even see the debug log in the terminal with all the redirects and rewrites created by the plugin, but somehow I'm still getting this error.

What I did:

  1. Wrap you next config with the next-translate-routes plugin
// next.config.js
const { i18n } = require("./next-i18next.config");
const withTranslateRoutes = require("next-translate-routes/plugin")

module.exports = withTranslateRoutes({
  pageExtensions: ["page.tsx", "page.ts", "page.jsx", "page.js"],
  reactStrictMode: true,
  eslint: {
    ignoreDuringBuilds: true,
  },
  esModule: true,
  images: {
    domains: [
      //...
    ],
  },
  i18n,
  translateRoutes: {
    debug: true,
  },
});
  1. Define your routes
// _routes.json
{
  "/": {
    "en": "hi",
    "es": "hola",
    "pt-BR": "oi"
  }
}
  1. Wrap you _app component with the withTranslateRoutes hoc
import { appWithTranslation } from "next-i18next";
import { wrapper } from "../redux";
import { withTranslateRoutes } from "next-translate-routes";

function MyApp({ Component, pageProps }: AppProps) {
  /**/
  return (
    <>
      <Component {...pageProps} />
    </>
  );
}

export default withTranslateRoutes(
  appWithTranslation(wrapper.withRedux(MyApp))
);

What I get in terminal:

[next-translate-routes] - Redirects: [
  {
    source: '/pt-BR/(hi|hola)/downloads/',
    destination: '/oi/downloads/',
    locale: false,
    permanent: false
  },
  {
    source: '/en/(oi|hola)/downloads/',
    destination: '/en/hi/downloads/',
    locale: false,
    permanent: false
  },
...
]
[next-translate-routes] - Rewrites: [
  {
    source: '/(oi|hi|hola)/downloads/',
    destination: '/downloads/'
  },
  {
    source: '/(oi|hi|hola)/about/',
    destination: '/about/'
  },
...
]

And eventually:

Error: [next-translate-routes] - No translate routes data found. next-translate-routes plugin is probably 
missing from next.config.js
    at withTranslateRoutes (\node_modules\next-translate-routes\react\withTranslateRoutes.js:63:15)
    at eval (webpack-internal:///./src/pages/_app.page.tsx:71:140)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

I have searched for other issues here and in Google, but haven't find anything similar. What am I missing?

_middleware.ts doesn't work on translated routes

Hello,

I really enjoy this library but I'm facing very weird behavior when using NextJS 12 _middleware.ts function.

Using _middleware.ts simple as:

import type { NextFetchEvent, NextRequest } from 'next/server'

const middleware = (req: NextRequest, ev: NextFetchEvent) => {
  return new Response('Hello, world!')
}

export default middleware;

works when:

- /pages
----/my-page <-- no _routes.json
--------index.tsx
--------_middleware.ts

And shows "Hello, world!"

But when I add _routes.json, middleware stops working.

- /pages
----/my-page
--------index.tsx
--------_routes.json <-- makes middleware not executing
--------_middleware.ts

It's quite important for me. Thanks!

Plugin can't be used with @sentry/nextjs

When using the @sentry/nextjs plugin, the Sentry's HoC withSentryConfig modifies the _app.tsx's output quite a bit. The result is that next-translate-router/plugin/loader.ts fails while looking for the import of next-translate-routes.

Any ideas how to deal with this?

routes.yaml ?

It would be nice to be able to customize ROUTES_DATA_FILE_NAMES (which is currently a const in config.tsx) and support yaml.
Yaml would be perfect to define routes and allow comments!

How to use next-translate-routes with I18next and withPlugins?

We are so frustrated as a team to find out Nextjs does not offer a complete solution to handle localized slugs and they even announced that there will be no i18n in Nextjs v13 which any complete frameworks like Django or RubyonRails even Nuxt offer for years. vercel/next.js#18485 (reply in thread)

We had shed tear and pain migrating our content heavy website which have 7 languages and 72k content. As any reasonable developer who do not wish to lose any traffic and backlink, we wanted to keep our routes as same as possible with old sitemap.

We are using i18next to handle translations and withPlugins package to handle all modification in next.config.js yet we could not figure out how to propery adjust next-translate-routes in our config.

code

our next.config.js:

// next.config.js
const path = require('path');
const withLess = require("next-with-less");
const withPlugins = require('next-compose-plugins');

const { i18n } = require('./next-i18next.config.js')

const { config } = require('process');

module.exports = withPlugins(
  [[withLess], [withBundleAnalyzer]],

  // I18N Stuff
  i18n,
)

our next-i18next.config.js:

module.exports = {
  debug: false, // It should be false

  i18n: {
    locales: ['en', 'tr', 'es', 'pt', 'fr', 'de', 'ru'],
    defaultLocale: 'en',
    localeDetection: true,

  },

  interpolation: {
    escapeValue: false
  },

}

Vercel Functions : No routes tree defined.

Hi,

I'm currently migrating the frontend of my NextJS app from Amplify to Vercel and I have an error on SSR page that is converted by Vercel to a Function.

Environment :

  • next-translate-routes: v1.5.5
  • NextJS: v12.0.7

Here you can see the SSR part :

export async function getServerSideProps(context) {
  const { Auth, API } = withSSRContext(context)
  let orders
  try {
    const user = await Auth.currentAuthenticatedUser()
    try {
      orders = await API.graphql({
        query: orderByUser,
        authMode: "AMAZON_COGNITO_USER_POOLS",
        variables: {
          userId: user.username,
          sortDirection: "DESC",
        },
      });
    } catch (err) {
      console.log("error fetching orders: ", err)
    }
  } catch (error) {
    context.res.writeHead(302, { Location: '/connexion' })
    context.res.end()
  }
  return {
    props: {
      ...(await serverSideTranslations(context.locale, ['common', 'orders'], nextI18NextConfig)),
      orders: orders ? orders.data.orderByUser.items.map(order => ({ ...order, cart: JSON.parse(order.cart) })) : null
    }
  }
}

This part was running fine on Amplify, but know on the Vercel Function logs I can see this error :

2021-12-12T18:10:55.595Z	2b1d4e33-0e24-433d-aa7b-219045d4bacc	ERROR	Error: > next-translate-routes - No routes tree defined. next-translate-routes plugin is probably missing from next.config.js
    at withTranslateRoutes(undefined) (/var/task/node_modules/next-translate-routes/index.js:308:19)
    at d (/var/task/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:33:498)
    at bb (/var/task/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:36:16)
    at a.b.render (/var/task/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:42:43)
    at a.b.read (/var/task/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:41:83)
    at Object.exports.renderToString (/var/task/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:52:138)
    at Object.renderPage (/var/task/node_modules/next/dist/server/render.js:686:46)
    at Object.defaultGetInitialProps (/var/task/node_modules/next/dist/server/render.js:316:51)
    at Function.getInitialProps (/var/task/.next/server/chunks/859.js:544:20)
    at Object.loadGetInitialProps (/var/task/node_modules/next/dist/shared/lib/utils.js:69:29)
2021-12-12T18:10:55.604Z	2b1d4e33-0e24-433d-aa7b-219045d4bacc	ERROR	Error: ENOENT: no such file or directory, scandir '/var/task/public/locales/en'
    at Object.readdirSync (fs.js:1047:3)
    at getLocaleNamespaces (/var/task/node_modules/next-i18next/dist/commonjs/config/createConfig.js:175:23)
    at /var/task/node_modules/next-i18next/dist/commonjs/config/createConfig.js:181:20
    at Array.map (<anonymous>)
    at getNamespaces (/var/task/node_modules/next-i18next/dist/commonjs/config/createConfig.js:180:44)
    at createConfig (/var/task/node_modules/next-i18next/dist/commonjs/config/createConfig.js:221:29)
    at _callee$ (/var/task/node_modules/next-i18next/dist/commonjs/serverSideTranslations.js:199:53)
    at tryCatch (/var/task/node_modules/regenerator-runtime/runtime.js:63:40)
    at Generator.invoke [as _invoke] (/var/task/node_modules/regenerator-runtime/runtime.js:294:22)
    at Generator.next (/var/task/node_modules/regenerator-runtime/runtime.js:119:21) {
  errno: -2,
  syscall: 'scandir',
  path: '/var/task/public/locales/en',
  page: '/mes-commandes'
}
RequestId: 2b1d4e33-0e24-433d-aa7b-219045d4bacc Error: Runtime exited with error: exit status 1
Runtime.ExitError

This is my next.config.js :

const WindiCSSWebpackPlugin = require('windicss-webpack-plugin')
// const { i18n } = require('./next-i18next.config');
const withTranslateRoutes = require('next-translate-routes/plugin')

module.exports = withTranslateRoutes({
  // i18n,
  i18n: {
    defaultLocale: 'fr',
    locales: ['fr', 'en'],
  },
  images: {
    domains: ['localhost', 'images.unsplash.com'],
    formats: ['image/avif', 'image/webp'],
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
    imageSizes: [16, 32, 48, 64, 94, 149, 256, 400],
  },
  env: {
    NEXT_PUBLIC_URL: process.env.NEXT_PUBLIC_URL,
    STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
    STRIPE_WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET,
    MJ_APIKEY_PUBLIC: process.env.MJ_APIKEY_PUBLIC,
    MJ_APIKEY_PRIVATE: process.env.MJ_APIKEY_PRIVATE,
  },
  webpack(config) {
    config.plugins.push(new WindiCSSWebpackPlugin())
    return config
  },
})

The rest of the site works correctly with the translation of the routes.
Do you have any idea why this error occurs?

Thanks in advance!

Keep default language locale in the URL

Would it be possible to keep the defaultLocale string in the URL? By default, it looks like it adds redirects to prevent this. But I would like to keep this part in the URL.

For example

{
   i18n: {
     ​​locales: ['en', 'nl'],
     defaultLocale: ‘nl’,
   },
   translateRoutes: {
     redirectToDefaultLocale: true, // This should add a redirect for `example.com` to `example.com/nl`
     disableRedirectsToDefaultLocale: true, // This should disable the redirects added by default to remove the defaultlocale
   }
}

Dependencies: Move Dependencies to PeerDependencies

Hi @cvolant

Thanks a lot for the work on this project! I have a question/suggestion since this is a library can we move the dependencies to dependencies and peerDependencies. As I understand it the library currently requires the exact version of the specified packages or higher, correct?

I would be happy to provide a PR.

old

  "dependencies": {
    "next": "^12.0.4",
    "path-to-regexp": "^6.2.0",
    "querystring": "^0.2.1",
    "react": "^17.0.2",
    "yamljs": "^0.3.0"
  },

new

  "peerDependencies": {
    "next": "^12.x",
    "path-to-regexp": "^6.x",
    "querystring": "^0.2.x",
    "react": "^17.x",
    "yamljs": "^0.3.x"
  },
  "devDependencies": {
    ...existingDevDependencies,
    "next": "12.0.4",
    "react": "17.0.4",
    "path-to-regexp": "6.2.0",
    "querystring": "0.2.1",
    "yamljs": "0.3.0"
  },

Setting ?queryparam when on root triggers refresh

The problem occurs when trying to set a query param when on the root page on non-default locale only. Setting the query param should trigger a global component to render, instead, the page refreshes and render the component. For some reason, it requested a script that is wrong (see image).

error

It's trying to access the it.js script where it is the locale in the url.

Im setting the Href of the Link component to '?queryparam=true'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.