diff --git a/README.md b/README.md index c5e92a983..efce1d86d 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,11 @@ The following is a list of all third-party dependencies included as part of the - Purpose: Supplementary Android Compose features. - License: Apache 2.0 +- **Appcompat** + - https://developer.android.com/jetpack/androidx/releases/appcompat + - Purpose: Allows access to new APIs on older API versions. + - License: Apache 2.0 + - **AndroidX Browser** - https://developer.android.com/jetpack/androidx/releases/browser - Purpose: Displays webpages with the user's default browser. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 436ecc460..becd19745 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -29,6 +29,52 @@ android { versionCode = 1 versionName = "1.0.0" + // This is so the build system only includes language resources in the APK for these + // languages, preventing translated strings from being included from other libraries that + // might support languages this app does not. + resourceConfigurations += arrayOf( + "af", + "be", + "bg", + "ca", + "cs", + "da", + "de", + "el", + "en", + "en-rGB", + "es", + "et", + "fa", + "fi", + "fr", + "hi", + "hr", + "hu", + "in", + "it", + "iw", + "ja", + "ko", + "lv", + "ml", + "nb", + "nl", + "pl", + "pt-rBR", + "pt-rPT", + "ro", + "ru", + "sk", + "sv", + "th", + "tr", + "uk", + "vi", + "zh-rCN", + "zh-rTW" + ) + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } @@ -102,6 +148,7 @@ dependencies { } implementation(libs.androidx.activity.compose) + implementation(libs.androidx.appcompat) implementation(libs.androidx.browser) implementation(libs.androidx.camera.camera2) implementation(libs.androidx.camera.lifecycle) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 183fe41f7..5ec4014e5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -16,10 +16,11 @@ android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:localeConfig="@xml/locales_config" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/LaunchTheme" - tools:targetApi="31"> + tools:targetApi="33"> + + + + diff --git a/app/src/main/java/com/x8bit/bitwarden/MainActivity.kt b/app/src/main/java/com/x8bit/bitwarden/MainActivity.kt index 4882fa9fd..2989b5370 100644 --- a/app/src/main/java/com/x8bit/bitwarden/MainActivity.kt +++ b/app/src/main/java/com/x8bit/bitwarden/MainActivity.kt @@ -2,26 +2,40 @@ package com.x8bit.bitwarden import android.content.Intent import android.os.Bundle -import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.app.AppCompatDelegate +import androidx.core.os.LocaleListCompat import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen +import com.x8bit.bitwarden.data.platform.repository.SettingsRepository import com.x8bit.bitwarden.ui.platform.feature.rootnav.RootNavScreen import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject /** * Primary entry point for the application. */ @AndroidEntryPoint -class MainActivity : ComponentActivity() { +class MainActivity : AppCompatActivity() { private val mainViewModel: MainViewModel by viewModels() + @Inject + lateinit var settingsRepository: SettingsRepository + override fun onCreate(savedInstanceState: Bundle?) { var shouldShowSplashScreen = true installSplashScreen().setKeepOnScreenCondition { shouldShowSplashScreen } super.onCreate(savedInstanceState) + // Within the app the language will change dynamically and will be managed + // by the OS, but we need to ensure we properly set the language when + // upgrading from older versions that handle this differently. + settingsRepository.appLanguage.localeName?.let { localeName -> + val localeList = LocaleListCompat.forLanguageTags(localeName) + AppCompatDelegate.setApplicationLocales(localeList) + } setContent { BitwardenTheme { RootNavScreen( diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSource.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSource.kt index 928de1ec5..2341f2693 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSource.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSource.kt @@ -1,12 +1,18 @@ package com.x8bit.bitwarden.data.platform.datasource.disk import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction +import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage import kotlinx.coroutines.flow.Flow /** * Primary access point for general settings-related disk information. */ interface SettingsDiskSource { + /** + * The currently persisted app language (or `null` if not set). + */ + var appLanguage: AppLanguage? + /** * Gets the current vault timeout (in minutes) for the given [userId] (or `null` if the vault * should never time out). diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSourceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSourceImpl.kt index c2e02e3ed..715b38cfb 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSourceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSourceImpl.kt @@ -4,16 +4,19 @@ import android.content.SharedPreferences import com.x8bit.bitwarden.data.platform.datasource.disk.BaseDiskSource.Companion.BASE_KEY import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow +import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.onSubscription +private const val APP_LANGUAGE_KEY = "$BASE_KEY:appLocale" private const val VAULT_TIMEOUT_ACTION_KEY = "$BASE_KEY:vaultTimeoutAction" private const val VAULT_TIME_IN_MINUTES_KEY = "$BASE_KEY:vaultTimeout" /** * Primary implementation of [SettingsDiskSource]. */ +@Suppress("TooManyFunctions") class SettingsDiskSourceImpl( val sharedPreferences: SharedPreferences, ) : BaseDiskSource(sharedPreferences = sharedPreferences), @@ -24,6 +27,18 @@ class SettingsDiskSourceImpl( private val mutableVaultTimeoutInMinutesFlowMap = mutableMapOf>() + override var appLanguage: AppLanguage? + get() = getString(key = APP_LANGUAGE_KEY) + ?.let { storedValue -> + AppLanguage.entries.firstOrNull { storedValue == it.localeName } + } + set(value) { + putString( + key = APP_LANGUAGE_KEY, + value = value?.localeName, + ) + } + override fun getVaultTimeoutInMinutes(userId: String): Int? = getInt(key = "${VAULT_TIME_IN_MINUTES_KEY}_$userId") diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepository.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepository.kt index 7e878c19d..dd45c81bc 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepository.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepository.kt @@ -2,12 +2,18 @@ package com.x8bit.bitwarden.data.platform.repository import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeout import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction +import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage import kotlinx.coroutines.flow.StateFlow /** * Provides an API for observing and modifying settings state. */ interface SettingsRepository { + /** + * The [AppLanguage] for the current user. + */ + var appLanguage: AppLanguage + /** * The [VaultTimeout] for the current user. */ diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryImpl.kt index 59dcbdb59..b7d0f990c 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryImpl.kt @@ -5,6 +5,7 @@ import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeout import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction +import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow @@ -23,6 +24,12 @@ class SettingsRepositoryImpl( private val unconfinedScope = CoroutineScope(dispatcherManager.unconfined) + override var appLanguage: AppLanguage + get() = settingsDiskSource.appLanguage ?: AppLanguage.DEFAULT + set(value) { + settingsDiskSource.appLanguage = value + } + override var vaultTimeout: VaultTimeout get() = activeUserId ?.let { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreen.kt index e32646206..5e6b0ef89 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceScreen.kt @@ -15,6 +15,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll @@ -25,12 +26,16 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.x8bit.bitwarden.R import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect +import com.x8bit.bitwarden.ui.platform.base.util.asText +import com.x8bit.bitwarden.ui.platform.components.BasicDialogState +import com.x8bit.bitwarden.ui.platform.components.BitwardenBasicDialog import com.x8bit.bitwarden.ui.platform.components.BitwardenScaffold import com.x8bit.bitwarden.ui.platform.components.BitwardenSelectionDialog import com.x8bit.bitwarden.ui.platform.components.BitwardenSelectionRow import com.x8bit.bitwarden.ui.platform.components.BitwardenTextRow import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar import com.x8bit.bitwarden.ui.platform.components.BitwardenWideSwitch +import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage /** * Displays the appearance screen. @@ -74,7 +79,7 @@ fun AppearanceScreen( ) { LanguageSelectionRow( currentSelection = state.language, - onThemeSelection = remember(viewModel) { + onLanguageSelection = remember(viewModel) { { viewModel.trySendAction(AppearanceAction.LanguageChange(it)) } }, modifier = Modifier.fillMaxWidth(), @@ -105,15 +110,22 @@ fun AppearanceScreen( @Composable private fun LanguageSelectionRow( - currentSelection: AppearanceState.Language, - onThemeSelection: (AppearanceState.Language) -> Unit, + currentSelection: AppLanguage, + onLanguageSelection: (AppLanguage) -> Unit, modifier: Modifier = Modifier, ) { - var shouldShowLanguageSelectionDialog by remember { mutableStateOf(false) } + var languageChangedDialogState: BasicDialogState by rememberSaveable { + mutableStateOf(BasicDialogState.Hidden) + } + var shouldShowLanguageSelectionDialog by rememberSaveable { mutableStateOf(false) } + + BitwardenBasicDialog( + visibilityState = languageChangedDialogState, + onDismissRequest = { languageChangedDialogState = BasicDialogState.Hidden }, + ) BitwardenTextRow( text = stringResource(id = R.string.language), - description = stringResource(id = R.string.language_change_requires_app_restart), onClick = { shouldShowLanguageSelectionDialog = true }, modifier = modifier, ) { @@ -129,14 +141,16 @@ private fun LanguageSelectionRow( title = stringResource(id = R.string.language), onDismissRequest = { shouldShowLanguageSelectionDialog = false }, ) { - AppearanceState.Language.entries.forEach { option -> + AppLanguage.entries.forEach { option -> BitwardenSelectionRow( text = option.text, isSelected = option == currentSelection, onClick = { shouldShowLanguageSelectionDialog = false - onThemeSelection( - AppearanceState.Language.entries.first { it == option }, + onLanguageSelection(option) + languageChangedDialogState = BasicDialogState.Shown( + title = R.string.language.asText(), + message = R.string.language_change_x_description.asText(option.text), ) }, ) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceViewModel.kt index 500863242..9480cc7c6 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceViewModel.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/AppearanceViewModel.kt @@ -1,11 +1,15 @@ package com.x8bit.bitwarden.ui.platform.feature.settings.appearance import android.os.Parcelable +import androidx.appcompat.app.AppCompatDelegate +import androidx.core.os.LocaleListCompat import androidx.lifecycle.SavedStateHandle import com.x8bit.bitwarden.R +import com.x8bit.bitwarden.data.platform.repository.SettingsRepository import com.x8bit.bitwarden.ui.platform.base.BaseViewModel import com.x8bit.bitwarden.ui.platform.base.util.Text import com.x8bit.bitwarden.ui.platform.base.util.asText +import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.update import kotlinx.parcelize.Parcelize @@ -18,11 +22,12 @@ private const val KEY_STATE = "state" */ @HiltViewModel class AppearanceViewModel @Inject constructor( + private val settingsRepository: SettingsRepository, savedStateHandle: SavedStateHandle, ) : BaseViewModel( initialState = savedStateHandle[KEY_STATE] ?: AppearanceState( - language = AppearanceState.Language.DEFAULT, + language = settingsRepository.appLanguage, showWebsiteIcons = false, theme = AppearanceState.Theme.DEFAULT, ), @@ -39,8 +44,13 @@ class AppearanceViewModel @Inject constructor( } private fun handleLanguageChanged(action: AppearanceAction.LanguageChange) { - // TODO: BIT-1328 implement language selection support mutableStateFlow.update { it.copy(language = action.language) } + settingsRepository.appLanguage = action.language + + val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags( + action.language.localeName, + ) + AppCompatDelegate.setApplicationLocales(appLocale) } private fun handleShowWebsiteIconsToggled(action: AppearanceAction.ShowWebsiteIconsToggle) { @@ -59,20 +69,10 @@ class AppearanceViewModel @Inject constructor( */ @Parcelize data class AppearanceState( - val language: Language, + val language: AppLanguage, val showWebsiteIcons: Boolean, val theme: Theme, ) : Parcelable { - /** - * Represents the languages supported by the app. - * - * TODO BIT-1328 populate values - */ - enum class Language(val text: Text) { - DEFAULT(text = R.string.default_system.asText()), - ENGLISH(text = "English".asText()), - } - /** * Represents the theme options the user can set. */ @@ -106,7 +106,7 @@ sealed class AppearanceAction { * Indicates that the user changed the Language. */ data class LanguageChange( - val language: AppearanceState.Language, + val language: AppLanguage, ) : AppearanceAction() /** diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/model/AppLanguage.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/model/AppLanguage.kt new file mode 100644 index 000000000..70f1d7431 --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/appearance/model/AppLanguage.kt @@ -0,0 +1,178 @@ +package com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model + +import com.x8bit.bitwarden.R +import com.x8bit.bitwarden.ui.platform.base.util.Text +import com.x8bit.bitwarden.ui.platform.base.util.asText + +/** + * Represents the languages supported by the app. + */ +enum class AppLanguage( + val localeName: String?, + val text: Text, +) { + DEFAULT( + localeName = null, + text = R.string.default_system.asText(), + ), + AFRIKAANS( + localeName = "af", + text = "Afrikaans".asText(), + ), + BELARUSIAN( + localeName = "be", + text = "Беларуская".asText(), + ), + BULGARIAN( + localeName = "bg", + text = "български".asText(), + ), + CATALAN( + localeName = "ca", + text = "català".asText(), + ), + CZECH( + localeName = "cs", + text = "čeština".asText(), + ), + DANISH( + localeName = "da", + text = "Dansk".asText(), + ), + GERMAN( + localeName = "de", + text = "Deutsch".asText(), + ), + GREEK( + localeName = "el", + text = "Ελληνικά".asText(), + ), + ENGLISH( + localeName = "en", + text = "English".asText(), + ), + ENGLISH_BRITISH( + localeName = "en-GB", + text = "English (British)".asText(), + ), + SPANISH( + localeName = "es", + text = "Español".asText(), + ), + ESTONIAN( + localeName = "et", + text = "eesti".asText(), + ), + PERSIAN( + localeName = "fa", + text = "فارسی".asText(), + ), + FINNISH( + localeName = "fi", + text = "suomi".asText(), + ), + FRENCH( + localeName = "fr", + text = "Français".asText(), + ), + HINDI( + localeName = "hi", + text = "हिन्दी".asText(), + ), + CROATIAN( + localeName = "hr", + text = "hrvatski".asText(), + ), + HUNGARIAN( + localeName = "hu", + text = "magyar".asText(), + ), + INDONESIAN( + localeName = "in", + text = "Bahasa Indonesia".asText(), + ), + ITALIAN( + localeName = "it", + text = "Italiano".asText(), + ), + HEBREW( + localeName = "iw", + text = "עברית".asText(), + ), + JAPANESE( + localeName = "ja", + text = "日本語".asText(), + ), + KOREAN( + localeName = "ko", + text = "한국어".asText(), + ), + LATVIAN( + localeName = "lv", + text = "Latvietis".asText(), + ), + MALAYALAM( + localeName = "ml", + text = "മലയാളം".asText(), + ), + NORWEGIAN( + localeName = "nb", + text = "norsk (bokmål)".asText(), + ), + DUTCH( + localeName = "nl", + text = "Nederlands".asText(), + ), + POLISH( + localeName = "pl", + text = "Polski".asText(), + ), + PORTUGUESE_BRAZILIAN( + localeName = "pt-BR", + text = "Português do Brasil".asText(), + ), + PORTUGUESE( + localeName = "pt-PT", + text = "Português".asText(), + ), + ROMANIAN( + localeName = "ro", + text = "română".asText(), + ), + RUSSIAN( + localeName = "ru", + text = "русский".asText(), + ), + SLOVAK( + localeName = "sk", + text = "slovenčina".asText(), + ), + SWEDISH( + localeName = "sv", + text = "svenska".asText(), + ), + THAI( + localeName = "th", + text = "ไทย".asText(), + ), + TURKISH( + localeName = "tr", + text = "Türkçe".asText(), + ), + UKRAINIAN( + localeName = "uk", + text = "українська".asText(), + ), + VIETNAMESE( + localeName = "vi", + text = "Tiếng Việt".asText(), + ), + CHINESE_SIMPLIFIED( + localeName = "zh-CN", + text = "中文(中国大陆)".asText(), + ), + CHINESE_TRADITIONAL( + localeName = "zh-TW", + text = "中文(台灣)".asText(), + ), +} diff --git a/app/src/main/res/values-af-rZA/strings.xml b/app/src/main/res/values-af/strings.xml similarity index 100% rename from app/src/main/res/values-af-rZA/strings.xml rename to app/src/main/res/values-af/strings.xml diff --git a/app/src/main/res/values-ar-rSA/strings.xml b/app/src/main/res/values-ar/strings.xml similarity index 100% rename from app/src/main/res/values-ar-rSA/strings.xml rename to app/src/main/res/values-ar/strings.xml diff --git a/app/src/main/res/values-az-rAZ/strings.xml b/app/src/main/res/values-az/strings.xml similarity index 100% rename from app/src/main/res/values-az-rAZ/strings.xml rename to app/src/main/res/values-az/strings.xml diff --git a/app/src/main/res/values-be-rBY/strings.xml b/app/src/main/res/values-be/strings.xml similarity index 100% rename from app/src/main/res/values-be-rBY/strings.xml rename to app/src/main/res/values-be/strings.xml diff --git a/app/src/main/res/values-bg-rBG/strings.xml b/app/src/main/res/values-bg/strings.xml similarity index 100% rename from app/src/main/res/values-bg-rBG/strings.xml rename to app/src/main/res/values-bg/strings.xml diff --git a/app/src/main/res/values-bn-rBD/strings.xml b/app/src/main/res/values-bn/strings.xml similarity index 100% rename from app/src/main/res/values-bn-rBD/strings.xml rename to app/src/main/res/values-bn/strings.xml diff --git a/app/src/main/res/values-bs-rBA/strings.xml b/app/src/main/res/values-bs/strings.xml similarity index 100% rename from app/src/main/res/values-bs-rBA/strings.xml rename to app/src/main/res/values-bs/strings.xml diff --git a/app/src/main/res/values-ca-rES/strings.xml b/app/src/main/res/values-ca/strings.xml similarity index 100% rename from app/src/main/res/values-ca-rES/strings.xml rename to app/src/main/res/values-ca/strings.xml diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs/strings.xml similarity index 100% rename from app/src/main/res/values-cs-rCZ/strings.xml rename to app/src/main/res/values-cs/strings.xml diff --git a/app/src/main/res/values-cy-rGB/strings.xml b/app/src/main/res/values-cy/strings.xml similarity index 100% rename from app/src/main/res/values-cy-rGB/strings.xml rename to app/src/main/res/values-cy/strings.xml diff --git a/app/src/main/res/values-da-rDK/strings.xml b/app/src/main/res/values-da/strings.xml similarity index 100% rename from app/src/main/res/values-da-rDK/strings.xml rename to app/src/main/res/values-da/strings.xml diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de/strings.xml similarity index 100% rename from app/src/main/res/values-de-rDE/strings.xml rename to app/src/main/res/values-de/strings.xml diff --git a/app/src/main/res/values-el-rGR/strings.xml b/app/src/main/res/values-el/strings.xml similarity index 100% rename from app/src/main/res/values-el-rGR/strings.xml rename to app/src/main/res/values-el/strings.xml diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es/strings.xml similarity index 100% rename from app/src/main/res/values-es-rES/strings.xml rename to app/src/main/res/values-es/strings.xml diff --git a/app/src/main/res/values-et-rEE/strings.xml b/app/src/main/res/values-et/strings.xml similarity index 100% rename from app/src/main/res/values-et-rEE/strings.xml rename to app/src/main/res/values-et/strings.xml diff --git a/app/src/main/res/values-eu-rES/strings.xml b/app/src/main/res/values-eu/strings.xml similarity index 100% rename from app/src/main/res/values-eu-rES/strings.xml rename to app/src/main/res/values-eu/strings.xml diff --git a/app/src/main/res/values-fa-rIR/strings.xml b/app/src/main/res/values-fa/strings.xml similarity index 100% rename from app/src/main/res/values-fa-rIR/strings.xml rename to app/src/main/res/values-fa/strings.xml diff --git a/app/src/main/res/values-fi-rFI/strings.xml b/app/src/main/res/values-fi/strings.xml similarity index 100% rename from app/src/main/res/values-fi-rFI/strings.xml rename to app/src/main/res/values-fi/strings.xml diff --git a/app/src/main/res/values-fil-rPH/strings.xml b/app/src/main/res/values-fil/strings.xml similarity index 100% rename from app/src/main/res/values-fil-rPH/strings.xml rename to app/src/main/res/values-fil/strings.xml diff --git a/app/src/main/res/values-fr-rFR/strings.xml b/app/src/main/res/values-fr/strings.xml similarity index 100% rename from app/src/main/res/values-fr-rFR/strings.xml rename to app/src/main/res/values-fr/strings.xml diff --git a/app/src/main/res/values-gl-rES/strings.xml b/app/src/main/res/values-gl/strings.xml similarity index 100% rename from app/src/main/res/values-gl-rES/strings.xml rename to app/src/main/res/values-gl/strings.xml diff --git a/app/src/main/res/values-hi-rIN/strings.xml b/app/src/main/res/values-hi/strings.xml similarity index 100% rename from app/src/main/res/values-hi-rIN/strings.xml rename to app/src/main/res/values-hi/strings.xml diff --git a/app/src/main/res/values-hr-rHR/strings.xml b/app/src/main/res/values-hr/strings.xml similarity index 100% rename from app/src/main/res/values-hr-rHR/strings.xml rename to app/src/main/res/values-hr/strings.xml diff --git a/app/src/main/res/values-hu-rHU/strings.xml b/app/src/main/res/values-hu/strings.xml similarity index 100% rename from app/src/main/res/values-hu-rHU/strings.xml rename to app/src/main/res/values-hu/strings.xml diff --git a/app/src/main/res/values-in-rID/strings.xml b/app/src/main/res/values-in/strings.xml similarity index 100% rename from app/src/main/res/values-in-rID/strings.xml rename to app/src/main/res/values-in/strings.xml diff --git a/app/src/main/res/values-it-rIT/strings.xml b/app/src/main/res/values-it/strings.xml similarity index 100% rename from app/src/main/res/values-it-rIT/strings.xml rename to app/src/main/res/values-it/strings.xml diff --git a/app/src/main/res/values-iw-rIL/strings.xml b/app/src/main/res/values-iw/strings.xml similarity index 100% rename from app/src/main/res/values-iw-rIL/strings.xml rename to app/src/main/res/values-iw/strings.xml diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja/strings.xml similarity index 100% rename from app/src/main/res/values-ja-rJP/strings.xml rename to app/src/main/res/values-ja/strings.xml diff --git a/app/src/main/res/values-ka-rGE/strings.xml b/app/src/main/res/values-ka/strings.xml similarity index 100% rename from app/src/main/res/values-ka-rGE/strings.xml rename to app/src/main/res/values-ka/strings.xml diff --git a/app/src/main/res/values-kn-rIN/strings.xml b/app/src/main/res/values-kn/strings.xml similarity index 100% rename from app/src/main/res/values-kn-rIN/strings.xml rename to app/src/main/res/values-kn/strings.xml diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko/strings.xml similarity index 100% rename from app/src/main/res/values-ko-rKR/strings.xml rename to app/src/main/res/values-ko/strings.xml diff --git a/app/src/main/res/values-lt-rLT/strings.xml b/app/src/main/res/values-lt/strings.xml similarity index 100% rename from app/src/main/res/values-lt-rLT/strings.xml rename to app/src/main/res/values-lt/strings.xml diff --git a/app/src/main/res/values-lv-rLV/strings.xml b/app/src/main/res/values-lv/strings.xml similarity index 100% rename from app/src/main/res/values-lv-rLV/strings.xml rename to app/src/main/res/values-lv/strings.xml diff --git a/app/src/main/res/values-ml-rIN/strings.xml b/app/src/main/res/values-ml/strings.xml similarity index 100% rename from app/src/main/res/values-ml-rIN/strings.xml rename to app/src/main/res/values-ml/strings.xml diff --git a/app/src/main/res/values-mr-rIN/strings.xml b/app/src/main/res/values-mr/strings.xml similarity index 100% rename from app/src/main/res/values-mr-rIN/strings.xml rename to app/src/main/res/values-mr/strings.xml diff --git a/app/src/main/res/values-my-rMM/strings.xml b/app/src/main/res/values-my/strings.xml similarity index 100% rename from app/src/main/res/values-my-rMM/strings.xml rename to app/src/main/res/values-my/strings.xml diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb/strings.xml similarity index 100% rename from app/src/main/res/values-nb-rNO/strings.xml rename to app/src/main/res/values-nb/strings.xml diff --git a/app/src/main/res/values-ne-rNP/strings.xml b/app/src/main/res/values-ne/strings.xml similarity index 100% rename from app/src/main/res/values-ne-rNP/strings.xml rename to app/src/main/res/values-ne/strings.xml diff --git a/app/src/main/res/values-nl-rNL/strings.xml b/app/src/main/res/values-nl/strings.xml similarity index 100% rename from app/src/main/res/values-nl-rNL/strings.xml rename to app/src/main/res/values-nl/strings.xml diff --git a/app/src/main/res/values-nn-rNO/strings.xml b/app/src/main/res/values-nn/strings.xml similarity index 100% rename from app/src/main/res/values-nn-rNO/strings.xml rename to app/src/main/res/values-nn/strings.xml diff --git a/app/src/main/res/values-or-rIN/strings.xml b/app/src/main/res/values-or/strings.xml similarity index 100% rename from app/src/main/res/values-or-rIN/strings.xml rename to app/src/main/res/values-or/strings.xml diff --git a/app/src/main/res/values-pl-rPL/strings.xml b/app/src/main/res/values-pl/strings.xml similarity index 100% rename from app/src/main/res/values-pl-rPL/strings.xml rename to app/src/main/res/values-pl/strings.xml diff --git a/app/src/main/res/values-ro-rRO/strings.xml b/app/src/main/res/values-ro/strings.xml similarity index 100% rename from app/src/main/res/values-ro-rRO/strings.xml rename to app/src/main/res/values-ro/strings.xml diff --git a/app/src/main/res/values-ru-rRU/strings.xml b/app/src/main/res/values-ru/strings.xml similarity index 100% rename from app/src/main/res/values-ru-rRU/strings.xml rename to app/src/main/res/values-ru/strings.xml diff --git a/app/src/main/res/values-si-rLK/strings.xml b/app/src/main/res/values-si/strings.xml similarity index 100% rename from app/src/main/res/values-si-rLK/strings.xml rename to app/src/main/res/values-si/strings.xml diff --git a/app/src/main/res/values-sk-rSK/strings.xml b/app/src/main/res/values-sk/strings.xml similarity index 100% rename from app/src/main/res/values-sk-rSK/strings.xml rename to app/src/main/res/values-sk/strings.xml diff --git a/app/src/main/res/values-sl-rSI/strings.xml b/app/src/main/res/values-sl/strings.xml similarity index 100% rename from app/src/main/res/values-sl-rSI/strings.xml rename to app/src/main/res/values-sl/strings.xml diff --git a/app/src/main/res/values-sr-rSP/strings.xml b/app/src/main/res/values-sr/strings.xml similarity index 100% rename from app/src/main/res/values-sr-rSP/strings.xml rename to app/src/main/res/values-sr/strings.xml diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv/strings.xml similarity index 100% rename from app/src/main/res/values-sv-rSE/strings.xml rename to app/src/main/res/values-sv/strings.xml diff --git a/app/src/main/res/values-ta-rIN/strings.xml b/app/src/main/res/values-ta/strings.xml similarity index 100% rename from app/src/main/res/values-ta-rIN/strings.xml rename to app/src/main/res/values-ta/strings.xml diff --git a/app/src/main/res/values-te-rIN/strings.xml b/app/src/main/res/values-te/strings.xml similarity index 100% rename from app/src/main/res/values-te-rIN/strings.xml rename to app/src/main/res/values-te/strings.xml diff --git a/app/src/main/res/values-th-rTH/strings.xml b/app/src/main/res/values-th/strings.xml similarity index 100% rename from app/src/main/res/values-th-rTH/strings.xml rename to app/src/main/res/values-th/strings.xml diff --git a/app/src/main/res/values-tr-rTR/strings.xml b/app/src/main/res/values-tr/strings.xml similarity index 100% rename from app/src/main/res/values-tr-rTR/strings.xml rename to app/src/main/res/values-tr/strings.xml diff --git a/app/src/main/res/values-uk-rUA/strings.xml b/app/src/main/res/values-uk/strings.xml similarity index 100% rename from app/src/main/res/values-uk-rUA/strings.xml rename to app/src/main/res/values-uk/strings.xml diff --git a/app/src/main/res/values-vi-rVN/strings.xml b/app/src/main/res/values-vi/strings.xml similarity index 100% rename from app/src/main/res/values-vi-rVN/strings.xml rename to app/src/main/res/values-vi/strings.xml diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 0c1a56ce8..4c5b16f9f 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,7 +1,7 @@ -