Самый правильный подход - сначала понять концепцию:
- Locale
- Configuration
- Ресурсы
- BaseContext и ContextWrapper
Обратите внимание, что: Там представляют собой 3 типа слоев [Context.getResources]:
- ресурсы верхнего уровня (например, название действия манифеста)
- ресурсы приложения
- ресурсы действий
Таким образом, изменение уровня приложения не повлияет на уровень активности.
И:
Если вы sh поддержите Android 6, вы следует использовать файл .apk, а не .aab (пакет приложений android). Это связано с тем, что в Android 6 вы можете выбрать только одну локаль по умолчанию в настройках, а затем .aab загрузит ТОЛЬКО необходимые ресурсы конфигурации:
Предположим, мы используем строки. xml на английском sh в качестве нашего языка по умолчанию и переведите его на иврит, используя другие строки-iw. xml
Если устройство Android 6 настроено на английском sh в качестве основного и единственного языка, .aab будет доставить только обычный ресурс Engli sh strings. xml. ИЛИ:
Если возможно, вы можете использовать только одну строку по умолчанию. xml с требуемым языком.
Решение:
В вашем BaseActivity, а также в вашем классе приложения:
abstract class BaseActivity : AppCompatActivity() {
override fun attachBaseContext(newBase: Context) {
val constrainedBaseCtx = LocaleUtil.constrainConfigurationLocale(newBase)
super.attachBaseContext(constrainedBaseCtx)
}
override fun onConfigurationChanged(newConfig: Configuration) {
val constrainedConfiguration = LocaleUtil.constrainConfigurationLocale(newConfig)
super.onConfigurationChanged(constrainedConfiguration)
}
override fun createConfigurationContext(overrideConfiguration: Configuration): Context {
val constrainedConf = LocaleUtil.constrainConfigurationLocale(overrideConfiguration)
return super.createConfigurationContext(constrainedConf)
}
}
Используйте вашу локальную утилиту:
/**
* Helps to change locales configuration for [Context] objects.
* Remember that there are 3 types of [Context.getResources] layers:
*
* 1. Top-level resources (ex: manifest activity name)
*
* 2. Application resources
*
* 3. Activity resources
*
* So, changing the Application layer won't affect the activity layer.
*/
object LocaleUtil {
const val DEFAULT_LANGUAGE = "iw"
const val DEFAULT_COUNTRY = "il"
/**
* Constraint This [context] Locale.
* @param constrainedCountry - the country to match the activity for
* @param constrainedLanguage - the language inside that country to match the activity for
* @return new / same instance configured [Context]. (depends on Android OS version)
*/
fun constrainConfigurationLocale(
context: Context,
constrainedCountry: String = DEFAULT_COUNTRY,
constrainedLanguage: String = DEFAULT_LANGUAGE
) : Context {
val newConf = constrainConfigurationLocale(
context.resources.configuration,
constrainedCountry,
constrainedLanguage
)
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1)
context.createConfigurationContext(newConf)
else
context
}
/**
* Constraint This [configuration] Locale.
* @param constrainedCountry - the country to match the activity for
* @param constrainedLanguage - the language inside that country to match the activity for
* @return new / same instance of [Configuration]. (depends on Android OS version)
*/
fun constrainConfigurationLocale(
currentConfiguration: Configuration,
constrainedCountry: String = DEFAULT_COUNTRY,
constrainedLanguage: String = DEFAULT_LANGUAGE
) : Configuration {
val configuration = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1)
Configuration(currentConfiguration)
else
currentConfiguration
val synthesizedLocale = Locale(constrainedLanguage, constrainedCountry)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val oldLocales = configuration.locales
@Suppress("UNNECESSARY_NOT_NULL_ASSERTION")
if (!oldLocales.isEmpty) {
if (!oldLocales[0].language!!.contentEquals(synthesizedLocale.language)) {
var newLocales = arrayOfNulls<Locale>(oldLocales.size() + 1)
newLocales[0] = synthesizedLocale // first locale determines layout direction
var deductionCount = 0
for (i in 0 until oldLocales.size()) {
if (newLocales[0]?.language?.contentEquals(oldLocales[i].language) != true) // add only different locale if not null
newLocales[i + 1 - deductionCount] = oldLocales[i]
else {
val temp = arrayOfNulls<Locale>(newLocales.size - 1)
for (j in 0..i) {
temp[j] = newLocales[j]
}
newLocales = temp
deductionCount++
}
}
configuration.locales = LocaleList(*newLocales)
}
} else {
configuration.locales = LocaleList(synthesizedLocale)
}
} else {
@Suppress("DEPRECATION", "UNNECESSARY_NOT_NULL_ASSERTION")
if (configuration.locale == null || !synthesizedLocale.language!!.contentEquals(configuration.locale.language!!))
configuration.setLocale(synthesizedLocale)
}
return configuration
}
}