i18n Slides for tech speakers with mdx-deck
Tags: gatsby, mdx, mdxdeck, i18next
Published: 2020-05-15 22:44:22

---
title: i18n Slides for tech speakers with mdx-deck
published: true
description: Multi language slides for tech speakers.
tags: #Gatsbyjs, #mdx, #mdx-deck, #i18next
imgone: 
---

# 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

```bash
kmdir slides && cd slides
```

and 

```bash
npm init -y
```

---

### Installing dependencies

```bash
npm i mdx-deck i18next react-i18next 
```

### Create project structure

Now we need to create a `/src` folder with our code base

```bash
mkdir src src/translations src/components src/docs
```

and our main file:

```bash
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:

```json
{
  "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:

```mdx
# 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:

```jsx
// ./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:

```md
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:

![](https://i.postimg.cc/rFQrzqLk/image.png)

#### Layout

Once last thing for you to know about mdx-deck it's their new layout system with their own built in [components](https://github.com/jxnblk/mdx-deck/blob/master/docs/components.md): `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 :

```html
<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:

```md

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`):

```bash
touch src/i18n.js src/translations/es.json src/translations/en.json
```

in our `i18n` file we need to place the `i18next` config:

```js
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:

```json
{
  "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:

```md
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:

```bash
touch src/components/IntlContent.js src/components/ChangeLang.js
```

- `src/components/IntlContent.js` 

```jsx
// 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` 

```jsx
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:

```md
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](https://slides-gdn562lk1.now.sh/#0) you can find the slides deployed and
the [repo](https://github.com/Jossdz/i18n-slides).

If you want to add themes or code demos check the next items on mdx-deck docs:

- [theming](https://github.com/jxnblk/mdx-deck/blob/master/docs/theming.md)
- [mdx-live-coding](https://github.com/JReinhold/mdx-deck-live-code)
- [mdx-deck-code-surfer](https://github.com/pomber/code-surfer)