@amazon-devices/expo-localization 2.0.1758683737
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/.eslintrc.js +2 -0
- package/CHANGELOG.md +198 -0
- package/CMakeLists.txt +50 -0
- package/LICENSE +7 -0
- package/README.kepler.md +109 -0
- package/README.md +41 -0
- package/THIRD_PARTY_NOTICES.txt +24 -0
- package/android/build.gradle +109 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/java/expo/modules/localization/LocalizationModule.kt +207 -0
- package/android/src/main/java/expo/modules/localization/LocalizationPackage.kt +35 -0
- package/android/src/main/java/expo/modules/localization/LocalizationUtils.kt +49 -0
- package/android/src/main/res/values/strings.xml +4 -0
- package/app.plugin.js +1 -0
- package/build/ExpoLocalization.d.ts +22 -0
- package/build/ExpoLocalization.d.ts.map +1 -0
- package/build/ExpoLocalization.js +166 -0
- package/build/ExpoLocalization.js.map +1 -0
- package/build/ExpoLocalization.kepler.d.ts +12 -0
- package/build/ExpoLocalization.kepler.d.ts.map +1 -0
- package/build/ExpoLocalization.kepler.js +26 -0
- package/build/ExpoLocalization.kepler.js.map +1 -0
- package/build/ExpoLocalization.native.d.ts +7 -0
- package/build/ExpoLocalization.native.d.ts.map +1 -0
- package/build/ExpoLocalization.native.js +14 -0
- package/build/ExpoLocalization.native.js.map +1 -0
- package/build/Localization.d.ts +163 -0
- package/build/Localization.d.ts.map +1 -0
- package/build/Localization.js +197 -0
- package/build/Localization.js.map +1 -0
- package/build/Localization.types.d.ts +202 -0
- package/build/Localization.types.d.ts.map +1 -0
- package/build/Localization.types.js +59 -0
- package/build/Localization.types.js.map +1 -0
- package/expo-module.config.json +10 -0
- package/ios/ExpoLocalization.podspec +32 -0
- package/ios/LocalizationModule.swift +212 -0
- package/kepler/ExpoLocalization.cpp +128 -0
- package/kepler/ExpoLocalization.h +22 -0
- package/kepler/KeplerInit.cpp +26 -0
- package/kepler/test/ExpoLocalization.cpp +78 -0
- package/package.json +1 -0
- package/plugin/build/withExpoLocalization.d.ts +7 -0
- package/plugin/build/withExpoLocalization.js +46 -0
- package/plugin/src/withExpoLocalization.ts +62 -0
- package/plugin/tsconfig.json +9 -0
- package/plugin/tsconfig.tsbuildinfo +1 -0
- package/react-native.config.js +21 -0
- package/src/ExpoLocalization.kepler.ts +40 -0
- package/src/ExpoLocalization.native.ts +18 -0
- package/src/ExpoLocalization.ts +203 -0
- package/src/Localization.ts +217 -0
- package/src/Localization.types.ts +207 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
package expo.modules.localization
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.icu.util.LocaleData
|
|
5
|
+
import android.icu.util.ULocale
|
|
6
|
+
import android.os.Build.VERSION
|
|
7
|
+
import android.os.Build.VERSION_CODES
|
|
8
|
+
import android.os.Bundle
|
|
9
|
+
import android.text.TextUtils
|
|
10
|
+
import android.text.TextUtils.getLayoutDirectionFromLocale
|
|
11
|
+
import android.text.format.DateFormat
|
|
12
|
+
import android.util.LayoutDirection
|
|
13
|
+
import android.util.Log
|
|
14
|
+
import android.view.View
|
|
15
|
+
import androidx.core.os.LocaleListCompat
|
|
16
|
+
import androidx.core.os.bundleOf
|
|
17
|
+
import expo.modules.kotlin.modules.Module
|
|
18
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
19
|
+
import java.text.DecimalFormatSymbols
|
|
20
|
+
import java.util.*
|
|
21
|
+
|
|
22
|
+
// EXPO_VERSIONING_NEEDS_EXPOVIEW_R
|
|
23
|
+
|
|
24
|
+
// must be kept in sync with https://github.com/facebook/react-native/blob/main/ReactAndroid/src/main/java/com/facebook/react/modules/i18nmanager/I18nUtil.java
|
|
25
|
+
private const val SHARED_PREFS_NAME = "com.facebook.react.modules.i18nmanager.I18nUtil"
|
|
26
|
+
private const val KEY_FOR_PREFS_ALLOWRTL = "RCTI18nUtil_allowRTL"
|
|
27
|
+
|
|
28
|
+
private const val LOCALE_SETTINGS_CHANGED = "onLocaleSettingsChanged"
|
|
29
|
+
private const val CALENDAR_SETTINGS_CHANGED = "onCalendarSettingsChanged"
|
|
30
|
+
|
|
31
|
+
class LocalizationModule : Module() {
|
|
32
|
+
private var observer: () -> Unit = {}
|
|
33
|
+
|
|
34
|
+
override fun definition() = ModuleDefinition {
|
|
35
|
+
Name("ExpoLocalization")
|
|
36
|
+
|
|
37
|
+
Constants {
|
|
38
|
+
bundledConstants.toShallowMap()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
AsyncFunction("getLocalizationAsync") {
|
|
42
|
+
return@AsyncFunction bundledConstants
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
Function("getLocales") {
|
|
46
|
+
return@Function getPreferredLocales()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
Function("getCalendars") {
|
|
50
|
+
return@Function getCalendars()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
Events(LOCALE_SETTINGS_CHANGED, CALENDAR_SETTINGS_CHANGED)
|
|
54
|
+
|
|
55
|
+
OnCreate {
|
|
56
|
+
appContext?.reactContext?.let {
|
|
57
|
+
setRTLFromStringResources(it)
|
|
58
|
+
}
|
|
59
|
+
observer = {
|
|
60
|
+
this@LocalizationModule.sendEvent(LOCALE_SETTINGS_CHANGED)
|
|
61
|
+
this@LocalizationModule.sendEvent(CALENDAR_SETTINGS_CHANGED)
|
|
62
|
+
}
|
|
63
|
+
Notifier.registerObserver(observer)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
OnDestroy {
|
|
67
|
+
Notifier.deregisterObserver(observer)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private fun setRTLFromStringResources(context: Context) {
|
|
72
|
+
// These keys are used by React Native here: https://github.com/facebook/react-native/blob/main/React/Modules/RCTI18nUtil.m
|
|
73
|
+
// We set them before React loads to ensure it gets rendered correctly the first time the app is opened.
|
|
74
|
+
val supportsRTL = appContext.reactContext?.getString(R.string.ExpoLocalization_supportsRTL)
|
|
75
|
+
if (supportsRTL != "true" && supportsRTL != "false") return
|
|
76
|
+
context
|
|
77
|
+
.getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE)
|
|
78
|
+
.edit()
|
|
79
|
+
.also {
|
|
80
|
+
it.putBoolean(KEY_FOR_PREFS_ALLOWRTL, supportsRTL == "true")
|
|
81
|
+
it.apply()
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// TODO: Bacon: add set language
|
|
86
|
+
private val bundledConstants: Bundle
|
|
87
|
+
get() {
|
|
88
|
+
val locale = Locale.getDefault()
|
|
89
|
+
val localeNames = getLocaleNames(locales)
|
|
90
|
+
val isRTL = TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL
|
|
91
|
+
val region = getRegionCode(locale)
|
|
92
|
+
val symbols = DecimalFormatSymbols(locale)
|
|
93
|
+
return bundleOf(
|
|
94
|
+
"currency" to getCurrencyCode(locale),
|
|
95
|
+
"decimalSeparator" to symbols.decimalSeparator.toString(),
|
|
96
|
+
"digitGroupingSeparator" to symbols.groupingSeparator.toString(),
|
|
97
|
+
"isoCurrencyCodes" to ISOCurrencyCodes,
|
|
98
|
+
"isMetric" to !USES_IMPERIAL.contains(region),
|
|
99
|
+
"isRTL" to isRTL,
|
|
100
|
+
// TODO: (barthap) this can throw IndexOutOfBounds exception - handle this properly
|
|
101
|
+
"locale" to localeNames[0],
|
|
102
|
+
"locales" to localeNames,
|
|
103
|
+
"region" to region,
|
|
104
|
+
"timezone" to TimeZone.getDefault().id
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private val locales: List<Locale>
|
|
109
|
+
get() {
|
|
110
|
+
val context = appContext.reactContext ?: return emptyList()
|
|
111
|
+
val configuration = context.resources.configuration
|
|
112
|
+
return if (VERSION.SDK_INT > VERSION_CODES.N) {
|
|
113
|
+
val locales = ArrayList<Locale>()
|
|
114
|
+
for (i in 0 until configuration.locales.size()) {
|
|
115
|
+
locales.add(configuration.locales[i])
|
|
116
|
+
}
|
|
117
|
+
locales
|
|
118
|
+
} else {
|
|
119
|
+
listOf(configuration.locale)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private fun getMeasurementSystem(locale: Locale): String? {
|
|
124
|
+
return if (VERSION.SDK_INT >= VERSION_CODES.P) {
|
|
125
|
+
when (LocaleData.getMeasurementSystem(ULocale.forLocale(locale))) {
|
|
126
|
+
LocaleData.MeasurementSystem.SI -> "metric"
|
|
127
|
+
LocaleData.MeasurementSystem.UK -> "uk"
|
|
128
|
+
LocaleData.MeasurementSystem.US -> "us"
|
|
129
|
+
else -> "metric"
|
|
130
|
+
}
|
|
131
|
+
} else {
|
|
132
|
+
if (getRegionCode(locale).equals("uk")) "uk"
|
|
133
|
+
else if (USES_IMPERIAL.contains(getRegionCode(locale))) "us"
|
|
134
|
+
else "metric"
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private fun getPreferredLocales(): List<Map<String, Any?>> {
|
|
139
|
+
val locales = mutableListOf<Map<String, Any?>>()
|
|
140
|
+
val localeList: LocaleListCompat = LocaleListCompat.getDefault()
|
|
141
|
+
for (i in 0 until localeList.size()) {
|
|
142
|
+
try {
|
|
143
|
+
val locale: Locale = localeList.get(i) ?: continue
|
|
144
|
+
val decimalFormat = DecimalFormatSymbols.getInstance(locale)
|
|
145
|
+
locales.add(
|
|
146
|
+
mapOf(
|
|
147
|
+
"languageTag" to locale.toLanguageTag(),
|
|
148
|
+
"regionCode" to getRegionCode(locale),
|
|
149
|
+
"textDirection" to if (getLayoutDirectionFromLocale(locale) == LayoutDirection.RTL) "rtl" else "ltr",
|
|
150
|
+
"languageCode" to locale.language,
|
|
151
|
+
|
|
152
|
+
// the following two properties should be deprecated once Intl makes it way to RN, instead use toLocaleString
|
|
153
|
+
"decimalSeparator" to decimalFormat.decimalSeparator.toString(),
|
|
154
|
+
"digitGroupingSeparator" to decimalFormat.groupingSeparator.toString(),
|
|
155
|
+
|
|
156
|
+
"measurementSystem" to getMeasurementSystem(locale),
|
|
157
|
+
"currencyCode" to decimalFormat.currency.currencyCode,
|
|
158
|
+
|
|
159
|
+
// currency symbol can be localized to display locale (1st on the list) or to the locale for the currency (as done here).
|
|
160
|
+
"currencySymbol" to Currency.getInstance(locale).getSymbol(locale),
|
|
161
|
+
"temperatureUnit" to getTemperatureUnit(locale),
|
|
162
|
+
)
|
|
163
|
+
)
|
|
164
|
+
} catch (e: Exception) {
|
|
165
|
+
// warn about the problematic locale
|
|
166
|
+
// we don't append the problematic locale to the list
|
|
167
|
+
Log.w("expo-localization", "Failed to get locale for index $i", e)
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return locales
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private fun uses24HourClock(): Boolean {
|
|
174
|
+
if (appContext.reactContext == null) return false
|
|
175
|
+
return DateFormat.is24HourFormat(appContext.reactContext)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private fun getCalendarType(): String {
|
|
179
|
+
return if (VERSION.SDK_INT >= VERSION_CODES.O) {
|
|
180
|
+
Calendar.getInstance().calendarType.toString()
|
|
181
|
+
} else {
|
|
182
|
+
"gregory"
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private fun getCalendars(): List<Map<String, Any?>> {
|
|
187
|
+
return listOf(
|
|
188
|
+
mapOf(
|
|
189
|
+
"calendar" to getCalendarType(),
|
|
190
|
+
"uses24hourClock" to uses24HourClock(), // we ideally would use hourCycle (one of h12, h23, h11, h24) instead, but not sure how to get it on android and ios
|
|
191
|
+
"firstWeekday" to Calendar.getInstance().firstDayOfWeek,
|
|
192
|
+
"timeZone" to Calendar.getInstance().timeZone.id
|
|
193
|
+
)
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Creates a shallow [Map] from the [Bundle]. Does not traverse nested arrays and bundles.
|
|
200
|
+
*/
|
|
201
|
+
private fun Bundle.toShallowMap(): Map<String, Any?> {
|
|
202
|
+
val map = HashMap<String, Any?>()
|
|
203
|
+
for (key in this.keySet()) {
|
|
204
|
+
map[key] = this[key]
|
|
205
|
+
}
|
|
206
|
+
return map
|
|
207
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
package expo.modules.localization
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.content.res.Configuration
|
|
5
|
+
import expo.modules.core.interfaces.ApplicationLifecycleListener
|
|
6
|
+
import expo.modules.core.interfaces.Package
|
|
7
|
+
|
|
8
|
+
object Notifier {
|
|
9
|
+
private val observers = mutableListOf<() -> Unit>()
|
|
10
|
+
|
|
11
|
+
fun registerObserver(observer: () -> Unit) {
|
|
12
|
+
observers.add(observer)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
fun deregisterObserver(observer: () -> Unit) {
|
|
16
|
+
observers.remove(observer)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
fun onConfigurationChanged() {
|
|
20
|
+
// Notify all observers
|
|
21
|
+
observers.forEach { it() }
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// TODO: Move to new listener API once it's available
|
|
26
|
+
class LocalizationPackage : Package {
|
|
27
|
+
override fun createApplicationLifecycleListeners(context: Context?): List<out ApplicationLifecycleListener> {
|
|
28
|
+
return listOf(object : ApplicationLifecycleListener {
|
|
29
|
+
override fun onConfigurationChanged(newConfig: Configuration?) {
|
|
30
|
+
super.onConfigurationChanged(newConfig)
|
|
31
|
+
Notifier.onConfigurationChanged()
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
package expo.modules.localization
|
|
2
|
+
|
|
3
|
+
import android.text.TextUtils
|
|
4
|
+
import java.util.*
|
|
5
|
+
|
|
6
|
+
val USES_IMPERIAL = listOf("US", "LR", "MM")
|
|
7
|
+
|
|
8
|
+
// https://wisevoter.com/country-rankings/countries-that-use-fahrenheit/
|
|
9
|
+
val USES_FAHRENHEIT = listOf("AG", "BZ", "VG", "FM", "MH", "MS", "KN", "BS", "CY", "TC", "US", "LR", "PW", "KY")
|
|
10
|
+
|
|
11
|
+
val ISOCurrencyCodes: Array<String> by lazy {
|
|
12
|
+
Currency.getAvailableCurrencies().map { it.currencyCode as String }.toTypedArray()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
fun getLocaleNames(locales: List<Locale>) = locales.map { it.toLanguageTag() }.toTypedArray()
|
|
16
|
+
|
|
17
|
+
fun getCountryCode(locale: Locale): String? {
|
|
18
|
+
return runCatching {
|
|
19
|
+
val country = locale.country
|
|
20
|
+
if (TextUtils.isEmpty(country)) null else country
|
|
21
|
+
}.getOrNull()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
fun getSystemProperty(key: String): String {
|
|
25
|
+
return runCatching {
|
|
26
|
+
val systemProperties = Class.forName("android.os.SystemProperties")
|
|
27
|
+
val get = systemProperties.getMethod("get", String::class.java)
|
|
28
|
+
get.invoke(systemProperties, key) as String
|
|
29
|
+
}.getOrNull() ?: ""
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
fun getCurrencyCode(locale: Locale): String? {
|
|
33
|
+
return runCatching {
|
|
34
|
+
val currency = Currency.getInstance(locale)
|
|
35
|
+
currency?.currencyCode
|
|
36
|
+
}.getOrNull()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
fun getRegionCode(locale: Locale): String? {
|
|
40
|
+
val miuiRegion = getSystemProperty("ro.miui.region")
|
|
41
|
+
return miuiRegion.ifEmpty {
|
|
42
|
+
getCountryCode(locale)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
fun getTemperatureUnit(locale: Locale): String? {
|
|
47
|
+
val countryCode = getRegionCode(locale) ?: return null
|
|
48
|
+
return if (USES_FAHRENHEIT.contains(countryCode)) "fahrenheit" else "celsius"
|
|
49
|
+
}
|
package/app.plugin.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./plugin/build/withExpoLocalization');
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Subscription } from 'expo-modules-core';
|
|
2
|
+
import { Localization, Calendar, Locale } from './Localization.types';
|
|
3
|
+
export declare function addLocaleListener(listener: (event: any) => void): Subscription;
|
|
4
|
+
export declare function addCalendarListener(listener: (event: any) => void): Subscription;
|
|
5
|
+
export declare function removeSubscription(subscription: Subscription): void;
|
|
6
|
+
declare const _default: {
|
|
7
|
+
readonly currency: string | null;
|
|
8
|
+
readonly decimalSeparator: string;
|
|
9
|
+
readonly digitGroupingSeparator: string;
|
|
10
|
+
readonly isRTL: boolean;
|
|
11
|
+
readonly isMetric: boolean;
|
|
12
|
+
readonly locale: string;
|
|
13
|
+
readonly locales: string[];
|
|
14
|
+
readonly timezone: string;
|
|
15
|
+
readonly isoCurrencyCodes: string[];
|
|
16
|
+
readonly region: string | null;
|
|
17
|
+
getLocales(): Locale[];
|
|
18
|
+
getCalendars(): Calendar[];
|
|
19
|
+
getLocalizationAsync(): Promise<Omit<Localization, "getCalendars" | "getLocales">>;
|
|
20
|
+
};
|
|
21
|
+
export default _default;
|
|
22
|
+
//# sourceMappingURL=ExpoLocalization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoLocalization.d.ts","sourceRoot":"","sources":["../src/ExpoLocalization.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAG3D,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAsB,MAAM,sBAAsB,CAAC;AAoC1F,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,CAAC,KAAK,KAAA,KAAK,IAAI,GAAG,YAAY,CAKzE;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,CAAC,KAAK,KAAA,KAAK,IAAI,GAAG,YAAY,CAK3E;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,YAAY,QAE5D;;uBAGiB,MAAM,GAAG,IAAI;+BAIL,MAAM;qCAGA,MAAM;oBAIvB,OAAO;uBAGJ,OAAO;qBAUT,MAAM;sBAYL,MAAM,EAAE;uBAOP,MAAM;+BAOE,MAAM,EAAE;qBAIlB,MAAM,GAAG,IAAI;kBAab,MAAM,EAAE;oBAgCN,QAAQ,EAAE;4BAcI,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,GAAG,YAAY,CAAC,CAAC;;AAlH1F,wBA4IE"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/* eslint-env browser */
|
|
2
|
+
import { Platform } from 'expo-modules-core';
|
|
3
|
+
import * as rtlDetect from 'rtl-detect';
|
|
4
|
+
const getNavigatorLocales = () => {
|
|
5
|
+
return Platform.isDOMAvailable ? navigator.languages || [navigator.language] : [];
|
|
6
|
+
};
|
|
7
|
+
const WEB_LANGUAGE_CHANGE_EVENT = 'languagechange';
|
|
8
|
+
// https://wisevoter.com/country-rankings/countries-that-use-fahrenheit/
|
|
9
|
+
const USES_FAHRENHEIT = [
|
|
10
|
+
'AG',
|
|
11
|
+
'BZ',
|
|
12
|
+
'VG',
|
|
13
|
+
'FM',
|
|
14
|
+
'MH',
|
|
15
|
+
'MS',
|
|
16
|
+
'KN',
|
|
17
|
+
'BS',
|
|
18
|
+
'CY',
|
|
19
|
+
'TC',
|
|
20
|
+
'US',
|
|
21
|
+
'LR',
|
|
22
|
+
'PW',
|
|
23
|
+
'KY',
|
|
24
|
+
];
|
|
25
|
+
export function addLocaleListener(listener) {
|
|
26
|
+
addEventListener(WEB_LANGUAGE_CHANGE_EVENT, listener);
|
|
27
|
+
return {
|
|
28
|
+
remove: () => removeEventListener(WEB_LANGUAGE_CHANGE_EVENT, listener),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export function addCalendarListener(listener) {
|
|
32
|
+
addEventListener(WEB_LANGUAGE_CHANGE_EVENT, listener);
|
|
33
|
+
return {
|
|
34
|
+
remove: () => removeEventListener(WEB_LANGUAGE_CHANGE_EVENT, listener),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function removeSubscription(subscription) {
|
|
38
|
+
subscription.remove();
|
|
39
|
+
}
|
|
40
|
+
export default {
|
|
41
|
+
get currency() {
|
|
42
|
+
// TODO: Add support
|
|
43
|
+
return null;
|
|
44
|
+
},
|
|
45
|
+
get decimalSeparator() {
|
|
46
|
+
return (1.1).toLocaleString().substring(1, 2);
|
|
47
|
+
},
|
|
48
|
+
get digitGroupingSeparator() {
|
|
49
|
+
const value = (1000).toLocaleString();
|
|
50
|
+
return value.length === 5 ? value.substring(1, 2) : '';
|
|
51
|
+
},
|
|
52
|
+
get isRTL() {
|
|
53
|
+
return rtlDetect.isRtlLang(this.locale) ?? false;
|
|
54
|
+
},
|
|
55
|
+
get isMetric() {
|
|
56
|
+
const { region } = this;
|
|
57
|
+
switch (region) {
|
|
58
|
+
case 'US': // USA
|
|
59
|
+
case 'LR': // Liberia
|
|
60
|
+
case 'MM': // Myanmar
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
return true;
|
|
64
|
+
},
|
|
65
|
+
get locale() {
|
|
66
|
+
if (!Platform.isDOMAvailable) {
|
|
67
|
+
return '';
|
|
68
|
+
}
|
|
69
|
+
const locale = navigator.language ||
|
|
70
|
+
navigator['systemLanguage'] ||
|
|
71
|
+
navigator['browserLanguage'] ||
|
|
72
|
+
navigator['userLanguage'] ||
|
|
73
|
+
this.locales[0];
|
|
74
|
+
return locale;
|
|
75
|
+
},
|
|
76
|
+
get locales() {
|
|
77
|
+
if (!Platform.isDOMAvailable) {
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
const { languages = [] } = navigator;
|
|
81
|
+
return Array.from(languages);
|
|
82
|
+
},
|
|
83
|
+
get timezone() {
|
|
84
|
+
const defaultTimeZone = 'Etc/UTC';
|
|
85
|
+
if (typeof Intl === 'undefined') {
|
|
86
|
+
return defaultTimeZone;
|
|
87
|
+
}
|
|
88
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone || defaultTimeZone;
|
|
89
|
+
},
|
|
90
|
+
get isoCurrencyCodes() {
|
|
91
|
+
// TODO(Bacon): Add this - very low priority
|
|
92
|
+
return [];
|
|
93
|
+
},
|
|
94
|
+
get region() {
|
|
95
|
+
// There is no way to obtain the current region, as is possible on native.
|
|
96
|
+
// Instead, use the country-code from the locale when possible (e.g. "en-US").
|
|
97
|
+
const { locale } = this;
|
|
98
|
+
const [, ...suffixes] = typeof locale === 'string' ? locale.split('-') : [];
|
|
99
|
+
for (const suffix of suffixes) {
|
|
100
|
+
if (suffix.length === 2) {
|
|
101
|
+
return suffix.toUpperCase();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
},
|
|
106
|
+
getLocales() {
|
|
107
|
+
const locales = getNavigatorLocales();
|
|
108
|
+
return locales?.map((languageTag) => {
|
|
109
|
+
// TextInfo is an experimental API that is not available in all browsers.
|
|
110
|
+
// We might want to consider using a locale lookup table instead.
|
|
111
|
+
const locale = typeof Intl !== 'undefined'
|
|
112
|
+
? new Intl.Locale(languageTag)
|
|
113
|
+
: { region: null, textInfo: null, language: null };
|
|
114
|
+
const { region, textInfo, language } = locale;
|
|
115
|
+
// Properties added only for compatibility with native, use `toLocaleString` instead.
|
|
116
|
+
const digitGroupingSeparator = Array.from((10000).toLocaleString(languageTag)).filter((c) => c > '9' || c < '0')[0] ||
|
|
117
|
+
null; // using 1e5 instead of 1e4 since for some locales (like pl-PL) 1e4 does not use digit grouping
|
|
118
|
+
const decimalSeparator = (1.1).toLocaleString(languageTag).substring(1, 2);
|
|
119
|
+
const temperatureUnit = region ? regionToTemperatureUnit(region) : null;
|
|
120
|
+
return {
|
|
121
|
+
languageTag,
|
|
122
|
+
languageCode: language || languageTag.split('-')[0] || 'en',
|
|
123
|
+
textDirection: textInfo?.direction || null,
|
|
124
|
+
digitGroupingSeparator,
|
|
125
|
+
decimalSeparator,
|
|
126
|
+
measurementSystem: null,
|
|
127
|
+
currencyCode: null,
|
|
128
|
+
currencySymbol: null,
|
|
129
|
+
regionCode: region || null,
|
|
130
|
+
temperatureUnit,
|
|
131
|
+
};
|
|
132
|
+
});
|
|
133
|
+
},
|
|
134
|
+
getCalendars() {
|
|
135
|
+
const locale = ((typeof Intl !== 'undefined'
|
|
136
|
+
? Intl.DateTimeFormat().resolvedOptions()
|
|
137
|
+
: null) ?? null);
|
|
138
|
+
return [
|
|
139
|
+
{
|
|
140
|
+
calendar: (locale?.calendar || locale?.calendars?.[0]) || null,
|
|
141
|
+
timeZone: locale?.timeZone || locale?.timeZones?.[0] || null,
|
|
142
|
+
uses24hourClock: (locale?.hourCycle || locale?.hourCycles?.[0])?.startsWith('h2') ?? null, //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/hourCycle
|
|
143
|
+
firstWeekday: locale?.weekInfo?.firstDay || null,
|
|
144
|
+
},
|
|
145
|
+
];
|
|
146
|
+
},
|
|
147
|
+
async getLocalizationAsync() {
|
|
148
|
+
const { currency, decimalSeparator, digitGroupingSeparator, isoCurrencyCodes, isMetric, isRTL, locale, locales, region, timezone, } = this;
|
|
149
|
+
return {
|
|
150
|
+
currency,
|
|
151
|
+
decimalSeparator,
|
|
152
|
+
digitGroupingSeparator,
|
|
153
|
+
isoCurrencyCodes,
|
|
154
|
+
isMetric,
|
|
155
|
+
isRTL,
|
|
156
|
+
locale,
|
|
157
|
+
locales,
|
|
158
|
+
region,
|
|
159
|
+
timezone,
|
|
160
|
+
};
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
function regionToTemperatureUnit(region) {
|
|
164
|
+
return USES_FAHRENHEIT.includes(region) ? 'fahrenheit' : 'celsius';
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=ExpoLocalization.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoLocalization.js","sourceRoot":"","sources":["../src/ExpoLocalization.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-env browser */\nimport { Platform, Subscription } 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\nconst WEB_LANGUAGE_CHANGE_EVENT = 'languagechange';\n// https://wisevoter.com/country-rankings/countries-that-use-fahrenheit/\nconst USES_FAHRENHEIT = [\n 'AG',\n 'BZ',\n 'VG',\n 'FM',\n 'MH',\n 'MS',\n 'KN',\n 'BS',\n 'CY',\n 'TC',\n 'US',\n 'LR',\n 'PW',\n 'KY',\n];\n\nexport function addLocaleListener(listener: (event) => void): Subscription {\n addEventListener(WEB_LANGUAGE_CHANGE_EVENT, listener);\n return {\n remove: () => removeEventListener(WEB_LANGUAGE_CHANGE_EVENT, listener),\n };\n}\n\nexport function addCalendarListener(listener: (event) => void): Subscription {\n addEventListener(WEB_LANGUAGE_CHANGE_EVENT, listener);\n return {\n remove: () => removeEventListener(WEB_LANGUAGE_CHANGE_EVENT, listener),\n };\n}\n\nexport function removeSubscription(subscription: Subscription) {\n subscription.remove();\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 const temperatureUnit = region ? regionToTemperatureUnit(region) : null;\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 temperatureUnit,\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\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\nfunction regionToTemperatureUnit(region: string) {\n return USES_FAHRENHEIT.includes(region) ? 'fahrenheit' : 'celsius';\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Subscription } from 'expo-modules-core';
|
|
2
|
+
import { Calendar, Locale } from './Localization.types';
|
|
3
|
+
export declare function addLocaleListener(listener: (event: any) => void): void;
|
|
4
|
+
export declare function addCalendarListener(listener: (event: any) => void): void;
|
|
5
|
+
export declare function removeSubscription(subscription: Subscription): void;
|
|
6
|
+
declare const module: {
|
|
7
|
+
getLocales: () => Locale[];
|
|
8
|
+
getCalendars: () => Calendar[];
|
|
9
|
+
locale: any;
|
|
10
|
+
};
|
|
11
|
+
export default module;
|
|
12
|
+
//# sourceMappingURL=ExpoLocalization.kepler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoLocalization.kepler.d.ts","sourceRoot":"","sources":["../src/ExpoLocalization.kepler.ts"],"names":[],"mappings":"AASA,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAE/C,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAC,MAAM,sBAAsB,CAAC;AAUtD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,CAAC,KAAK,KAAA,KAAK,IAAI,QAE1D;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,CAAC,KAAK,KAAA,KAAK,IAAI,QAE5D;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,YAAY,QAE5D;AAED,QAAA,MAAM,MAAM;sBAnBM,MAAM,EAAE;wBACN,QAAQ,EAAE;;CAsB7B,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
*
|
|
4
|
+
* PROPRIETARY/CONFIDENTIAL
|
|
5
|
+
*
|
|
6
|
+
* Use is subject to license terms.
|
|
7
|
+
*/
|
|
8
|
+
import { TurboModuleRegistry } from '@amazon-devices/keplerscript-turbomodule-api';
|
|
9
|
+
const nativeModule = TurboModuleRegistry.getEnforcing('ExpoLocalization');
|
|
10
|
+
const i18nManager = TurboModuleRegistry.getEnforcing('I18nManager');
|
|
11
|
+
export function addLocaleListener(listener) {
|
|
12
|
+
i18nManager.addListener('Locale', listener);
|
|
13
|
+
}
|
|
14
|
+
export function addCalendarListener(listener) {
|
|
15
|
+
i18nManager.addListener('Timezone', listener);
|
|
16
|
+
}
|
|
17
|
+
export function removeSubscription(subscription) {
|
|
18
|
+
i18nManager.removeListeners();
|
|
19
|
+
}
|
|
20
|
+
const module = {
|
|
21
|
+
getLocales: nativeModule.getLocales,
|
|
22
|
+
getCalendars: nativeModule.getCalendars,
|
|
23
|
+
locale: i18nManager.getAppLocale(),
|
|
24
|
+
};
|
|
25
|
+
export default module;
|
|
26
|
+
//# sourceMappingURL=ExpoLocalization.kepler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoLocalization.kepler.js","sourceRoot":"","sources":["../src/ExpoLocalization.kepler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAoB,mBAAmB,EAAC,MAAM,oCAAoC,CAAC;AAU1F,MAAM,YAAY,GAAG,mBAAmB,CAAC,YAAY,CAAO,kBAAkB,CAAS,CAAC;AACxF,MAAM,WAAW,GAAG,mBAAmB,CAAC,YAAY,CAAC,aAAa,CAAQ,CAAC;AAE3E,MAAM,UAAU,iBAAiB,CAAC,QAAyB;IACvD,WAAW,CAAC,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAyB;IACzD,WAAW,CAAC,WAAW,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,YAA0B;IACzD,WAAW,CAAC,eAAe,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,MAAM,GAAG;IACX,UAAU,EAAE,YAAY,CAAC,UAAU;IACnC,YAAY,EAAE,YAAY,CAAC,YAAY;IACvC,MAAM,EAAE,WAAW,CAAC,YAAY,EAAE;CACrC,CAAC;AAEF,eAAe,MAAM,CAAC","sourcesContent":["/*\n * Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n *\n * PROPRIETARY/CONFIDENTIAL\n *\n * Use is subject to license terms.\n */\n\nimport {KeplerTurboModule, TurboModuleRegistry} from '@amazon-devices/keplerscript-turbomodule-api';\nimport {Subscription} from 'expo-modules-core';\n\nimport {Calendar, Locale} from './Localization.types';\n\ninterface Spec extends KeplerTurboModule {\n getLocales(): Locale[];\n getCalendars(): Calendar[];\n}\n\nconst nativeModule = TurboModuleRegistry.getEnforcing<Spec>('ExpoLocalization') as Spec;\nconst i18nManager = TurboModuleRegistry.getEnforcing('I18nManager') as any;\n\nexport function addLocaleListener(listener: (event) => void) {\n i18nManager.addListener('Locale', listener);\n}\n\nexport function addCalendarListener(listener: (event) => void) {\n i18nManager.addListener('Timezone', listener);\n}\n\nexport function removeSubscription(subscription: Subscription) {\n i18nManager.removeListeners();\n}\n\nconst module = {\n getLocales: nativeModule.getLocales,\n getCalendars: nativeModule.getCalendars,\n locale: i18nManager.getAppLocale(),\n};\n\nexport default module;\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Subscription } from 'expo-modules-core';
|
|
2
|
+
declare const ExpoLocalizationModule: any;
|
|
3
|
+
export declare function addLocaleListener(listener: (event: any) => void): Subscription;
|
|
4
|
+
export declare function addCalendarListener(listener: (event: any) => void): Subscription;
|
|
5
|
+
export declare function removeSubscription(subscription: Subscription): void;
|
|
6
|
+
export default ExpoLocalizationModule;
|
|
7
|
+
//# 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":"AAAA,OAAO,EAAgB,YAAY,EAAuB,MAAM,mBAAmB,CAAC;AAEpF,QAAA,MAAM,sBAAsB,KAA0C,CAAC;AAGvE,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,CAAC,KAAK,KAAA,KAAK,IAAI,GAAG,YAAY,CAEzE;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,CAAC,KAAK,KAAA,KAAK,IAAI,GAAG,YAAY,CAE3E;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,YAAY,QAE5D;AAED,eAAe,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EventEmitter, requireNativeModule } from 'expo-modules-core';
|
|
2
|
+
const ExpoLocalizationModule = requireNativeModule('ExpoLocalization');
|
|
3
|
+
const emitter = new EventEmitter(ExpoLocalizationModule);
|
|
4
|
+
export function addLocaleListener(listener) {
|
|
5
|
+
return emitter.addListener('onLocaleSettingsChanged', listener);
|
|
6
|
+
}
|
|
7
|
+
export function addCalendarListener(listener) {
|
|
8
|
+
return emitter.addListener('onCalendarSettingsChanged', listener);
|
|
9
|
+
}
|
|
10
|
+
export function removeSubscription(subscription) {
|
|
11
|
+
return emitter.removeSubscription(subscription);
|
|
12
|
+
}
|
|
13
|
+
export default ExpoLocalizationModule;
|
|
14
|
+
//# sourceMappingURL=ExpoLocalization.native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoLocalization.native.js","sourceRoot":"","sources":["../src/ExpoLocalization.native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAgB,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAEpF,MAAM,sBAAsB,GAAG,mBAAmB,CAAC,kBAAkB,CAAC,CAAC;AACvE,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,sBAAsB,CAAC,CAAC;AAEzD,MAAM,UAAU,iBAAiB,CAAC,QAAyB;IACzD,OAAO,OAAO,CAAC,WAAW,CAAC,yBAAyB,EAAE,QAAQ,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAyB;IAC3D,OAAO,OAAO,CAAC,WAAW,CAAC,2BAA2B,EAAE,QAAQ,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,YAA0B;IAC3D,OAAO,OAAO,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;AAClD,CAAC;AAED,eAAe,sBAAsB,CAAC","sourcesContent":["import { EventEmitter, Subscription, requireNativeModule } from 'expo-modules-core';\n\nconst ExpoLocalizationModule = requireNativeModule('ExpoLocalization');\nconst emitter = new EventEmitter(ExpoLocalizationModule);\n\nexport function addLocaleListener(listener: (event) => void): Subscription {\n return emitter.addListener('onLocaleSettingsChanged', listener);\n}\n\nexport function addCalendarListener(listener: (event) => void): Subscription {\n return emitter.addListener('onCalendarSettingsChanged', listener);\n}\n\nexport function removeSubscription(subscription: Subscription) {\n return emitter.removeSubscription(subscription);\n}\n\nexport default ExpoLocalizationModule;\n"]}
|