decentraland / decentraland/godot-explorer

Localization v2: Client Language Forwarding to Scenes

Open
#2,707 0 comments 0 reactions 1 assignee Claimed by @EibrielInv View on GitHub
enhancement feature parity metrics mobile
Dominant language
Rust
Stars
18
Forks
19
Avg merge
4d 2h
Merged PRs (30d)
43

Description

## **⚠️ Problem:**
Scenes cannot know the player's language, so a LATAM player with the client in ES/PT-BR still reads English scene content — signage, dialogs, in-world UI, quest text. Client localization (#2667) and webviews (#2706) cover chrome only; scene content is where Playtime is actually spent.

## **🏁 Scope:**
Protocol-level bridge exposing the client's resolved locale to SDK7 scenes, consumed by a creator-facing helper (`getPlayerLanguage()`), plus notification when the player switches language mid-session. Out of scope: translating any scene content, translation tooling for creators, server-driven copy, editor support.

## **📝 Deliverables:**
- [ ] `locale` field added to `GetExplorerInformationResponse` in `decentraland/protocol` (BCP-47)
- [ ] Godot client populates it from the resolved app locale, not raw `OS.get_locale()`
- [ ] `getPlayerLanguage()` helper exposed in `js-sdk-toolchain`, returning the tag
- [ ] Fallback contract: unsupported/unset/old client → `en`, never empty
- [ ] Language change in Settings propagated to running scenes without reload
- [ ] Old scenes on older SDK unaffected — additive field, no breaking change
- [ ] `decentraland/docs` issue filed and linked for the creator-facing API + example
- [ ] SDK7 sample scene switching a string on locale
- [ ] Parity ticket opened on `unity-explorer` so the API is not Godot-only
- [ ] `SCENE_LOCALE_REQUESTED` event with `scene_id` + `locale`, to measure creator adoption

## Metrics
1. **Target metric:** Playtime.
2. **Expected direction:** Increase median session length for ES/PT-BR cohorts in scenes that adopt the API, closing the gap vs the EN cohort in the same scenes. Baseline unknown — locale segmentation only exists once #2667 ships the `language` property.
3. **How it's measured:** `SCENE_LOCALE_REQUESTED` for adoption (leading indicator: # scenes + # sessions calling it), then session length segmented by `language` × scene in Metabase/Snowflake, 4 weeks post-release.

## Dependency
Blocked on #2667 for the resolved-locale source of truth. Protocol PR can land in parallel; client must not report a locale that disagrees with the UI.

## Implementation Specs:

Delivery path: **protocol field first, change notification as a fast-follow.**

**Transport — `GetExplorerInformationResponse`**

Today the message carries `agent` (1), `platform` (2), `configurations` (3, `map`). Two options:

| Option | Notes |
|---|---|
| `configurations["locale"]` | No protocol change, ships in hours. Untyped, undiscoverable, no doc contract, agreed by convention across clients — the failure mode that rots. Stopgap only, if a build must ship before the next protocol release. |
| **`string locale = 4;`** | Recommended. Typed, documented, cross-client. Additive — old clients return empty, scene falls back to `en`; old scenes unaffected. Costs a protocol release + SDK typings. |

**Creator surface**

`getPlayerLanguage()` wraps `getExplorerInformation()` from `~system/Runtime` — the call scenes already make for `platform`. No new API concept for creators to learn.

**Change notification**

Pull-only means a scene reading at init misses a mid-session switch, which the Settings override in #2667 makes real.

| Option | Notes |
|---|---|
| Poll | Scene re-reads on a timer. Zero platform work, wasteful, and what creators will do by default if we ship nothing. |
| **Scene event** | Emit `localeChanged` on the existing scene event bus — parity with how realm/comms changes reach scenes. Preferred. |
| SDK component | Read-only observable component. Heavier, needs an ADR. Only worth it if more client settings follow (accessibility, units, text size) — separate ticket, not a blocker. |

**Cross-cutting**
- Send full BCP-47 (`pt-BR`), not `pt`. Scenes can truncate; they cannot recover the region.
- One source of truth with client chrome — the two disagreeing is the worst outcome.
- Privacy: locale is user-set and would become readable by arbitrary scene code. No other user setting is today. Confirm before shipping.

## **🔗 References:**
- [decentraland/godot-explorer#2667](https://github.com/decentraland/godot-explorer/issues/2667) — client localization; supplies the resolved locale and the settings override this forwards.
- [decentraland/godot-explorer#2706](https://github.com/decentraland/godot-explorer/issues/2706) — v2, same locale forwarded to embedded webviews. Same source of truth, different transport.
- [decentraland/protocol `runtime.proto`](https://github.com/decentraland/protocol/blob/main/proto/decentraland/kernel/apis/runtime.proto) — `GetExplorerInformationResponse` as it stands; the message this modifies.
- [decentraland/unity-explorer `RuntimeImplementation.cs`](https://github.com/decentraland/unity-explorer/blob/main/Explorer/Assets/DCL/Infrastructure/CrdtEcsBridge/JsModulesImplementation/RuntimeImplementation.cs) — desktop's implementation of the same RPC; parity target so the field is not Godot-only.
- [decentraland/unity-explorer#270](https://github.com/decentraland/unity-explorer/pull/270) — ES enabled with nothing behind it broke desktop. Do not report a locale scenes cannot rely on.

## Notes
- Does exposing a user setting to arbitrary scene code need sign-off?
- Ship the `configurations` stopgap, or wait for the protocol release?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.