next-translations
v8.6.3
Published
Translations to NextJS app
Downloads
387
Maintainers
Keywords
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",
}