i18n without Sub-path Routing and Domain Routing #29932
Replies: 15 comments 33 replies
-
I mentioned this new feature to next-i18next and they told me this have to be manage here: |
Beta Was this translation helpful? Give feedback.
-
I would love this. The switch of next-i18next to using Next.js's localization features is incredibly frustrating for this use case. You're either stuck using legacy code, have to migrate to a different localization library, or have to integrate nextjs with react-i18next yourself. |
Beta Was this translation helpful? Give feedback.
-
I have this need too |
Beta Was this translation helpful? Give feedback.
-
any change here? |
Beta Was this translation helpful? Give feedback.
-
I need this feature.. |
Beta Was this translation helpful? Give feedback.
-
The only problem regarding this is SEO, but having the /[locale] AND the cookie would be the best /[locale] for web crawlers and cookies for users |
Beta Was this translation helpful? Give feedback.
-
As of Next.js v12, this can be done with middleware that reads a cookie and then rewrites the response with a new locale: middleware.ts
In your i18n config, also turn off locale detection so Next ignores its own next.config.js
|
Beta Was this translation helpful? Give feedback.
-
Is there any way to do this with App router? |
Beta Was this translation helpful? Give feedback.
-
I dove into next-intl source code and I created this middleware hack. Manually sets the intl header and cookie. It's risky because their constants may change in the future. Let me know if you'll find a way to import constants from library next-intl: 3.0.0-beta.19 import { NextRequest, NextResponse } from 'next/server';
const locales = ['en-US', 'pl-PL'];
const defaultLocale = 'en-US';
function getLocale(request: NextRequest) {
const acceptedLanguages = request.headers.get('accept-language');
if (acceptedLanguages) {
const locale = locales.find((l) => acceptedLanguages.includes(l));
if (locale) {
return { locale, localeShort: locale.split('-')[0] };
}
}
return { locale: defaultLocale, localeShort: defaultLocale.split('-')[0] };
}
export function middleware(request: NextRequest) {
const { locale, localeShort } = getLocale(request);
const requestHeaders = new Headers(request.headers);
const response = NextResponse.next({
request: {
headers: requestHeaders,
},
});
// Full locale (e.g. `en-US`)
response.headers.set('x-locale', locale);
// Set header to simulate correct response for `next-intl`
response.headers.set('X-NEXT-INTL-LOCALE', localeShort);
// Set cookie to simulate correct response for `next-intl`
response.cookies.set('NEXT_LOCALE', localeShort);
return response;
}
export const config = {
matcher: [
// Skip all internal paths (_next)
'/((?!_next).*)',
// Optional: only run on root (/) URL
// '/'
],
}; |
Beta Was this translation helpful? Give feedback.
-
Super +1 on this! |
Beta Was this translation helpful? Give feedback.
-
If you want to get the locale dynamically depending on the user, I have found another simple solution. // server.ts
import { cache } from "react";
import { headers } from "next/headers";
import acceptLanguage from "accept-language";
import { getRequestConfig, getTranslator } from "next-intl/server";
import { auth } from "@acme/auth"; // This is from
import "server-only";
import { defaultLanguage, languages } from "./config"; // This is a simple file an array of languages available for the user and the default language
import { getMessages, isSupportedLocale } from "./utils";
acceptLanguage.languages([...languages]);
export const getLocale = cache(async () => {
const session = await auth();
// If the user is logged in, use their locale
if (session?.user?.locale) {
return session.user.locale;
}
// If the user is not logged in, use the headers locale
const headerLanguage = acceptLanguage.get(headers().get("accept-language"));
if (headerLanguage && isSupportedLocale(headerLanguage)) {
return headerLanguage;
}
return defaultLanguage;
});
export const getI18n = cache(async () => {
const locale = await getLocale();
const t = await getTranslator(locale);
return t;
});
export default getRequestConfig(async ({ locale }) => ({
messages: await getMessages(locale),
})); and then you would have to add the plugin to the next app: // next.config.ts
export default nextIntlPlugin(
'../../packages/i18n/server.ts'
)(config); In your server component or page then you would simply do: export default function Page(){
const t = await getI18n();
return (<p>{t("translation.key.whatever")}</p>)
} |
Beta Was this translation helpful? Give feedback.
-
I have been diggin arround this quite a lot and came across this superb article about using i18next and a cookie solution. |
Beta Was this translation helpful? Give feedback.
-
Describe the feature you'd like to request
I'm developing a SaaS application and I would like to manage the i18n without sub-path routing or domain routing.
Describe the solution you'd like
I would like to use a third way (using just a cookie for example).
In a SaaS application its not so nice to use sub-path/domain routing for the language and it's not necessary any SEO performance
Describe alternatives you've considered
Just store the configuration in a cookie to get the current locale and be able to change it with the current useRouter or with a new method
Beta Was this translation helpful? Give feedback.
All reactions