Electron
2.5M weekly downloads

Electron Localization Guide

Build multilingual desktop apps with Electron. Handle main process, renderer, and system locale detection. Cross-platform i18n done right.

Prerequisites

  • Electron 28+ application
  • Node.js 18+
  • Basic Electron architecture understanding

Common Challenges

Problems developers face when localizing Electron apps—and how IntlPull helps.

Process Complexity

Electron has main and renderer processes. Translations must be available in both.

Native Menu Localization

Native menus are built in main process before window loads. Timing matters.

Context Isolation

Modern Electron uses context isolation. Translations need preload script bridge.

i18next-electron Features

Why i18next-electron is a great choice for Electron localization.

Cross-Process i18n

Share translations between main and renderer processes. Consistent language across your app.

vs separate translation instances

System Locale Detection

Detect OS language via app.getLocale(). Match user's system preferences automatically.

vs manual detection

Native Menus

Localize native menus, dialogs, and system UI. Platform-appropriate translations.

vs web-only UI

Offline Support

Bundle translations with app. No network required. Perfect for offline desktop apps.

vs online-only translation

React/Vue Integration

Use react-i18next or vue-i18n in renderer. Familiar patterns for web developers.

vs learning new APIs

Auto-Updates

Update translations without app update via IntlPull OTA. Ship translation fixes fast.

vs rebuilding for typos

Quick Setup

Get i18next-electron running in your Electron project.

1

Install Dependencies

Add i18next packages for Electron.

npm install i18next i18next-fs-backend
# For React renderer:
npm install react-i18next
2

Create Translation Files

Set up locale files in resources.

// resources/locales/en/translation.json
{
  "app": {
    "name": "My App",
    "version": "Version {{version}}"
  },
  "menu": {
    "file": "File",
    "edit": "Edit",
    "view": "View",
    "quit": "Quit"
  },
  "welcome": "Welcome to {{appName}}"
}

// resources/locales/es/translation.json
{
  "app": {
    "name": "Mi App",
    "version": "Version {{version}}"
  },
  "menu": {
    "file": "Archivo",
    "edit": "Editar",
    "view": "Ver",
    "quit": "Salir"
  },
  "welcome": "Bienvenido a {{appName}}"
}
3

Configure Main Process

Initialize i18next in main process.

// main/i18n.ts
import i18next from 'i18next';
import Backend from 'i18next-fs-backend';
import { app } from 'electron';
import path from 'path';

const isDev = !app.isPackaged;

export async function initI18n() {
  const locale = app.getLocale().split('-')[0]; // 'en-US' -> 'en'
  
  await i18next.use(Backend).init({
    lng: locale,
    fallbackLng: 'en',
    backend: {
      loadPath: isDev
        ? path.join(__dirname, '../resources/locales/{{lng}}/{{ns}}.json')
        : path.join(process.resourcesPath, 'locales/{{lng}}/{{ns}}.json'),
    },
  });
  
  return i18next;
}

export { i18next };
4

Create Preload Bridge

Expose i18n to renderer via preload.

// preload/index.ts
import { contextBridge, ipcRenderer } from 'electron';

contextBridge.exposeInMainWorld('i18n', {
  t: (key: string, options?: object) => ipcRenderer.invoke('i18n:translate', key, options),
  changeLanguage: (lng: string) => ipcRenderer.invoke('i18n:changeLanguage', lng),
  getLanguage: () => ipcRenderer.invoke('i18n:getLanguage'),
});

// main/index.ts (add IPC handlers)
import { ipcMain } from 'electron';
import { i18next } from './i18n';

ipcMain.handle('i18n:translate', (_, key, options) => i18next.t(key, options));
ipcMain.handle('i18n:changeLanguage', (_, lng) => i18next.changeLanguage(lng));
ipcMain.handle('i18n:getLanguage', () => i18next.language);
5

Localize Native Menu

Build localized application menu.

// main/menu.ts
import { Menu, app } from 'electron';
import { i18next } from './i18n';

export function createMenu() {
  const template: Electron.MenuItemConstructorOptions[] = [
    {
      label: i18next.t('menu.file'),
      submenu: [
        { label: i18next.t('menu.quit'), role: 'quit' },
      ],
    },
    {
      label: i18next.t('menu.edit'),
      submenu: [
        { label: 'Undo', role: 'undo' },
        { label: 'Redo', role: 'redo' },
      ],
    },
  ];
  
  const menu = Menu.buildFromTemplate(template);
  Menu.setApplicationMenu(menu);
}

IntlPull Integration

Connect IntlPull to manage translations professionally.

1

Install IntlPull CLI

Add the CLI for translation management.

npm install -D @intlpull/cli
2

Configure intlpull.json

Set up the project configuration.

{
  "projectId": "your-project-id",
  "format": "json",
  "sourceLocale": "en",
  "localesDir": "./resources/locales",
  "filePattern": "{locale}/translation.json"
}
3

Pull Translations

Download translations before build.

npx intlpull pull
4

Add to Build Process

Integrate with electron-builder.

// package.json
{
  "scripts": {
    "i18n:pull": "intlpull pull",
    "build": "npm run i18n:pull && electron-builder"
  },
  "build": {
    "extraResources": [
      {
        "from": "resources/locales",
        "to": "locales"
      }
    ]
  }
}

Frequently Asked Questions

Ready to Localize Your Electron App?

Start with our free tier. No credit card required.

    Electron Localization Guide | IntlPull | IntlPull