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

feat: next-international V2 #361

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft

feat: next-international V2 #361

wants to merge 10 commits into from

Conversation

QuiiBz
Copy link
Owner

@QuiiBz QuiiBz commented Feb 17, 2024

Development branch for #359

Breaking changes

Single createI18n function

Instead of having two separate createI18nClient / createI18nServer methods that needs to live in separate files and each expose distinct but similar methods (useI18n / getI18n), a single createI18n function is introduced to replace all of them.

You can import from the same file the getI18n / getScopedI18n methods, without worrying about client vs server - it's taken care of by next-international automatically. These functions both return a Promise, which you can either await inside a Server Component or use() inside a Client Component.

Before/after

Before

// locales/client.ts
export const { useI18n, useScopedI18n, ... } = createI18nClient(...)

// locales/server.ts
export const { getI18n, getScopedI18n, ... } = createI18nServer(...)

// Client Component
import { useI18n } from '@/locales/client'

export function ClientComponent() {
  const t = useI18n()
  ...
}

// Server Component
import { getI18n } from '@/locales/server'

export async function ServerComponent() {
  const t = await getI18n()
  ...
}

After

// locales/index.ts
export const { getI18n, getScopedI18n, ... } = createI18n(...)

// Client Component
import { getI18n } from '@/locales'
import { use } from 'react'

export function Component() {
  const t = use(getI18n())
  ...
}

// Server Component
import { getI18n } from '@/locales/server'

export async function ServerComponent() {
  const t = await getI18n()
  ...
}

Improved middleware

Previously, it was complex to use next-international's middleware with custom code or external middlewares (e.g. next-auth). The improved createI18nMiddleware function now accepts a full middleware-like signature ((request: NextRequest) => NextResponse) as the first argument, meaning you can very easily add custom logic:

Before/after

Before

const I18nMiddleware = createI18nMiddleware({
  locales: ['en', 'fr'],
  defaultLocale: 'en'
})
 
export function middleware(request: NextRequest) {
  return I18nMiddleware(request)
}

After

export const middleware = createI18nMiddleware(request => {
  // Any custom logic using a raw `NextRequest` and returning a raw `NextResponse`
  return NextResponse.next()
}, {
  locales: ['en', 'fr'],
  defaultLocale: 'en'
});

Removal of I18nProviderClient

With the new approach in next-international v2, the I18nProviderClient component is no longer needed - you can simply remove it completely!

Rename getStaticParams to generateI18nStaticParams

The utility function used for static rendering in combinaison with Next.js' generateStaticParams function has been renamed from getStaticParams to generateI18nStaticParams, in order to match the other function names:

Before/after

Before

// locales/server.ts
export const { getStaticParams, ... } = createI18n(...)

// app/[locale]/layout.tsx
import { getStaticParams } from '@/locales'

export function generateStaticParams() {
  return getStaticParams()
}

After

// locales/index.ts
export const { generateI18nStaticParams, ... } = createI18n(...)

// app/[locale]/layout.tsx
import { generateI18nStaticParams } from '@/locales'

export const dynamicParams = false
export function generateStaticParams() {
  return generateI18nStaticParams()
}

Rename locale helpers

The locale helper functions have been renamed to be more simple:

  • useCurrentLocale() -> getLocale()
  • getCurrentLocale() -> getLocale()
  • No update: useChangeLocale() (this one keeps the use* naming because it can only be used inside Client Components)

@QuiiBz QuiiBz added this to the 2.0 milestone Feb 17, 2024
Copy link

vercel bot commented Feb 17, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
next-international ✅ Ready (Inspect) Visit Preview Mar 4, 2024 11:50am

@stunaz
Copy link

stunaz commented Mar 24, 2024

@QuiiBz sorry to bother, any update on this?

@QuiiBz
Copy link
Owner Author

QuiiBz commented Apr 3, 2024

@QuiiBz sorry to bother, any update on this?

It's still in progress.

@dariolongo-dufercodev
Copy link

Any update on v2?
without new middleware can't be used with auth.js (v5)
Thanks!

@noxify
Copy link

noxify commented May 10, 2024

Hi @dariolongo-dufercodev,

Have you tried to chain the middleware?

Wasn't able to find the original source, but here an example how you could do it (with authjs instead of lucia):

https://github.com/noxify/t3-turbo-lucia/tree/main/apps/nextjs/src

Maybe a workaround but should work until the new middleware is available.

@dariolongo-dufercodev
Copy link

Hi @noxify,
this is exactly the solution i found after some research, the code is very similar, thanks!
I haven't tried that yet, but I'll write results asap.
Thanks

@dariolongo-dufercodev
Copy link

Maybe it could be easier than expected:

export default auth((req) => {
  // here is possible access to req.auth
  const isLoggedIn = !!req.auth;
  
  if (... apply logic here ...) {
      return NextResponse.redirect(new URL(DEFAULT_REDIRECT_HOME_URL, url));
  }
  return I18nMiddleware(req);
}

Copy link

@gabriel-logan gabriel-logan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer having two separated files

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

Successfully merging this pull request may close these issues.

5 participants