Skip to content

Instantly share code, notes, and snippets.

@acewf
Last active September 2, 2019 11:22
Show Gist options
  • Save acewf/e7f183a0cbc38b6dcd6581bdc10ed9ee to your computer and use it in GitHub Desktop.
Save acewf/e7f183a0cbc38b6dcd6581bdc10ed9ee to your computer and use it in GitHub Desktop.
gatsby i18next localisation for static pages
// load your translations
// add whatever number namespaces you need
const localesNSContent = {
'en':[
{
content:fs.readFileSync(`src/locales/en/translations.json`, 'utf8'),
ns:'translations'
}
],
'pt':[
{
content:fs.readFileSync(`src/locales/pt/translations.json`, 'utf8'),
ns:'translations'
}
],
};
const availableLocales = [
{ value: 'en', text: 'English' },
{ value: 'de', text: 'Deutsch' }
]
exports.onCreatePage = async (props) => {
const { page, actions: { createPage, deletePage, createRedirect } } = props;
deletePage(page);
if (page.path.includes('404')) {
createPage({
...page,
context: {
locale: 'en-us',
data: localesNSContent['en-us']
}
})
}
if (page.path === '/') {
createPage({
...page,
context: {
availableLocales
}
});
} else {
availableLocales.map(({ value }) => {
let newPath = `/${value}${page.path}`;
if (page.path === '/homepage/') {
newPath = `/${value}`
}
const localePage = {
...page,
originalPath: page.path,
path: newPath,
context: {
availableLocales,
locale: value,
routed: true,
data: localesNSContent[value],
originalPath: page.path
},
}
createPage(localePage)
});
}
}
// file location could be src/i18n/index.js
import i18n from "i18next"
export const defaultLocale = 'en'
export const defaultNamespace = 'translations'
export const options = {
fallbackLng: defaultLocale,
ns: [defaultNamespace],
defaultNS: defaultNamespace,
debug: true,
interpolation: {
escapeValue: false, // not needed for react!!
},
react: {
wait: true,
}
}
export default () => {
i18n.init(options);
return i18n;
}
// file location should be src/pages/page-2.js
import React from 'react'
import { Link } from 'gatsby'
import Layout from '../components/layout'
import SEO from '../components/seo'
import withI18next from '../components/withI18next'
const SecondPage = ({ pageContext: { locale }, t }) => {
return (
<Layout>
<SEO title="Page two" />
<h1>{t('title')}</h1>
<p>Welcome to page 2</p>
<p>{'login'}</p>
<Link to={`/${locale}/`}>Go back to the homepage</Link>
</Layout>
)
}
export default withI18next({ ns: 'translations' })(SecondPage);
// file location could be src/components/withI18next.js
import React, { Component } from 'react';
import { I18nextProvider } from 'react-i18next';
import { I18nProvider } from 'gatsby-i18n';
import { I18n } from 'react-i18next';
// import from /src/i18n/index.js
import setupI18next from '../i18n';
const lngFormat = (locale) => (locale.replace(/-[a-z]{2}$/, e => (e.toUpperCase())))
const withI18next = (options = {}) => Comp => {
class I18nHOC extends Component {
constructor(props) {
super(props);
const { pageContext, data } = props;
this.state = {
...options,
data: (data) ? data : pageContext.data
}
this.i18n = setupI18next(pageContext);
this.activateLng();
}
activateLng = () => {
const { pageContext } = this.props;
const { data, parserMethod } = this.state;
this.parseFromContext(data);
this.i18n.changeLanguage(lngFormat(pageContext.locale));
};
parseFromContext = (data) => {
const { pageContext } = this.props;
if (data) {
const lng = lngFormat(pageContext.locale);
data.forEach(({ ns = 'translations', content }) => {
if (!this.i18n.hasResourceBundle(lng, ns)) {
this.i18n.addResources(lng, ns, content);
}
});
}
}
componentDidUpdate(prevProps) {
if (this.props.pageContext.locale !== prevProps.pageContext.locale) {
this.activateLng();
}
}
render() {
const { ns } = this.state;
return (
<I18nextProvider i18n={this.i18n} defaultNS={ns}>
<I18nProvider {...this.props.pageContext}>
<I18n>
{t => (
<Comp {...this.props} t={t} locale={this.props.pageContext.locale} />
)}
</I18n>
</I18nProvider>
</I18nextProvider>
);
}
}
return I18nHOC;
};
export default withI18next;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment