@ankhorage/orchestrator-module-expo-localization 0.1.2 → 0.1.4

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @ankhorage/orchestrator-module-expo-localization
2
2
 
3
+ ## 0.1.4
4
+
5
+ ### Patch Changes
6
+
7
+ - ee45f8e: Update packages
8
+
9
+ ## 0.1.3
10
+
11
+ ### Patch Changes
12
+
13
+ - 35a8eab: Generate localization wiring through `@ankh/runtime` renderer config (prop resolver + `setLanguage` action handler) instead of Surface translation context.
14
+
3
15
  ## 0.1.2
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -3,14 +3,17 @@
3
3
  Adds localization support to Expo apps.
4
4
 
5
5
  ## 🎯 What you get
6
+
6
7
  - Localization setup instantly
7
8
  - No boilerplate
8
9
  - Fully reversible
9
10
 
10
11
  ## 📦 Usage
12
+
11
13
  ```ts
12
- orchestrator.install('expo-localization')
14
+ orchestrator.install('expo-localization');
13
15
  ```
14
16
 
15
17
  ## 🧠 Why this exists
18
+
16
19
  Standardizes localization setup across apps.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { expoLocalizationModule } from './module';
2
1
  export { type ExpoLocalizationModuleConfig, parseExpoLocalizationModuleConfig } from './config';
3
2
  export { EXPO_LOCALIZATION_MODULE_ID, expoLocalizationModule } from './module';
4
- export default expoLocalizationModule;
5
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAElD,OAAO,EAAE,KAAK,4BAA4B,EAAE,iCAAiC,EAAE,MAAM,UAAU,CAAC;AAChG,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAE/E,eAAe,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,4BAA4B,EAAE,iCAAiC,EAAE,MAAM,UAAU,CAAC;AAChG,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,3 @@
1
- import { expoLocalizationModule } from './module';
2
1
  export { parseExpoLocalizationModuleConfig } from './config';
3
2
  export { EXPO_LOCALIZATION_MODULE_ID, expoLocalizationModule } from './module';
4
- export default expoLocalizationModule;
5
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAElD,OAAO,EAAqC,iCAAiC,EAAE,MAAM,UAAU,CAAC;AAChG,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAE/E,eAAe,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqC,iCAAiC,EAAE,MAAM,UAAU,CAAC;AAChG,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"templateFiles.d.ts","sourceRoot":"","sources":["../src/templateFiles.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AASpE,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAChD,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACtD,GAAG,oBAAoB,EAAE,CAoCzB"}
1
+ {"version":3,"file":"templateFiles.d.ts","sourceRoot":"","sources":["../src/templateFiles.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AASpE,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAChD,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACtD,GAAG,oBAAoB,EAAE,CAyCzB"}
@@ -22,6 +22,11 @@ export function buildLocalizationWriteFiles(args) {
22
22
  content: readTemplate('useT.ts.tpl'),
23
23
  overwrite: true,
24
24
  },
25
+ {
26
+ path: 'src/plugins/localization/runtimeLocalization.ts',
27
+ content: readTemplate('runtimeLocalization.ts.tpl'),
28
+ overwrite: true,
29
+ },
25
30
  {
26
31
  path: 'src/plugins/localization/LocalizationProvider.tsx',
27
32
  content: renderTemplate('LocalizationProvider.tsx.tpl', {
@@ -1 +1 @@
1
- {"version":3,"file":"templateFiles.js","sourceRoot":"","sources":["../src/templateFiles.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"templateFiles.js","sourceRoot":"","sources":["../src/templateFiles.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,10 +1,27 @@
1
1
  {
2
+ "license": "MIT",
2
3
  "name": "@ankhorage/orchestrator-module-expo-localization",
3
- "version": "0.1.2",
4
+ "version": "0.1.4",
4
5
  "description": "Expo localization module for @ankhorage/orchestrator.",
5
6
  "type": "module",
6
7
  "main": "./dist/index.js",
7
8
  "types": "./dist/index.d.ts",
9
+ "homepage": "https://github.com/ankhorage/orchestrator-module-expo-localization#readme",
10
+ "bugs": {
11
+ "url": "https://github.com/ankhorage/orchestrator-module-expo-localization/issues"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/ankhorage/orchestrator-module-expo-localization.git"
16
+ },
17
+ "keywords": [
18
+ "typescript",
19
+ "expo",
20
+ "localization",
21
+ "i18n",
22
+ "orchestrator-module",
23
+ "react-native"
24
+ ],
8
25
  "sideEffects": false,
9
26
  "files": [
10
27
  "dist",
@@ -21,29 +38,26 @@
21
38
  },
22
39
  "scripts": {
23
40
  "build": "rm -rf dist tsconfig.tsbuildinfo && bun x tsc -p tsconfig.json",
24
- "lint": "eslint . --max-warnings=0",
25
- "lint:fix": "eslint . --fix --max-warnings=0",
26
- "format": "prettier --write .",
27
- "format:check": "prettier --check .",
28
- "knip": "knip",
41
+ "lint": "ankhorage-eslint . --max-warnings=0",
42
+ "lint:fix": "ankhorage-eslint . --fix --max-warnings=0",
43
+ "format": "ankhorage-prettier --write .",
44
+ "format:check": "ankhorage-prettier --check .",
45
+ "knip": "ankhorage-knip",
29
46
  "test": "bun test",
30
47
  "changeset": "changeset",
31
- "changeset:version": "changeset version"
48
+ "version-packages": "changeset version"
32
49
  },
33
50
  "dependencies": {
34
- "@ankhorage/orchestrator": "^0.1.1"
51
+ "@ankhorage/orchestrator": "^0.2.2"
35
52
  },
36
53
  "devDependencies": {
37
- "@ankhorage/devtools": "^1.0.0",
38
- "@changesets/cli": "^2.30.0",
39
- "@types/bun": "^1.3.11",
40
- "@types/node": "^25.2.3",
41
- "eslint": "^10.2.0",
42
- "knip": "^5.83.1",
43
- "prettier": "^3.8.1",
54
+ "@ankhorage/devtools": "^1.0.6",
55
+ "@changesets/cli": "^2.31.0",
56
+ "@types/bun": "^1.3.13",
57
+ "@types/node": "^25.6.0",
44
58
  "typescript": "^5.9.3"
45
59
  },
46
- "packageManager": "bun@1.3.11",
60
+ "packageManager": "bun@1.3.13",
47
61
  "publishConfig": {
48
62
  "access": "public"
49
63
  }
@@ -1,11 +1,14 @@
1
1
  /* generated by @ankhorage/orchestrator-module-expo-localization */
2
- import React, { useEffect, useState } from "react";
2
+ import { RuntimeRendererConfigProvider } from "@ankh/runtime";
3
+ import React, { useEffect, useMemo, useState } from "react";
3
4
  import * as ExpoLocalization from "expo-localization";
4
5
  import { useTranslation } from "react-i18next";
5
6
 
6
- import { TranslationProvider } from "@ankhorage/surface";
7
-
8
7
  import { initI18n } from "./i18n";
8
+ import {
9
+ createLocalizationActionHandlers,
10
+ createLocalizationNodePropsResolver,
11
+ } from "./runtimeLocalization";
9
12
 
10
13
  export interface LocalizationPluginConfig {
11
14
  defaultLocale?: string;
@@ -45,9 +48,18 @@ __RESOURCE_LINES__
45
48
  }
46
49
  }, [currentLocale, i18n.language]);
47
50
 
51
+ const runtimeRendererConfig = useMemo(() => {
52
+ const translate = i18n.isInitialized ? t : (key: string) => key;
53
+
54
+ return {
55
+ resolveNodeProps: createLocalizationNodePropsResolver(translate),
56
+ actionHandlers: createLocalizationActionHandlers(i18n),
57
+ };
58
+ }, [i18n, i18n.isInitialized, i18n.language, t]);
59
+
48
60
  return (
49
- <TranslationProvider t={i18n.isInitialized ? t : (key: string) => key} i18n={i18n}>
61
+ <RuntimeRendererConfigProvider value={runtimeRendererConfig}>
50
62
  {children}
51
- </TranslationProvider>
63
+ </RuntimeRendererConfigProvider>
52
64
  );
53
65
  }
@@ -0,0 +1,106 @@
1
+ /* generated by @ankhorage/orchestrator-module-expo-localization */
2
+ import type { RuntimeActionHandlers, RuntimeNodePropsResolver } from "@ankh/runtime";
3
+ import type { i18n as I18nInstance } from "i18next";
4
+
5
+ const LOCALIZED_PROP_PAIRS = [
6
+ ["i18nKey", "text"],
7
+ ["titleI18nKey", "title"],
8
+ ["descriptionI18nKey", "description"],
9
+ ["eyebrowI18nKey", "eyebrow"],
10
+ ["labelI18nKey", "label"],
11
+ ["helperTextI18nKey", "helperText"],
12
+ ["errorTextI18nKey", "errorText"],
13
+ ["metaI18nKey", "meta"],
14
+ ["childrenI18nKey", "children"],
15
+ ] as const;
16
+
17
+ function isNonEmptyString(value: unknown): value is string {
18
+ return typeof value === "string" && value.length > 0;
19
+ }
20
+
21
+ function hasOwnProp(props: Record<string, unknown>, key: string) {
22
+ return Object.prototype.hasOwnProperty.call(props, key);
23
+ }
24
+
25
+ function isRecord(value: unknown): value is Record<string, unknown> {
26
+ return typeof value === "object" && value !== null;
27
+ }
28
+
29
+ function resolveLocalizedPropValue(args: {
30
+ props: Record<string, unknown>;
31
+ keyProp: string;
32
+ targetProp: string;
33
+ translate: (key: string) => string;
34
+ }): string | undefined {
35
+ const { props, keyProp, targetProp, translate } = args;
36
+ const key = props[keyProp];
37
+
38
+ if (!isNonEmptyString(key)) {
39
+ return undefined;
40
+ }
41
+
42
+ const translated = translate(key);
43
+ if (isNonEmptyString(translated) && translated !== key) {
44
+ return translated;
45
+ }
46
+
47
+ if (hasOwnProp(props, targetProp)) {
48
+ return undefined;
49
+ }
50
+
51
+ return key;
52
+ }
53
+
54
+ function isSetLanguageAction(action: {
55
+ type: string;
56
+ payload?: unknown;
57
+ }): action is {
58
+ type: "setLanguage";
59
+ payload: { locale: string };
60
+ } {
61
+ return (
62
+ action.type === "setLanguage" &&
63
+ isRecord(action.payload) &&
64
+ isNonEmptyString(action.payload.locale)
65
+ );
66
+ }
67
+
68
+ export function createLocalizationNodePropsResolver(
69
+ translate: (key: string) => string,
70
+ ): RuntimeNodePropsResolver {
71
+ return ({ props }) => {
72
+ let resolvedProps: Record<string, unknown> | undefined;
73
+
74
+ for (const [keyProp, targetProp] of LOCALIZED_PROP_PAIRS) {
75
+ const localizedValue = resolveLocalizedPropValue({
76
+ props,
77
+ keyProp,
78
+ targetProp,
79
+ translate,
80
+ });
81
+
82
+ if (localizedValue === undefined) {
83
+ continue;
84
+ }
85
+
86
+ resolvedProps ??= { ...props };
87
+ resolvedProps[targetProp] = localizedValue;
88
+ }
89
+
90
+ return resolvedProps ?? props;
91
+ };
92
+ }
93
+
94
+ export function createLocalizationActionHandlers(
95
+ i18n: Pick<I18nInstance, "changeLanguage">,
96
+ ): RuntimeActionHandlers {
97
+ return {
98
+ setLanguage: ({ action }) => {
99
+ if (!isSetLanguageAction(action)) {
100
+ return;
101
+ }
102
+
103
+ void i18n.changeLanguage(action.payload.locale);
104
+ },
105
+ };
106
+ }