Internationalization (i18n) is a big topic by itself. The broadest definition has to do with translating your user interface to other languages. Localization (l10n) is a more specific term, and it describes how to adapt your application to a specific locale or market. Different locales can have the same language, but they still have their customs, like date formatting or measures.

The problem could be solved by pushing the translations behind an end point and loading them dynamically to decouple the problem from webpack. This would also allow you to implement a translation interface within your application to allow your translators, or even users, to translate the application. The downside of this approach is that then you have a translation backend to maintain.

Another approach is to let webpack generate static builds, each per language. The problem is that you have to update your application each time your translations change.

i18n with Webpack#

The basic idea of i18n with webpack is often the same. You have a translation definition that is then mapped to the application through replacements. The result contains a translated version of the application. You can use multiple translation formats through a couple of solutions:

To illustrate the setup, i18n-webpack-plugin is a good starting point.

Setting Up a Project#

To prove that translation works, set up something to replace:


console.log(__("Hello world"));

To translate that into Finnish, set up a definition:


{ "Hello world": "Terve maailma" }

The next step is to glue the files together using webpack.

To make ESLint aware of the global __ function, you should add it to your linting rules through globals.__: true.

Setting Up I18nWebpackPlugin#

Install i18n-webpack-plugin and glob helper first. The latter is needed for capturing translation files.

npm install glob i18n-webpack-plugin --save-dev

On the webpack side, you should iterate through the available languages, and then set up a configuration for each:


const path = require("path");
const glob = require("glob");
const I18nPlugin = require("i18n-webpack-plugin");

const PATHS = {
  build: path.join(__dirname, "i18n-build"),
  i18nDemo: path.join(__dirname, "app", "i18n.js"),

const TRANSLATIONS = [{ language: "en" }].concat(
  glob.sync("./languages/*.json").map(file => ({
    language: path.basename(file, path.extname(file)),
    translation: require(file),

module.exports ={ language, translation }) => ({
  entry: {
    index: PATHS.i18nDemo,
  output: {
    filename: `[name].${language}.js`,
  plugins: [new I18nPlugin(translation)],

To make it convenient to build, set a shortcut:


"scripts": {
  "build:i18n": "webpack --config webpack.i18n.js",

If you build now (npm run build:i18n), you should end up with a new directory containing two translated files and translated code in each.

To take the example further, generate a page for each translation as described in the Multiple Pages chapter and add a language selector. The language definition can be handled through webpack's DefinePlugin. A user interface widget could rely on that and load languages based a page or directory naming convention.

The techniques discussed in the Code Splitting chapter are valid with i18n. You could define dynamic imports to load translation files on demand. Doing this would push the problem of loading and maintaining translations elsewhere.


The other webpack approaches follow a similar idea but require more work. They are more flexible, and if you go with a loader based solution, then you can set up split points to load languages on demand.

To recap:

  • Internationalization (i18n) and localization (l10n) are important problems if you target multiple markets with your application.
  • Webpack supports multiple approaches to i18n. At simplest you can replace specific annotations although more sophisticated alternatives are available.
  • The problem can be handled by pushing it to a server. It would also allow you to handle translating the actual application through the same API.

The next chapter covers various testing setups and tools that work with webpack.

Previous chapter
Web Workers
Next chapter

This book is available through Leanpub (digital), Amazon (paperback), and Kindle (digital). By purchasing the book you support the development of further content. A part of profit (~30%) goes to Tobias Koppers, the author of webpack.

Need help?