aralroca/next-translate

Change language without modifying the URL (/[lang]/rest)

Opened this issue · 5 comments

What version of this package are you using?
2.6.0

What problem do you want to solve?
We have a dashboard app that is hidden from search engines, so we do not need SEO, using Next 13.5 with pages router and next-translate latest version and we would like to be able to change language without adding the locale inside the url, I see that setLanguage uses next-router to pass the locale but would it be possible to allow to change the locale without changing the URL ?

What do you think is the correct solution to this problem?
Maybe there is a way to use the NEXT_LOCALE cookie or something else to accomplish the same behavior, I am not familiar enough with this library

Are you willing to submit a pull request to implement this change?
It depends of the complexity of what would have to be modified

I'm facing a similar problem
I want a default route without being explicit on URL.. and another language to be explicit
Anyone has some idea?

We are on the same boat, trying to switch languages without using [lang]/route. the setLanguage complains about that the next/router is not found.

Error: No router instance found.
You should only use "next/router" on the client side of your app.

Source
components/organisms/Header/index.tsx (33:14) @ locale

  31 | date.setTime(date.getTime() + expireMs);
  32 | document.cookie = `NEXT_LOCALE=${locale};expires=${date.toUTCString()};path=/`;
> 33 | setLanguage(locale);

Ok, after finding this comment #1022 (comment)
we were able to implement a language switcher using ?lang=de or ?lang=en. without /en/ or /fr/ or /en/ in the path.

Attempting to implement the solution you refer to @Eusebiotrigo didn't work for me unfortunately. I still get:

Error: No router instance found.
You should only use "next/router" on the client side of your app.

😩

+1

No real official way, for now, to do so. However, you can implement it using I18nProvider. It's not recommended though. Check #492 (comment)

Here's what's worked for me, as ugly as it may be.

  1. Create a hook, let's call it, useI18nProviderNamespaces that maps all your locales to translation files:
import commonEn from 'public/locales/en/common.json';
import dashboardEn from 'public/locales/en/dashboard.json';
import commonFr from 'public/locales/fr/common.json';
import dashboardFr from 'public/locales/fr/dashboard.json';

type Locale = 'en' | 'fr';

const localeMapping = {
  en: {
    common: commonEn,
    dashboard: dashboardEn,
  },  
  fr: {
    common: commonFr,
    dashboard: dashboardFr,
  },
};

export const useI18nProviderNamespaces = (locale: string) =>
  localeMapping[locale as Locale];
  1. In your _app.tsx file add I18nProvider so it becomes something like:
const locale = props.pageProps.locale;
const i18nProviderNamespaces = useI18nProviderNamespaces(locale);

<I18nProvider lang={locale} namespaces={i18nProviderNamespaces}>
  <MyApp {...props} />
</I18nProvider>
  1. Finally, expose locale prop to every page:
export const getServerSideProps: GetServerSideProps = async ({ req }) => ({
  props: { locale: req.cookies.NEXT_LOCALE ?? 'en' },
});

You can polish it up a bit to suit your use case. The language will be determined by setting the cookie NEXT_LOCALE to user selected locale. You can modify your language selector logic to do so.

Hope it helps.