npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

next-translations

v8.6.3

Published

Translations to NextJS app

Downloads

387

Readme

next-translations

Thanks to this package you will be able to add to your website written in NextJS to download/manage translations on your website! Thanks to this package you will be able to build a very efficient website that will have generated pages WITH nested translations!. Powerful package also for STATIC and SERVER SIDE RENDERING sites in NextJS! Works without i18n!

install translations

npm i next-translations

translations.config.js - you need to add this config file to your project

| Parameter | Type | Default | Description | | :------------------------------- | :----------------------------------------------------------------- | :------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | defaultLocale | string | 'en' | Required. The default language on your site | | locales | string[] | ['en'] | Required. All available languages on your website. | | sitesForLoggedUser | string[] | [] | All paths available ONLY for the active session | | sitedForLoggedAndNotLoggedUser | string[] | [] | All paths available for the all sessions | | redirectForLoggedUser | string | '/' | Redirects the user when on a route for non-logged in users | | redirectForNotLoggedUser | string | '/' | Redirects the user when in the route for logged in users | | errorPagePath | string | '/404' | Showing if we have a custom link to the error page so that unnecessary redirects are not made | | outputFolderTranslations | string | '/public/locales' | The path to your translations. NOTE: If you download translations using next-translations, they will be saved to the given address. For the site to work properly, they must be in the /public folder. | | defaultLocaleWithMultirouting | boolean | undefined | The language to be excluded from multi routing. For example, we want /index.js to have the language from defaultLocale prop, then it should be substituted into this variable. Other languages (if any) will be available in /pages/[locale] | | constNamespaces | string[] | ['common'] | These are all the namespaces we use throughout the project so as not to define them on every page. | | componentNameToReplaced | string | 'TComponent' | The name of the component in translations that will be captured and replaced in tComponent. | | namespacesToFetch | string[] | ['common'] | All the namespaces you want to fetch during link Fetch Translations | | linkFetchTranslations | (version: string, language: string, namespace: string) => string | undefined | A function to download our translations from the api. It is called every time it wants to load a given translation in a given language and namespace. The function returns single values that we entered in the fields: locales, namespaces. To return, we need to return a link to our api, e.g. return https://your-api-to-download-translations/${version}/${language}/${namespace} Note: if you add NEXT_PUBLIC_NEXT_TRANSLATIONS_APP_ENV to your .env file then you can access the version of the page, e.g.: dev, int, prd etc.. |

configuration

Attention! To avoid a translation error when building a page, add getTranslationsProps to each page! If you don't have these pages, you may get messages about no translation!

  • /404
  • /500
  • /offline

example translations in /public/locales/en/common.json

{
  "section":{
    "title": "Example title in your site!"
  }
}

/pages/_app.tsx for STATIC SITES and SERVER SIDE RENDERING

import { initializeTranslations } from "next-translations/hooks";
import { InitializeRedirectsTranslations, validLink } from "next-translations/redirects";
import type { AppProps } from "next/app";
import { useEffect } from "react";
import { useRouter } from "next/router";

export default function App({ Component, pageProps }: AppProps) {

  // add this line
  initializeTranslations(pageProps?.translations);

  // add this lint if you want to use redirects: sitesForLoggedUser.
  // You can add this in user context for example.
  InitializeRedirectsTranslations({
    isLoggedUser: true, // true or false for STATIC PAGES. Attention! if isLoggedUser is undefined then no redirects are performed!
    isLoggedUser: pageProps?.isLoggedUser || false, // for SERVER SIDE RENDERING pages. Attention! if isLoggedUser is undefined then no redirects are performed!
    enable: true, // default is true. Checks if routing can be done on the page. If it's false, it doesn't do routing.
    withQuery: true, // default is true. Listens for query during redirects
    withHash: true, // default is true. Listens for hash during redirects
  });

  //example
  InitializeRedirectsTranslations({
    isLoggedUser: !!user,
    enable: user !== undefined,
    withQuery: true,
    withHash: false,
  });

  //checking routes and return valid route
  useEffect(() => {
    if (!router.isReady) {
      return;
    }

    let queryValue = "";
    if (window.location.search.length > 0) {
      const splitQuery = window.location.search.split("?");
      const getQueryValue = splitQuery.at(1);
      if (getQueryValue) {
        queryValue = getQueryValue;
      }
    }

    let hashValue = "";
    if (window.location.hash.length > 0) {
      const splitHash = window.location.hash.split("#");
      const getHashValue = splitHash.at(1);
      if (getHashValue) {
        hashValue = getHashValue;
      }
    }

    // works in the same way as page redirects. If the user does not have access to a given subpage, he will return a link to the subpage to which he has based on the config
    const result = validLink({
      isLoggedUser: false, // checking if the user is logged in
      locale: "en", // the locale we want to change to. If is undefined, the locale is selected based on the currently used one
      path: "/user", // path where we want to generate the link. If is undefined, the locale is selected based on the currently used one
      router: router, // need to add router from nextjs
      query: queryValue, // query to your link.
      hash: hashValue, // hash to your link
    });
  }, [router, user]);

  return (
    <main>
        <Component {...pageProps} />
    </main>
  );
}

/pages/yourPath.tsx - for STATIC SITES

Note: if you don't have defaultLocaleWithMultirouting defined, then you MUST keep content in /pages/[locale]/yourPath.tsx, otherwise you will only have the language that was set as defaultLocale!

import { getTranslationsProps } from "next-translations";
import { useTranslation } from "next-translations/hooks";
import { GetStaticProps } from "next";

function Home() {
  const { t, pageTranslations } = useTranslation("common"); // enter the given namespace that you use in the given section
  const { t, pageTranslations } = useTranslation("common:section"); // if you want you can also refer to namespace, along with nested elements - 1 example
  const { t, pageTranslations } = useTranslation("common.section"); // if you want you can also refer to namespace, along with nested elements - 2 example

  // t -> thanks to this function, you can download a given text/object/array at your discretion - just like you have downloaded/added in translations

  // pageTranslations -> all translations that are available on this subpage

  return (
    <div>
      t("section.title") // downloading translation - without nested elements
      t("title") // downloading translation - if you using nested elements
    </div>
  );
}

export const getStaticProps: GetStaticProps = async ctx => {
  const translationsProps = await getTranslationsProps(ctx, ["common"]); // add here all translations in string[] that you use on this subpage

  // you have access to:
  // ctx.locale - current locale
  // ctx.locales - all locales
  // ctx.defaultLocale - default locale

  return {
    props: {
      ...translationsProps,
    },
  };
}

export default Home;

/pages/yourPath.tsx - for SERVER SIDE RENDERING

Note: if you don't have defaultLocaleWithMultirouting defined, then you MUST keep content in /pages/[locale]/yourPath.tsx, otherwise you will only have the language that was set as defaultLocale!

import { getTranslationsPropsServer } from "next-translations/server";
import { useTranslation } from "next-translations/hooks";
import { GetServerSideProps } from "next";

function Home() {
  const { t, pageTranslations } = useTranslation("common"); // enter the given namespace that you use in the given section
  const { t, pageTranslations } = useTranslation("common:section"); // if you want you can also refer to namespace, along with nested elements - 1 example
  const { t, pageTranslations } = useTranslation("common.section"); // if you want you can also refer to namespace, along with nested elements - 2 example

  // t -> thanks to this function, you can download a given text/object/array at your discretion - just like you have downloaded/added in translations

  // pageTranslations -> all translations that are available on this subpage

  return (
    <div>
      t("section.title") // downloading translation - without nested elements
      t("title") // downloading translation - if you using nested elements
    </div>
  );
}


export const getServerSideProps: GetServerSideProps = async ctx => {
  let translatesProps = null;
  const translationsNamespaces = [namespaces.account];

  if (process.env.NODE_ENV === "development") {
    translatesProps = await getTranslationsProps(ctx, translationsNamespaces);  // add here all translations in string[] that you use on this subpage
  } else {
    translatesProps = await getTranslationsPropsServer(  // add here all translations in string[] that you use on this subpage
      ctx,
      translationsNamespaces,
    );
  }

  // you have access to:
  // ctx.locale - current locale
  // ctx.locales - all locales
  // ctx.defaultLocale - default locale

  return {
    props: {
      ...translatesProps,
      isLoggedUser: true, // or false, add this prop if you want to use redirects: sitesForLoggedUser
    },
  };
};

export default Home;

/pages/[locale]/yourPath.tsx - for STATIC SITES

import { getTranslationsProps, getStaticPaths, getPaths } from "next-translations"; // add getStaticPaths only if you using: export { getStaticPaths }, if you using getStaticPaths from next - dont add this import!
import { useTranslation } from "next-translations/hooks";
import { GetStaticProps, GetStaticPaths } from "next";

function Home() {
  const { t, pageTranslations } = useTranslation("common"); // enter the given namespace that you use in the given section
  const { t, pageTranslations } = useTranslation("common:section"); // if you want you can also refer to namespace, along with nested elements - 1 example
  const { t, pageTranslations } = useTranslation("common.section"); // if you want you can also refer to namespace, along with nested elements - 2 example

  // t -> thanks to this function, you can download a given text/object/array at your discretion - just like you have downloaded/added in translations

  // pageTranslations -> all translations that are available on this subpage

  return (
    <div>
      t("section.title") // downloading translation - without nested elements
      t("title") // downloading translation - if you using nested elements
    </div>
  );
}

export const getStaticProps: GetStaticProps = async ctx => {
  const translationsProps = await getTranslationsProps(ctx, ["common"]); // add here all translations in string[] that you use on this subpage

  // you have access to:
  // ctx.locale - current locale
  // ctx.locales - all locales
  // ctx.defaultLocale - default locale

  return {
    props: {
      ...translationsProps,
    },
  };
}


export { getStaticPaths }; // IMPORTANT ADD THIS LINE TO ENABLE MULTI ROUTING


//ALTERNATIVE with Nextjs getStaticPaths - if you using this, don't impoty getStaticPaths from next-translations

export const getStaticPaths: GetStaticPaths = async () => { // IMPORTANT ADD THIS LINE TO ENABLE MULTI ROUTING (alternative)
  return {
    fallback: false,
    paths: getPaths(),
  };
}

export default Home;

/pages/[locale]/yourPath.tsx - for SERVER SIDE RENDERING

Attention! You manage the site's languages via slug! eg: /en/home - page with en language, /pl/home - page with pl language

import { getTranslationsPropsServer } from "next-translations/server";
import { useTranslation } from "next-translations/hooks";
import { GetServerSideProps } from "next";

function Home() {
  const { t, pageTranslations } = useTranslation("common"); // enter the given namespace that you use in the given section
  const { t, pageTranslations } = useTranslation("common", true); // translations without log errors
  const { t, pageTranslations } = useTranslation("common:section"); // if you want you can also refer to namespace, along with nested elements - 1 example
  const { t, pageTranslations } = useTranslation("common.section"); // if you want you can also refer to namespace, along with nested elements - 2 example

  // t -> thanks to this function, you can download a given text/object/array at your discretion - just like you have downloaded/added in translations

  // pageTranslations -> all translations that are available on this subpage

  return (
    <div>
      t("section.title") // downloading translation - without nested elements
      t("title") // downloading translation - if you using nested elements
    </div>
  );
}

export const getServerSideProps: GetServerSideProps = async ctx => {
  let translatesProps = null;
  const translationsNamespaces = [namespaces.account];

  if (process.env.NODE_ENV === "development") {
    translatesProps = await getTranslationsProps(ctx, translationsNamespaces); // add here all translations in string[] that you use on this subpage
  } else {
    translatesProps = await getTranslationsPropsServer( // add here all translations in string[] that you use on this subpage
      ctx,
      translationsNamespaces,
    );
  }

  // you have access to:
  // ctx.locale - current locale
  // ctx.locales - all locales
  // ctx.defaultLocale - default locale

  return {
    props: {
      ...translatesProps,
      isLoggedUser: true, // or false, add this prop if you want to use redirects: sitesForLoggedUser
    },
  };
};

export default Home;

useTranslation - all functions

const { t, tString, tNumber, tArray, tObject, tComponent, pageTranslations } = useTranslation("common"); // enter the given namespace that you use in the given section
const { t, pageTranslations } = useTranslation("common:section"); // if you want you can also refer to namespace, along with nested elements - 1 example
const { t, pageTranslations } = useTranslation("common.section"); // if you want you can also refer to namespace, along with nested elements - 2 example

pageTranslations // all translations that are available on this subpage

t("section.text1"); // if there is a translation, it returns it as any, if not, it returns undefined

tString("section.text2"); // if there is a translation and it has a string type, it returns it as string, if it doesn't find it, or it has the wrong type, it returns undefined.

tNumber("section.text3"); // if there is a translation and it has a number type, it returns it as number, if it doesn't find it, or it has the wrong type, it returns undefined.

tArray("section.text4"); // if there is a translation and it has a any[] type, it returns it as any[], if it doesn't find it, or it has the wrong type, it returns undefined.

tObject("section.text5"); // if there is a translation and it has a object type, it returns it as object, if it doesn't find it, or it has the wrong type, it returns undefined.


//if there is a translation and it has type string, if it doesn't find it or it has wrong type it returns undefined. If it contains <TComponent> value </TComponent> or <TComponent/>, you can create your own component based on the values returned from the callback. **Note** the text inside <TComponent> must be separated by a space between <TComponent> and </TComponent>!!!!! Example of correct implementation:
{
  "title": "example paragraph <TComponent> xxxx sad </TComponent> paragraph"
}
tComponent(
  "section.textLink",
  ({ textBefore, textComponent, textAfter, text }) => { // value from callback to create your own component. text is returned when it doesn't find a TComponent inside the text
    return (
      <div>
        <p>{textBefore}</p>
        <Link href="/">{textComponent}</Link>
        <p>{textAfter}</p>
      </div>
    );
  },
);

Avaible types

// import type {T_t, T_tString, T_tNumber, T_tArray, T_tObject, T_tComponent} from "next-translations/hooks"

- T_t
- T_tString
- T_tNumber
- T_tArray
- T_tObject
- T_tComponent

package.json

"scripts": {
    "getTranslations": "node node_modules/next-translations/getTranslations", // script to fetch all translations from your api **linkFetchTranslations**
    "dev": "npm run getTranslations && next dev",
    "build": "npm run getTranslations && next build",
}