How to Add Internationalization (i18n) to your Preact application

Learn how you can add Internationalization (i18n) to your Preact Application with preact-i18n.

What is Internationalization (i18n)?

Step 1: Setup Preact CLI & Create new project

$ npm install -g preact-cli
$ preact create default my-project
$ cd my-project && npm run start

Step 2: Add preact-i18n library

$ npm install --save preact-i18n

Step 3: Create a definition file

{ 
"home": {
"title": "主頁",
"text": "這是個Home組件。"
}
}

Step 4: Import IntlProvider and definition file

import { IntlProvider } from 'preact-i18n';
import definition from '../i18n/zh-tw.json';

Step 5: Expose the definition via <IntlProvider>

render() {
return(
<IntlProvider definition={definition}>
<div id="app" />
</IntlProvider>
);
}
import { h, Component } from 'preact';
import { Router } from 'preact-router';
import Header from './header';import Home from '../routes/home';
import Profile from '../routes/profile';
// Import IntlProvider and the definition file.
import { IntlProvider } from 'preact-i18n';
import definition from '../i18n/zh-tw.json';
export default class App extends Component {

handleRoute = e => {
this.currentUrl = e.url;
};
render() {
return (
// Expose the definition to your whole app via <IntlProvider>
<IntlProvider definition={definition}>
<div id="app">
<Header />
<Router onChange={this.handleRoute}>
<Home path="/" />
<Profile path="/profile/" user="me" />
<Profile path="/profile/:user" />
</Router>
</div>
</IntlProvider>
);
}
}

Step 6: Use <Text> to translate string literals

import { Text } from 'preact-i18n';const Home = () => ( 
<div>
<h1>
<Text id="home.title">Home</Text>
</h1>
<p>
<Text id="home.text">This is the Home component.</Text>
</p>
</div>
);
export default Home;

Fallback Text

<Text id="unknown.definition">This is a fallback text.</Text>// It will render this text: "This is a fallback text."

<Localizer> and <MarkupText>

{ 
"first_name": "名",
"last_name": "姓",
"link": "這是個<a href='https://www.google.com'>連結</a>"
}
import { Text, Localizer, MarkupText } from 'preact-i18n';const Home = () => ( 
<div>
<Localizer>
<input placeholder={<Text id="first_name" />} />
</Localizer>
<Localizer>

<input placeholder={<Text id="last_name" />} />
</Localizer>
<MarkupText id="link">
This is a <a href="https://www.google.com">link</a>
</MarkupText>
</div>
);
export default Home;

Templating

{
"page": "{{count}} / {{total}} 頁"
}
import { Text } from 'preact-i18n'; const Home = () => ( 
<div>
<h2>
<Text id="page" fields={{ count: 5, total: 10 }}>
5 / 10 Pages
</Text>
</h2>
</div>
);
export default Home;

Pluralization

{
"apple": {
"singular": "Henry has {{count}} apple.",
"plural":"Henry has {{count}} apples."
}
}
import { Text } from 'preact-i18n'; const Home = () => ( 
<div>
<p>
<Text id="apple" plural={1} fields={{ count: 1 }} />
</p>
<p>
<Text id="apple" plural={100} fields={{ count: 100 }} />
</p>
</div>
);
export default Home;

Dynamically import language definition file

import { Component } from 'preact'; 
import { IntlProvider } from 'preact-i18n';
import defaultDefinition from '../i18n/zh-tw.json'; export default class App extends Component { state = {
definition: defaultDefinition
}
changeLanguage = (lang) => {
// Call this function to change language
import(`../i18n/${lang}.json`)
.then(definition => this.setState({ definition }));

};
render({ }, { definition }) {
return (
<IntlProvider definition={definition}>
<div id="app" />
</IntlProvider>
);
}
}

Who’s using preact-i18n?

Remote for Slides Progressive Web App (Traditional Chinese, Español, Polski)

Google Developer Expert in Web Technologies | Front-end Web Developer | Making the web better with Preact, Polymer, Web Components, PWA & Firebase