We use the MDXJS package to write content in Markdown and use React components in it.
Is there a way of using the i18next / react-i18next package inside the MDX / Markdown files?
We use the MDXJS package to write content in Markdown and use React components in it.
Is there a way of using the i18next / react-i18next package inside the MDX / Markdown files?
i18next
inside MDX
:When you import an MDX
file, you just use it as any other React component:
import { default as SomeContent } from './some-content.mdx';
...
<SomeContent />
Therefore, you can also pass down some props, in this case the t
function, and use it inside in some specific ways:
import { default as SomeContent } from './some-content.mdx';
export const SomeComponent: React.FC = React.memo((props) => {
const { t } = useTranslation();
return (
<SomeContent t={ t } someProp="Some value" />
);
});
If you want to check if this is working or see which props are accessible from within your MDX
file, add this inside it:
<pre>{ JSON.stringify(props, null, ' ') }</pre>
<pre>{ typeof props.t }</pre>
For the example above, it will display:
{"someProp":"Some value"}
function
Note that you can't use these props inside "raw" MD
elements, even if you add a wrapper around them:
### Doesn't work: { props.t('some.translation') }
Doesn't work: { props.t('some.translation') }.
Doesn't work: <>{ props.t('some.translation') }</>.
Doesn't work: <Fragment>{ props.t('some.translation') }</Fragment>.
Doesn't work: <span>{ props.t('some.translation') }</span>.
So you would have to write HTML
tags instead:
<h3>Works: { props.t('some.translation') }</h3>
<p>Works: { props.t('some.translation') }.</p>
<p>Works: <>{ props.t('some.translation') }</>.</p>
<p>Works: <Fragment>{ props.t('some.translation') }</Fragment>.</p>
<p>Works: <span>{ props.t('some.translation') }</span>.</p>
MDX
in i18next
:If you set returnObjects: true
in your i18next
config, you can also add MDX
components inside your translation files:
import { default as ContentEN } from './content.en.mdx';
import { default as ContentES } from './content.es.mdx';
i18next.use(initReactI18next).init({
resources: {
en: {
translation: {
content: ContentEN,
},
},
es: {
translation: {
content: ContentES,
},
},
},
returnObjects: true,
}));
And then you would use it like this in any of your components (and yes, you can also pass down t
or any other prop, just as before:
export const SomeComponent: React.FC = React.memo((props) => {
const { t } = useTranslation();
const Content = t('content');
return (
<Content t={ t } someProp="Some value" />
);
});
i18next
inside @mdx-js/runtime
:If you are using @mdx-js/runtime
, then you would pass down your props as scope
:
import { default as SomeContent } from './some-content.mdx';
export const SomeComponent: React.FC = React.memo((props) => {
const { t } = useTranslation();
return (
<MDX components={ ... } scope={ { t, someProp: 'Some value' } }>{ props.mdx }</MDX>
);
});