Skip to content

feat: add Device localization support#23

Open
benjam-es wants to merge 2 commits intoNativePHP:mainfrom
benjam-es:feature/device-localization
Open

feat: add Device localization support#23
benjam-es wants to merge 2 commits intoNativePHP:mainfrom
benjam-es:feature/device-localization

Conversation

@benjam-es
Copy link

Summary

  • Add localization() method to Device returning an immutable Localization value object
  • Exposes locale, language code, region code, timezone, currency code, and preferred language via the Device.GetLocale bridge function
  • Add Localization data object under Native\Mobile\Data namespace
  • Update Device facade docblock

@benjam-es
Copy link
Author

Linked PR: NativePHP/mobile-device#1

Return device locale, language, region, timezone, currency, and
preferred language via the Device.GetLocale bridge function as an
immutable Localization data object.
@benjam-es benjam-es force-pushed the feature/device-localization branch from 77e8a2b to f29767d Compare February 19, 2026 21:21
@benjam-es
Copy link
Author

Screenshot 2026-02-19 at 21 58 09

Working example

When two or more locales are configured via `nativephp.locales`,
the build now injects CFBundleLocalizations into Info.plist (iOS)
and generates locales_config.xml with a manifest reference (Android).
This fixes iOS reporting incorrect Locale.current and enables the
per-app language picker on Android 13+.
@benjam-es benjam-es closed this Feb 20, 2026
@benjam-es
Copy link
Author

This adds build-time locale support to go alongside the Device::localization() method from the previous commit.

What it does:

On iOS, if your app doesn't declare CFBundleLocalizations in Info.plist, the system scopes Locale.current to just the bundle's development region — so even if the user's phone is set to French, your app sees English. This fixes that by injecting the localizations array into both Info.plist files during the build.

On Android, Locale.getDefault() already works fine regardless, but Android 13+ has a per-app language picker in system settings that only shows up if the app ships a locales_config.xml. This generates that file and wires it into the manifest.

How to use it:

Add the locales your app supports to config/nativephp.php:

'locales' => ['en', 'fr', 'es', 'de'],

If the array has fewer than two entries (or is empty), nothing happens — it's fully opt-in and a single locale is a no-op on both platforms.

What changed:

  • config/nativephp.php — new locales key
  • BuildIosAppCommandupdateLocalizationConfig() injects CFBundleLocalizations into plists
  • PreparesBuildupdateLocalizationConfiguration() generates locales_config.xml and updates the manifest
  • tests/Unit/LocalizationConfigTest.php — 6 tests covering injection, replacement, skip behaviour, cleanup, and idempotency
  • tests/Concerns/MocksPreparesBuildDependencies.php — extracted the shared trait stubs that were duplicated across test files

@simonhamp
Copy link
Member

Wouldn't intl support in PHP take care of this more cleanly?

@benjam-es
Copy link
Author

@simonhamp Tested this — without CFBundleLocalizations, the app always returned English regardless of device language. iOS scopes the locale at the process level to the bundle's development region, so intl would hit the same wall since it reads from the same OS source.

The build-time config tells iOS "this app supports these languages" which unblocks correct locale reporting for everything inside the app. Without it, the App Store listing also only shows the development region language, and the app won't appear in the iOS 16+ per-app language settings.

On Android, Locale.getDefault() works without it, but locales_config.xml enables the per-app language picker on 13+.

intl is useful for formatting once you have the locale, but the native config is needed upstream so the OS actually reports the right one.

@benjam-es
Copy link
Author

Also worth noting — as we lean more into native UI elements (Edge components, native navigation, etc.), the app needs to be locale-aware at the native layer, not just in PHP. Having the device report the correct locale is foundational for that.

@simonhamp
Copy link
Member

simonhamp commented Mar 5, 2026

I'm not sure that's a fair test yet. We don't have intl support in iOS currently

I do agree that having it at the native layer does also make sense

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants