expo-localization 12.0.0 → 13.1.0

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
@@ -10,6 +10,40 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 13.1.0 — 2022-07-07
14
+
15
+ ### 🎉 New features
16
+
17
+ - Native module on Android is now written in Kotlin using the new API. ([#17775](https://github.com/expo/expo/pull/17775) by [@barthap](https://github.com/barthap))
18
+
19
+ ### 💡 Others
20
+
21
+ - Migrated Expo modules definitions to the new naming convention. ([#17193](https://github.com/expo/expo/pull/17193) by [@tsapeta](https://github.com/tsapeta))
22
+
23
+ ## 13.0.0 — 2022-04-18
24
+
25
+ ### 🛠 Breaking changes
26
+
27
+ - Guess the device language on iOS rather than using the app-specific language. ([#15807](https://github.com/expo/expo/pull/15807) by [@EvanBacon](https://github.com/EvanBacon))
28
+
29
+ ### 🎉 New features
30
+
31
+ - Use JSI host object instead of the bridge module for communication between JavaScript and native code. ([#16972](https://github.com/expo/expo/pull/16972) by [@tsapeta](https://github.com/tsapeta))
32
+
33
+ ### 🐛 Bug fixes
34
+
35
+ - Exception in HostObject::get for prop 'NativeUnimoduleProxy': java.lang.NullPointerException ([#16316](https://github.com/expo/expo/pull/16316) by [@nomi9995](https://github.com/nomi9995))
36
+
37
+ ### ⚠️ Notices
38
+
39
+ - On Android bump `compileSdkVersion` to `31`, `targetSdkVersion` to `31` and `Java` version to `11`. ([#16941](https://github.com/expo/expo/pull/16941) by [@bbarthec](https://github.com/bbarthec))
40
+
41
+ ## 12.0.1 - 2022-02-01
42
+
43
+ ### 🐛 Bug fixes
44
+
45
+ - Fix `Plugin with id 'maven' not found` build error from Android Gradle 7. ([#16080](https://github.com/expo/expo/pull/16080) by [@kudo](https://github.com/kudo))
46
+
13
47
  ## 12.0.0 — 2021-12-03
14
48
 
15
49
  ### 🎉 New features
package/README.md CHANGED
@@ -4,12 +4,12 @@ Provides an interface for native user localization information.
4
4
 
5
5
  # API documentation
6
6
 
7
- - [Documentation for the master branch](https://github.com/expo/expo/blob/master/docs/pages/versions/unversioned/sdk/localization.md)
8
- - [Documentation for the latest stable release](https://docs.expo.io/versions/latest/sdk/localization/)
7
+ - [Documentation for the main branch](https://github.com/expo/expo/blob/main/docs/pages/versions/unversioned/sdk/localization.md)
8
+ - [Documentation for the latest stable release](https://docs.expo.dev/versions/latest/sdk/localization/)
9
9
 
10
10
  # Installation in managed Expo projects
11
11
 
12
- For managed [managed](https://docs.expo.io/versions/latest/introduction/managed-vs-bare/) Expo projects, please follow the installation instructions in the [API documentation for the latest stable release](https://docs.expo.io/versions/latest/sdk/localization/).
12
+ For [managed](https://docs.expo.dev/versions/latest/introduction/managed-vs-bare/) Expo projects, please follow the installation instructions in the [API documentation for the latest stable release](https://docs.expo.dev/versions/latest/sdk/localization/).
13
13
 
14
14
  # Installation in bare React Native projects
15
15
 
@@ -1,63 +1,80 @@
1
1
  apply plugin: 'com.android.library'
2
2
  apply plugin: 'kotlin-android'
3
- apply plugin: 'maven'
3
+ apply plugin: 'maven-publish'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '12.0.0'
6
+ version = '13.1.0'
7
7
 
8
8
  buildscript {
9
+ def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
10
+ if (expoModulesCorePlugin.exists()) {
11
+ apply from: expoModulesCorePlugin
12
+ applyKotlinExpoModulesCorePlugin()
13
+ }
14
+
9
15
  // Simple helper that allows the root project to override versions declared by this library.
10
16
  ext.safeExtGet = { prop, fallback ->
11
17
  rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
12
18
  }
13
19
 
20
+ // Ensures backward compatibility
21
+ ext.getKotlinVersion = {
22
+ if (ext.has("kotlinVersion")) {
23
+ ext.kotlinVersion()
24
+ } else {
25
+ ext.safeExtGet("kotlinVersion", "1.6.10")
26
+ }
27
+ }
28
+
14
29
  repositories {
15
30
  mavenCentral()
16
31
  }
17
32
 
18
33
  dependencies {
19
- classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${safeExtGet('kotlinVersion', '1.4.21')}")
34
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${getKotlinVersion()}")
20
35
  }
21
36
  }
22
37
 
23
- // Upload android library to maven with javadoc and android sources
24
- configurations {
25
- deployerJars
26
- }
27
-
28
38
  // Creating sources with comments
29
39
  task androidSourcesJar(type: Jar) {
30
40
  classifier = 'sources'
31
41
  from android.sourceSets.main.java.srcDirs
32
42
  }
33
43
 
34
- // Put the androidSources and javadoc to the artifacts
35
- artifacts {
36
- archives androidSourcesJar
37
- }
38
-
39
- uploadArchives {
40
- repositories {
41
- mavenDeployer {
42
- configuration = configurations.deployerJars
43
- repository(url: mavenLocal().url)
44
+ afterEvaluate {
45
+ publishing {
46
+ publications {
47
+ release(MavenPublication) {
48
+ from components.release
49
+ // Add additional sourcesJar to artifacts
50
+ artifact(androidSourcesJar)
51
+ }
52
+ }
53
+ repositories {
54
+ maven {
55
+ url = mavenLocal().url
56
+ }
44
57
  }
45
58
  }
46
59
  }
47
60
 
48
61
  android {
49
- compileSdkVersion safeExtGet("compileSdkVersion", 30)
62
+ compileSdkVersion safeExtGet("compileSdkVersion", 31)
50
63
 
51
64
  compileOptions {
52
- sourceCompatibility JavaVersion.VERSION_1_8
53
- targetCompatibility JavaVersion.VERSION_1_8
65
+ sourceCompatibility JavaVersion.VERSION_11
66
+ targetCompatibility JavaVersion.VERSION_11
67
+ }
68
+
69
+ kotlinOptions {
70
+ jvmTarget = JavaVersion.VERSION_11.majorVersion
54
71
  }
55
72
 
56
73
  defaultConfig {
57
74
  minSdkVersion safeExtGet("minSdkVersion", 21)
58
- targetSdkVersion safeExtGet("targetSdkVersion", 30)
75
+ targetSdkVersion safeExtGet("targetSdkVersion", 31)
59
76
  versionCode 22
60
- versionName "12.0.0"
77
+ versionName "13.1.0"
61
78
  }
62
79
  lintOptions {
63
80
  abortOnError false
@@ -67,5 +84,6 @@ android {
67
84
  dependencies {
68
85
  implementation project(':expo-modules-core')
69
86
 
70
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${safeExtGet('kotlinVersion', '1.4.21')}"
87
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
88
+ implementation "androidx.core:core-ktx:1.6.0"
71
89
  }
@@ -3,67 +3,56 @@ package expo.modules.localization
3
3
  import android.os.Bundle
4
4
  import android.view.View
5
5
  import android.text.TextUtils
6
- import android.content.Context
7
6
  import android.os.Build.VERSION
8
7
  import android.os.Build.VERSION_CODES
8
+ import androidx.core.os.bundleOf
9
9
 
10
- import expo.modules.core.Promise
11
- import expo.modules.core.ExportedModule
12
- import expo.modules.core.interfaces.ExpoMethod
10
+ import expo.modules.kotlin.modules.Module
11
+ import expo.modules.kotlin.modules.ModuleDefinition
13
12
 
14
13
  import kotlin.collections.ArrayList
15
- import java.lang.ref.WeakReference
16
14
  import java.text.DecimalFormatSymbols
17
15
  import java.util.*
18
16
 
19
- class LocalizationModule(context: Context) : ExportedModule(context) {
20
- private val contextRef: WeakReference<Context> = WeakReference(context)
17
+ class LocalizationModule : Module() {
18
+ override fun definition() = ModuleDefinition {
19
+ Name("ExpoLocalization")
21
20
 
22
- private val applicationContext: Context?
23
- get() = contextRef.get()?.applicationContext
24
-
25
- override fun getName() = "ExpoLocalization"
26
-
27
- override fun getConstants(): Map<String, Any> {
28
- val constants = HashMap<String, Any>()
29
- val bundle = bundledConstants
30
- for (key in bundle.keySet()) {
31
- constants[key] = bundle[key] as Any
21
+ Constants {
22
+ bundledConstants.toShallowMap()
32
23
  }
33
- return constants
34
- }
35
24
 
36
- @ExpoMethod
37
- fun getLocalizationAsync(promise: Promise) {
38
- promise.resolve(bundledConstants)
25
+ AsyncFunction("getLocalizationAsync") {
26
+ return@AsyncFunction bundledConstants
27
+ }
39
28
  }
40
29
 
41
30
  // TODO: Bacon: add set language
42
31
  private val bundledConstants: Bundle
43
32
  get() {
44
33
  val locale = Locale.getDefault()
45
- val locales = locales
46
34
  val localeNames = getLocaleNames(locales)
47
35
  val isRTL = TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL
48
36
  val region = getRegionCode(locale)
49
37
  val symbols = DecimalFormatSymbols(locale)
50
- return Bundle().apply {
51
- putString("currency", getCurrencyCode(locale))
52
- putString("decimalSeparator", symbols.decimalSeparator.toString())
53
- putString("digitGroupingSeparator", symbols.groupingSeparator.toString())
54
- putStringArrayList("isoCurrencyCodes", iSOCurrencyCodes)
55
- putBoolean("isMetric", !USES_IMPERIAL.contains(region))
56
- putBoolean("isRTL", isRTL)
57
- putString("locale", localeNames[0])
58
- putStringArrayList("locales", localeNames)
59
- putString("region", region)
60
- putString("timezone", TimeZone.getDefault().id)
61
- }
38
+ return bundleOf(
39
+ "currency" to getCurrencyCode(locale),
40
+ "decimalSeparator" to symbols.decimalSeparator.toString(),
41
+ "digitGroupingSeparator" to symbols.groupingSeparator.toString(),
42
+ "isoCurrencyCodes" to ISOCurrencyCodes,
43
+ "isMetric" to !USES_IMPERIAL.contains(region),
44
+ "isRTL" to isRTL,
45
+ // TODO: (barthap) this can throw IndexOutOfBounds exception - handle this properly
46
+ "locale" to localeNames[0],
47
+ "locales" to localeNames,
48
+ "region" to region,
49
+ "timezone" to TimeZone.getDefault().id
50
+ )
62
51
  }
63
52
 
64
- private val locales: ArrayList<Locale>
53
+ private val locales: List<Locale>
65
54
  get() {
66
- val context = applicationContext ?: return ArrayList()
55
+ val context = appContext.reactContext ?: return emptyList()
67
56
  val configuration = context.resources.configuration
68
57
  return if (VERSION.SDK_INT > VERSION_CODES.N) {
69
58
  val locales = ArrayList<Locale>()
@@ -72,7 +61,7 @@ class LocalizationModule(context: Context) : ExportedModule(context) {
72
61
  }
73
62
  locales
74
63
  } else {
75
- arrayListOf(configuration.locale)
64
+ listOf(configuration.locale)
76
65
  }
77
66
  }
78
67
 
@@ -80,6 +69,19 @@ class LocalizationModule(context: Context) : ExportedModule(context) {
80
69
  val miuiRegion = getSystemProperty("ro.miui.region")
81
70
  return if (!TextUtils.isEmpty(miuiRegion)) {
82
71
  miuiRegion
83
- } else getCountryCode(locale)
72
+ } else {
73
+ getCountryCode(locale)
74
+ }
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Creates a shallow [Map] from the [Bundle]. Does not traverse nested arrays and bundles.
80
+ */
81
+ private fun Bundle.toShallowMap(): Map<String, Any?> {
82
+ val map = HashMap<String, Any?>()
83
+ for (key in this.keySet()) {
84
+ map[key] = this[key]
84
85
  }
86
+ return map
85
87
  }
@@ -2,15 +2,14 @@ package expo.modules.localization
2
2
 
3
3
  import android.text.TextUtils
4
4
  import java.util.*
5
- import kotlin.collections.ArrayList
6
5
 
7
6
  val USES_IMPERIAL = listOf("US", "LR", "MM")
8
7
 
9
- val iSOCurrencyCodes: ArrayList<String> by lazy {
10
- Currency.getAvailableCurrencies().map { it.currencyCode as String } as ArrayList<String>
8
+ val ISOCurrencyCodes: Array<String> by lazy {
9
+ Currency.getAvailableCurrencies().map { it.currencyCode as String }.toTypedArray()
11
10
  }
12
11
 
13
- fun getLocaleNames(locales: ArrayList<Locale>) = locales.map { it.toLanguageTag() } as ArrayList
12
+ fun getLocaleNames(locales: List<Locale>) = locales.map { it.toLanguageTag() }.toTypedArray()
14
13
 
15
14
  fun getCountryCode(locale: Locale): String? {
16
15
  return runCatching {
@@ -13,3 +13,4 @@ declare const _default: {
13
13
  getLocalizationAsync(): Promise<Localization>;
14
14
  };
15
15
  export default _default;
16
+ //# sourceMappingURL=ExpoLocalization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpoLocalization.d.ts","sourceRoot":"","sources":["../src/ExpoLocalization.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;;;;;;;;;;;;4BAqEpB,QAAQ,YAAY,CAAC;;AAnErD,wBA6FE"}
@@ -1,2 +1,3 @@
1
- declare const _default: import("expo-modules-core").ProxyNativeModule;
1
+ declare const _default: any;
2
2
  export default _default;
3
+ //# sourceMappingURL=ExpoLocalization.native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpoLocalization.native.d.ts","sourceRoot":"","sources":["../src/ExpoLocalization.native.ts"],"names":[],"mappings":";AAEA,wBAAuD"}
@@ -1,3 +1,3 @@
1
- import { NativeModulesProxy } from 'expo-modules-core';
2
- export default NativeModulesProxy.ExpoLocalization;
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ export default requireNativeModule('ExpoLocalization');
3
3
  //# sourceMappingURL=ExpoLocalization.native.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoLocalization.native.js","sourceRoot":"","sources":["../src/ExpoLocalization.native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,eAAe,kBAAkB,CAAC,gBAAgB,CAAC","sourcesContent":["import { NativeModulesProxy } from 'expo-modules-core';\n\nexport default NativeModulesProxy.ExpoLocalization;\n"]}
1
+ {"version":3,"file":"ExpoLocalization.native.js","sourceRoot":"","sources":["../src/ExpoLocalization.native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,eAAe,mBAAmB,CAAC,kBAAkB,CAAC,CAAC","sourcesContent":["import { requireNativeModule } from 'expo-modules-core';\n\nexport default requireNativeModule('ExpoLocalization');\n"]}
@@ -44,6 +44,8 @@ export declare const locale: string;
44
44
  /**
45
45
  * List of all the native languages provided by the user settings.
46
46
  * These are returned in the order the user defines in their device settings.
47
+ *
48
+ * @example `['en', 'en-US', 'zh-Hans', 'zh-Hans-CN', 'en-emodeng']`
47
49
  */
48
50
  export declare const locales: string[];
49
51
  /**
@@ -76,3 +78,4 @@ export declare const region: string | null;
76
78
  * ```
77
79
  */
78
80
  export declare function getLocalizationAsync(): Promise<Localization>;
81
+ //# sourceMappingURL=Localization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Localization.d.ts","sourceRoot":"","sources":["../src/Localization.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,YAAY,EAAE,CAAC;AAGxB;;;;GAIG;AACH,eAAO,MAAM,QAAQ,eAA4B,CAAC;AAGlD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,QAAoC,CAAC;AAGlE;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,QAA0C,CAAC;AAG9E;;GAEG;AACH,eAAO,MAAM,gBAAgB,UAAoC,CAAC;AAGlE;;;GAGG;AACH,eAAO,MAAM,QAAQ,SAA4B,CAAC;AAGlD;;;;;GAKG;AACH,eAAO,MAAM,KAAK,SAAyB,CAAC;AAG5C;;;;;GAKG;AACH,eAAO,MAAM,MAAM,QAA0B,CAAC;AAG9C;;;;;GAKG;AACH,eAAO,MAAM,OAAO,UAA2B,CAAC;AAGhD;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,QAA4B,CAAC;AAGlD;;;;;GAKG;AACH,eAAO,MAAM,MAAM,eAA0B,CAAC;AAG9C;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,YAAY,CAAC,CAElE"}
@@ -51,6 +51,8 @@ export const locale = ExpoLocalization.locale;
51
51
  /**
52
52
  * List of all the native languages provided by the user settings.
53
53
  * These are returned in the order the user defines in their device settings.
54
+ *
55
+ * @example `['en', 'en-US', 'zh-Hans', 'zh-Hans-CN', 'en-emodeng']`
54
56
  */
55
57
  export const locales = ExpoLocalization.locales;
56
58
  // @needsAudit
@@ -1 +1 @@
1
- {"version":3,"file":"Localization.js","sourceRoot":"","sources":["../src/Localization.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAKlD,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC;AAElD,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,gBAAgB,CAAC;AAElE,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,gBAAgB,CAAC,sBAAsB,CAAC;AAE9E,cAAc;AACd;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,gBAAgB,CAAC;AAElE,cAAc;AACd;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC;AAElD,cAAc;AACd;;;;;GAKG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC;AAE5C,cAAc;AACd;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;AAE9C,cAAc;AACd;;;GAGG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,CAAC;AAEhD,cAAc;AACd;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC;AAElD,cAAc;AACd;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;AAE9C,cAAc;AACd;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,OAAO,MAAM,gBAAgB,CAAC,oBAAoB,EAAE,CAAC;AACvD,CAAC","sourcesContent":["import ExpoLocalization from './ExpoLocalization';\nimport { Localization } from './Localization.types';\n\nexport { Localization };\n\n// @needsAudit\n/**\n * Three-character ISO 4217 currency code. Returns `null` on web.\n *\n * @example `'USD'`, `'EUR'`, `'CNY'`, `null`\n */\nexport const currency = ExpoLocalization.currency;\n\n// @needsAudit\n/**\n * Decimal separator used for formatting numbers.\n *\n * @example `','`, `'.'`\n */\nexport const decimalSeparator = ExpoLocalization.decimalSeparator;\n\n// @needsAudit\n/**\n * Digit grouping separator used when formatting numbers larger than 1000.\n *\n * @example `'.'`, `''`, `','`\n */\nexport const digitGroupingSeparator = ExpoLocalization.digitGroupingSeparator;\n\n// @needsAudit\n/**\n * A list of all the supported language ISO codes.\n */\nexport const isoCurrencyCodes = ExpoLocalization.isoCurrencyCodes;\n\n// @needsAudit\n/**\n * Boolean value that indicates whether the system uses the metric system.\n * On Android and web, this is inferred from the current region.\n */\nexport const isMetric = ExpoLocalization.isMetric;\n\n// @needsAudit\n/**\n * Returns if the system's language is written from Right-to-Left.\n * This can be used to build features like [bidirectional icons](https://material.io/design/usability/bidirectionality.html).\n *\n * Returns `false` in Server Side Rendering (SSR) environments.\n */\nexport const isRTL = ExpoLocalization.isRTL;\n\n// @needsAudit\n/**\n * An [IETF BCP 47 language tag](https://en.wikipedia.org/wiki/IETF_language_tag),\n * consisting of a two-character language code and optional script, region and variant codes.\n *\n * @example `'en'`, `'en-US'`, `'zh-Hans'`, `'zh-Hans-CN'`, `'en-emodeng'`\n */\nexport const locale = ExpoLocalization.locale;\n\n// @needsAudit\n/**\n * List of all the native languages provided by the user settings.\n * These are returned in the order the user defines in their device settings.\n */\nexport const locales = ExpoLocalization.locales;\n\n// @needsAudit\n/**\n * The current time zone in display format.\n * On Web time zone is calculated with Intl.DateTimeFormat().resolvedOptions().timeZone. For a\n * better estimation you could use the moment-timezone package but it will add significant bloat to\n * your website's bundle size.\n *\n * @example `'America/Los_Angeles'`\n */\nexport const timezone = ExpoLocalization.timezone;\n\n// @needsAudit\n/**\n * The region code for your device that comes from the Region setting under Language & Region on iOS.\n * This value is always available on iOS, but might return `null` on Android or web.\n *\n * @example `'US'`, `'NZ'`, `null`\n */\nexport const region = ExpoLocalization.region;\n\n// @needsAudit\n/**\n * Get the latest native values from the device. Locale can be changed on some Android devices\n * without resetting the app.\n * > On iOS, changing the locale will cause the device to reset meaning the constants will always be\n * correct.\n *\n * @example\n * ```ts\n * // When the app returns from the background on Android...\n *\n * const { locale } = await Localization.getLocalizationAsync();\n * ```\n */\nexport async function getLocalizationAsync(): Promise<Localization> {\n return await ExpoLocalization.getLocalizationAsync();\n}\n"]}
1
+ {"version":3,"file":"Localization.js","sourceRoot":"","sources":["../src/Localization.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAKlD,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC;AAElD,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,gBAAgB,CAAC;AAElE,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,gBAAgB,CAAC,sBAAsB,CAAC;AAE9E,cAAc;AACd;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,gBAAgB,CAAC;AAElE,cAAc;AACd;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC;AAElD,cAAc;AACd;;;;;GAKG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC;AAE5C,cAAc;AACd;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;AAE9C,cAAc;AACd;;;;;GAKG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,CAAC;AAEhD,cAAc;AACd;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC;AAElD,cAAc;AACd;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;AAE9C,cAAc;AACd;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,OAAO,MAAM,gBAAgB,CAAC,oBAAoB,EAAE,CAAC;AACvD,CAAC","sourcesContent":["import ExpoLocalization from './ExpoLocalization';\nimport { Localization } from './Localization.types';\n\nexport { Localization };\n\n// @needsAudit\n/**\n * Three-character ISO 4217 currency code. Returns `null` on web.\n *\n * @example `'USD'`, `'EUR'`, `'CNY'`, `null`\n */\nexport const currency = ExpoLocalization.currency;\n\n// @needsAudit\n/**\n * Decimal separator used for formatting numbers.\n *\n * @example `','`, `'.'`\n */\nexport const decimalSeparator = ExpoLocalization.decimalSeparator;\n\n// @needsAudit\n/**\n * Digit grouping separator used when formatting numbers larger than 1000.\n *\n * @example `'.'`, `''`, `','`\n */\nexport const digitGroupingSeparator = ExpoLocalization.digitGroupingSeparator;\n\n// @needsAudit\n/**\n * A list of all the supported language ISO codes.\n */\nexport const isoCurrencyCodes = ExpoLocalization.isoCurrencyCodes;\n\n// @needsAudit\n/**\n * Boolean value that indicates whether the system uses the metric system.\n * On Android and web, this is inferred from the current region.\n */\nexport const isMetric = ExpoLocalization.isMetric;\n\n// @needsAudit\n/**\n * Returns if the system's language is written from Right-to-Left.\n * This can be used to build features like [bidirectional icons](https://material.io/design/usability/bidirectionality.html).\n *\n * Returns `false` in Server Side Rendering (SSR) environments.\n */\nexport const isRTL = ExpoLocalization.isRTL;\n\n// @needsAudit\n/**\n * An [IETF BCP 47 language tag](https://en.wikipedia.org/wiki/IETF_language_tag),\n * consisting of a two-character language code and optional script, region and variant codes.\n *\n * @example `'en'`, `'en-US'`, `'zh-Hans'`, `'zh-Hans-CN'`, `'en-emodeng'`\n */\nexport const locale = ExpoLocalization.locale;\n\n// @needsAudit\n/**\n * List of all the native languages provided by the user settings.\n * These are returned in the order the user defines in their device settings.\n *\n * @example `['en', 'en-US', 'zh-Hans', 'zh-Hans-CN', 'en-emodeng']`\n */\nexport const locales = ExpoLocalization.locales;\n\n// @needsAudit\n/**\n * The current time zone in display format.\n * On Web time zone is calculated with Intl.DateTimeFormat().resolvedOptions().timeZone. For a\n * better estimation you could use the moment-timezone package but it will add significant bloat to\n * your website's bundle size.\n *\n * @example `'America/Los_Angeles'`\n */\nexport const timezone = ExpoLocalization.timezone;\n\n// @needsAudit\n/**\n * The region code for your device that comes from the Region setting under Language & Region on iOS.\n * This value is always available on iOS, but might return `null` on Android or web.\n *\n * @example `'US'`, `'NZ'`, `null`\n */\nexport const region = ExpoLocalization.region;\n\n// @needsAudit\n/**\n * Get the latest native values from the device. Locale can be changed on some Android devices\n * without resetting the app.\n * > On iOS, changing the locale will cause the device to reset meaning the constants will always be\n * correct.\n *\n * @example\n * ```ts\n * // When the app returns from the background on Android...\n *\n * const { locale } = await Localization.getLocalizationAsync();\n * ```\n */\nexport async function getLocalizationAsync(): Promise<Localization> {\n return await ExpoLocalization.getLocalizationAsync();\n}\n"]}
@@ -2,23 +2,23 @@ export declare type Localization = {
2
2
  /**
3
3
  * Three-character ISO 4217 currency code. Returns `null` on web.
4
4
  *
5
- * @example `USD`, `EUR`, `CNY`, null
5
+ * @example `'USD'`, `'EUR'`, `'CNY'`, `null`
6
6
  */
7
7
  currency: string | null;
8
8
  /**
9
9
  * Decimal separator used for formatting numbers.
10
10
  *
11
- * @example `,`, '.'
11
+ * @example `','`, `'.'`
12
12
  */
13
13
  decimalSeparator: string;
14
14
  /**
15
15
  * Digit grouping separator used when formatting numbers larger than 1000.
16
16
  *
17
- * @example `.`, '', ','
17
+ * @example `'.'`, `''`, `','`
18
18
  */
19
19
  digitGroupingSeparator: string;
20
20
  /**
21
- * List of all the supported language ISO codes.
21
+ * A list of all the supported language ISO codes.
22
22
  */
23
23
  isoCurrencyCodes: string[];
24
24
  /**
@@ -30,35 +30,38 @@ export declare type Localization = {
30
30
  * Returns if the system's language is written from Right-to-Left.
31
31
  * This can be used to build features like [bidirectional icons](https://material.io/design/usability/bidirectionality.html).
32
32
  *
33
- * Returns `false` in SSR environments.
33
+ * Returns `false` in Server Side Rendering (SSR) environments.
34
34
  */
35
35
  isRTL: boolean;
36
36
  /**
37
37
  * An [IETF BCP 47 language tag](https://en.wikipedia.org/wiki/IETF_language_tag),
38
38
  * consisting of a two-character language code and optional script, region and variant codes.
39
39
  *
40
- * @example `en`, `en-US`, `zh-Hans`, `zh-Hans-CN`, `en-emodeng`
40
+ * @example `'en'`, `'en-US'`, `'zh-Hans'`, `'zh-Hans-CN'`, `'en-emodeng'`
41
41
  */
42
42
  locale: string;
43
43
  /**
44
- * List of all the languages provided by the user settings.
44
+ * List of all the native languages provided by the user settings.
45
45
  * These are returned in the order the user defines in their device settings.
46
46
  *
47
- * @example [`en`, `en-US`, `zh-Hans`, `zh-Hans-CN`, `en-emodeng`]
47
+ * @example `['en', 'en-US', 'zh-Hans', 'zh-Hans-CN', 'en-emodeng']`
48
48
  */
49
49
  locales: string[];
50
50
  /**
51
51
  * The region code for your device that comes from the Region setting under Language & Region on iOS.
52
52
  * This value is always available on iOS, but might return `null` on Android or web.
53
53
  *
54
- * @example `US`, `NZ`, null
54
+ * @example `'US'`, `'NZ'`, `null`
55
55
  */
56
56
  region: string | null;
57
57
  /**
58
- * The current timezone in display format.
59
- * On Web timezone is calculated with Intl.DateTimeFormat().resolvedOptions().timeZone. For a better estimation you could use the moment-timezone package but it will add significant bloat to your website's bundle size.
58
+ * The current time zone in display format.
59
+ * On Web time zone is calculated with Intl.DateTimeFormat().resolvedOptions().timeZone. For a
60
+ * better estimation you could use the moment-timezone package but it will add significant bloat to
61
+ * your website's bundle size.
60
62
  *
61
- * @example `America/Los_Angeles`
63
+ * @example `'America/Los_Angeles'`
62
64
  */
63
65
  timezone: string;
64
66
  };
67
+ //# sourceMappingURL=Localization.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Localization.types.d.ts","sourceRoot":"","sources":["../src/Localization.types.ts"],"names":[],"mappings":"AACA,oBAAY,YAAY,GAAG;IACzB;;;;OAIG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,sBAAsB,EAAE,MAAM,CAAC;IAC/B;;OAEG;IACH,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,KAAK,EAAE,OAAO,CAAC;IACf;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;OAKG;IACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Localization.types.js","sourceRoot":"","sources":["../src/Localization.types.ts"],"names":[],"mappings":"","sourcesContent":["export type Localization = {\n /**\n * Three-character ISO 4217 currency code. Returns `null` on web.\n *\n * @example `USD`, `EUR`, `CNY`, null\n */\n currency: string | null;\n /**\n * Decimal separator used for formatting numbers.\n *\n * @example `,`, '.'\n */\n decimalSeparator: string;\n /**\n * Digit grouping separator used when formatting numbers larger than 1000.\n *\n * @example `.`, '', ','\n */\n digitGroupingSeparator: string;\n /**\n * List of all the supported language ISO codes.\n */\n isoCurrencyCodes: string[];\n /**\n * Boolean value that indicates whether the system uses the metric system.\n * On Android and web, this is inferred from the current region.\n */\n isMetric: boolean;\n /**\n * Returns if the system's language is written from Right-to-Left.\n * This can be used to build features like [bidirectional icons](https://material.io/design/usability/bidirectionality.html).\n *\n * Returns `false` in SSR environments.\n */\n isRTL: boolean;\n /**\n * An [IETF BCP 47 language tag](https://en.wikipedia.org/wiki/IETF_language_tag),\n * consisting of a two-character language code and optional script, region and variant codes.\n *\n * @example `en`, `en-US`, `zh-Hans`, `zh-Hans-CN`, `en-emodeng`\n */\n locale: string;\n /**\n * List of all the languages provided by the user settings.\n * These are returned in the order the user defines in their device settings.\n *\n * @example [`en`, `en-US`, `zh-Hans`, `zh-Hans-CN`, `en-emodeng`]\n */\n locales: string[];\n /**\n * The region code for your device that comes from the Region setting under Language & Region on iOS.\n * This value is always available on iOS, but might return `null` on Android or web.\n *\n * @example `US`, `NZ`, null\n */\n region: string | null;\n /**\n * The current timezone in display format.\n * On Web timezone is calculated with Intl.DateTimeFormat().resolvedOptions().timeZone. For a better estimation you could use the moment-timezone package but it will add significant bloat to your website's bundle size.\n *\n * @example `America/Los_Angeles`\n */\n timezone: string;\n};\n"]}
1
+ {"version":3,"file":"Localization.types.js","sourceRoot":"","sources":["../src/Localization.types.ts"],"names":[],"mappings":"","sourcesContent":["// @needsAudit\nexport type Localization = {\n /**\n * Three-character ISO 4217 currency code. Returns `null` on web.\n *\n * @example `'USD'`, `'EUR'`, `'CNY'`, `null`\n */\n currency: string | null;\n /**\n * Decimal separator used for formatting numbers.\n *\n * @example `','`, `'.'`\n */\n decimalSeparator: string;\n /**\n * Digit grouping separator used when formatting numbers larger than 1000.\n *\n * @example `'.'`, `''`, `','`\n */\n digitGroupingSeparator: string;\n /**\n * A list of all the supported language ISO codes.\n */\n isoCurrencyCodes: string[];\n /**\n * Boolean value that indicates whether the system uses the metric system.\n * On Android and web, this is inferred from the current region.\n */\n isMetric: boolean;\n /**\n * Returns if the system's language is written from Right-to-Left.\n * This can be used to build features like [bidirectional icons](https://material.io/design/usability/bidirectionality.html).\n *\n * Returns `false` in Server Side Rendering (SSR) environments.\n */\n isRTL: boolean;\n /**\n * An [IETF BCP 47 language tag](https://en.wikipedia.org/wiki/IETF_language_tag),\n * consisting of a two-character language code and optional script, region and variant codes.\n *\n * @example `'en'`, `'en-US'`, `'zh-Hans'`, `'zh-Hans-CN'`, `'en-emodeng'`\n */\n locale: string;\n /**\n * List of all the native languages provided by the user settings.\n * These are returned in the order the user defines in their device settings.\n *\n * @example `['en', 'en-US', 'zh-Hans', 'zh-Hans-CN', 'en-emodeng']`\n */\n locales: string[];\n /**\n * The region code for your device that comes from the Region setting under Language & Region on iOS.\n * This value is always available on iOS, but might return `null` on Android or web.\n *\n * @example `'US'`, `'NZ'`, `null`\n */\n region: string | null;\n /**\n * The current time zone in display format.\n * On Web time zone is calculated with Intl.DateTimeFormat().resolvedOptions().timeZone. For a\n * better estimation you could use the moment-timezone package but it will add significant bloat to\n * your website's bundle size.\n *\n * @example `'America/Los_Angeles'`\n */\n timezone: string;\n};\n"]}
@@ -3,5 +3,8 @@
3
3
  "platforms": ["ios", "android"],
4
4
  "ios": {
5
5
  "modulesClassNames": ["LocalizationModule"]
6
+ },
7
+ "android": {
8
+ "modulesClassNames": ["expo.modules.localization.LocalizationModule"]
6
9
  }
7
10
  }
@@ -5,26 +5,37 @@ import ExpoModulesCore
5
5
 
6
6
  public class LocalizationModule: Module {
7
7
  public func definition() -> ModuleDefinition {
8
- name("ExpoLocalization")
8
+ Name("ExpoLocalization")
9
9
 
10
- constants {
10
+ Constants {
11
11
  return Self.getCurrentLocalization()
12
12
  }
13
13
 
14
- function("getLocalizationAsync") {
14
+ AsyncFunction("getLocalizationAsync") {
15
15
  return Self.getCurrentLocalization()
16
16
  }
17
17
  }
18
+
19
+ // If the application isn't manually localized for the device language then the
20
+ // native `Locale.current` will fallback on using English US
21
+ // [cite](https://stackoverflow.com/questions/48136456/locale-current-reporting-wrong-language-on-device).
22
+ // This method will attempt to return the locale that the device is using regardless of the app,
23
+ // providing better parity across platforms.
24
+ static func getPreferredLocale() -> Locale {
25
+ guard let preferredIdentifier = Locale.preferredLanguages.first else {
26
+ return Locale.current
27
+ }
28
+ return Locale(identifier: preferredIdentifier)
29
+ }
18
30
 
19
31
  static func getCurrentLocalization() -> [String: Any?] {
20
- let locale = Locale.current
32
+ let locale = getPreferredLocale()
21
33
  let languageCode = locale.languageCode ?? "en"
22
34
  var languageIds = Locale.preferredLanguages
23
35
 
24
36
  if languageIds.isEmpty {
25
37
  languageIds.append("en-US")
26
38
  }
27
-
28
39
  return [
29
40
  "currency": locale.currencyCode ?? "USD",
30
41
  "decimalSeparator": locale.decimalSeparator ?? ".",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-localization",
3
- "version": "12.0.0",
3
+ "version": "13.1.0",
4
4
  "description": "Provides an interface for native user localization information.",
5
5
  "main": "build/Localization.js",
6
6
  "types": "build/Localization.d.ts",
@@ -47,5 +47,5 @@
47
47
  "peerDependencies": {
48
48
  "expo": "*"
49
49
  },
50
- "gitHead": "2e5c6983b86d5ecfca028ba64002897d8adc2cc4"
50
+ "gitHead": "6e131f2da851a47c3a24eb3d6fc971a1a7822086"
51
51
  }
@@ -1,3 +1,3 @@
1
- import { NativeModulesProxy } from 'expo-modules-core';
1
+ import { requireNativeModule } from 'expo-modules-core';
2
2
 
3
- export default NativeModulesProxy.ExpoLocalization;
3
+ export default requireNativeModule('ExpoLocalization');
@@ -62,6 +62,8 @@ export const locale = ExpoLocalization.locale;
62
62
  /**
63
63
  * List of all the native languages provided by the user settings.
64
64
  * These are returned in the order the user defines in their device settings.
65
+ *
66
+ * @example `['en', 'en-US', 'zh-Hans', 'zh-Hans-CN', 'en-emodeng']`
65
67
  */
66
68
  export const locales = ExpoLocalization.locales;
67
69
 
@@ -1,24 +1,25 @@
1
+ // @needsAudit
1
2
  export type Localization = {
2
3
  /**
3
4
  * Three-character ISO 4217 currency code. Returns `null` on web.
4
5
  *
5
- * @example `USD`, `EUR`, `CNY`, null
6
+ * @example `'USD'`, `'EUR'`, `'CNY'`, `null`
6
7
  */
7
8
  currency: string | null;
8
9
  /**
9
10
  * Decimal separator used for formatting numbers.
10
11
  *
11
- * @example `,`, '.'
12
+ * @example `','`, `'.'`
12
13
  */
13
14
  decimalSeparator: string;
14
15
  /**
15
16
  * Digit grouping separator used when formatting numbers larger than 1000.
16
17
  *
17
- * @example `.`, '', ','
18
+ * @example `'.'`, `''`, `','`
18
19
  */
19
20
  digitGroupingSeparator: string;
20
21
  /**
21
- * List of all the supported language ISO codes.
22
+ * A list of all the supported language ISO codes.
22
23
  */
23
24
  isoCurrencyCodes: string[];
24
25
  /**
@@ -30,35 +31,37 @@ export type Localization = {
30
31
  * Returns if the system's language is written from Right-to-Left.
31
32
  * This can be used to build features like [bidirectional icons](https://material.io/design/usability/bidirectionality.html).
32
33
  *
33
- * Returns `false` in SSR environments.
34
+ * Returns `false` in Server Side Rendering (SSR) environments.
34
35
  */
35
36
  isRTL: boolean;
36
37
  /**
37
38
  * An [IETF BCP 47 language tag](https://en.wikipedia.org/wiki/IETF_language_tag),
38
39
  * consisting of a two-character language code and optional script, region and variant codes.
39
40
  *
40
- * @example `en`, `en-US`, `zh-Hans`, `zh-Hans-CN`, `en-emodeng`
41
+ * @example `'en'`, `'en-US'`, `'zh-Hans'`, `'zh-Hans-CN'`, `'en-emodeng'`
41
42
  */
42
43
  locale: string;
43
44
  /**
44
- * List of all the languages provided by the user settings.
45
+ * List of all the native languages provided by the user settings.
45
46
  * These are returned in the order the user defines in their device settings.
46
47
  *
47
- * @example [`en`, `en-US`, `zh-Hans`, `zh-Hans-CN`, `en-emodeng`]
48
+ * @example `['en', 'en-US', 'zh-Hans', 'zh-Hans-CN', 'en-emodeng']`
48
49
  */
49
50
  locales: string[];
50
51
  /**
51
52
  * The region code for your device that comes from the Region setting under Language & Region on iOS.
52
53
  * This value is always available on iOS, but might return `null` on Android or web.
53
54
  *
54
- * @example `US`, `NZ`, null
55
+ * @example `'US'`, `'NZ'`, `null`
55
56
  */
56
57
  region: string | null;
57
58
  /**
58
- * The current timezone in display format.
59
- * On Web timezone is calculated with Intl.DateTimeFormat().resolvedOptions().timeZone. For a better estimation you could use the moment-timezone package but it will add significant bloat to your website's bundle size.
59
+ * The current time zone in display format.
60
+ * On Web time zone is calculated with Intl.DateTimeFormat().resolvedOptions().timeZone. For a
61
+ * better estimation you could use the moment-timezone package but it will add significant bloat to
62
+ * your website's bundle size.
60
63
  *
61
- * @example `America/Los_Angeles`
64
+ * @example `'America/Los_Angeles'`
62
65
  */
63
66
  timezone: string;
64
67
  };
package/tsconfig.json CHANGED
@@ -5,5 +5,5 @@
5
5
  "outDir": "./build"
6
6
  },
7
7
  "include": ["./src"],
8
- "exclude": ["**/__mocks__/*", "**/__tests__/*"]
8
+ "exclude": ["**/__mocks__/*", "**/__tests__/*", "**/__stories__/*"]
9
9
  }
@@ -1,10 +0,0 @@
1
- package expo.modules.localization
2
-
3
- import android.content.Context
4
- import expo.modules.core.BasePackage
5
- import expo.modules.core.ExportedModule
6
-
7
- class LocalizationPackage : BasePackage() {
8
- override fun createExportedModules(context: Context): List<ExportedModule> =
9
- listOf(LocalizationModule(context))
10
- }