expo-localization 14.1.0 → 14.2.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,17 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 14.2.0 — 2023-05-08
14
+
15
+ ### 🐛 Bug fixes
16
+
17
+ - Fixed invalid timezone returned for `getCalendars` on Web. ([#22003](https://github.com/expo/expo/pull/22003) by [@aleqsio](https://github.com/aleqsio))
18
+ - Fixed errors thrown on Play Console pre-launch report. ([#22003](https://github.com/expo/expo/pull/22003) by [@aleqsio](https://github.com/aleqsio))
19
+
20
+ ## 14.1.1 — 2023-02-09
21
+
22
+ _This version does not introduce any user-facing changes._
23
+
13
24
  ## 14.1.0 — 2023-02-03
14
25
 
15
26
  ### 💡 Others
package/README.md CHANGED
@@ -1,4 +1,11 @@
1
- # expo-localization
1
+ <p>
2
+ <a href="https://docs.expo.dev/versions/latest/sdk/localization/">
3
+ <img
4
+ src="../../.github/resources/expo-localization.svg"
5
+ alt="expo-localization"
6
+ height="64" />
7
+ </a>
8
+ </p>
2
9
 
3
10
  Provides an interface for native user localization information.
4
11
 
@@ -9,7 +16,7 @@ Provides an interface for native user localization information.
9
16
 
10
17
  # Installation in managed Expo projects
11
18
 
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/).
19
+ For [managed](https://docs.expo.dev/archive/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
20
 
14
21
  # Installation in bare React Native projects
15
22
 
@@ -18,7 +25,7 @@ For bare React Native projects, you must ensure that you have [installed and con
18
25
  ### Add the package to your npm dependencies
19
26
 
20
27
  ```
21
- expo install expo-localization
28
+ npx expo install expo-localization
22
29
  ```
23
30
 
24
31
  ### Configure for iOS
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
3
3
  apply plugin: 'maven-publish'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '14.1.0'
6
+ version = '14.2.0'
7
7
 
8
8
  buildscript {
9
9
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
@@ -22,7 +22,7 @@ buildscript {
22
22
  if (ext.has("kotlinVersion")) {
23
23
  ext.kotlinVersion()
24
24
  } else {
25
- ext.safeExtGet("kotlinVersion", "1.6.10")
25
+ ext.safeExtGet("kotlinVersion", "1.8.10")
26
26
  }
27
27
  }
28
28
 
@@ -74,7 +74,7 @@ android {
74
74
  minSdkVersion safeExtGet("minSdkVersion", 21)
75
75
  targetSdkVersion safeExtGet("targetSdkVersion", 33)
76
76
  versionCode 22
77
- versionName "14.1.0"
77
+ versionName "14.2.0"
78
78
  }
79
79
  lintOptions {
80
80
  abortOnError false
@@ -10,6 +10,7 @@ import android.text.TextUtils
10
10
  import android.text.TextUtils.getLayoutDirectionFromLocale
11
11
  import android.text.format.DateFormat
12
12
  import android.util.LayoutDirection
13
+ import android.util.Log
13
14
  import android.view.View
14
15
  import androidx.core.os.LocaleListCompat
15
16
  import androidx.core.os.bundleOf
@@ -131,26 +132,32 @@ class LocalizationModule : Module() {
131
132
  val locales = mutableListOf<Map<String, Any?>>()
132
133
  val localeList: LocaleListCompat = LocaleListCompat.getDefault()
133
134
  for (i in 0 until localeList.size()) {
134
- val locale: Locale = localeList.get(i) ?: continue
135
- val decimalFormat = DecimalFormatSymbols.getInstance(locale)
136
- locales.add(
137
- mapOf(
138
- "languageTag" to locale.toLanguageTag(),
139
- "regionCode" to getRegionCode(locale),
140
- "textDirection" to if (getLayoutDirectionFromLocale(locale) == LayoutDirection.RTL) "rtl" else "ltr",
141
- "languageCode" to locale.language,
142
-
143
- // the following two properties should be deprecated once Intl makes it way to RN, instead use toLocaleString
144
- "decimalSeparator" to decimalFormat.decimalSeparator.toString(),
145
- "digitGroupingSeparator" to decimalFormat.groupingSeparator.toString(),
146
-
147
- "measurementSystem" to getMeasurementSystem(locale),
148
- "currencyCode" to decimalFormat.currency.currencyCode,
149
-
150
- // currency symbol can be localized to display locale (1st on the list) or to the locale for the currency (as done here).
151
- "currencySymbol" to Currency.getInstance(locale).getSymbol(locale),
135
+ try {
136
+ val locale: Locale = localeList.get(i) ?: continue
137
+ val decimalFormat = DecimalFormatSymbols.getInstance(locale)
138
+ locales.add(
139
+ mapOf(
140
+ "languageTag" to locale.toLanguageTag(),
141
+ "regionCode" to getRegionCode(locale),
142
+ "textDirection" to if (getLayoutDirectionFromLocale(locale) == LayoutDirection.RTL) "rtl" else "ltr",
143
+ "languageCode" to locale.language,
144
+
145
+ // the following two properties should be deprecated once Intl makes it way to RN, instead use toLocaleString
146
+ "decimalSeparator" to decimalFormat.decimalSeparator.toString(),
147
+ "digitGroupingSeparator" to decimalFormat.groupingSeparator.toString(),
148
+
149
+ "measurementSystem" to getMeasurementSystem(locale),
150
+ "currencyCode" to decimalFormat.currency.currencyCode,
151
+
152
+ // currency symbol can be localized to display locale (1st on the list) or to the locale for the currency (as done here).
153
+ "currencySymbol" to Currency.getInstance(locale).getSymbol(locale),
154
+ )
152
155
  )
153
- )
156
+ } catch (e: Exception) {
157
+ // warn about the problematic locale
158
+ // we don't append the problematic locale to the list
159
+ Log.w("expo-localization", "Failed to get locale for index $i", e)
160
+ }
154
161
  }
155
162
  return locales
156
163
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoLocalization.d.ts","sourceRoot":"","sources":["../src/ExpoLocalization.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAsB,MAAM,sBAAsB,CAAC;;;;;;;;;;;;kBAqF1E,MAAM,EAAE;oBA8BN,QAAQ,EAAE;4BAkBI,QAAQ,KAAK,YAAY,EAAE,cAAc,GAAG,YAAY,CAAC,CAAC;;AApH1F,wBA8IE"}
1
+ {"version":3,"file":"ExpoLocalization.d.ts","sourceRoot":"","sources":["../src/ExpoLocalization.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAsB,MAAM,sBAAsB,CAAC;;;;;;;;;;;;kBAqF1E,MAAM,EAAE;oBA8BN,QAAQ,EAAE;4BAaI,QAAQ,KAAK,YAAY,EAAE,cAAc,GAAG,YAAY,CAAC,CAAC;;AA/G1F,wBAyIE"}
@@ -97,12 +97,9 @@ export default {
97
97
  });
98
98
  },
99
99
  getCalendars() {
100
- // Prefer locales with region codes as they contain more info about calendar.
101
- // They seem to always exist in the list for each locale without region
102
- const locales = [...getNavigatorLocales()].sort((a, b) => a.includes('-') === b.includes('-') ? 0 : a.includes('-') ? -1 : 1);
103
- const locale = (locales[0] && typeof Intl !== 'undefined'
104
- ? new Intl.Locale(locales[0])
105
- : null);
100
+ const locale = ((typeof Intl !== 'undefined'
101
+ ? Intl.DateTimeFormat().resolvedOptions()
102
+ : null) ?? null);
106
103
  return [
107
104
  {
108
105
  calendar: (locale?.calendar || locale?.calendars?.[0]) || null,
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoLocalization.js","sourceRoot":"","sources":["../src/ExpoLocalization.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-env browser */\nimport { Platform } from 'expo-modules-core';\nimport * as rtlDetect from 'rtl-detect';\n\nimport { Localization, Calendar, Locale, CalendarIdentifier } from './Localization.types';\n\nconst getNavigatorLocales = () => {\n return Platform.isDOMAvailable ? navigator.languages || [navigator.language] : [];\n};\n\ntype ExtendedLocale = Intl.Locale &\n // typescript definitions for navigator language don't include some modern Intl properties\n Partial<{\n textInfo: { direction: 'ltr' | 'rtl' };\n timeZones: string[];\n weekInfo: { firstDay: number };\n hourCycles: string[];\n timeZone: string;\n calendars: string[];\n }>;\n\nexport default {\n get currency(): string | null {\n // TODO: Add support\n return null;\n },\n get decimalSeparator(): string {\n return (1.1).toLocaleString().substring(1, 2);\n },\n get digitGroupingSeparator(): string {\n const value = (1000).toLocaleString();\n return value.length === 5 ? value.substring(1, 2) : '';\n },\n get isRTL(): boolean {\n return rtlDetect.isRtlLang(this.locale) ?? false;\n },\n get isMetric(): boolean {\n const { region } = this;\n switch (region) {\n case 'US': // USA\n case 'LR': // Liberia\n case 'MM': // Myanmar\n return false;\n }\n return true;\n },\n get locale(): string {\n if (!Platform.isDOMAvailable) {\n return '';\n }\n const locale =\n navigator.language ||\n navigator['systemLanguage'] ||\n navigator['browserLanguage'] ||\n navigator['userLanguage'] ||\n this.locales[0];\n return locale;\n },\n get locales(): string[] {\n if (!Platform.isDOMAvailable) {\n return [];\n }\n const { languages = [] } = navigator;\n return Array.from(languages);\n },\n get timezone(): string {\n const defaultTimeZone = 'Etc/UTC';\n if (typeof Intl === 'undefined') {\n return defaultTimeZone;\n }\n return Intl.DateTimeFormat().resolvedOptions().timeZone || defaultTimeZone;\n },\n get isoCurrencyCodes(): string[] {\n // TODO(Bacon): Add this - very low priority\n return [];\n },\n get region(): string | null {\n // There is no way to obtain the current region, as is possible on native.\n // Instead, use the country-code from the locale when possible (e.g. \"en-US\").\n const { locale } = this;\n const [, ...suffixes] = typeof locale === 'string' ? locale.split('-') : [];\n for (const suffix of suffixes) {\n if (suffix.length === 2) {\n return suffix.toUpperCase();\n }\n }\n return null;\n },\n\n getLocales(): Locale[] {\n const locales = getNavigatorLocales();\n return locales?.map((languageTag) => {\n // TextInfo is an experimental API that is not available in all browsers.\n // We might want to consider using a locale lookup table instead.\n const locale =\n typeof Intl !== 'undefined'\n ? (new Intl.Locale(languageTag) as unknown as ExtendedLocale)\n : { region: null, textInfo: null, language: null };\n const { region, textInfo, language } = locale;\n\n // Properties added only for compatibility with native, use `toLocaleString` instead.\n const digitGroupingSeparator =\n Array.from((10000).toLocaleString(languageTag)).filter((c) => c > '9' || c < '0')[0] ||\n null; // using 1e5 instead of 1e4 since for some locales (like pl-PL) 1e4 does not use digit grouping\n const decimalSeparator = (1.1).toLocaleString(languageTag).substring(1, 2);\n\n return {\n languageTag,\n languageCode: language || languageTag.split('-')[0] || 'en',\n textDirection: (textInfo?.direction as 'ltr' | 'rtl') || null,\n digitGroupingSeparator,\n decimalSeparator,\n measurementSystem: null,\n currencyCode: null,\n currencySymbol: null,\n regionCode: region || null,\n };\n });\n },\n getCalendars(): Calendar[] {\n // Prefer locales with region codes as they contain more info about calendar.\n // They seem to always exist in the list for each locale without region\n const locales = [...getNavigatorLocales()].sort((a, b) =>\n a.includes('-') === b.includes('-') ? 0 : a.includes('-') ? -1 : 1\n );\n const locale = (locales[0] && typeof Intl !== 'undefined'\n ? new Intl.Locale(locales[0])\n : null) as unknown as null | ExtendedLocale;\n return [\n {\n calendar: ((locale?.calendar || locale?.calendars?.[0]) as CalendarIdentifier) || null,\n timeZone: locale?.timeZone || locale?.timeZones?.[0] || null,\n uses24hourClock: (locale?.hourCycle || locale?.hourCycles?.[0])?.startsWith('h2') ?? null, //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/hourCycle\n firstWeekday: locale?.weekInfo?.firstDay || null,\n },\n ];\n },\n async getLocalizationAsync(): Promise<Omit<Localization, 'getCalendars' | 'getLocales'>> {\n const {\n currency,\n decimalSeparator,\n digitGroupingSeparator,\n isoCurrencyCodes,\n isMetric,\n isRTL,\n locale,\n locales,\n region,\n timezone,\n } = this;\n return {\n currency,\n decimalSeparator,\n digitGroupingSeparator,\n isoCurrencyCodes,\n isMetric,\n isRTL,\n locale,\n locales,\n region,\n timezone,\n };\n },\n};\n"]}
1
+ {"version":3,"file":"ExpoLocalization.js","sourceRoot":"","sources":["../src/ExpoLocalization.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-env browser */\nimport { Platform } from 'expo-modules-core';\nimport * as rtlDetect from 'rtl-detect';\n\nimport { Localization, Calendar, Locale, CalendarIdentifier } from './Localization.types';\n\nconst getNavigatorLocales = () => {\n return Platform.isDOMAvailable ? navigator.languages || [navigator.language] : [];\n};\n\ntype ExtendedLocale = Intl.Locale &\n // typescript definitions for navigator language don't include some modern Intl properties\n Partial<{\n textInfo: { direction: 'ltr' | 'rtl' };\n timeZones: string[];\n weekInfo: { firstDay: number };\n hourCycles: string[];\n timeZone: string;\n calendars: string[];\n }>;\n\nexport default {\n get currency(): string | null {\n // TODO: Add support\n return null;\n },\n get decimalSeparator(): string {\n return (1.1).toLocaleString().substring(1, 2);\n },\n get digitGroupingSeparator(): string {\n const value = (1000).toLocaleString();\n return value.length === 5 ? value.substring(1, 2) : '';\n },\n get isRTL(): boolean {\n return rtlDetect.isRtlLang(this.locale) ?? false;\n },\n get isMetric(): boolean {\n const { region } = this;\n switch (region) {\n case 'US': // USA\n case 'LR': // Liberia\n case 'MM': // Myanmar\n return false;\n }\n return true;\n },\n get locale(): string {\n if (!Platform.isDOMAvailable) {\n return '';\n }\n const locale =\n navigator.language ||\n navigator['systemLanguage'] ||\n navigator['browserLanguage'] ||\n navigator['userLanguage'] ||\n this.locales[0];\n return locale;\n },\n get locales(): string[] {\n if (!Platform.isDOMAvailable) {\n return [];\n }\n const { languages = [] } = navigator;\n return Array.from(languages);\n },\n get timezone(): string {\n const defaultTimeZone = 'Etc/UTC';\n if (typeof Intl === 'undefined') {\n return defaultTimeZone;\n }\n return Intl.DateTimeFormat().resolvedOptions().timeZone || defaultTimeZone;\n },\n get isoCurrencyCodes(): string[] {\n // TODO(Bacon): Add this - very low priority\n return [];\n },\n get region(): string | null {\n // There is no way to obtain the current region, as is possible on native.\n // Instead, use the country-code from the locale when possible (e.g. \"en-US\").\n const { locale } = this;\n const [, ...suffixes] = typeof locale === 'string' ? locale.split('-') : [];\n for (const suffix of suffixes) {\n if (suffix.length === 2) {\n return suffix.toUpperCase();\n }\n }\n return null;\n },\n\n getLocales(): Locale[] {\n const locales = getNavigatorLocales();\n return locales?.map((languageTag) => {\n // TextInfo is an experimental API that is not available in all browsers.\n // We might want to consider using a locale lookup table instead.\n const locale =\n typeof Intl !== 'undefined'\n ? (new Intl.Locale(languageTag) as unknown as ExtendedLocale)\n : { region: null, textInfo: null, language: null };\n const { region, textInfo, language } = locale;\n\n // Properties added only for compatibility with native, use `toLocaleString` instead.\n const digitGroupingSeparator =\n Array.from((10000).toLocaleString(languageTag)).filter((c) => c > '9' || c < '0')[0] ||\n null; // using 1e5 instead of 1e4 since for some locales (like pl-PL) 1e4 does not use digit grouping\n const decimalSeparator = (1.1).toLocaleString(languageTag).substring(1, 2);\n\n return {\n languageTag,\n languageCode: language || languageTag.split('-')[0] || 'en',\n textDirection: (textInfo?.direction as 'ltr' | 'rtl') || null,\n digitGroupingSeparator,\n decimalSeparator,\n measurementSystem: null,\n currencyCode: null,\n currencySymbol: null,\n regionCode: region || null,\n };\n });\n },\n getCalendars(): Calendar[] {\n const locale = ((typeof Intl !== 'undefined'\n ? Intl.DateTimeFormat().resolvedOptions()\n : null) ?? null) as unknown as null | ExtendedLocale;\n return [\n {\n calendar: ((locale?.calendar || locale?.calendars?.[0]) as CalendarIdentifier) || null,\n timeZone: locale?.timeZone || locale?.timeZones?.[0] || null,\n uses24hourClock: (locale?.hourCycle || locale?.hourCycles?.[0])?.startsWith('h2') ?? null, //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/hourCycle\n firstWeekday: locale?.weekInfo?.firstDay || null,\n },\n ];\n },\n async getLocalizationAsync(): Promise<Omit<Localization, 'getCalendars' | 'getLocales'>> {\n const {\n currency,\n decimalSeparator,\n digitGroupingSeparator,\n isoCurrencyCodes,\n isMetric,\n isRTL,\n locale,\n locales,\n region,\n timezone,\n } = this;\n return {\n currency,\n decimalSeparator,\n digitGroupingSeparator,\n isoCurrencyCodes,\n isMetric,\n isRTL,\n locale,\n locales,\n region,\n timezone,\n };\n },\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-localization",
3
- "version": "14.1.0",
3
+ "version": "14.2.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": "1815e2eaad8c753588c7b1eb74420174a28e01f4"
50
+ "gitHead": "4ba50c428c8369bb6b3a51a860d4898ad4ccbe78"
51
51
  }
@@ -118,14 +118,9 @@ export default {
118
118
  });
119
119
  },
120
120
  getCalendars(): Calendar[] {
121
- // Prefer locales with region codes as they contain more info about calendar.
122
- // They seem to always exist in the list for each locale without region
123
- const locales = [...getNavigatorLocales()].sort((a, b) =>
124
- a.includes('-') === b.includes('-') ? 0 : a.includes('-') ? -1 : 1
125
- );
126
- const locale = (locales[0] && typeof Intl !== 'undefined'
127
- ? new Intl.Locale(locales[0])
128
- : null) as unknown as null | ExtendedLocale;
121
+ const locale = ((typeof Intl !== 'undefined'
122
+ ? Intl.DateTimeFormat().resolvedOptions()
123
+ : null) ?? null) as unknown as null | ExtendedLocale;
129
124
  return [
130
125
  {
131
126
  calendar: ((locale?.calendar || locale?.calendars?.[0]) as CalendarIdentifier) || null,