How do you localize a Wails 3 desktop app so the interface, Go services, native dialogs and exported files agree about the language a person is using? This Wails internationalization guide starts with a practical answer: keep the display language explicit, treat system locale as a first-run hint, and give every translated message a stable owner. A working React or Vue translation library is not a complete desktop localization plan.
Wails connects a Go application with a web front end through runtime integration and generated bindings. In Wails 3, the front-end runtime, menus, dialogs, events and windows may show text in different places. Your app must decide where each human-readable message is produced, how it travels to the display, and which language policy applies. Go error codes and file identifiers should remain stable while descriptions may change.
Imagine a cross-platform field-notes application used by a technician in Mexico, a researcher in France and an archivist in Japan. Each imports photographs, adds descriptions, searches records, prints a report and restores an earlier session. We will follow their real work through language choice, missing resources, screen readers, right-to-left testing and packaged releases, rather than treating translation as a list of labels.
Quick answer: the reliable Wails 3 localization model
Separate five things: the language of interface messages; the locale used for dates and numbers; the language of user-created documents; the native operating-system presentation; and the stable machine identifiers that make actions work. A user’s language choice should not rename a disk file, change a database key or convert measurements stored in original units. An application can show Spanish guidance while preserving an English customer note verbatim.
A practical architecture uses a preference store for the user’s choice, a shared locale-resolution policy, application-owned front-end translation dictionaries and structured Go responses with codes plus data. The renderer selects the display message from the dictionary. Native menu labels and dialogs are localized at their own creation points. Exports use a separately selected report language so saved evidence is not silently rewritten.
A worked field-notes journey
The technician launches the app on a computer whose operating-system region is United States but whose interface language is Spanish. The app offers Español, Français, 日本語 and English because those are the verified editions shipped. The technician selects Español; a progress bar reads ‘Importando’ and a final notice reports the exact number of files imported. If one photo fails, the message identifies the failed file and invites retry without claiming all work was completed.
Later the technician exports a report for an English-speaking manager. The report language is chosen independently of the application language. Dates use an explicitly identified reporting convention, decimal values are formatted for that report, and the original notes remain unchanged. The same project reopened on another machine retains the selected language when the setting belongs to the project; otherwise, the user’s personal app preference takes precedence. Document those ownership decisions before translating.
Understand what Wails supplies—and what it does not
Wails 3 supplies native desktop integration around a web UI and Go code; the current official front-end runtime describes window management, menus, native dialogs, system information and typed events. It is not a promise that importing its runtime translates the application. The frontend can use a well-maintained internationalization system appropriate to the web framework, while Go supplies structured domain results. Consult the versioned runtime documentation for exact APIs used by your project.
Wails 2 examples use different runtime and binding conventions from Wails 3. Copying code without checking the major version can turn a correct localization concept into a broken implementation. Choose your actual Wails version first, check where the runtime package is imported, and test generated bindings after build. Where platform behavior differs, describe that difference to readers and avoid pretending one screenshot represents every operating system.
Create a translation contract before writing dictionaries
For every string, record a stable key, owner, source meaning, placeholders, intended user action, conditions under which it appears and whether the text is shown in a web component, a Go-originated result, a native dialog, a menu, a notification or an export. A key named ‘import.failed.permission’ is more useful than ‘message17’: it tells reviewers which event is being described and where a translation may belong.
Include context in translator notes. The English word ‘Open’ might mean ‘open a file’, ‘open an application window’, or ‘open status’. Each needs a different key and may demand a different verb in another language. Preserve punctuation, placeholder tokens and plural rules with test fixtures. Do not make translators infer whether a number counts pages, photographs, bytes or minutes.
Locale resolution and fallback
Decide how to resolve locale tags before launch. A reasonable hierarchy is explicit in-app selection, a retained user preference, an available language matching the system’s preferred language, and the product default. The matching algorithm should know which translations are shipped and should not promise that a regional variant exists because its language prefix matches. A French Canadian setting may reasonably fall back to generic French if that is the documented policy; it must not accidentally load an unrelated region’s legal notices.
Formatting and language do not always move together. A person might read English while wanting a European date convention or a Japanese currency presentation. Keep time-zone selection, number formatting, measurement units and content language visible when they matter. Do not conflate a locale tag with citizenship, identity or competence. Support a deliberate override and retain that choice predictably.
An end-to-end implementation sequence
Inventory every text surface, then centralize display keys and create a stable language selector with accessible names in each language. Implement a frontend translation service, resolve supported locales, and add a message catalog for error codes returned from Go. Design the native menu refresh process, ensure file dialogs use available translatable titles without assuming all OS controls are controlled by the app, and create a build-time check that all mandatory keys exist.
Next, run a task-based review for normal actions, failures and recovery. Record what the user expected, what happened, which component owned the message and which build was tested. Translation testing is incomplete if it only opens the first screen in a development web server. Install the Wails build on clean Windows, macOS and Linux environments included in your support statement, and repeat the work without a network connection.
Field guide: 28 real translation failures and how to resolve them
The following cases are organized by the point at which meaning can be lost. Each begins with something a reader actually encounters, identifies the engineering cause, offers a correction and gives a test that can be repeated. These are design examples, not claims that Wails itself automatically produces the failure.
1. First launch uses the wrong display language
What the person encounters. A Spanish-speaking user opens the app and sees English because the system region is set to a country associated with English. The welcome text implies language was chosen intelligently. Region and preferred interface language are different signals; a single operating-system value is not proof that this person wishes to read English.
What to change. Show the list of supported languages at first-run or choose only from explicitly documented matches. Record a chosen language separately from regional formats. Test a Spanish preferred language with a US number format, then relaunch. The visible selection and saved preference should remain coherent.
Why this matters. Bad inference is particularly costly during onboarding, when users have not learned where language settings are located. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
2. Version-two samples in a version-three application
What the person encounters. The team copies an older online Wails example and the language setup works in development notes but fails in the current build. Wails runtime packages, generated bindings and application lifecycles differ across major releases; an old snippet can reference a missing facility.
What to change. Label examples by major version, consult the Wails 3 runtime reference and keep one tested integration path in the project. Build from a clean checkout and exercise a command plus a menu label on every supported platform rather than only checking compilation.
Why this matters. Documentation provenance matters as much as translator competence when an ecosystem is evolving. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
3. Web labels translated, Go errors untranslated
What the person encounters. A user chooses Japanese and can read buttons, but a failed photo import shows a raw English backend error with an internal path. The error originates in Go, where returned strings were written for developers, not for readers and not for a locale-aware renderer.
What to change. Return a stable error category and safe, structured details. Map the category to a localized user message in the frontend. Simulate permission denial and damaged input in Japanese; verify the message says what failed without revealing confidential filesystem data.
Why this matters. A fluent interface can lose trust immediately if failure states expose unhelpful technical language. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
4. Native menu remains in the old language
What the person encounters. After changing French to English, the central window updates but the application menu still shows French command names. Native menu items were built separately from the web component tree and did not participate in its reactive localization refresh.
What to change. Make language changes trigger regeneration or replacement of the app-owned menu text, keeping command identifiers unchanged. Switch languages twice while the menu is open and closed; confirm each item still invokes the same underlying command.
Why this matters. The text of a command can be translated, but the command’s identity and effect must not shift. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
5. A dialog title is fixed in source code
What the person encounters. A French user opens an export dialog whose app-supplied title is English, although the export screen itself is French. The app localizes HTML strings but supplies a literal title when requesting a native file dialog.
What to change. Fetch the approved title for the active language before invoking the dialog. Accept that system-owned button labels may follow OS settings. Compare the app-supplied dialog title with selected language, then document where the operating system controls built-in wording.
Why this matters. Distinguishing application ownership from OS ownership prevents impossible translation promises. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
6. Machine path is converted as if it were prose
What the person encounters. A translated confirmation message changes the spelling of a folder name and later attempts to open a nonexistent path. The app treated a filesystem path as ordinary translatable content instead of immutable task data.
What to change. Translate only the surrounding sentence and keep the actual path as an exact, safely rendered value with appropriate isolation. Use filenames with accents, emoji, spaces and right-to-left characters; compare every operation with the original byte-preserved target.
Why this matters. Translation must never make an application act on a different file than the one the user selected. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
7. Wrong plural form for file counts
What the person encounters. The importer reports one file as plural or treats zero as a normal success despite a failure, and readers misinterpret the result. An English singular-versus-plural shortcut was transplanted into languages with more plural categories.
What to change. Use a locale-aware plural message format supported by the chosen frontend internationalization library; define zero-state text separately where meaning differs. Test zero, one, two, five and larger counts in each language using actual UI messages, including mixed success and failure results.
Why this matters. Counts carry operational meaning: a grammatically plausible sentence may still falsely signal complete import. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
8. Numbers appear with the wrong punctuation
What the person encounters. A French report shows a period for a decimal or renders a thousands separator that looks like a decimal in the intended market. The app concatenated numeric values into English-formatted strings before selecting the target language.
What to change. Keep the numeric value typed, apply locale-aware formatting at rendering, and preserve measurement units and required precision. Check a value such as 1234.50 alongside the underlying stored number and exported computation in each supported locale.
Why this matters. Display conventions should change presentation, not magnitude or calculations. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
9. Time-zone and date ambiguity in exports
What the person encounters. A report produced after midnight shows a different day from an audit log, and neither explains its time zone. The UI formats local time while Go stores an instant, but the report applies an unspecified offset and translated dates without context.
What to change. Define the event instant, display time zone and report policy. If records cross jurisdictions, label the time zone and keep canonical timestamps. Generate a report around daylight-saving transitions and compare the log, table and CSV source; all should describe one event.
Why this matters. Users should never be left to guess whether a translated date changed the underlying event. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
10. Missing translation silently falls back
What the person encounters. A German language pack ships without a label for a new action, so one button appears in English with no indication of incomplete support. The release pipeline allowed missing keys and relied entirely on a permissive runtime fallback.
What to change. Define mandatory keys, block release on missing critical messages, and make noncritical fallback deliberate rather than invisible. Remove a key in a test branch and verify the build check catches it before packaging, with a readable diagnostic.
Why this matters. Graceful fallback is useful for resilience; it must not conceal a product’s missing high-stakes instructions. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
11. Offline app asks for remote dictionaries
What the person encounters. The installer works without the internet, but switching to French on a train leaves blank messages. The translation catalog was fetched from a remote endpoint rather than bundled with the offline application’s supported languages.
What to change. Ship required language resources in the desktop package and treat remote translation updates as optional, validated enhancements. Disconnect network access before first launch, change every supported language and test export, error and recovery flows.
Why this matters. Offline behavior is a core promise when a field tool is sold as usable outside reliable connectivity. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
12. A language selection is not retained
What the person encounters. A user spends time choosing Japanese and must repeat the choice on every launch or new project. The setting lived only in volatile frontend state and was never given a documented storage owner.
What to change. Store the explicit preference at a well-defined user or project scope, with a migration path for future releases. Choose Japanese, restart, open a second workspace and inspect which scope retains the choice according to product policy.
Why this matters. A setting that disappears without explanation makes the translated interface feel unreliable. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
13. Language switching changes user data
What the person encounters. An operator switches app language and the software rewrites note headings that were originally entered in Spanish. The model has no boundary between UI-owned strings and user-authored content, or applies translation to records automatically.
What to change. Keep authored notes unchanged unless the person starts an explicit translation operation with preview and consent. Snapshot project records, switch UI language repeatedly, then diff records and exported original content.
Why this matters. Interface localization is not permission to rewrite historical evidence or personal writing. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
14. An event message arrives after language change
What the person encounters. A file import begins in English, the user switches to French, and a completed status event displays in the old language. An asynchronous event carried a preformatted English sentence from Go instead of a stable status code and typed values.
What to change. Send an event code, count and document reference. Render the message in the currently active language when it is received. Start a slow import, change language mid-operation and validate progress, completion and failure notices.
Why this matters. Async systems demand a clear decision about language at display time rather than operation-start time. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
15. Accessibility names were not updated
What the person encounters. A translated icon button shows Spanish tooltip text, but the screen reader announces its former English accessible name. Visible labels and accessibility properties come from separate components or hard-coded attributes.
What to change. Make accessible names, descriptions, live regions, keyboard-help text and visible labels share the same translation ownership. Navigate using keyboard and screen reader with Spanish and French packs, triggering both normal and error states.
Why this matters. A feature is not localized for users who cannot perceive its translated visual label. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
16. Right-to-left layout breaks a filename
What the person encounters. A right-to-left language flips the direction of the page and displays a Latin file path in unreadable order. Paragraph flow and embedded identifiers have different directional requirements; mirroring everything is not equivalent to correct reading order.
What to change. Apply RTL layout to appropriate interface regions while isolating paths, email addresses, codes and numbers as meaningful segments. Use an Arabic page with a mixed-script path, keyboard focus and a drag-and-drop target; verify the actual selected file.
Why this matters. The app must preserve operational identity even when visual reading order changes. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
17. Translated shortcut labels do not match keys
What the person encounters. A menu label describes one shortcut, but the actual keyboard accelerator follows a platform-specific binding not updated with the text. The displayed human explanation and the action’s accelerator were maintained independently.
What to change. Define shortcut bindings as structured actions and generate their displayed representation per platform and locale. Check each shortcut on Windows, macOS and Linux with localized menus and non-English keyboard layouts.
Why this matters. A shortcut is part of the interaction contract, not merely a punctuation pattern in a sentence. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
18. A translator reuses one word for several actions
What the person encounters. A button that means ‘open a file’ and a status badge that means ‘open issue’ share the same translated key. The source extracted the word without explaining role, object or grammatical function.
What to change. Create separate keys and give translators a screenshot, object label and intended action for each one. Ask a target-language reviewer to complete both tasks without guessing what the identical word refers to.
Why this matters. Context prevents short strings from becoming high-impact usability defects. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
19. Export contains placeholder tokens
What the person encounters. A CSV report contains unexpanded tokens such as a count placeholder instead of localized explanatory text. Template substitution was tested in the UI but not in the separate export renderer.
What to change. Use typed export templates, validate placeholder counts and keep machine-readable CSV columns stable when that is the contract. Export all supported locales with special characters, inspect the resulting bytes and round-trip through the expected reader.
Why this matters. Exports remain part of the product even when they are created outside its visible interface. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
20. Report language silently follows device language
What the person encounters. A field worker’s app is Spanish but the document must go to an English-speaking regulator; the exported report is unexpectedly Spanish. The export subsystem copied active UI locale without asking what language the document recipient needs.
What to change. Expose report language as an explicit decision or project policy distinct from UI language and recorded in export metadata. Switch UI to Spanish, export English and confirm neither the underlying notes nor the selected interface preference changes.
Why this matters. Different readers can require different languages for the same underlying dataset. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
21. Font lacks the target script
What the person encounters. An Arabic translation renders empty squares in a packaged Linux build even though the development laptop displays the text. The developer relied on locally installed fonts and did not test the fonts available on supported target systems.
What to change. Select fonts with coverage appropriate for shipped scripts and account for platform fallback; avoid bundling fonts without license checks. Install clean virtual machines and render representative strings, numbers, file paths and diacritics.
Why this matters. A translation unavailable to the display is not a usable translation. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
22. Native notifications use stale language
What the person encounters. A background sync produces an English notification while the main application is now Japanese. The notification message was assembled when a Go worker began, before the current language was read or applied.
What to change. Store a code and payload; choose an approved localized message at notification delivery time or capture the intended preference explicitly. Change locale during background work, minimize the window and observe notification wording and click behavior.
Why this matters. Lifecycle timing is central to multilingual desktop messages. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
23. Installer and application language disagree
What the person encounters. The main window has Japanese translations, but installation, first-launch and update prompts appear only in English without warning. The team evaluated the app’s web UI but excluded installer, updater and OS-owned packaging surfaces.
What to change. Inventory what the packaging mechanism controls and distinguish selectable app text from vendor-owned or operating-system text. Install and update using a clean Japanese-language profile; document expected and actual languages for every distinct surface.
Why this matters. A complete release claim must match the experience before the main app opens. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
24. Help content opens the wrong edition
What the person encounters. The French Help button opens an English help article even though an approved French guide exists. The link was hard-coded without language routing or available-version checks.
What to change. Maintain a language-to-help mapping with verified URLs and an accessible notice when only the default help edition is available. Test every language’s Help, troubleshooting and privacy links with live or bundled documentation.
Why this matters. Support materials are part of the user journey, not optional extras to be checked after release. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
25. Security denial is softened in translation
What the person encounters. A translation says an export succeeded although the actual Go operation was blocked by permissions. The translator received a standalone sentence without its error state, or an error code was incorrectly mapped to a success key.
What to change. Require state-dependent messages to distinguish attempted, denied, partial and completed operations, with a reviewer checking both verb and consequence. Simulate read-only directories and denied permissions, inspect status codes and final filesystem state.
Why this matters. Language must never conceal a failed operation or invite a user to act as though it succeeded. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
26. A bundled pack has the wrong revision
What the person encounters. A previously translated menu looks correct, but a new warning from the latest app release is missing in one language. The pack version is detached from the source-message revision and the app did not enforce compatibility.
What to change. Track schema or catalog version with each app release and verify required key coverage against that exact source revision. Upgrade an older installed copy with a retained language preference and run both new and old user workflows.
Why this matters. Release QA is a compatibility test between code, data and language resources. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
27. Telemetry records translated strings as identifiers
What the person encounters. An analytics event changes its name with the interface language and dashboards mistakenly split one event into three. Human-facing labels were reused as internal analytics identifiers.
What to change. Keep event names and machine codes invariant; localize only what the human reads and anonymize any diagnostic context appropriately. Trigger the same action across English, French and Japanese while comparing event IDs and user-visible confirmation.
Why this matters. Stable identifiers protect both privacy review and operational analysis without constraining translated explanations. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
28. The release only tests the developer workstation
What the person encounters. The desktop team declares language QA complete after exercising a browser preview on the machine used to write the app. Development mode did not test installed assets, native menus, dialogs, packaging permissions or differences between host platforms.
What to change. Write a deployment matrix of supported operating systems, architectures, display languages, offline state, accessibility and normal/failure flows. Install the release artifact in a clean account and use task scripts with captured evidence for every promised platform.
Why this matters. Actual readers use installed products, not development demos. A reviewer should document the supported locale, the action taken, the visible result and the product state; otherwise a screenshot can appear correct while the workflow is still broken.
Release plan: from source changes to a trusted desktop build
Begin by creating a known baseline in the default language and listing all surfaces that show human language. Freeze resource keys for a translation cycle, explain the context to language reviewers, and test dictionaries for missing identifiers, malformed plural messages, unexpected HTML and placeholder mismatches. Keep executable commands and saved data out of translation files. Code review should reject new user-facing literals that bypass the catalog without a documented reason.
Next, combine language review with product testing. Ask reviewers to accomplish five tasks without a guided tour: start the application, import a small project, repair a deliberately failed import, change display language, and export a report for a different audience. Record where the meaning was unclear. A product can satisfy a string coverage percentage and still mislead readers about whether a file was written, restored, moved or deleted.
Package the candidate release rather than testing only a development server. On each supported operating system, test a fresh installation and an upgrade with an existing language preference. Unplug the network, stress uncommon filenames, use a non-English keyboard and verify application-owned native menus and notifications. When a defect is fixed, rerun the affected journey plus the adjacent actions so changes do not create new inconsistencies.
Frequently asked questions
Does Wails 3 translate a React or Vue app automatically?
No. Wails provides desktop integration and frontend/backend communication. Your own UI catalog and locale policy remain responsible for readable app text; native menus and Go-originated messages need their own coverage.
Should Go return already translated sentences?
It can in a deliberately designed server-owned localization system, but structured codes and typed arguments often make language switching and frontend consistency easier. Decide ownership and test asynchronous responses.
What is the safest way to choose a language at first launch?
Offer shipped languages or choose by a documented matching policy using the operating system’s relevant preference. A person’s explicit choice should override future guesses and survive restart.
Can one set of translated strings cover native dialogs?
Only text the application owns can be supplied in the selected language. Operating-system controls can remain in the host’s language. Explain that distinction and check the real packaged build.
Should localized exports use the application’s language?
Not necessarily. The recipient may need another language. Offer an export-language choice while preserving user-authored source content and data identifiers.
How can teams test language changes during long-running tasks?
Return typed events or codes, switch the language while work continues, and verify progress, failure, cancellation and completion messages after the switch.
Do right-to-left languages mean reversing every symbol?
No. Use appropriate layout direction but preserve the direction and exact spelling of file paths, technical identifiers, codes and mixed-script segments.
What is the minimum evidence for release?
A tested installed build, supported-locale matrix, task-based normal and error journeys, coverage and placeholder checks, plus findings for native dialogs, accessibility, updates and offline use.
Primary documentation and related chapters
The Wails front-end runtime reference describes current runtime integration, menus, dialogs and events. The Wails architecture overview provides background on Go and the web UI; check whether an example refers to Wails 2 or Wails 3 before adapting it. For a wider explanation of preserving meaning, read Master Art of Translation: The Complete System. Browse the Translate Like a Pro series index for other platform-specific guides.
Final principle
The goal is not to make a Wails app display the maximum number of translated strings. It is to let people understand the next action, see an accurate account of its result, recover from failures and share outputs without losing the source meaning. A reliable language system keeps the interface readable while preserving the identity of files, events and user-authored data.