All side optimized Next.js translations

Example with a backend server

.
└── public
└── locales
├── en
| └── common.json
└── de
└── common.json

What to do to reach this step:

  1. in locize: signup at https://locize.app/register and login
  2. in locize: create a new project
  3. in locize: add all your additional languages (this can also be done via API)
  4. install the locize-cli (npm i locize-cli)

Use the locize-cli

Yes, let’s adapt for that:

// next-i18next.config.js
const LocizeBackend = require('i18next-locize-backend/cjs')
const ChainedBackend= require('i18next-chained-backend').default
const LocalStorageBackend = require('i18next-localstorage-backend').default
const isBrowser = typeof window !== 'undefined'module.exports = {
// debug: true,
i18n: {
defaultLocale: 'en',
locales: ['en', 'de', 'it'],
},
backend: {
backendOptions: [{
expirationTime: 60 * 60 * 1000 // 1 hour
}, {
projectId: 'd3b405cf-2532-46ae-adb8-99e88d876733',
version: 'latest'
}],
backends: isBrowser ? [LocalStorageBackend, LocizeBackend] : [],
},
serializeConfig: false,
use: isBrowser ? [ChainedBackend] : []
}
//
// Without the getStaticProps or getServerSideProps function,
// the translsations are loaded via configured i18next backend.
//
// export const getStaticProps = async ({ locale }) => {
// return {
// props: await serverSideTranslations(locale, ['common', 'footer'])
// }
// }

That’s it! Let’s check the result:

Additional hint:

// next-i18next.config.js
const LocizeBackend = require('i18next-locize-backend/cjs')
const isBrowser = typeof window !== 'undefined'module.exports = {
// debug: true,
i18n: {
defaultLocale: 'en',
locales: ['en', 'de', 'it'],
},
backend: isBrowser ? {
projectId: 'd3b405cf-2532-46ae-adb8-99e88d876733',
version: 'production'
} : undefined,
serializeConfig: false,
use: isBrowser ? [LocizeBackend] : []
}

Static Website example

Done so? Then let’s continue here:

// next-i18next.config.js
const LocizeBackend = require('i18next-locize-backend/cjs')
const ChainedBackend= require('i18next-chained-backend').default
const LocalStorageBackend = require('i18next-localstorage-backend').default
// If you've configured caching for your locize version, you may not need the i18next-localstorage-backend and i18next-chained-backend plugin.
// https://docs.locize.com/more/caching
const isBrowser = typeof window !== 'undefined'module.exports = {
// debug: true,
i18n: {
defaultLocale: 'en',
locales: ['en', 'de', 'it'],
},
backend: {
backendOptions: [{
expirationTime: 60 * 60 * 1000 // 1 hour
}, {
projectId: 'd3b405cf-2532-46ae-adb8-99e88d876733',
version: 'latest'
}],
backends: isBrowser ? [LocalStorageBackend, LocizeBackend] : [],
},
serializeConfig: false,
use: isBrowser ? [ChainedBackend] : []
}
export function makeStaticProps(ns = [], opt = {}) {
return async function getStaticProps(ctx) {
const props = await getI18nProps(ctx, ns)
if (opt.emptyI18nStoreStore) {
// let the client fetch the translations
props._nextI18Next.initialI18nStore = null
}
return {
props
}
}
}
const getStaticProps = makeStaticProps(['common', 'footer'], { emptyI18nStoreStore: true })
export { getStaticPaths, getStaticProps }

That’s it! Let’s check the result:

Continuous Localization

save missing translations

// next-i18next.config.js
const LocizeBackend = require('i18next-locize-backend/cjs')
const isBrowser = typeof window !== 'undefined'module.exports = {
// debug: true,
i18n: {
defaultLocale: 'en',
locales: ['en', 'de'],
},
backend: {
projectId: 'd3b405cf-2532-46ae-adb8-99e88d876733',
apiKey: '14bbe1fa-6ffc-40f5-9226-7462aa4a042f',
version: 'latest'
},
serializeConfig: false,
use: isBrowser ? [LocizeBackend] : [],
saveMissing: true // do not set saveMissing to true for production and also not when using the chained backend
}
<div>{t('new.key', 'this will be added automatically')}</div>

👀 but there’s more…

// next-i18next.config.js
const LocizeBackend = require('i18next-locize-backend/cjs')
const isBrowser = typeof window !== 'undefined'const locizeOptions = {
projectId: 'd3b405cf-2532-46ae-adb8-99e88d876733',
apiKey: '14bbe1fa-6ffc-40f5-9226-7462aa4a042f',
version: 'latest'
}
module.exports = {
// debug: true,
i18n: {
defaultLocale: 'en',
locales: ['en', 'de'],
},
backend: locizeOptions,
locizeLastUsed: locizeOptions,
serializeConfig: false,
use: isBrowser ? [LocizeBackend, require('locize').locizePlugin, require('locize-lastused/cjs')] : [], // do not use locize-lastused on production
saveMissing: true // do not set saveMissing to true for production and also not when using the chained backend
}

📦 Let’s prepare for production 🚀

// next-i18next.config.js
const LocizeBackend = require('i18next-locize-backend/cjs')
const isBrowser = typeof window !== 'undefined'const locizeOptions = {
projectId: 'd3b405cf-2532-46ae-adb8-99e88d876733',
apiKey: '14bbe1fa-6ffc-40f5-9226-7462aa4a042f',
version: 'latest'
}
module.exports = {
// debug: true,
i18n: {
defaultLocale: 'en',
locales: ['en', 'de'],
},
backend: locizeOptions,
locizeLastUsed: locizeOptions,
serializeConfig: false,
use: isBrowser ? [LocizeBackend, require('locize').locizePlugin, require('locize-lastused/cjs')] : [], // do not use locize-lastused on production
saveMissing: true // do not set saveMissing to true for production and also not when using the chained backend
}

🎉🥳 Congratulations 🎊🎁

👍

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Adriano Raiano

Adriano Raiano

founder of locize.com; Software Architect, Bachelor in Computer Science #serverless #nodejs #cqrs #ddd always in search for #innovative and #disruptive stuff