Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for internationalization #382

Open
gmreburn opened this issue Jan 25, 2024 · 3 comments
Open

Support for internationalization #382

gmreburn opened this issue Jan 25, 2024 · 3 comments

Comments

@gmreburn
Copy link

[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?

@alabdulaal
Copy link

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.

@ddeisadze
Copy link

@gmreburn were you able to solve this?

@gmreburn
Copy link
Author

gmreburn commented Apr 1, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants