Fall back to "en" when a paywall screen omits `default_locale` (#4111)
<!-- Thank you for contributing to Purchases! Before pressing the "Create Pull Request" button, please provide the following: --> ### Checklist - [x] If applicable, unit tests - [x] If applicable, create follow-up issues for `purchases-ios` and hybrids ### Motivation `default_locale` was a required field on both paywall screen models. The backend serves it as `null` for template-derived screens, so those paywalls fail to decode and fall back to the default paywall. On the workflow path the failure is not scoped to the field, it discards the entire `PublishedWorkflow`, so one bad screen takes every other screen in the workflow with it. ### Description This needs two fixes, not one: a default handles a missing value, but an explicit null still fails. We now fall back to en in both cases. I applied the same behavior to both paywall models. Only the workflow path is failing in production right now, but both models have the same requirement. I verified the fix against the payload the backend actually sends. Previously, both null and a missing value failed; now present, null, and missing values all behave consistently, falling back to en when needed. All relevant test suites and checks pass. The four existing HTTP timeout failures also reproduce on a clean HEAD, so they’re unrelated. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Localized deserialization-only change with a safe default; no auth, billing, or persistence impact. > > **Overview** > Paywall screen JSON decoding no longer fails when the backend sends **`default_locale` as `null`** (common on template-derived screens) or omits the key. **`WorkflowScreen`** and **`PaywallComponentsData`** now use **`DefaultLocaleIdSerializer`** plus a property default of **`en`**, so valid strings are kept and null, missing, or non-string JSON values all resolve to English instead of aborting deserialization. > > On the workflow path, a decode failure previously dropped the entire **`PublishedWorkflow`**, not just one screen; this change keeps those workflows loadable. Malformed **`default_locale`** values are not coerced into odd locale strings, aligning with iOS string-only behavior. > > Unit tests cover present, null, missing, and invalid **`default_locale`** payloads and assert both models decode the same way. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit b78cc5df10e70470f3d75fc4c0209091e7c32a0b. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
M
Monika Mateska committed
cfa1e4c9f5ce1681193332580745ed8dba22cdf3
Parent: 2ca15ec
Committed by GitHub <noreply@github.com>
on 8/28/2026, 10:19:01 AM