wordpress-mobile / wordpress-mobile/GutenbergKit

Resolve consumer locales against shipped translation bundles

Open
#490 0 comments 0 reactions 0 assignees View on GitHub

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:

  1. Full tag (xx-yy) — match if shipped
  2. Language-only tag (xx) — match if shipped
  3. 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_LOCALES list 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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.