Translating a Desktop App Into 31 Languages: What It Takes
Translating a desktop app into dozens of languages takes far more than translating its strings. You also need correct plural forms for each language, a right-to-left layout for Arabic, Hebrew and Persian, a sensible way to pick the user's language, fonts that cover every script, and a way to keep 30-plus translations in step as the interface changes. The strings themselves are the easy part.
This page uses Edge Drop, a Windows clipboard shelf built with Electron and available in 31 interface languages, as a running example. If you're still choosing a framework, Electron vs Tauri for overlay apps compares the two.
1. Get every string out of the code
Before anyone translates anything, every piece of visible text needs a key: button labels, menu items, tooltips, error messages, settings descriptions and tray menu entries. Code calls a lookup function with that key instead of containing the English text.
Common choices in JavaScript and TypeScript apps:
- i18next, with JSON resource files and built-in plural handling.
- FormatJS, built on ICU MessageFormat.
- Fluent, Mozilla's localisation system.
- A plain typed dictionary, one object per language. Edge Drop keeps all 31 dictionaries in a single TypeScript module.
Whatever you choose, watch for strings that outlive their feature. Edge Drop's translation file still contains a "Bottom Edge" string and a "Save File" string that no part of the app uses, because those features don't exist. Every unused string still gets translated 31 times, so prune them.
2. Handle plurals with CLDR rules, not count === 1
English has two plural categories, but many languages have more. The Unicode CLDR plural rules define them:
| Language | Cardinal plural categories |
|---|---|
| English, German, Hindi | one, other |
| French, Spanish, Portuguese | one, many, other |
| Hebrew | one, two, other |
| Russian, Polish, Czech | one, few, many, other |
| Arabic | zero, one, two, few, many, other |
| Japanese, Korean, Chinese | other |
Two details catch people out. French and Hindi put 0 in the "one" category, so "0 élément" is correct French. And Japanese, Korean and Chinese have a single form, so the count usually just sits next to the noun.
JavaScript has these rules built in through Intl.PluralRules:
const ar = new Intl.PluralRules('ar');
[0, 1, 2, 3, 11, 100].map((n) => `${n}: ${ar.select(n)}`);
// ["0: zero", "1: one", "2: two", "3: few", "11: many", "100: other"]
new Intl.PluralRules('fr').select(0); // "one"
i18next uses the same categories as key suffixes (item_one, item_other, item_few and so on) and picks the right one when you pass count. Translators then supply one string per category their language uses.
3. Support right-to-left languages properly
Arabic, Hebrew and Persian read right to left, and the whole layout should mirror, not just the text.
- Set direction in markup. Put
dir="rtl"on thehtmlelement (or setdocument.documentElement.dirwhen the language changes). The W3C recommends using markup rather than CSS to set the base direction. - Use logical CSS properties.
margin-inline-startandpadding-inline-endflip automatically;margin-leftdoesn't. - Decide which images to mirror. Back and forward arrows usually need to flip. Go image by image: some can simply be flipped, others need a separate right-to-left version.
- Test mixed text. A Hebrew sentence with an English product name or a URL is where bidirectional bugs appear.
Edge Drop sets the document direction to right-to-left for Arabic, Persian and Hebrew. The screen edge the shelf sits on is a separate setting and doesn't change with the language. RTL clipboard shelves on Windows covers how right-to-left text behaves on the clipboard itself.
4. Pick the user's language sensibly
Most people expect an app to start in their Windows display language. Electron gives you three related APIs, each with a different meaning:
| API | What it returns |
|---|---|
app.getLocale() | The locale Chromium is using for the app (call it after the ready event) |
app.getSystemLocale() | The system locale; on Windows 11 this follows the regional format for numbers, dates and times |
app.getPreferredSystemLanguages() | The user's preferred languages in order, from Windows' Language & region settings |
For the interface language, the preferred-languages list is usually the right signal; the system locale is better for date and number formats. Match the first preferred language you support, fall back to English, and always offer a manual choice that persists.
Edge Drop's Language setting (Settings > Behaviour) defaults to System Default (Auto), which maps the Windows language to one of its 31 languages and falls back to English. Choosing a language manually overrides it. How to change language and RTL layout shows the setting.
5. Make sure fonts cover every script
An app supporting Arabic, Bengali, Hindi, Thai, Hebrew, Greek, Japanese, Korean and Chinese needs fonts for many scripts. Without them, users see boxes or a jarring fallback font in the middle of a sentence.
Options:
- Rely on the system font fallback. Chromium falls back to installed Windows fonts. It usually works, but the result can look inconsistent.
- Bundle fonts. Google's Noto family covers more than 1,000 languages and over 150 scripts, so you can pick the Noto fonts for the scripts you support. Edge Drop bundles its fonts rather than loading them from the web, which also keeps the app offline.
Check line height and clipping for scripts with tall marks, such as Thai and Devanagari, and for Arabic, which needs proper shaping. Larger text settings make clipping worse, so test them together; what makes an overlay clipboard app accessible covers text size and contrast.
6. Catch layout problems before translation with pseudolocalization
Pseudolocalization swaps your English strings for longer, accented versions such as [Šéţţîñĝš ţàƀ !!!] so you can spot problems before any real translation arrives. Microsoft's guidance suggests lengthening English text by about 40%, and notes that short strings of one or two words can grow far more.
It reveals:
- text that's truncated or overflows,
- strings still hard-coded in the source (they stay in plain English),
- sentences built by joining fragments, which can't be translated correctly.
Windows also defines pseudo-locales for testing formats: qps-ploc (base), qps-ploca (East Asian) and qps-plocm (mirrored, for right-to-left).
7. Choose a translation workflow you can sustain
The hard part of 30-plus languages is keeping them current. Every new setting needs 30 translations before it ships, or users see English mixed in.
- Pull requests against the translation files work for a handful of languages and contributors.
- Crowdin offers free plans for open-source projects and gives translators a web editor that understands plurals and context.
- Weblate has a free hosted plan for libre projects and can be self-hosted.
Whichever you use, give translators context: where a string appears, how much space it has, and what any placeholders mean. A screenshot or a short note prevents most bad translations.
A checklist
- Move every visible string into translation files, and delete unused ones.
- Use CLDR plural categories through
Intl.PluralRulesor your library. - Set
dir="rtl"for right-to-left languages and use logical CSS properties. - Default to the user's preferred Windows language, with a manual override.
- Make sure your fonts cover every script you ship.
- Run a pseudolocalized build to catch truncation and hard-coded text.
- Set up a workflow that keeps every language complete before each release.
FAQ
How many languages should a small app support?
Start with the languages your users actually speak; download statistics or support requests show which. Adding a language you can't keep up to date leaves those users with a half-English interface after the next release.
Is machine translation good enough for an app interface?
It's a starting point. Short interface strings are ambiguous out of context ("Clear" can mean empty or transparent), so a native speaker should review them.
Which languages does Edge Drop support?
31: English (US), Spanish, French, German, Italian, Portuguese, Russian, Japanese, Korean, Chinese (Simplified), Chinese (Traditional), Hindi, Arabic, Persian, Bengali, Turkish, Vietnamese, Polish, Dutch, Swedish, Indonesian, Ukrainian, Greek, Czech, Romanian, Hungarian, Danish, Finnish, Thai, Hebrew and Norwegian.
Related reading
- Clipboard Managers for Arabic, Hebrew and Persian on Windows
- Accessible Clipboard Managers for Windows: A Checklist
- Electron vs Tauri for Overlay Apps: Drag-Out, Focus, Memory
- How to Build Edge Drop From Source on Windows
Sources
- Language Plural Rules (Unicode CLDR) — plural categories per language.
- Intl.PluralRules (MDN) — built-in plural selection in JavaScript.
- Plurals (i18next docs) — plural key suffixes and the
countoption. - app (Electron docs) —
getLocale,getSystemLocaleandgetPreferredSystemLanguages. - Structural markup and right-to-left text in HTML (W3C) — use the
dirattribute for base direction. - Logical properties and values (MDN) — direction-aware CSS.
- Adjust layout and fonts, and support RTL (Microsoft Learn) — flow direction and mirroring images for Windows apps.
- Pseudolocalization (Microsoft Learn) — text expansion and Windows pseudo-locales.
- Noto fonts (Google) — coverage of languages and scripts.
- Crowdin for open source (Crowdin) — free plans for open-source projects.
- Weblate hosting (Weblate) — hosted and libre plans.
- Project Fluent (Mozilla) and FormatJS — alternative localisation libraries.
Deepender Yadav created Edge Drop and builds and tests it, from the edge-hover shelf to each release. A B.Tech Computer Science Engineering student, Deepender writes the Edge Drop guides, comparisons and developer posts, and checks product details against the app's source code.
GitHub · LinkedInCopy. Stack. Drop.
Transform your clipboard into an interactive edge shelf. Stack, pin, and drag assets into any app with zero friction.
Download for Windows Get from Microsoft Store
How to Install Guide · First 10 Minutes Guide · Drag & Drop Guide · Edge Drop vs Win+V · Support
Free · Lightweight · Privacy First