Skip to content

Commit

Permalink
Switch from constants to getters
Browse files Browse the repository at this point in the history
  • Loading branch information
zoontek committed Jan 28, 2019
1 parent a162180 commit 3af4fee
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 275 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.os.Build;
import android.os.LocaleList;
import android.text.TextUtils;
Expand Down Expand Up @@ -31,9 +32,9 @@

public class RNLocalizeModule extends ReactContextBaseJavaModule implements LifecycleEventListener {

private static final List<String> USES_FAHRENHEIT_UNIT =
private static final List<String> USES_FAHRENHEIT =
Arrays.asList("BS", "BZ", "KY", "PR", "PW", "US");
private static final List<String> USES_IMPERIAL_SYSTEM =
private static final List<String> USES_IMPERIAL=
Arrays.asList("LR", "MM", "US");
private static final List<String> USES_RTL_LAYOUT =
Arrays.asList("ar", "ckb", "fa", "he", "ks", "lrc", "mzn", "ps", "ug", "ur", "yi");
Expand All @@ -49,15 +50,17 @@ public RNLocalizeModule(ReactApplicationContext reactContext) {
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);

BroadcastReceiver mConfigReceiver = new BroadcastReceiver() {
BroadcastReceiver mLocalizationReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() != null)
onLanguagesConfigDidChange();
if (intent.getAction() != null) {
onLocalizationDidChange();
}
}
};

getReactApplicationContext().registerReceiver(mConfigReceiver, filter);
getReactApplicationContext()
.registerReceiver(mLocalizationReceiver, filter);
}

@Override
Expand All @@ -68,21 +71,22 @@ public String getName() {
@Override
public @Nullable Map<String, Object> getConstants() {
HashMap<String, Object> constants = new HashMap<>();
constants.put("config", getConfig());
constants.put("initialConstants", getExported());

return constants;
}

@Override
public void initialize() {
getReactApplicationContext().addLifecycleEventListener(this);
getReactApplicationContext()
.addLifecycleEventListener(this);
}

private void onLanguagesConfigDidChange() {
private void onLocalizationDidChange() {
if (applicationIsPaused) {
emitChangeOnResume = true;
} else {
emitLanguagesConfigDidChange();
emitLocalizationDidChange();
}
}

Expand All @@ -91,7 +95,7 @@ public void onHostResume() {
applicationIsPaused = false;

if (emitChangeOnResume) {
emitLanguagesConfigDidChange();
emitLocalizationDidChange();
emitChangeOnResume = false;
}
}
Expand All @@ -104,29 +108,32 @@ public void onHostPause() {
@Override
public void onHostDestroy() {}

private void emitLanguagesConfigDidChange() {
getReactApplicationContext().getJSModule(RCTDeviceEventEmitter.class)
.emit("languagesConfigDidChange", getConfig());
private void emitLocalizationDidChange() {
getReactApplicationContext()
.getJSModule(RCTDeviceEventEmitter.class)
.emit("localizationDidChange", getExported());
}

private List<Locale> getLocales() {
List<Locale> locales = new ArrayList<>();
Configuration config = getReactApplicationContext()
.getResources()
.getConfiguration();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
LocaleList localeList = getReactApplicationContext().getResources()
.getConfiguration().getLocales();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
locales.add(config.locale);
} else {
LocaleList localeList = config.getLocales();

for (int i = 0; i < localeList.size(); i++)
for (int i = 0; i < localeList.size(); i++) {
locales.add(localeList.get(i));
} else {
locales.add(getReactApplicationContext().getResources()
.getConfiguration().locale);
}
}

return locales;
}

private String getLanguageCode(Locale locale) {
private static String getLanguageCode(Locale locale) {
String languageCode = locale.getLanguage();

switch (languageCode) {
Expand All @@ -141,140 +148,88 @@ private String getLanguageCode(Locale locale) {
return languageCode;
}

private String getScriptCode(Locale locale) {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? locale.getScript() : "";
private static @Nullable String getScriptCode(Locale locale) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
String scriptCode = locale.getScript();
return scriptCode.equals("") ? null : scriptCode;
}
return null;
}

private String getCountryCode(Locale locale, String fallback) {
private static String getCountryCode(Locale locale, String fallback) {
String countryCode = locale.getCountry();
return countryCode != null ? countryCode : fallback;
}

private String getCurrencyCode(Locale locale, String fallback) {
private static String getCurrencyCode(Locale locale, String fallback) {
Currency currency = Currency.getInstance(locale);
return currency != null ? currency.getCurrencyCode() : fallback;
}

private boolean getIsRTL(Locale locale) {
private static boolean getIsRTL(Locale locale) {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1
? TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL
: USES_RTL_LAYOUT.contains(getLanguageCode(locale));
}

private String concatCodes(String code1, String code2) {
return code1 + (code2.equals("") ? code2 : "-" + code2);
}

private String getTemperatureUnit(Locale locale) {
return USES_FAHRENHEIT_UNIT.contains(getCountryCode(locale, "US")) ? "fahrenheit" : "celsius";
private static String getTemperatureUnit(Locale locale) {
return USES_FAHRENHEIT.contains(getCountryCode(locale, "US"))
? "fahrenheit" : "celsius";
}

private boolean getUses24HourClock() {
return DateFormat.is24HourFormat(getReactApplicationContext());
private static boolean getUsesMetricSystem(Locale locale) {
return !USES_IMPERIAL.contains(getCountryCode(locale,"US"));
}

private boolean getUsesMetricSystem(Locale locale) {
return !USES_IMPERIAL_SYSTEM.contains(getCountryCode(locale,"US"));
}

private WritableMap getConfig() {
List<HashMap<String, Object>> extracteds = new ArrayList<>();
List<String> fallbacks = new ArrayList<>();
List<Locale> locales = getLocales();
private WritableMap getExported() {
List<Locale> deviceLocales = getLocales();
List<String> currenciesCache = new ArrayList<>();

Locale currentLocale = locales.get(0);
Locale currentLocale = deviceLocales.get(0);
String currentCountryCode = getCountryCode(currentLocale, "US");

WritableArray languages = Arguments.createArray();
WritableArray locales = Arguments.createArray();
WritableArray currencies = Arguments.createArray();

for (int i = 0; i < locales.size(); i++) {
HashMap<String, Object> extracted = new HashMap<>();
Locale locale = locales.get(i);

for (Locale locale: deviceLocales) {
String languageCode = getLanguageCode(locale);
String partialCode = concatCodes(languageCode, getScriptCode(locale));
String currencyCode = getCurrencyCode(locale, "USD");
String scriptCode = getScriptCode(locale);
String countryCode = getCountryCode(locale, currentCountryCode);
String currencyCode = getCurrencyCode(locale, "USD");

if (!currenciesCache.contains(currencyCode)) {
currenciesCache.add(currencyCode);
currencies.pushString(currencyCode);
}

extracted.put("languageCode", languageCode);
extracted.put("partialCode", partialCode);
extracted.put("fullCode", concatCodes(partialCode, countryCode));
extracted.put("isRTL", getIsRTL(locale));

extracteds.add(extracted);
}
WritableMap result = Arguments.createMap();
String languageTag = languageCode;

int extractedsSize = extracteds.size();
result.putString("languageCode", languageCode);
result.putString("countryCode", countryCode);
result.putBoolean("isRTL", getIsRTL(locale));

for (int i = 0; i < extractedsSize; i++) {
HashMap<String, Object> extracted = extracteds.get(i);
String languageCode = (String) extracted.get("languageCode");
String partialCode = (String) extracted.get("partialCode");
boolean isRTL = (boolean) extracted.get("isRTL");

WritableMap language = Arguments.createMap();
language.putString("code", (String) extracted.get("fullCode"));
language.putBoolean("isRTL", isRTL);
language.putBoolean("isFallback", false);

languages.pushMap(language);

String nextLanguageCode = null;
String nextPartialCode = null;

if (i + 1 < extractedsSize) {
nextLanguageCode = (String) extracteds.get(i + 1).get("languageCode");
nextPartialCode = (String) extracteds.get(i + 1).get("partialCode");
if (scriptCode != null) {
languageTag += "-" + scriptCode;
result.putString("scriptCode", scriptCode);
}

if (!partialCode.equals(languageCode)) {
if (partialCode.equals(nextPartialCode)) {
continue;
}

if (!fallbacks.contains(partialCode)) {
fallbacks.add(partialCode);

WritableMap fallback = Arguments.createMap();
fallback.putString("code", partialCode);
fallback.putBoolean("isRTL", isRTL);
fallback.putBoolean("isFallback", true);
languageTag += "-" + countryCode;
result.putString("languageTag", languageTag);

languages.pushMap(fallback);
}
}

if (!languageCode.equals(nextPartialCode) && !languageCode.equals(nextLanguageCode)) {
if (!fallbacks.contains(languageCode)) {
fallbacks.add(languageCode);
locales.pushMap(result);
}

WritableMap fallback = Arguments.createMap();
fallback.putString("code", languageCode);
fallback.putBoolean("isRTL", isRTL);
fallback.putBoolean("isFallback", true);
WritableMap exported = Arguments.createMap();

languages.pushMap(fallback);
}
}
}
exported.putString("calendar", "gregorian");
exported.putString("country", currentCountryCode);
exported.putArray("currencies", currencies);
exported.putArray("locales", locales);
exported.putString("temperatureUnit", getTemperatureUnit(currentLocale));
exported.putString("timeZone", TimeZone.getDefault().getID());
exported.putBoolean("uses24HourClock", DateFormat.is24HourFormat(getReactApplicationContext()));
exported.putBoolean("usesMetricSystem", getUsesMetricSystem(currentLocale));

WritableMap config = Arguments.createMap();
config.putArray("languages", languages);
config.putArray("currencies", currencies);
config.putString("calendar", "gregorian");
config.putString("country", currentCountryCode);
config.putString("temperatureUnit", getTemperatureUnit(currentLocale));
config.putString("timeZone", TimeZone.getDefault().getID());
config.putBoolean("uses24HourClock", getUses24HourClock());
config.putBoolean("usesMetricSystem", getUsesMetricSystem(currentLocale));

return config;
return exported;
}
}
48 changes: 25 additions & 23 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
declare module "react-native-localize" {
export type LocalizationEvent = "change";

export type Calendar = "gregorian" | "japanese" | "buddhist";
export type TemperatureUnit = "celsius" | "fahrenheit";

export interface LanguagesConfig {
readonly languages: string[];
readonly currencies: string[];
readonly calendar: Calendar;
readonly country: string;
readonly temperatureUnit: TemperatureUnit;
readonly timeZone: string;
readonly uses24HourClock: boolean;
readonly usesMetricSystem: boolean;
}

export type LanguagesEmitterSubscription = {
remove: () => void;
export type Locale = {
readonly languageCode: string;
readonly scriptCode?: string;
readonly countryCode: string;
readonly languageTag: string;
readonly isRTL: boolean;
};
export type LanguagesEvent = "configDidChange";
export type LanguagesEventHandler = (config: LanguagesConfig) => any;

interface RNLocalizeModule extends LanguagesConfig {
addListener: (
type: LanguagesEvent,
handler: LanguagesEventHandler,
) => LanguagesEmitterSubscription;
}
export function getCalendar(): Calendar;
export function getCountry(): string;
export function getCurrencies(): string[];
export function getLocales(): Locale[];
export function getTemperatureUnit(): TemperatureUnit;
export function getTimeZone(): string;
export function uses24HourClock(): boolean;
export function usesMetricSystem(): boolean;

export function addEventListener(
type: LocalizationEvent,
handler: Function,
): void;

let Module: RNLocalizeModule;
export default Module;
export function removeEventListener(
type: LocalizationEvent,
handler: Function,
): void;
}
Loading

0 comments on commit 3af4fee

Please sign in to comment.