@symbiote-native/localization 3.0.2 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +42 -32
  2. package/package.json +15 -15
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @symbiote-native/localization
2
2
 
3
3
  Port of [`expo-localization`](https://docs.expo.dev/versions/latest/sdk/localization/) for
4
- [SymbioteNative](../../README.md) — the device's locale list and preferred calendar settings,
4
+ [SymbioteNative](../../README.md) - the device's locale list and preferred calendar settings,
5
5
  reachable from every adapter (React, Vue, Svelte, Solid, Angular), not just React.
6
6
 
7
7
  Built the same way as [`@symbiote-native/battery`](../battery) and
@@ -25,41 +25,41 @@ npx @symbiote-native/cli add --localization
25
25
  ```
26
26
 
27
27
  Either way: installs `@symbiote-native/localization` and wires the native autolinking
28
- automatically — see [`@symbiote-native/cli`](../cli).
28
+ automatically - see [`@symbiote-native/cli`](../cli).
29
29
 
30
30
  <details>
31
- <summary>Manual install (no CLI — installing and wiring native autolinking by hand)</summary>
31
+ <summary>Manual install (no CLI - installing and wiring native autolinking by hand)</summary>
32
32
 
33
33
  ```bash
34
34
  npm install @symbiote-native/localization
35
35
  ```
36
36
 
37
37
  Depends on `expo-localization` and `expo-modules-core` directly (regular dependencies, pinned to
38
- exact versions — never a caret range, since this package's `core/` is hand-ported against one
38
+ exact versions - never a caret range, since this package's `core/` is hand-ported against one
39
39
  specific native API shape and a newer resolve could silently drift the two apart). Never install
40
- `expo-localization` yourself, and never add the `expo` package to this project — it bundles its
40
+ `expo-localization` yourself, and never add the `expo` package to this project - it bundles its
41
41
  own Metro/Babel pipeline that conflicts with this project's own.
42
42
 
43
43
  ### Required one-time step: native autolinking wiring
44
44
 
45
45
  Unlike a plain RN native module, `expo-localization`'s native code is discovered by
46
- `expo-modules-autolinking`, not RN's own `react-native.config.cjs` mechanism — this needs wiring
46
+ `expo-modules-autolinking`, not RN's own `react-native.config.cjs` mechanism - this needs wiring
47
47
  into the native host app **once**, covering this package and every other `expo-modules-core`
48
48
  package (`@symbiote-native/battery`, `@symbiote-native/device`, ...) with zero further changes:
49
49
 
50
50
  | Platform | Touches |
51
51
  | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
52
- | iOS | `ios/Podfile` — add `use_expo_modules!` |
53
- | iOS | `AppDelegate.swift` — Expo's runtime-bootstrap hook |
54
- | Android | `settings.gradle` / `app/build.gradle` — resolve and include the Expo Gradle projects |
55
- | Android | `MainApplication.kt` — Expo's bootstrap hook, plus a hand-written native-module name map (there's no `expo` meta-package here to auto-generate one) |
52
+ | iOS | `ios/Podfile` - add `use_expo_modules!` |
53
+ | iOS | `AppDelegate.swift` - Expo's runtime-bootstrap hook |
54
+ | Android | `settings.gradle` / `app/build.gradle` - resolve and include the Expo Gradle projects |
55
+ | Android | `MainApplication.kt` - Expo's bootstrap hook, plus a hand-written native-module name map (there's no `expo` meta-package here to auto-generate one) |
56
56
 
57
- Full mechanics — the Podfile pieces that normally ship inside the `expo` package, the `expo`
58
- peer-dependency exclusion list — live in the `symbiote-expo-native-module` skill. Reference
57
+ Full mechanics - the Podfile pieces that normally ship inside the `expo` package, the `expo`
58
+ peer-dependency exclusion list - live in the `symbiote-expo-native-module` skill. Reference
59
59
  implementation: `examples/expo-react/ios/Podfile` and
60
60
  `examples/expo-react/android/app/src/main/java/com/canaryexpo/MainApplication.kt`.
61
61
 
62
- No platform permission string is needed — locale and calendar settings are read-only system
62
+ No platform permission string is needed - locale and calendar settings are read-only system
63
63
  state with no runtime permission prompt on either platform.
64
64
 
65
65
  </details>
@@ -67,33 +67,33 @@ state with no runtime permission prompt on either platform.
67
67
  ## Shape
68
68
 
69
69
  ```
70
- src/core/ types.ts — Locale, Weekday, CalendarIdentifier, Calendar, hand-ported
70
+ src/core/ types.ts - Locale, Weekday, CalendarIdentifier, Calendar, hand-ported
71
71
  verbatim from Localization.types.ts. native-module.ts resolves the
72
72
  native module through expo-modules-core's requireNativeModule and
73
- exposes addLocaleListener/addCalendarListener. localization.ts —
73
+ exposes addLocaleListener/addCalendarListener. localization.ts,
74
74
  getLocales/getCalendars, synchronous getters delegating straight to the
75
75
  native module.
76
- src/react/hooks/ @symbiote-native/localization/react — useLocales, useCalendars
77
- src/vue/composables/ @symbiote-native/localization/vue — same two names, Vue lifecycle
78
- src/svelte/runes/ @symbiote-native/localization/svelte — same two names, read as `.current`
79
- src/solid/primitives/ @symbiote-native/localization/solid — createLocales, createCalendars
76
+ src/react/hooks/ @symbiote-native/localization/react - useLocales, useCalendars
77
+ src/vue/composables/ @symbiote-native/localization/vue - same two names, Vue lifecycle
78
+ src/svelte/runes/ @symbiote-native/localization/svelte - same two names, read as `.current`
79
+ src/solid/primitives/ @symbiote-native/localization/solid - createLocales, createCalendars
80
80
  (each returns an Accessor)
81
- src/angular/services/ @symbiote-native/localization/angular — LocalesService, CalendarsService
81
+ src/angular/services/ @symbiote-native/localization/angular - LocalesService, CalendarsService
82
82
  (`.connect()` returns a Signal)
83
83
  ```
84
84
 
85
85
  Two independent getters, each with its own native change listener and its own reactive hook per
86
- adapter — mirroring `@symbiote-native/battery`'s shape of shipping several distinct hooks in one
86
+ adapter - mirroring `@symbiote-native/battery`'s shape of shipping several distinct hooks in one
87
87
  package, not one combined hook. Solid's naming differs on purpose: `create*`, not `use*`, which
88
88
  Solid reserves for consuming something that already exists. Each hook/composable/rune/primitive/
89
89
  service seeds its return value from the
90
- matching synchronous `get*()` call (no initial "loading" state needed — the native call is
90
+ matching synchronous `get*()` call (no initial "loading" state needed - the native call is
91
91
  sync, not async) and recomputes it whenever the matching listener fires.
92
92
 
93
93
  ## Use it
94
94
 
95
95
  ```tsx
96
- // React — examples/expo-react/screens/LocalizationScreen.tsx
96
+ // React - examples/expo-react/screens/LocalizationScreen.tsx
97
97
  import { useLocales, useCalendars } from '@symbiote-native/localization/react';
98
98
 
99
99
  function LocalizationScreen() {
@@ -110,7 +110,7 @@ function LocalizationScreen() {
110
110
  ```
111
111
 
112
112
  ```vue
113
- <!-- Vue — examples/expo-vue-sfc/screens/LocalizationScreen.vue -->
113
+ <!-- Vue - examples/expo-vue-sfc/screens/LocalizationScreen.vue -->
114
114
  <script setup lang="ts">
115
115
  import { useLocales, useCalendars } from '@symbiote-native/localization/vue';
116
116
 
@@ -140,7 +140,7 @@ const calendars = useCalendars(); // Ref<Calendar[]>
140
140
  ```
141
141
 
142
142
  ```tsx
143
- // Solid — an accessor per getter; call it to read, so a component body that runs once still
143
+ // Solid - an accessor per getter; call it to read, so a component body that runs once still
144
144
  // re-renders the leaf that reads it.
145
145
  import {
146
146
  createLocales,
@@ -161,7 +161,7 @@ function LocalizationScreen() {
161
161
  ```
162
162
 
163
163
  ```ts
164
- // Angular — examples/expo-angular/src/screens/LocalizationScreen.ts
164
+ // Angular - examples/expo-angular/src/screens/LocalizationScreen.ts
165
165
  import { Component, inject } from '@angular/core';
166
166
  import {
167
167
  LocalesService,
@@ -179,7 +179,7 @@ export class LocalizationScreen {
179
179
 
180
180
  Two independent synchronous getters (`getLocales`, `getCalendars`), each with its own
181
181
  listener-based subscription (`addLocaleListener`/`addCalendarListener`) and its own adapter-level
182
- lifecycle hook — one hook/composable/service per getter, matching upstream's own `useLocales`/
182
+ lifecycle hook - one hook/composable/service per getter, matching upstream's own `useLocales`/
183
183
  `useCalendars` being two separate hooks, not one combined hook.
184
184
 
185
185
  ```ts
@@ -189,7 +189,7 @@ addLocaleListener(listener): EventSubscription // fires when loc
189
189
  addCalendarListener(listener): EventSubscription // fires when calendar settings change
190
190
  ```
191
191
 
192
- Plus `Locale`, `Weekday` (enum), `CalendarIdentifier` (enum), `Calendar` — ported from upstream's
192
+ Plus `Locale`, `Weekday` (enum), `CalendarIdentifier` (enum), `Calendar` - ported from upstream's
193
193
  `Localization.types.ts`.
194
194
 
195
195
  ```ts
@@ -211,16 +211,26 @@ import {
211
211
  ```
212
212
 
213
213
  Each hook/composable/service seeds its initial value from the matching synchronous `get*()`
214
- call, then subscribes to the matching listener for updates, and unsubscribes on unmount —
214
+ call, then subscribes to the matching listener for updates, and unsubscribes on unmount:
215
215
  mirroring upstream's own `useLocales`/`useCalendars`.
216
216
 
217
+ ## Common questions
218
+
219
+ - **Locale changed in Settings, app shows the old one.** On Android re-read the locales when the
220
+ app returns to the foreground (`AppState`); on iOS they stay fixed while the app runs.
221
+ - **Empty `getLocales()`?** No, it has at least one entry, in the user's order.
222
+ - **In-app language picker?** Often unnecessary: iOS and Android support per-app language.
223
+
224
+ Sources: [Expo docs: Localization](https://docs.expo.dev/versions/latest/sdk/localization/),
225
+ [React Native localization with Expo](https://better-i18n.com/en/blog/react-native-expo-localization/).
226
+
217
227
  ## Test it
218
228
 
219
- No Fabric/Descriptor angle at all — localization is a pure synchronous-function + `EventEmitter`
229
+ No Fabric/Descriptor angle at all - localization is a pure synchronous-function + `EventEmitter`
220
230
  listener surface, never a view. Tests inject a fake native-module object in place of the real
221
231
  `requireNativeModule` resolution (`src/core/localization.test.ts`,
222
232
  `src/{react,vue,svelte,solid,angular}/**/*.test.{ts,tsx}`, `vitest`), the same pattern
223
- `@symbiote-native/battery` and `@symbiote-native/device` use — no `installFabric()`, no
233
+ `@symbiote-native/battery` and `@symbiote-native/device` use - no `installFabric()`, no
224
234
  ViewConfig for the core test; the adapter hook/composable/service tests do use `installFabric()`
225
235
  purely to mount a host component, same as every other sibling package. Native rendering itself is
226
- verified on-device — see the parent [README](../../README.md).
236
+ verified on-device - see the parent [README](../../README.md).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbiote-native/localization",
3
- "version": "3.0.2",
3
+ "version": "3.0.3",
4
4
  "description": "expo-localization wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, Svelte, Solid, and Angular adapters. Two independent synchronous getters (getLocales, getCalendars), each with its own native change listener and its own reactive hook per adapter.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -70,7 +70,7 @@
70
70
  },
71
71
  "dependencies": {
72
72
  "expo-localization": "57.0.1",
73
- "expo-modules-core": "57.0.5"
73
+ "expo-modules-core": "57.0.20"
74
74
  },
75
75
  "peerDependencies": {
76
76
  "@angular/core": ">=20",
@@ -80,12 +80,12 @@
80
80
  "solid-js": ">=1.9.0",
81
81
  "svelte": ">=5.56.0",
82
82
  "vue": ">=3.5.0",
83
- "@symbiote-native/angular": "^3.1.2",
84
- "@symbiote-native/engine": "^1.3.1",
85
- "@symbiote-native/react": "^3.0.4",
86
- "@symbiote-native/solid": "^3.0.4",
87
- "@symbiote-native/svelte": "^3.0.4",
88
- "@symbiote-native/vue": "^3.0.4"
83
+ "@symbiote-native/angular": "^3.2.0",
84
+ "@symbiote-native/engine": "^1.5.0",
85
+ "@symbiote-native/react": "^3.2.0",
86
+ "@symbiote-native/solid": "^3.1.0",
87
+ "@symbiote-native/svelte": "^3.1.0",
88
+ "@symbiote-native/vue": "^3.2.0"
89
89
  },
90
90
  "peerDependenciesMeta": {
91
91
  "@symbiote-native/angular": {
@@ -133,13 +133,13 @@
133
133
  "solid-js": "^1.9.14",
134
134
  "svelte": "^5.56.0",
135
135
  "typescript": "~6.0.0",
136
- "@symbiote-native/angular": "3.1.2",
137
- "@symbiote-native/engine": "1.3.1",
138
- "@symbiote-native/react": "3.0.4",
139
- "@symbiote-native/solid": "3.0.4",
140
- "@symbiote-native/svelte": "3.0.4",
141
- "@symbiote-native/test-utils": "0.4.4",
142
- "@symbiote-native/vue": "3.0.4"
136
+ "@symbiote-native/angular": "3.2.0",
137
+ "@symbiote-native/engine": "1.5.0",
138
+ "@symbiote-native/react": "3.2.0",
139
+ "@symbiote-native/solid": "3.1.0",
140
+ "@symbiote-native/svelte": "3.1.0",
141
+ "@symbiote-native/test-utils": "0.4.6",
142
+ "@symbiote-native/vue": "3.2.0"
143
143
  },
144
144
  "scripts": {
145
145
  "typecheck": "tsc --build",