i18n Slides for tech speakers
If you are a developer who likes to share what you learn probbaly, you like to do it in local meetups or in big conferences either way your slides are a great asset to share content, but it's only accesible to people who know the language your slides are writen.
Another topic that will make you would like to keep reading is that speaking about code it implies share code, that in the most slide's making software is kinda weak.
If we are developers let's code our slides internationalized.
Tools
We are going to use:
- mdx-deck
- i18next
- react-i18next
Process
Let's create a new folder an a new npm project on it
kmdir slides && cd slides
and
npm init -y
Installing dependencies
npm i mdx-deck i18next react-i18next
Create project structure
Now we need to create a /src
folder with our code base
mkdir src src/translations src/components src/docs
and our main file:
touch src/deck.mdx
Running our project
Now that we have our dependencies and de entire project structure let's configure our scripts in order to execute our project:
{
"name": "slides",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"i18next": "^19.4.4",
"mdx-deck": "^4.1.1",
"mdx-deck-code-surfer": "^0.5.5",
"react-i18next": "^11.4.0"
},
"devDependencies": {},
"scripts": {
"dev": "mdx-deck ./src/deck.mdx",
"build": "mdx-deck build ./src/deck.mdx",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Now everything is settup add the next content to your deck.mdx
file:
# Welcome to mdx-deck
---
## this is a mix of markdown and React
Since we are using mdx you can write on this file md tags or react components imported on our deck.mdx
file like the next one:
// ./src/components/Counter.js
import React, { useState } from "react";
function Counter() {
const [counter, setCounter] = useState(0);
return (
<div>
<button onClick={() => setCounter(counter - 1)}>-</button>
<h3>{counter}</h3>
<button onClick={() => setCounter(counter + 1)}>+</button>
</div>
);
}
export default Counter;
Once you create your Counter component, update your deck.mdx
file for it to use it:
import Counter from "./components/Counter";
# Welcome to mdx-deck
<Counter />
---
## this is a mix of markdown and React
With the Counter component render we should be something like this in our first slide:
Layout
Once last thing for you to know about mdx-deck it's their new layout system with their own built in components: Head
, Header
and Footer
.
If you want to add metadata and SEO related stuff to your project you can use the Head
component directly in your :
<Head>
<title>My Presentation</title>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@jossdz" />
<meta name="twitter:title" content="My Presentation" />
<meta name="twitter:description" content="A really great presentation" />
<meta name="twitter:image" content="https://example.com/card.png" />
</Head>
If what you want is display persistent content across slides what you want to use is the Header
and Footer
components, as Head
you can import both from mdx-deck-
package and use it directly in your deck.mdx
file:
import Counter from "./components/Counter";
import { Head, Header, Footer } from "mdx-deck";
<Head>
<title>My Presentation | @jossdz</title>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@jxnblk" />
<meta name="twitter:title" content="My Presentation" />
<meta name="twitter:description" content="A really great presentation" />
<meta name="twitter:image" content="https://example.com/card.png" />
</Head>
<Header>
## i18n slides
</Header>
<Footer>
@jossdz
</Footer>
# Welcome to mdx-deck
<Counter />
---
## this is a mix of markdown and React
Adding i18n
Let's add i18next, for this part you'll need a i18n
file and as muchs json files as you want for each language(for me will be enough with en
and es
):
touch src/i18n.js src/translations/es.json src/translations/en.json
in our i18n
file we need to place the i18next
config:
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import en from "./translations/en.json";
import es from "./translations/es.json";
i18n.use(initReactI18next).init({
lng: "en",
resources: {
en,
es,
},
});
export default i18n;
for the [lang].json files the structure shuold be like follows:
{
"translation": {
"key": "hello world",
"list": ["item1", "item2", "item3", "item4"]
}
}
If we want to make this configuration aplied to our site we neet to import our file i18n
in our deck, this import can be placed at the top of the file:
import "./i18n"
import Counter from "./components/Counter";
import { Head, Header, Footer } from "mdx-deck";
Now we can create the components to show out content based on the default language and to change our language:
touch src/components/IntlContent.js src/components/ChangeLang.js
-
src/components/IntlContent.js
// import the useTranslation hook from react-i18next
import { useTranslation } from "react-i18next";
import React from "react";
const IntlContent = ({ label, htmlElement }) => {
// then extract the 't' funtion to get the translation based on a key in our translation json
const { t } = useTranslation();
switch (htmlElement) {
case "h1":
return <h1>{t(label)}</h1>;
case "h2":
return <h2>{t(label)}</h2>;
case "h3":
return <h3>{t(label)}</h3>;
case "h4":
return <h4>{t(label)}</h4>;
case "ul":
const elements = t("list", { returnObjects: true });
return (
<ul>
{elements.map((el, i) => (
<li key={i}>{el}</li>
))}
</ul>
);
default:
return <p>{t(label)}</p>;
}
};
export default IntlContent;
-
src/components/IntlContent.js
import React from "react";
import { useTranslation } from "react-i18next";
function ChangeLang() {
// now we will get the i18n object which let us change the language
const { i18n } = useTranslation();
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
};
return (
<div>
// you shuold change the languajes based on the ones you are using
<button onClick={() => changeLanguage("es")}>es</button>
<button onClick={() => changeLanguage("en")}>en</button>
</div>
);
}
export default ChangeLang;
Least let's use our new powerful couple of components in our deck, at the end your deck should looks like this:
import "./i18n";
import Counter from "./components/Counter";
import { Head, Header, Footer } from "mdx-deck";
import ChangeLang from "./components/ChangeLang";
import IntlContent from "./components/IntlContent";
<Head>
<title>My Presentation | @jossdz</title>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@jxnblk" />
<meta name="twitter:title" content="My Presentation" />
<meta name="twitter:description" content="A really great presentation" />
<meta name="twitter:image" content="https://example.com/card.png" />
</Head>
<Header>
## i18n slides
</Header>
<Footer>
@jossdz
</Footer>
<ChangeLang/>
<IntlContent htmlElement="h1" label="key"/>
<Counter />
---
## this is a mix of markdown and React
Thanks for read, here you can find the slides deployed and
the repo.
If you want to add themes or code demos check the next items on mdx-deck docs:
Top comments (0)