next-international

repository·main·Indexed 23 days ago

https://github.com/quiibz/next-international

Type-safe internationalization (i18n) for Next.js supporting App Router, Pages Router, and Static Rendering. It provides 100% type-safety for translation functions, parameters, and plurals without requiring Webpack setup or a CLI. Key features include scoped translations via useScopedI18n and getScopedI18n, locale management with useChangeLocale and getCurrentLocale, and flexible URL mapping strategies (redirect, rewrite, rewriteDefault) via middleware.

Tokens
15.8K
Snippets
45
Records
77
Agent score
79%

What's inside next-international

  1. Overview of next-international

    main

    next-international is a type-safe internationalization (i18n) library designed specifically for Next.js. It provides a developer experience focused on type safety for translation keys, scopes, parameters, and plurals without requiring a CLI, code generation, or complex Webpack configurations.

    Key features include:

    • 100% Type-safety: Type-safe t(), scopedT(), parameters, plurals, and changeLocale().
    • Lightweight: No dependencies and supports lazy-loading.
    • Flexible Rendering: Supports Server Components, Client Components, and Static Rendering.
    • Router Support: Compatible with both Next.js App Router and Pages Router.
  2. How plural suffix type safety works

    main

    The count parameter is mandatory for plural keys. The type safety for the count value is derived from the union of the suffixes you define in your locale file:

    • zero: Specifically allows the value 0.
    • one: Autocompletes values like 1, 21, 31, etc., but accepts any number.
    • two: Autocompletes values like 2, 22, 32, etc., but accepts any number.
    • few, many, and other: Allow any number.
  3. Key features of next-international

    main

    The library offers several core benefits for Next.js developers:

    • 100% Type-safety: Provides type-safe functions for t(), scopedT(), parameters, plurals, and changeLocale(). Works with locales defined in either TypeScript or JSON.
    • Zero Configuration: No Webpack setup or CLI required; it relies on pure TypeScript.
    • Performance: Small footprint, no dependencies, and supports lazy-loading for both server and client sides.
    • Next.js Compatibility: Full support for App Router, Pages Router, and Static Rendering.
  4. Configure I18nProviderClient in Next.js App Router

    main

    In the Next.js App Router, move your routes into an app/[locale]/ directory. To enable translations in Client Components, wrap your component tree with I18nProviderClient within a layout file.

    Note: For Next.js 15+, params is a Promise and must be awaited.

    // app/[locale]/client/layout.tsx
    import { ReactElement } from 'react'
    import { I18nProviderClient } from '../../locales/client'
    
    export default async function SubLayout({ params, children }: { params: Promise<{ locale: string }>, children: ReactElement }) {
      const { locale } = await params
    
      return (
        <I18nProviderClient locale={locale}>
          {children}
        </I18nProviderClient>
      )
    }
  5. Get and change the locale using hooks

    main

    To access and manipulate the current language in your application, export useChangeLocale and useCurrentLocale from your createI18n configuration file.

    • useCurrentLocale(): A hook that returns the current active locale string.
    • useChangeLocale(): A hook that returns a function used to switch the application's locale by passing the new locale identifier as an argument.
    // locales/index.ts
    export const {
      useChangeLocale,
      useCurrentLocale,
      ...
    } = createI18n({
      ...
    })
    
    // In your component
    import { useChangeLocale, useCurrentLocale } from '../locales'
    
    export default function Page() {
      const changeLocale = useChangeLocale()
      const locale = useCurrentLocale()
    
      return (
        <>
          <p>Current locale: {locale}</p>
          <button onClick={() => changeLocale('en')}>English</button>
          <button onClick={() => changeLocale('fr')}>French</button>
        </>
      )
    }
  6. Override the user's locale resolution

    main

    You can customize how the locale is determined from an incoming request by providing a resolveLocaleFromRequest function to createI18nMiddleware.

    By default, the middleware attempts to extract the locale from the Accept-Language header. Providing this function allows you to implement custom logic to force a specific locale.

    Note: This function is only invoked if the user does not already have a Next-Locale cookie set.

    // middleware.ts
    const I18nMiddleware = createI18nMiddleware({
      locales: ['en', 'fr'],
      defaultLocale: 'en',
      resolveLocaleFromRequest: request => {
        // Do your logic here to resolve the locale
        return 'fr'
      }
    })
  7. Translate text using useI18n and useScopedI18n

    main

    Use the useI18n hook for top-level translations and useScopedI18n to create a scoped translation function for a specific key prefix.

    Both hooks support:

    • Dot notation: Accessing nested keys (e.g., t('hello.world')).
    • Interpolation: Passing variables into strings using {key} syntax. You can pass both strings and React elements (like <strong>) as interpolation values.
    // pages/index.ts
    import { useI18n, useScopedI18n } from '../locales'
    
    export default function Page() {
      const t = useI18n()
      const scopedT = useScopedI18n('hello')
    
      return (
        <div>
          <p>{t('hello')}</p>
    
          {/* Both are equivalent: */}
          <p>{t('hello.world')}</p>
          <p>{scopedT('world')}</p>
    
          <p>{t('welcome', { name: 'John' })}</p>
          <p>{t('welcome', { name: <strong>John</strong> })}</p>
        </div>
      )
    }
  8. Explore next-international examples

    main

    Complete implementation examples for next-international are available in the repository's example directories. You can find specific implementations for both the Next.js Pages Router and the App Router:

    • Next.js Pages Router: See examples/next-pages in the GitHub repository.
    • Next.js App Router: See examples/next-app in the GitHub repository.

    For a live, interactive environment using the App Router, you can use the provided CodeSandbox template.

  9. Set up a custom render for testing

    main

    To test components that use next-international, you must create a custom render function. This allows you to wrap your components in necessary providers (like I18nProvider) during testing. The following implementation uses @testing-library/react and is compatible with both Vitest and Jest.

    // customRender.tsx
    import { ReactElement } from 'react'
    import { cleanup, render } from '@testing-library/react'
    import { afterEach } from 'vitest'
    
    afterEach(() => {
      cleanup()
    })
    
    const customRender = (ui: ReactElement, options = {}) =>
      render(ui, {
        // wrap provider(s) here if needed
        wrapper: ({ children }) => children,
        ...options,
      })
    
    export * from '@testing-library/react'
    export { default as userEvent } from '@testing-library/user-event'
    export { customRender as render }