This package has been deprecated

Author message:

Package has been moved to https://www.npmjs.com/package/@nimpl/i18n

next-translation

1.0.3 • Public • Published

next-translation

npm version

Next Translation is an internationalization library for Next.js App Router.

Why one more library?

Server components are a recent feature in React. Existing translation libraries are not yet well-optimized for them. If they support it, then only by disabling Next.js static optimization.

This library is an attempt to create a highly optimized solution exclusively using the current capabilities of React.js, Next.js and node.js.

Features

Support for loading translations during page rendering (instead of the application build step), allowing for up-to-date translations with ISR or SSR;

Support for revalidation logic, i.e. you can specify how often translations should be updated (or that they should not be updated at all);

Optimized caching system - not a single extra request will be sent, even with parallel building (which is now enabled by default);

Passing only those translations to the client that are needed on the client;

Embedding parameters in client translations on the server;

Support for html entities.

Installation

Using npm:

npm i next-translation

Using yarn:

yarn add next-translation

Usage

NextTranslationProvider

It is recommended to use the configuring provider at the page level.

import NextTranlationProvider from 'next-translation/NextTranlationProvider'

export default function HomePage({ params }: { params: { lang: string } }) {
    return (
        <NextTranlationProvider lang={params.lang} clientTerms={['shared', 'banking.about']}>
            {/* ... */}
        </NextTranlationProvider>
    )
}

Client terms will be passed to the client. You can specify both namespaces and specific keys.

Note: Layout lives independently, so it needs to be wrapped in NextTranslationProvider separately.

Server components

Use getTranslation for simple translations

import getTranslation from 'next-tranlation/getTranslation';

const ServerComponent: React.FC = () => {
    const { t } = getTranslation();

    return (
        <div>
            {/* Welcome to Next Translation */}
            {t('header.nav.home')}
        </div>
    )
}

Use ServerTranslation to get complex translations

import ServerTranslation from 'next-tranlation/ServerTranslation';

const ServerComponent: React.FC = () => (
    <ServerTranslation
        term='intro.description' // We have {{number}} tariffs. Read more about pricings <link>special section</link>
        components={{
            link: <a href='#' />
        }}
        query={{ number: 5 }}
    />
)

Client components

The translations specified in NextTranslationProvider are passed to the client, but you can specify additional translations in any parent server component using NextTranslationTransmitter.

You can specify both namespaces and specific keys.

import NextTranslationTransmitter from 'next-tranlation/NextTranslationTransmitter';
import ClientComponent from './ClientComponent';

const ServerComponent: React.FC = () => (
    <NextTranslationTransmitter terms={['header.nav']}>
        <ClientComponent />
    </NextTranslationTransmitter>
)

Use useTranslation for simple translations

"use client";

import useTranslation from 'next-tranlation/useTranslation';

const ClientComponent: React.FC = () => {
    const { t } = useTranslation();

    return (
        <div>
            {/* Welcome to Next Translation */}
            {t('header.nav.home')}
        </div>
    )
}

Use ClientTranslation for complex translations

"use client";

import ClientTranslation from 'next-tranlation/ClientTranslation';

const ClientComponent: React.FC = () => (
    <ClientTranslation
        term='intro.description' // We have {{number}} tariffs. Read more about pricings <link>special section</link>
        components={{
            link: <a href='#' />
        }}
        query={{ number: 5 }}
    />
)

Other

Use createTranslation to get a simple translation outside the page tree.

import createTranslation from 'next-translation/createTranslation'
// ...
export async function generateMetadata({ params }: { params: { lang: string } }) {
    const { t } = await createTranslation(params.lang);
    return {
        title: t('homePage.meta.title'),
    }
}

Options

You can pass opts as the second argument of t.

Now you can pass a query there to inject variable strings inside translations.

const Component: React.FC = () => {
    return (
        <div>
            {/* Price starts from ${{price}} */}
            {t('pricing.tariffs.solo', { query: { price: 16.99 } })}
        </div>
    )
}

Also you can inject query to client terms on the server side. For example, when they depend on the server environment or when you get values from a database on the server.

Just add an array value instead of a string in terms arr, where the second element will be the query object.

import NextTranslationTransmitter from 'next-tranlation/NextTranslationTransmitter';
import ClientComponent from './ClientComponent';

const ServerComponent: React.FC = () => (
    <NextTranslationTransmitter terms={[['home.welcome', { stage: process.env.GITHUB_REF === 'main' ? 'production' : 'test' }]]}>
        <ClientComponent />
    </NextTranslationTransmitter>
)

Configuration

Config file

Create next-translation.js file in the root directory

/** @type {import('next-translation/configuration/types').Config} */
module.exports = {
    load: async (lang) => {
        const resp = await fetch(`https://api.translation-example.com/terms/${lang}`, {
            method: 'POST',
        });
        const data = await resp.json();
        return { data, meta: {} };
    },
    languages: ['en', 'de', 'fr'],
    revalidate: 3600,
    checkIsActual: async (lang, lastLoadMeta) => {
        // ...
    },
    retryAttempts: 2,
};

Options

load [required]

Asynchronous function for translates loading.

Function will receive 2 arguments:

key - current language;

meta - meta data from previous request.

Function should return object with keys:

data - object with translates;

meta - object with additional data which will be passed to the next load.

Don't combine next.js fetch caching with the next-translation load caching, it will repeat the logic and may not work correctly.

languages [required]

Array of allowed languages. Languages outside of this array will be ignored.

revalidate [optional]

Option works similarly to the next.js option. Setting it to false will disable revalidation, meaning the data will be cached indefinitely. Setting it to 0 will request the data each time, while setting it to a number will determine the time in seconds for revalidation to occur.

retryAttempts [optional]

Number of retries when loading data (3 by default)

checkIsActual [optional]

Check that the data is up to date. Use it when you can perform additional steps to ensure that cached data is up to date. For example, make a HEAD request with meta information, or check the meta on a different route. Option type:

(key: string, meta?: { [key: string]: string }) => Promise<boolean>

where:

key - target language

meta - meta information returned from the load function

Configure app

You also need to configure the environment for correct caching to work, for this you need to wrap your next.config.js in withNextTranslation

const withNextTranslation = require('next-translation/withNextTranslation').default;

/** @type {import('next').NextConfig} */
const nextConfig = {};

module.exports = async (phase) => {
    const withTranslation = await withNextTranslation(phase);
    return withTranslation(nextConfig);
}

Note: the library does not modify the webpack or application configuration, it only configures the process.

App organization

Pages structure

app
    [lang]
        page-name
            page.tsx
        page.tsx
        layout.tsx
    (root)
        page-name
            page.tsx
        page.tsx
        layout.tsx

Why so?

You can only create one root layout. In the root (/app) we don't know the language, so we can't add a lang attribute there on the server side.

Therefore, the only way to do it is to create a root layout for localized pages in the [lang] folder.

// /app/[lang]/layout.tsx
type RootLayoutProps = { children: React.ReactNode; params: { lang: string } }

export default function RootLayout({ children, params }: RootLayoutProps) {
  return (
    <html lang={params.lang}>
      <body>{children}</body>
    </html>
  )
}

Additionally

Create tasks with wishes, ideas, difficulties, etc. All of them will definitely be considered and thought over.

License

MIT

Package Sidebar

Install

npm i next-translation

Weekly Downloads

6

Version

1.0.3

License

MIT

Unpacked Size

40.8 kB

Total Files

36

Last publish

Collaborators

  • vordgi