1import { getMainActivityOrThrow } from '@expo/config-plugins/build/android/Manifest';
2import { ExpoConfig } from '@expo/config-types';
3import {
4  AndroidConfig,
5  withAndroidManifest,
6  withPlugins,
7  withStringsXml,
8} from 'expo/config-plugins';
9
10type ConfigPluginProps = {
11  supportsRTL?: boolean;
12  allowDynamicLocaleChangesAndroid?: boolean;
13};
14
15function withExpoLocalizationIos(config: ExpoConfig) {
16  if (config.extra?.supportsRTL == null) return config;
17  if (!config.ios) config.ios = {};
18  if (!config.ios.infoPlist) config.ios.infoPlist = {};
19  config.ios.infoPlist.ExpoLocalization_supportsRTL = config.extra?.supportsRTL || false;
20  return config;
21}
22
23function withExpoLocalizationAndroid(config: ExpoConfig, data: ConfigPluginProps) {
24  if (data.allowDynamicLocaleChangesAndroid) {
25    config = withAndroidManifest(config, (config) => {
26      const mainActivity = getMainActivityOrThrow(config.modResults);
27      if (!mainActivity.$['android:configChanges']?.includes('locale')) {
28        mainActivity.$['android:configChanges'] += '|locale';
29      }
30      if (!mainActivity.$['android:configChanges']?.includes('layoutDirection')) {
31        mainActivity.$['android:configChanges'] += '|layoutDirection';
32      }
33      return config;
34    });
35  }
36  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    );
46    return config;
47  });
48}
49
50function withExpoLocalization(
51  config: ExpoConfig,
52  data: ConfigPluginProps = {
53    allowDynamicLocaleChangesAndroid: true,
54  }
55) {
56  return withPlugins(config, [
57    [withExpoLocalizationIos, data],
58    [withExpoLocalizationAndroid, data],
59  ]);
60}
61
62export default withExpoLocalization;
63