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

Use i18next with app folder let /de/pathname redirect to /pathname on Typescript not working #39

Open
i-ked-ii opened this issue Nov 6, 2024 · 4 comments

Comments

@i-ked-ii
Copy link

i-ked-ii commented Nov 6, 2024

i want en as default language, where user access /de/about I want let it redirect to /about . only language is "de" hide the language. how can i do this

Screenshot 2567-11-06 at 22 12 39

Screenshot 2567-11-06 at 22 13 00

Screenshot 2567-11-06 at 22 16 10

@adrai
Copy link
Member

adrai commented Nov 6, 2024

You may need to change the middleware.ts to your needs...
maybe a rewrite instead of a redirect is already sufficient?

- return NextResponse.redirect(new URL(`/${lng}${req.nextUrl.pathname}${req.nextUrl.search}`, req.url))
+ return NextResponse.rewrite(new URL(`/${lng}${req.nextUrl.pathname}${req.nextUrl.search}`, req.url))

@i-ked-ii
Copy link
Author

i-ked-ii commented Nov 7, 2024

You may need to change the middleware.ts to your needs... maybe a rewrite instead of a redirect is already sufficient?

- return NextResponse.redirect(new URL(`/${lng}${req.nextUrl.pathname}${req.nextUrl.search}`, req.url))
+ return NextResponse.rewrite(new URL(`/${lng}${req.nextUrl.pathname}${req.nextUrl.search}`, req.url))

I change the middleware.ts but not working.

import acceptLanguage from 'accept-language'
import { fallbackLng, languages } from 'src/app/i18n/settings'

acceptLanguage.languages(languages)

export const config = {
  // matcher: '/:lng*'
  matcher: ['/((?!api|_next/static|_next/image|assets|favicon.ico|sw.js|site.webmanifest).*)'],
}

const cookieName = 'i18next'

export function middleware(req: NextRequest) {
  if (req.nextUrl.pathname.indexOf('icon') > -1 || req.nextUrl.pathname.indexOf('chrome') > -1) return NextResponse.next()
  let lng: string | undefined | null
  if (req.cookies.has(cookieName)) lng = acceptLanguage.get(req.cookies.get(cookieName)?.value)
  if (!lng) lng = acceptLanguage.get(req.headers.get('Accept-Language'))
  if (!lng) lng = fallbackLng

  // Redirect if lng in path is not supported
  if (
    !languages.some(loc => req.nextUrl.pathname.startsWith(`/${loc}`)) &&
    !req.nextUrl.pathname.startsWith('/_next')
  ) {
    return NextResponse.rewrite(new URL(`/${lng}${req.nextUrl.pathname}${req.nextUrl.search}`, req.url))
  }

  if (req.headers.has('referer')) {
    const refererUrl = new URL(req.headers.get('referer') || '')
    const lngInReferer = languages.find((l) => refererUrl.pathname.startsWith(`/${l}`))
    const response = NextResponse.next()
    if (lngInReferer) response.cookies.set(cookieName, lngInReferer)
    return response
  }

  return NextResponse.next()
}
// src/app/i18n/settings.ts
export const fallbackLng = 'en'
export const languages = [fallbackLng, 'en']
export const defaultNS = 'translation'
export const cookieName = 'i18next'

export function getOptions (lng = fallbackLng, ns: string | string[] = defaultNS) {
  return {
    // debug: true,
    supportedLngs: languages,
    // preload: languages,
    defaultLocale: fallbackLng,
    fallbackLng,
    lng,
    fallbackNS: defaultNS,
    defaultNS,
    ns,
  }
}
// src/app/i18n/index.ts
import { createInstance, Namespace, FlatNamespace, KeyPrefix } from 'i18next'
import resourcesToBackend from 'i18next-resources-to-backend'
import { initReactI18next } from 'react-i18next/initReactI18next'
import { FallbackNs } from 'react-i18next'
import { getOptions } from './settings'

const initI18next = async (lng: string, ns: string | string[]) => {
  const i18nInstance = createInstance()
  await i18nInstance
    .use(initReactI18next)
    .use(resourcesToBackend((language: string, namespace: string) => import(`@/locales/${language}/${namespace}.json`)))
    .init(getOptions(lng, ns))
  return i18nInstance
}

type $Tuple<T> = readonly [T?, ...T[]];
type $FirstNamespace<Ns extends Namespace> = Ns extends readonly any[] ? Ns[0] : Ns;

export async function useTranslation<
  Ns extends FlatNamespace | $Tuple<FlatNamespace>,
  KPrefix extends KeyPrefix<FallbackNs<Ns extends FlatNamespace ? FlatNamespace : $FirstNamespace<FlatNamespace>>> = undefined
>(
  lng: string,
  ns?: Ns,
  options: { keyPrefix?: KPrefix } = {},
) {
  const i18nextInstance = await initI18next(lng, Array.isArray(ns) ? ns as string[] : ns as string)
  return {
    t: Array.isArray(ns) ? i18nextInstance.getFixedT(lng, ns[0], options.keyPrefix) : i18nextInstance.getFixedT(lng, ns as FlatNamespace, options.keyPrefix),
    i18n: i18nextInstance,
  }
}

Screenshot 2567-11-07 at 08 49 29

@adrai
Copy link
Member

adrai commented Nov 7, 2024

Then you have some other issue... if you do it here: https://github.com/i18next/next-app-dir-i18next-example-ts it works.

btw: these are Next.js specific questions... and what I've done here is just an example of how you can use i18next with Next.js app router setup...

@i-ked-ii
Copy link
Author

i-ked-ii commented Nov 11, 2024

It's working when app folder out src folder. I testing on this project https://github.com/i18next/next-app-dir-i18next-example-ts

You may need to change the middleware.ts to your needs... maybe a rewrite instead of a redirect is already sufficient?

- return NextResponse.redirect(new URL(`/${lng}${req.nextUrl.pathname}${req.nextUrl.search}`, req.url))
+ return NextResponse.rewrite(new URL(`/${lng}${req.nextUrl.pathname}${req.nextUrl.search}`, req.url))

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

2 participants