expo-localization 15.0.1 → 15.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,16 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 15.0.3 — 2024-05-06
14
+
15
+ ### 🎉 New features
16
+
17
+ - Added a `forcesRTL` manifest flag for forcing RTL to be on. ([#28129](https://github.com/expo/expo/pull/28129) by [@aleqsio](https://github.com/aleqsio))
18
+
19
+ ## 15.0.2 — 2024-05-01
20
+
21
+ _This version does not introduce any user-facing changes._
22
+
13
23
  ## 15.0.1 — 2024-04-23
14
24
 
15
25
  _This version does not introduce any user-facing changes._
@@ -1,7 +1,7 @@
1
1
  apply plugin: 'com.android.library'
2
2
 
3
3
  group = 'host.exp.exponent'
4
- version = '15.0.1'
4
+ version = '15.0.3'
5
5
 
6
6
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
7
7
  apply from: expoModulesCorePlugin
@@ -14,7 +14,7 @@ android {
14
14
  namespace "expo.modules.localization"
15
15
  defaultConfig {
16
16
  versionCode 22
17
- versionName "15.0.1"
17
+ versionName "15.0.3"
18
18
  }
19
19
  }
20
20
 
@@ -22,7 +22,7 @@ import java.util.*
22
22
  // 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
23
23
  private const val SHARED_PREFS_NAME = "com.facebook.react.modules.i18nmanager.I18nUtil"
24
24
  private const val KEY_FOR_PREFS_ALLOWRTL = "RCTI18nUtil_allowRTL"
25
-
25
+ private const val KEY_FOR_PREFS_FORCERTL = "RCTI18nUtil_forceRTL"
26
26
  private const val LOCALE_SETTINGS_CHANGED = "onLocaleSettingsChanged"
27
27
  private const val CALENDAR_SETTINGS_CHANGED = "onCalendarSettingsChanged"
28
28
 
@@ -70,14 +70,31 @@ class LocalizationModule : Module() {
70
70
  // These keys are used by React Native here: https://github.com/facebook/react-native/blob/main/React/Modules/RCTI18nUtil.m
71
71
  // We set them before React loads to ensure it gets rendered correctly the first time the app is opened.
72
72
  val supportsRTL = appContext.reactContext?.getString(R.string.ExpoLocalization_supportsRTL)
73
- if (supportsRTL != "true" && supportsRTL != "false") return
74
- context
75
- .getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE)
76
- .edit()
77
- .also {
78
- it.putBoolean(KEY_FOR_PREFS_ALLOWRTL, supportsRTL == "true")
79
- it.apply()
73
+ val forcesRTL = appContext.reactContext?.getString(R.string.ExpoLocalization_forcesRTL)
74
+
75
+ if (forcesRTL == "true") {
76
+ context
77
+ .getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE)
78
+ .edit()
79
+ .also {
80
+ it.putBoolean(KEY_FOR_PREFS_ALLOWRTL, true)
81
+ it.putBoolean(KEY_FOR_PREFS_FORCERTL, true)
82
+ it.apply()
83
+ }
84
+ } else {
85
+ if (supportsRTL == "true" || supportsRTL == "false") {
86
+ context
87
+ .getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE)
88
+ .edit()
89
+ .also {
90
+ it.putBoolean(KEY_FOR_PREFS_ALLOWRTL, supportsRTL == "true")
91
+ if (forcesRTL == "false") {
92
+ it.putBoolean(KEY_FOR_PREFS_FORCERTL, false)
93
+ }
94
+ it.apply()
95
+ }
80
96
  }
97
+ }
81
98
  }
82
99
 
83
100
  // TODO: Bacon: add set language
@@ -114,6 +131,7 @@ class LocalizationModule : Module() {
114
131
  }
115
132
  locales
116
133
  } else {
134
+ @Suppress("DEPRECATION")
117
135
  listOf(configuration.locale)
118
136
  }
119
137
  }
@@ -24,7 +24,7 @@ object Notifier {
24
24
 
25
25
  // TODO: Move to new listener API once it's available
26
26
  class LocalizationPackage : Package {
27
- override fun createApplicationLifecycleListeners(context: Context?): List<out ApplicationLifecycleListener> {
27
+ override fun createApplicationLifecycleListeners(context: Context?): List<ApplicationLifecycleListener> {
28
28
  return listOf(object : ApplicationLifecycleListener {
29
29
  override fun onConfigurationChanged(newConfig: Configuration?) {
30
30
  super.onConfigurationChanged(newConfig)
@@ -1,4 +1,5 @@
1
1
  <?xml version="1.0" encoding="utf-8"?>
2
2
  <resources>
3
3
  <string name="ExpoLocalization_supportsRTL" translatable="false">unset</string>
4
+ <string name="ExpoLocalization_forcesRTL" translatable="false">unset</string>
4
5
  </resources>
@@ -23,8 +23,12 @@ public class LocalizationModule: Module {
23
23
  return Self.getCalendars()
24
24
  }
25
25
  OnCreate {
26
- if let enableRTL = Bundle.main.object(forInfoDictionaryKey: "ExpoLocalization_supportsRTL") as? Bool {
27
- self.setSupportsRTL(enableRTL)
26
+ if let forceRTL = Bundle.main.object(forInfoDictionaryKey: "ExpoLocalization_forcesRTL") as? Bool {
27
+ self.setRTLPreferences(true, forceRTL)
28
+ } else {
29
+ if let enableRTL = Bundle.main.object(forInfoDictionaryKey: "ExpoLocalization_supportsRTL") as? Bool {
30
+ self.setRTLPreferences(enableRTL, false)
31
+ }
28
32
  }
29
33
  }
30
34
 
@@ -53,13 +57,20 @@ public class LocalizationModule: Module {
53
57
  return NSLocale.characterDirection(forLanguage: NSLocale.preferredLanguages.first ?? "en-US") == NSLocale.LanguageDirection.rightToLeft
54
58
  }
55
59
 
56
- func setSupportsRTL(_ supportsRTL: Bool) {
60
+ func setRTLPreferences(_ supportsRTL: Bool, _ forceRTL: Bool) {
57
61
  // These keys are used by React Native here: https://github.com/facebook/react-native/blob/main/React/Modules/RCTI18nUtil.m
58
62
  // We set them before React loads to ensure it gets rendered correctly the first time the app is opened.
59
63
  // On iOS we need to set both forceRTL and allowRTL so apps don't have to include localization strings.
60
64
  // Uses required reason API based on the following reason: CA92.1
61
- UserDefaults.standard.set(supportsRTL, forKey: "RCTI18nUtil_allowRTL")
62
- UserDefaults.standard.set(supportsRTL ? isRTLPreferredForCurrentLocale() : false, forKey: "RCTI18nUtil_forceRTL")
65
+
66
+ if forceRTL {
67
+ UserDefaults.standard.set(true, forKey: "RCTI18nUtil_allowRTL")
68
+ UserDefaults.standard.set(true, forKey: "RCTI18nUtil_forceRTL")
69
+ } else {
70
+ UserDefaults.standard.set(supportsRTL, forKey: "RCTI18nUtil_allowRTL")
71
+ UserDefaults.standard.set(supportsRTL ? isRTLPreferredForCurrentLocale() : false, forKey: "RCTI18nUtil_forceRTL")
72
+ }
73
+
63
74
  UserDefaults.standard.synchronize()
64
75
  }
65
76
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-localization",
3
- "version": "15.0.1",
3
+ "version": "15.0.3",
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": "ee4f30ef3b5fa567ad1bf94794197f7683fdd481"
50
+ "gitHead": "7995f30a8d2af4836f3aef9fe322e9403fc23d34"
51
51
  }
@@ -1,6 +1,7 @@
1
1
  import { ExpoConfig } from '@expo/config-types';
2
2
  type ConfigPluginProps = {
3
3
  supportsRTL?: boolean;
4
+ forcesRTL?: boolean;
4
5
  allowDynamicLocaleChangesAndroid?: boolean;
5
6
  };
6
7
  declare function withExpoLocalization(config: ExpoConfig, data?: ConfigPluginProps): ExpoConfig;
@@ -2,14 +2,20 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const Manifest_1 = require("@expo/config-plugins/build/android/Manifest");
4
4
  const config_plugins_1 = require("expo/config-plugins");
5
- function withExpoLocalizationIos(config) {
6
- if (config.extra?.supportsRTL == null)
5
+ function withExpoLocalizationIos(config, data) {
6
+ const mergedConfig = { ...config.extra, ...data };
7
+ if (mergedConfig?.supportsRTL == null && mergedConfig?.forcesRTL == null)
7
8
  return config;
8
9
  if (!config.ios)
9
10
  config.ios = {};
10
11
  if (!config.ios.infoPlist)
11
12
  config.ios.infoPlist = {};
12
- config.ios.infoPlist.ExpoLocalization_supportsRTL = config.extra?.supportsRTL || false;
13
+ if (mergedConfig?.supportsRTL != null) {
14
+ config.ios.infoPlist.ExpoLocalization_supportsRTL = mergedConfig?.supportsRTL;
15
+ }
16
+ if (mergedConfig?.forcesRTL != null) {
17
+ config.ios.infoPlist.ExpoLocalization_forcesRTL = mergedConfig?.forcesRTL;
18
+ }
13
19
  return config;
14
20
  }
15
21
  function withExpoLocalizationAndroid(config, data) {
@@ -26,12 +32,23 @@ function withExpoLocalizationAndroid(config, data) {
26
32
  });
27
33
  }
28
34
  return (0, config_plugins_1.withStringsXml)(config, (config) => {
29
- config.modResults = config_plugins_1.AndroidConfig.Strings.setStringItem([
30
- {
31
- $: { name: 'ExpoLocalization_supportsRTL', translatable: 'false' },
32
- _: String(data.supportsRTL ?? config.extra?.supportsRTL),
33
- },
34
- ], config.modResults);
35
+ const mergedConfig = { ...config.extra, ...data };
36
+ if (mergedConfig?.supportsRTL != null) {
37
+ config.modResults = config_plugins_1.AndroidConfig.Strings.setStringItem([
38
+ {
39
+ $: { name: 'ExpoLocalization_supportsRTL', translatable: 'false' },
40
+ _: String(mergedConfig?.supportsRTL ?? 'unset'),
41
+ },
42
+ ], config.modResults);
43
+ }
44
+ if (mergedConfig?.forcesRTL != null) {
45
+ config.modResults = config_plugins_1.AndroidConfig.Strings.setStringItem([
46
+ {
47
+ $: { name: 'ExpoLocalization_forcesRTL', translatable: 'false' },
48
+ _: String(mergedConfig?.forcesRTL ?? 'unset'),
49
+ },
50
+ ], config.modResults);
51
+ }
35
52
  return config;
36
53
  });
37
54
  }
@@ -9,14 +9,21 @@ import {
9
9
 
10
10
  type ConfigPluginProps = {
11
11
  supportsRTL?: boolean;
12
+ forcesRTL?: boolean;
12
13
  allowDynamicLocaleChangesAndroid?: boolean;
13
14
  };
14
15
 
15
- function withExpoLocalizationIos(config: ExpoConfig) {
16
- if (config.extra?.supportsRTL == null) return config;
16
+ function withExpoLocalizationIos(config: ExpoConfig, data: ConfigPluginProps) {
17
+ const mergedConfig = { ...config.extra, ...data };
18
+ if (mergedConfig?.supportsRTL == null && mergedConfig?.forcesRTL == null) return config;
17
19
  if (!config.ios) config.ios = {};
18
20
  if (!config.ios.infoPlist) config.ios.infoPlist = {};
19
- config.ios.infoPlist.ExpoLocalization_supportsRTL = config.extra?.supportsRTL || false;
21
+ if (mergedConfig?.supportsRTL != null) {
22
+ config.ios.infoPlist.ExpoLocalization_supportsRTL = mergedConfig?.supportsRTL;
23
+ }
24
+ if (mergedConfig?.forcesRTL != null) {
25
+ config.ios.infoPlist.ExpoLocalization_forcesRTL = mergedConfig?.forcesRTL;
26
+ }
20
27
  return config;
21
28
  }
22
29
 
@@ -34,15 +41,29 @@ function withExpoLocalizationAndroid(config: ExpoConfig, data: ConfigPluginProps
34
41
  });
35
42
  }
36
43
  return withStringsXml(config, (config) => {
37
- config.modResults = AndroidConfig.Strings.setStringItem(
38
- [
39
- {
40
- $: { name: 'ExpoLocalization_supportsRTL', translatable: 'false' },
41
- _: String(data.supportsRTL ?? config.extra?.supportsRTL),
42
- },
43
- ],
44
- config.modResults
45
- );
44
+ const mergedConfig = { ...config.extra, ...data };
45
+ if (mergedConfig?.supportsRTL != null) {
46
+ config.modResults = AndroidConfig.Strings.setStringItem(
47
+ [
48
+ {
49
+ $: { name: 'ExpoLocalization_supportsRTL', translatable: 'false' },
50
+ _: String(mergedConfig?.supportsRTL ?? 'unset'),
51
+ },
52
+ ],
53
+ config.modResults
54
+ );
55
+ }
56
+ if (mergedConfig?.forcesRTL != null) {
57
+ config.modResults = AndroidConfig.Strings.setStringItem(
58
+ [
59
+ {
60
+ $: { name: 'ExpoLocalization_forcesRTL', translatable: 'false' },
61
+ _: String(mergedConfig?.forcesRTL ?? 'unset'),
62
+ },
63
+ ],
64
+ config.modResults
65
+ );
66
+ }
46
67
  return config;
47
68
  });
48
69
  }