wordpress-mobile / wordpress-mobile/GutenbergKit
Resolve consumer locales against shipped translation bundles
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 29
- Forks
- 6
- Avg merge
- 1d 9h
- Merged PRs (30d)
- 41
Description
Summary
Consumers currently pass locale to EditorConfiguration as an opaque string, and src/utils/localization.js does a single-level dynamic import. If the tag doesn't match a shipped translations/*.json exactly, the editor silently falls back to English. The supported-locales list lives in bin/prep-translations.js; consumers don't see it, and have no way to ask "what's the closest bundle you actually ship?". This means each client has to mirror that table to do the right thing — and historically hasn't.
Concretely on WP-Android (today): PerAppLocaleManager.getCurrentLocaleLanguageCode() returns Locale.getLanguage() — ISO 639-1 only — so a Brazilian user sends pt (matches), a Chinese user sends zh (no zh-cn/zh-tw match → English), and a user who picked en_GB / nl_BE / pt_BR in the language picker loses their region variant before we ever reach GutenbergKit.
Proposed shape
Move locale resolution into the library so every client gets correct behaviour without re-implementing the table:
1. Platform-native setLocale overloads
// Android
setLocale(locale: Locale) // new — resolves internally
setLocale(locale: String) // existing — power-user / tests
// iOS
func setLocale(_ locale: Locale) // new
func setLocale(_ identifier: String) // existing
The new overloads call toLanguageTag().lowercased() (or Locale.identifier on iOS) and run the resolution chain before storing the string for serialization. The wire format stays unchanged — only the consumer-facing API gains type safety.
2. Resolution chain
For an input tag xx-yy:
- Full tag (
xx-yy) — match if shipped - Language-only tag (
xx) — match if shipped - Fall back to
en
Determined at runtime against the actually-bundled translation files, not a hard-coded list — that way the resolver stays correct when SUPPORTED_LOCALES in bin/prep-translations.js changes without anyone remembering to update a duplicate.
3. JS-side fallback becomes defensive
localization.js's catch-and-warn stays as a defense-in-depth net but should rarely fire in practice once the Android/iOS resolver narrows to a known-shipped tag.
Out of scope
- Changing the
SUPPORTED_LOCALESlist itself. - Changing the wire format of
EditorConfiguration.locale. - Pluralization / RTL handling — separate concerns.
Why this matters
Two clients today (WP-Android, WP-iOS) and a third on the way (the GutenbergKit preloader being added in WP-Android #22579, where every preloaded session has to remember to overlay the locale or it ships English regardless of device language). One resolver in the library closes all three at once and any future client by default.
Related
- WP-Android PR that made the footgun visible: https://github.com/wordpress-mobile/WordPress-Android/pull/22836
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read src/utils/localization.js and bin/prep-translations.js first to understand dynamic imports and the shipped locale set. Then trace the Android and iOS setLocale entry points described in the issue. Done means platform-native locale overloads resolve full and language-only tags against bundled translations, preserve the existing wire format, and leave the JavaScript fallback defensive.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, kotlin, swift
- Domain
- internationalization, mobile-dev
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100