From b194d3d271bbd5b1894390abe19d51d3d7e7cd01 Mon Sep 17 00:00:00 2001 From: Alexander Marchuk Date: Thu, 22 Oct 2015 20:39:23 +0300 Subject: [PATCH] [android] refactor: TTS refactored. --- android/AndroidManifest.xml | 3 +- android/jni/com/mapswithme/maps/sound/tts.cpp | 4 +- android/res/values/strings-tts.xml | 80 +++++++ .../src/com/mapswithme/maps/MwmActivity.java | 3 +- .../com/mapswithme/maps/MwmApplication.java | 29 +-- .../maps/search/SearchFragment.java | 18 +- .../maps/settings/MapPrefsFragment.java | 2 +- .../mapswithme/maps/sound/LanguageData.java | 71 ++++++ .../com/mapswithme/maps/sound/TtsPlayer.java | 203 ++++++++++-------- android/src/com/mapswithme/util/Config.java | 36 +++- android/src/com/mapswithme/util/Language.java | 41 ---- .../{in.json => id.json}/localize.json | 0 12 files changed, 325 insertions(+), 165 deletions(-) create mode 100644 android/res/values/strings-tts.xml create mode 100644 android/src/com/mapswithme/maps/sound/LanguageData.java rename data/sound-strings/{in.json => id.json}/localize.json (100%) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 7f012cb66f..d397d503c7 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -171,8 +171,7 @@ android:name="com.mapswithme.maps.MwmActivity" android:launchMode="singleTask" android:theme="@style/MwmTheme.MainActivity" - android:windowSoftInputMode="stateAlwaysHidden|adjustPan"> - + android:windowSoftInputMode="stateAlwaysHidden|adjustPan"/> EnableTurnNotifications(enable == JNI_TRUE ? true : false); + return frm()->EnableTurnNotifications(static_cast(enable)); } JNIEXPORT jboolean JNICALL Java_com_mapswithme_maps_sound_TtsPlayer_nativeAreTurnNotificationsEnabled(JNIEnv * env, jclass clazz) { - return frm()->AreTurnNotificationsEnabled() ? JNI_TRUE : JNI_FALSE; + return static_cast(frm()->AreTurnNotificationsEnabled()); } JNIEXPORT void JNICALL diff --git a/android/res/values/strings-tts.xml b/android/res/values/strings-tts.xml new file mode 100644 index 0000000000..e96013793a --- /dev/null +++ b/android/res/values/strings-tts.xml @@ -0,0 +1,80 @@ + + + + + en + ru + pl + sv + tr + fr + nl + de + ar + el + it + cs + hu + ro + ja + da + es + fi + hi + hr + id + ko + pt + sk + sw + th + zh-tw:zh-Hant + zh-cn:zh-Hans + + + + English + Русский + Polski + Svenska + Türkçe + Français + Nederlands + Deutsch + العربية + Ελληνικά + Italiano + Čeština + Magyar + Română + 日本語 + Dansk + Español + Suomi + हिन्दी + Hrvatski + TODO: Indonesian + 한국어 + Português + Slovenčina + Kiswahili + ไทย + TODO: Chinese Traditional + TODO: Chinese Simplified + + diff --git a/android/src/com/mapswithme/maps/MwmActivity.java b/android/src/com/mapswithme/maps/MwmActivity.java index 53b9cbeebd..1e886890bc 100644 --- a/android/src/com/mapswithme/maps/MwmActivity.java +++ b/android/src/com/mapswithme/maps/MwmActivity.java @@ -767,14 +767,13 @@ public class MwmActivity extends BaseMwmFragmentActivity { super.onStart(); - TtsPlayer.INSTANCE.reinitIfLocaleChanged(); if (!mIsFragmentContainer) popFragment(); } private void adjustZoomButtons(boolean routingActive) { - boolean show = (routingActive || Config.getShowZoomButtons()); + boolean show = (routingActive || Config.showZoomButtons()); UiUtils.showIf(show, mBtnZoomIn, mBtnZoomOut); if (!show) diff --git a/android/src/com/mapswithme/maps/MwmApplication.java b/android/src/com/mapswithme/maps/MwmApplication.java index 52dfc07e8a..7287cc9d11 100644 --- a/android/src/com/mapswithme/maps/MwmApplication.java +++ b/android/src/com/mapswithme/maps/MwmApplication.java @@ -1,16 +1,17 @@ package com.mapswithme.maps; +import android.app.Application; import android.content.SharedPreferences; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Environment; import android.preference.PreferenceManager; import android.util.Log; - import com.google.gson.Gson; import com.mapswithme.country.ActiveCountryTree; import com.mapswithme.country.CountryItem; import com.mapswithme.maps.background.Notifier; import com.mapswithme.maps.bookmarks.data.BookmarkManager; +import com.mapswithme.maps.sound.TtsPlayer; import com.mapswithme.util.Config; import com.mapswithme.util.Constants; import com.mapswithme.util.UiUtils; @@ -24,7 +25,8 @@ import com.parse.SaveCallback; import java.io.File; -public class MwmApplication extends android.app.Application implements ActiveCountryTree.ActiveCountryListener +public class MwmApplication extends Application + implements ActiveCountryTree.ActiveCountryListener { private final static String TAG = "MwmApplication"; @@ -32,32 +34,32 @@ public class MwmApplication extends android.app.Application implements ActiveCou private static final String PREF_PARSE_DEVICE_TOKEN = "ParseDeviceToken"; private static final String PREF_PARSE_INSTALLATION_ID = "ParseInstallationId"; - private static MwmApplication mSelf; + private static MwmApplication sSelf; + private static SharedPreferences sPrefs; private final Gson mGson = new Gson(); - private static SharedPreferences mPrefs; - private boolean mAreCountersInitialised; + private boolean mAreCountersInitialized; private boolean mIsFrameworkInitialized; public MwmApplication() { super(); - mSelf = this; + sSelf = this; } public static MwmApplication get() { - return mSelf; + return sSelf; } public static Gson gson() { - return mSelf.mGson; + return sSelf.mGson; } public static SharedPreferences prefs() { - return mPrefs; + return sPrefs; } @Override @@ -92,10 +94,10 @@ public class MwmApplication extends android.app.Application implements ActiveCou super.onCreate(); initParse(); - mPrefs = getSharedPreferences(getString(R.string.pref_file_name), MODE_PRIVATE); + sPrefs = getSharedPreferences(getString(R.string.pref_file_name), MODE_PRIVATE); } - public synchronized void initNativeCore() + public void initNativeCore() { if (mIsFrameworkInitialized) return; @@ -107,6 +109,7 @@ public class MwmApplication extends android.app.Application implements ActiveCou ActiveCountryTree.addListener(this); initNativeStrings(); BookmarkManager.getIcons(); // init BookmarkManager (automatically loads bookmarks) + TtsPlayer.INSTANCE.init(this); mIsFrameworkInitialized = true; } @@ -226,9 +229,9 @@ public class MwmApplication extends android.app.Application implements ActiveCou public void initCounters() { - if (!mAreCountersInitialised) + if (!mAreCountersInitialized) { - mAreCountersInitialised = true; + mAreCountersInitialized = true; Config.updateLaunchCounter(); PreferenceManager.setDefaultValues(this, R.xml.prefs_misc, false); } diff --git a/android/src/com/mapswithme/maps/search/SearchFragment.java b/android/src/com/mapswithme/maps/search/SearchFragment.java index 9ae98d5214..0c4f16cd51 100644 --- a/android/src/com/mapswithme/maps/search/SearchFragment.java +++ b/android/src/com/mapswithme/maps/search/SearchFragment.java @@ -15,7 +15,6 @@ import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; - import com.mapswithme.country.ActiveCountryTree; import com.mapswithme.country.CountrySuggestFragment; import com.mapswithme.maps.Framework; @@ -24,7 +23,6 @@ import com.mapswithme.maps.R; import com.mapswithme.maps.base.BaseMwmFragment; import com.mapswithme.maps.base.OnBackPressListener; import com.mapswithme.maps.location.LocationHelper; -import com.mapswithme.maps.sound.TtsPlayer; import com.mapswithme.maps.widget.SearchToolbarController; import com.mapswithme.util.InputUtils; import com.mapswithme.util.Language; @@ -82,7 +80,7 @@ public class SearchFragment extends BaseMwmFragment } // TODO: This code only for demonstration purposes and will be removed soon - if (trySwitchOnTurnSound(query) || tryChangeMapStyle(query)) + if (tryChangeMapStyle(query)) return; runSearch(); @@ -333,20 +331,6 @@ public class SearchFragment extends BaseMwmFragment return true; } - - private boolean trySwitchOnTurnSound(String query) - { - final boolean sound = "?sound".equals(query); - final boolean nosound = "?nosound".equals(query); - - if (!sound && !nosound) - return false; - - hideSearch(); - TtsPlayer.INSTANCE.enable(sound); - - return sound; - } // FIXME END protected void showSingleResultOnMap(int resultIndex) diff --git a/android/src/com/mapswithme/maps/settings/MapPrefsFragment.java b/android/src/com/mapswithme/maps/settings/MapPrefsFragment.java index f2211f8bd3..83d7dc7682 100644 --- a/android/src/com/mapswithme/maps/settings/MapPrefsFragment.java +++ b/android/src/com/mapswithme/maps/settings/MapPrefsFragment.java @@ -87,7 +87,7 @@ public class MapPrefsFragment extends BaseXmlSettingsFragment }); pref = findPreference(getString(R.string.pref_show_zoom_buttons)); - ((SwitchPreference)pref).setChecked(Config.getShowZoomButtons()); + ((SwitchPreference)pref).setChecked(Config.showZoomButtons()); pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override diff --git a/android/src/com/mapswithme/maps/sound/LanguageData.java b/android/src/com/mapswithme/maps/sound/LanguageData.java new file mode 100644 index 0000000000..96cf084a10 --- /dev/null +++ b/android/src/com/mapswithme/maps/sound/LanguageData.java @@ -0,0 +1,71 @@ +package com.mapswithme.maps.sound; + +import java.util.Locale; + +public class LanguageData +{ + public final Locale locale; + public final String name; + public final String internalCode; + + private int mStatus; + + private LanguageData(String name, Locale locale, String internalCode) + { + this.locale = locale; + this.name = name; + this.internalCode = internalCode; + } + + static LanguageData parse(String line, String name) + { + String[] parts = line.split(":"); + String internalCode = (parts.length > 1 ? parts[1] : null); + + parts = parts[0].split("-"); + String language = parts[0]; + String country = (parts.length > 1 ? parts[1] : ""); + Locale locale = new Locale(language, country.toUpperCase()); + + return new LanguageData(name, locale, (internalCode == null ? language : internalCode)); + } + + void setStatus(int status) + { + mStatus = status; + } + + public int getStatus() + { + return mStatus; + } + + public boolean matchesLocale(Locale locale) + { + String lang = locale.getLanguage(); + if (!lang.equals(this.locale.getLanguage())) + return false; + + if ("zh".equals(lang) && "zh-Hant".equals(internalCode)) + { + // Chinese is a special case + String country = locale.getCountry(); + return "TW".equals(country) || + "MO".equals(country) || + "HK".equals(country); + } + + return true; + } + + public boolean matchesInternalCode(String internalCode) + { + return this.internalCode.equals(internalCode); + } + + @Override + public String toString() + { + return "(" + mStatus + ") " + name + ": " + locale + ", internal: " + internalCode; + } +} diff --git a/android/src/com/mapswithme/maps/sound/TtsPlayer.java b/android/src/com/mapswithme/maps/sound/TtsPlayer.java index e9d1fceb1d..d154e8b27a 100644 --- a/android/src/com/mapswithme/maps/sound/TtsPlayer.java +++ b/android/src/com/mapswithme/maps/sound/TtsPlayer.java @@ -1,14 +1,18 @@ package com.mapswithme.maps.sound; +import android.content.Context; +import android.content.res.Resources; import android.speech.tts.TextToSpeech; +import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Log; -import android.widget.Toast; - import com.mapswithme.maps.Framework; import com.mapswithme.maps.MwmApplication; -import com.mapswithme.util.Language; +import com.mapswithme.maps.R; +import com.mapswithme.util.Config; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; @@ -16,143 +20,148 @@ public enum TtsPlayer { INSTANCE; + private static final String TAG = "TtsPlayer"; private static final Locale DEFAULT_LOCALE = Locale.US; private static final float SPEECH_RATE = 1.2f; - // The both mTtts and mTtsLocale should be initialized before usage. private TextToSpeech mTts; - private Locale mTtsLocale; - private boolean mIsLocaleChanging; + private boolean mInitializing; - private final static String TAG = "TtsPlayer"; + // TTS is locked down due to lack of supported languages + private boolean mUnavailable; TtsPlayer() {} - public void reinitIfLocaleChanged() + private @Nullable LanguageData findSupportedLanguage(String internalCode, List langs) { - if (!isValid()) - return; // TtsPlayer was not inited yet. + if (TextUtils.isEmpty(internalCode)) + return null; - final Locale locale = getDefaultLocale(); - if (!isLocaleEqual(locale)) - initTts(locale); + for (LanguageData lang : langs) + if (lang.matchesInternalCode(internalCode)) + return lang; + + return null; } - private Locale getDefaultLocale() + private @Nullable LanguageData findSupportedLanguage(Locale locale, List langs) { - final Locale locale = Locale.getDefault(); - return locale == null ? DEFAULT_LOCALE : locale; + if (locale == null) + return null; + + for (LanguageData lang : langs) + if (lang.matchesLocale(locale)) + return lang; + + return null; } - private boolean isLocaleEqual(Locale locale) + private void setLanguageInternal(LanguageData lang) { - return locale.getLanguage().equals(mTtsLocale.getLanguage()) && - locale.getCountry().equals(mTtsLocale.getCountry()); + mTts.setLanguage(lang.locale); + nativeSetTurnNotificationsLocale(lang.internalCode); + Config.setTtsLanguage(lang.internalCode); } - private boolean isLocaleAvailable(Locale locale) + public void setLanguage(LanguageData lang) { - final int avail = mTts.isLanguageAvailable(locale); - return avail == TextToSpeech.LANG_AVAILABLE || avail == TextToSpeech.LANG_COUNTRY_AVAILABLE || - avail == TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE; + if (lang != null) + setLanguageInternal(lang); } - private void initTts(final Locale locale) + private LanguageData getDefaultLanguage(List langs) { - if (mIsLocaleChanging) - return; // Preventing reiniting while creating TextToSpeech object. There's a small possibility a new locale is skipped. + Locale defLocale = Locale.getDefault(); + if (defLocale == null) + defLocale = DEFAULT_LOCALE; - if (mTts != null && mTtsLocale != null && mTtsLocale.equals(locale)) - return; - - mTtsLocale = null; - mIsLocaleChanging = true; - - if (mTts != null) + LanguageData lang = findSupportedLanguage(defLocale, langs); + if (lang == null) { - mTts.stop(); - mTts.shutdown(); + // No supported languages found, lock down TTS :( + mUnavailable = true; + Config.setTtsEnabled(false); } - mTts = new TextToSpeech(MwmApplication.get(), new TextToSpeech.OnInitListener() + return lang; + } + + public LanguageData getSelectedLanguage(List langs) + { + return findSupportedLanguage(Config.getTtsLanguage(), langs); + } + + public void init(Context context) + { + if (mTts != null || mInitializing || mUnavailable) + return; + + mInitializing = true; + mTts = new TextToSpeech(context, new TextToSpeech.OnInitListener() { @Override public void onInit(int status) { - // This method is called asynchronously. - mIsLocaleChanging = false; if (status == TextToSpeech.ERROR) { - Log.w(TAG, "Can't initialize TextToSpeech for locale " + locale.getLanguage() + " " + locale.getCountry()); + Log.e(TAG, "Failed to initialize TextToSpeach"); + mUnavailable = true; + mInitializing = false; return; } - if (isLocaleAvailable(locale)) - { - Log.i(TAG, "The locale " + locale.getLanguage() + " " + locale.getCountry() + " will be used for TTS."); - mTtsLocale = locale; - } - else if (isLocaleAvailable(DEFAULT_LOCALE)) - { - Log.w(TAG, "TTS is not available for locale " + locale.getLanguage() + " " + locale.getCountry() + - ". The default locale " + DEFAULT_LOCALE.getLanguage() + " " + DEFAULT_LOCALE.getCountry() + " will be used."); - mTtsLocale = DEFAULT_LOCALE; - } - else - { - Log.w(TAG, "TTS is not available for locale " + locale.getLanguage() + " " + locale.getCountry() + - " and for the default locale " + DEFAULT_LOCALE.getLanguage() + " " + DEFAULT_LOCALE.getCountry() + - ". TTS will be switched off."); - mTtsLocale = null; - return; - } + List langs = getAvailableLanguages(false); + LanguageData defLang = getDefaultLanguage(langs); + LanguageData lang = getSelectedLanguage(langs); + if (lang == null) + lang = defLang; - String localeTwine = Language.localeToTwineLanguage(mTtsLocale); - if (TextUtils.isEmpty(localeTwine)) + if (lang != null) { - Log.w(TAG, "Cann't get a twine language name for the locale " + locale.getLanguage() + " " + locale.getCountry() + - ". TTS will be switched off."); - mTtsLocale = null; - return; + String curLangCode = Config.getTtsLanguage(); + if (defLang != null && !defLang.matchesInternalCode(curLangCode)) + { + // Selected TTS locale does not match current defaults. And it was NOT set by user. + // Assume that the current locale was equal to old default one. + // So, let the new default locale be current. + if (!Config.isTtsLanguageSetByUser()) + lang = findSupportedLanguage(defLang.internalCode, langs); + } + + setLanguage(lang); } mTts.setSpeechRate(SPEECH_RATE); - nativeSetTurnNotificationsLocale(localeTwine); - mTts.setLanguage(mTtsLocale); - Log.i(TAG, "setLocaleIfAvailable() onInit nativeSetTurnNotificationsLocale(" + localeTwine + ")"); + setEnabled(Config.isTtsEnabled()); + mInitializing = false; } }); } - private boolean isValid() + public boolean isReady() { - return !mIsLocaleChanging && mTts != null && mTtsLocale != null; + return (mTts != null && !mUnavailable && !mInitializing); } private void speak(String textToSpeak) { - // @TODO(vbykoianko) removes these two toasts below when the test period is finished. - Toast.makeText(MwmApplication.get(), textToSpeak, Toast.LENGTH_SHORT).show(); - if (mTts.speak(textToSpeak, TextToSpeech.QUEUE_ADD, null) == TextToSpeech.ERROR) - { - Log.e(TAG, "TextToSpeech returns TextToSpeech.ERROR."); - Toast.makeText(MwmApplication.get(), "TTS error", Toast.LENGTH_SHORT).show(); - } + //noinspection deprecation + mTts.speak(textToSpeak, TextToSpeech.QUEUE_ADD, null); } public void playTurnNotifications() { // It's necessary to call Framework.nativeGenerateTurnNotifications() even if TtsPlayer is invalid. final String[] turnNotifications = Framework.nativeGenerateTurnNotifications(); - - if (turnNotifications != null && isValid()) + + if (turnNotifications != null && isReady()) for (String textToSpeak : turnNotifications) speak(textToSpeak); } public void stop() { - if(mTts != null) + if (isReady()) mTts.stop(); } @@ -161,18 +170,40 @@ public enum TtsPlayer return nativeAreTurnNotificationsEnabled(); } - // Note. After a call of enable(true) the flag enabled in cpp core will be set. - // But later in onInit callback the initialization could fail. - // In that case isValid() returns false and every call of playTurnNotifications returns in the beginning. - public void enable(boolean enabled) + public void setEnabled(boolean enabled) { - if (enabled && !isValid()) - initTts(getDefaultLocale()); nativeEnableTurnNotifications(enabled); } + public List getAvailableLanguages(boolean includeDownloadable) + { + List res = new ArrayList<>(); + if (mUnavailable || mTts == null) + return res; + + Resources resources = MwmApplication.get().getResources(); + String[] codes = resources.getStringArray(R.array.tts_languages_supported); + String[] names = resources.getStringArray(R.array.tts_language_names); + + for (int i = 0; i < codes.length; i++) + { + LanguageData lang = LanguageData.parse(codes[i], names[i]); + int status = mTts.isLanguageAvailable(lang.locale); + + int requiredStatus = (includeDownloadable ? TextToSpeech.LANG_MISSING_DATA + : TextToSpeech.LANG_AVAILABLE); + if (status >= requiredStatus) + { + lang.setStatus(status); + res.add(lang); + } + } + + return res; + } + private native static void nativeEnableTurnNotifications(boolean enable); private native static boolean nativeAreTurnNotificationsEnabled(); - private native static void nativeSetTurnNotificationsLocale(String locale); + private native static void nativeSetTurnNotificationsLocale(String code); private native static String nativeGetTurnNotificationsLocale(); } diff --git a/android/src/com/mapswithme/util/Config.java b/android/src/com/mapswithme/util/Config.java index e8faa5bfdf..c48c7b0639 100644 --- a/android/src/com/mapswithme/util/Config.java +++ b/android/src/com/mapswithme/util/Config.java @@ -13,6 +13,10 @@ public final class Config private static final String KEY_APP_LAST_SESSION_TIMESTAMP = "LastSessionTimestamp"; private static final String KEY_APP_FIRST_INSTALL_FLAVOR = "FirstInstallFlavor"; + private static final String KEY_TTS_ENABLED = "TtsEnabled"; + private static final String KEY_TTS_LANGUAGE = "TtsLanguage"; + private static final String KEY_TTS_LANGUAGE_SET_BY_USER = "TtsLanguageSetByUser"; + private static final String KEY_PREF_ZOOM_BUTTONS = "ZoomButtonsEnabled"; private static final String KEY_PREF_STATISTICS = "StatisticsEnabled"; @@ -167,7 +171,37 @@ public final class Config incrementSessionNumber(); } - public static boolean getShowZoomButtons() + public static boolean isTtsEnabled() + { + return getBool(KEY_TTS_ENABLED, true); + } + + public static void setTtsEnabled(boolean enabled) + { + setBool(KEY_TTS_ENABLED, enabled); + } + + public static boolean isTtsLanguageSetByUser() + { + return getBool(KEY_TTS_LANGUAGE_SET_BY_USER); + } + + public static void setTtsLanguageSetByUser() + { + setBool(KEY_TTS_LANGUAGE_SET_BY_USER, true); + } + + public static String getTtsLanguage() + { + return getString(KEY_TTS_LANGUAGE); + } + + public static void setTtsLanguage(String language) + { + setString(KEY_TTS_LANGUAGE, language); + } + + public static boolean showZoomButtons() { return getBool(KEY_PREF_ZOOM_BUTTONS, true); } diff --git a/android/src/com/mapswithme/util/Language.java b/android/src/com/mapswithme/util/Language.java index cc1ed97527..151ae76103 100644 --- a/android/src/com/mapswithme/util/Language.java +++ b/android/src/com/mapswithme/util/Language.java @@ -1,18 +1,14 @@ package com.mapswithme.util; import android.content.Context; -import android.text.TextUtils; -import android.util.Log; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; - import com.mapswithme.maps.MwmApplication; import java.util.Locale; public class Language { - private final static String TAG = "Language"; // Locale.getLanguage() returns even 3-letter codes, not that we need in the C++ core, // so we use locale itself, like zh_CN public static String getDefaultLocale() @@ -34,41 +30,4 @@ public class Language return getDefaultLocale(); } - - // Converts Locale to twine language name. - // If locale can be converted returns a twine language name. For example zh-Hans, ru, en and so on. - // If not returns an empty string. - public static String localeToTwineLanguage(Locale locale) - { - if (locale == null) - { - Log.e(TAG, "localeToTwineLanguage was called with null Locale."); - return ""; - } - - final String chinese = Locale.CHINESE.getLanguage(); - final String language = locale.getLanguage(); - final String country = locale.getCountry(); - - if (chinese == null || language == null || country == null) - { - Log.e(TAG, "Methods Locale.getLanguage or Locale.getCountry return null."); - return ""; - } - - if (chinese.equals(language)) - { - if (country.equals("TW") || country.equals("MO") || country.equals("HK")) - { - return "zh-Hant"; // Chinese traditional - } - return "zh-Hans"; // Chinese simplified - } - if (TextUtils.isEmpty(language)) - { - Log.e(TAG, "locale.getLanguage() returns null or empty string."); - return ""; - } - return language; - } } diff --git a/data/sound-strings/in.json/localize.json b/data/sound-strings/id.json/localize.json similarity index 100% rename from data/sound-strings/in.json/localize.json rename to data/sound-strings/id.json/localize.json