platforms
platforms copied to clipboard
Support for internationalization
[domain]
conflicts with Next.js's routing guide on internationalization that recommends a [locale]
directory. How can this work with next-intl/middleware
or something similar?
The problem with using something like next-intl/middleware
is that their middleware returns a NextResponse
and so is the rewrites of this repo and you can't return two responses. I have tried chaining multiple middleware functions but I think you can't do that. You can try using something like https://github.com/vercel/next.js/tree/canary/examples/app-dir-i18n-routing but then you will have to change the rewrites to take the locale into consideration.
@gmreburn were you able to solve this?
Yes, we solved this problem in a less elegant way. It works, but I'd love a solution that provides both the domain and locale as a dynamic route. I think the structure could work like /[domain]/[locale]/
with some middleware magic.
For our solution, we use [locale] as a dynamic route and use a helper function within components to access the domain via server or client components. We use a load balancer to accept traffic from multiple domains and route to the same Next.js process. I think this solution could be adapted to work with middleware, but we didn't go to that length. Please share if you take the time to do so.
/**
* Get domain from env variables for local,
* from request if it was provided (for server side),
* or from location object (for client side)
*
* @param headers
*/
export function getDomain(headers?: ReadonlyHeaders): string {
let domain = null
if (process.env.NEXT_PUBLIC_CLIENT_DOMAIN) {
// if a domain is configured in env variables, return from env
domain = process.env.NEXT_PUBLIC_CLIENT_DOMAIN)
} else if (headers) {
// try to parse from request
domain = getDomainFromHeaders(headers)
} else if (typeof window !== 'undefined') {
// if no request specified and env variable is not set
// try to get from location global object
domain = window.location?.host
}
if (!domain) {
throw new Error('Could not parse the domain')
}
return domain
}
export function getDomainFromHeaders(headers: ReadonlyHeaders): string | null {
return headers.get('X-Forwarded-Host') ?? headers.get('Host')
}
`
You can use it in a client or SSR component:
```ts
import { headers } from 'next/headers'
import { getDomain } from '@/helpers/global'
export default async function MyServerComponent() {
const headersList = headers()
const domain = getDomain(headersList)
...
Or with a client component:
'use client'
import { getDomain } from '@/helpers/global'
export default function MyClientComponent() {
const domain = getDomain()
...
For local development we set NEXT_PUBLIC_CLIENT_DOMAIN
in .env.local
to a domain name we desire for testing purposes.