// Convenient, but its labels cannot use i18next
{ role: "editMenu" }
// To localize it, expand and label every item
{
label: t("menu.edit"),
submenu: [
{ label: t("menu.undo"), role: "undo" },
{ label: t("menu.redo"), role: "redo" },
{ label: t("menu.copy"), role: "copy" }
]
}
electron-menu-i18next
Skip repetitive menu labeling in your main process and localize native Electron menu items without losing their native role behavior.
Role labels come from your own i18next instance, with readable English fallbacks when translations are missing.
npm install @solisware/electron-menu-i18next
The problem
Menus built from Electron roles do not speak your language
Assign a shorthand role such as viewMenu or editMenu and Electron creates the complete submenu for you, labels included. It is quick to build, but those labels are not consistently driven by your translations, and the shorthand hides the individual items you need to localize. Both approaches require i18next to be initialized in the main process; the difference is how much wiring for menu labels you maintain yourself.
const template = [{
label: t("menu.edit"),
submenu: [
{ role: "undo" },
{ role: "redo" },
{ role: "copy" }
]
}];
const localizedTemplate =
localizeMenuTemplate(template, { t });
What it does
One template. Every locale.Native behavior preserved.
Pass in your i18next translation function and menu template. The package walks every nested role item, resolves its label, and returns a localized copy while Electron keeps control of native actions and shortcuts.
Role behavior stays native
Only the label changes. Undo, redo, shortcuts, and platform behavior remain under Electron’s control.
Nested templates are covered
Every submenu is walked recursively, so deeply nested role items receive localized labels too.
Designed for the main process
Use the i18next translator initialized in your main process, right where Electron builds the application menu.
Ready for language changes
Localize the template again after a language change and rebuild the menu without restarting the app.
Usage
Drop it into an existing menu template
Once your main process has initialized i18next, pass its translator into your existing Electron menu setup. The package returns a localized copy of your template that is ready for Electron to build, while roles, shortcuts, and native behavior remain untouched. Reuse the same installer whenever the language changes.
import { app, Menu, type MenuItemConstructorOptions } from "electron";
import { localizeMenuTemplate } from "@solisware/electron-menu-i18next";
import { translate as t } from "./i18n.js";
function createMenuTemplate(): MenuItemConstructorOptions[] {
return [{
label: t("menu.edit"),
submenu: [
{ role: "undo" },
{ role: "redo" },
{ type: "separator" },
{ role: "cut" },
{ role: "copy" },
{ role: "paste" }
]
}];
}
export function installApplicationMenu(): void {
const localizedTemplate = localizeMenuTemplate(createMenuTemplate(), {
t,
appName: app.name
});
Menu.setApplicationMenu(Menu.buildFromTemplate(localizedTemplate));
}
// Call this after initializeI18n() and again after a language change.
Supports ESM and CommonJS. TypeScript declarations are included.
API
Two functions. Minimal configuration.
localizeMenuTemplate(template, options)
Returns a localized copy of the template
Walks the complete menu tree and adds a localized label to every role item that does not already define one. It returns a new template and leaves the original unchanged.
getRoleLabel(role, options)
Returns one localized label
Resolves the localized label for one role. It is useful for tray menus, context menus, and individual menu items built outside a complete template.
Shared options
How it works
From template to native menu
Keep your existing Electron workflow and add localization at the boundary before the menu is built.
Your menu template
Define native roles, custom items, and nested submenus as usual.
Localize role labels
localizeMenuTemplate() resolves every eligible role label.
Build the native menu
Electron creates the final menu with its native behavior intact.
Safe by default
Explicit labels stay untouched
Items that already define a label remain exactly as provided.
Your template stays unchanged
Localization returns a new menu tree and does not mutate the original.
Missing translations stay readable
Known Electron roles fall back to clear English labels included with the package.
Get started
Install it and localize your menu bar today
Free, open source, and built from a real problem in Axion Notes.