【发布时间】:2021-07-11 07:33:11
【问题描述】:
我正在我的android项目中实现本地化。我已经实现了依赖注入,因此代码看起来更干净,并且每个类在本地化实现过程中都有自己的小功能。
问题: 在应用程序第一次启动时,应用程序使用我手机的本地化 (en-GB),在我更改语言后,应用程序成功更改配置并重新创建其活动,并使用我想要的 strings.xml 文件(在这种情况下是 values-de 文件夹中的字符串)。一切正常,即使我退出应用程序并返回应用程序,本地化也是我设置的。唯一的问题是,当我强制关闭应用程序并再次打开它时。它显示了原始 values/strings.xml 文件中的字符串,即使在我正常工作时使用的每种方法中都设置了另一种语言的参数(通过调试检查)。
App.kt 在清单中被引用,strings.xml 文件都被翻译,LocaleHelper.kt 成功地将上下文返回给应用程序,其中包含从 SharedPreferences 检索到的新本地化。
LocaleHelper.kt
object LocaleHelper {
const val SELECTED_LANGUAGE = "Locale.Helper.Selected.Language"
fun onAttach(context: Context): Context {
val locale = getLocale(context)
return setLocale(context, locale)
}
private fun getLocale(context: Context): Locale {
return load(context)
}
fun setLocale(context: Context, locale: Locale): Context {
persist(context, locale)
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
updateResources(context, locale)
} else
updateResourcesLegacy(context, locale)
}
fun isRTL(locale: Locale): Boolean {
return Locales.RTL.contains(locale.language)
}
private fun getPreferences(context: Context): SharedPreferences {
return context.getSharedPreferences(LocaleHelper::class.java.name, Context.MODE_PRIVATE)
}
private fun persist(context: Context, locale: Locale?) {
if (locale == null) return
getPreferences(context)
.edit()
.putString(SELECTED_LANGUAGE, locale.language)
.apply()
}
private fun load(context: Context): Locale {
val preferences = getPreferences(context)
val language = preferences.getString(SELECTED_LANGUAGE, Locale.getDefault().language)
return Locale(language!!)
}
@TargetApi(Build.VERSION_CODES.N)
private fun updateResources(context: Context, locale: Locale): Context {
Locale.setDefault(locale)
val configuration = context.resources.configuration
configuration.setLocale(locale)
configuration.setLayoutDirection(locale)
return context.createConfigurationContext(configuration)
}
@SuppressWarnings("deprecation")
private fun updateResourcesLegacy(context: Context, locale: Locale): Context {
Locale.setDefault(locale)
val resources = context.resources
val configuration = resources.configuration
configuration.locale = locale
configuration.setLayoutDirection(locale)
resources.updateConfiguration(configuration, resources.displayMetrics)
return context
}
}
LocaleHelperActivityDelegate.kt 和 LocaleHelperActivityDelegateImpl.kt
interface LocaleHelperActivityDelegate {
fun setLocale(activity: Activity, newLocale: Locale)
fun setWelcomeActivityLocale(activity: Activity, newLocale: Locale)
fun attachBaseContext(newBase: Context): Context
fun onPaused()
fun onResumed(activity: Activity)
fun onCreate(activity: Activity)
}
class LocaleHelperActivityDelegateImpl : LocaleHelperActivityDelegate {
val KEY_ACTIVITY_LOCALE_CHANGED = "activity_locale_changed"
override fun onCreate(activity: Activity) {
activity.window.decorView.layoutDirection =
if (LocaleHelper.isRTL(Locale.getDefault())) View.LAYOUT_DIRECTION_RTL else View.LAYOUT_DIRECTION_LTR
}
var locale: Locale = Locale.getDefault()
override fun setLocale(activity: Activity, newLocale: Locale) {
LocaleHelper.setLocale(activity, newLocale)
locale = newLocale
activity.startActivity(activity.intent)
activity.overridePendingTransition(0, 0)
activity.intent.putExtra(KEY_ACTIVITY_LOCALE_CHANGED, true)
activity.finish()
activity.overridePendingTransition(0, 0)
}
override fun setWelcomeActivityLocale(activity: Activity, newLocale: Locale) {
LocaleHelper.setLocale(activity, newLocale)
locale = newLocale
activity.startActivity(activity.intent)
activity.overridePendingTransition(0, 0)
activity.intent.putExtra(KEY_ACTIVITY_LOCALE_CHANGED, true)
activity.finish()
activity.overridePendingTransition(0, 0)
}
override fun attachBaseContext(newBase: Context): Context {
return LocaleHelper.onAttach(newBase)
}
override fun onPaused() {
locale = Locale.getDefault()
}
override fun onResumed(activity: Activity) {
val localeDefault = Locale.getDefault()
val isLocaleChanged = activity.intent.getBooleanExtra(KEY_ACTIVITY_LOCALE_CHANGED, false)
if(isLocaleChanged) {
activity.startActivity(activity.parentActivityIntent)
activity.overridePendingTransition(0, 0)
activity.finish()
activity.overridePendingTransition(0, 0)
}
}
}
class LocaleHelperApplicationDelegate {
fun attachBaseContext(base: Context): Context {
return LocaleHelper.onAttach(base)
}
fun onConfigurationChanged(context: Context) {
LocaleHelper.onAttach(context)
}
}
LocaleAwareCompatActivity.kt
open class LocaleAwareCompatActivity : AppCompatActivity() {
private val localeDelegate = LocaleHelperActivityDelegateImpl()
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(localeDelegate.attachBaseContext(newBase))
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
localeDelegate.onCreate(this)
}
override fun onResume() {
super.onResume()
localeDelegate.onResumed(this)
}
override fun onPause() {
super.onPause()
localeDelegate.onPaused()
}
open fun updateLocale(locale: Locale) {
localeDelegate.setLocale(this, locale)
}
}
BaseActivity.kt,在项目的每个Activity类中实现
open class BaseActivity : AppCompatActivity() {
private val localeDelegate = LocaleHelperActivityDelegateImpl()
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(localeDelegate.attachBaseContext(newBase))
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
localeDelegate.onCreate(this)
}
override fun onResume() {
super.onResume()
localeDelegate.onResumed(this)
}
override fun onPause() {
super.onPause()
localeDelegate.onPaused()
}
open fun updateLocale(locale: Locale) {
localeDelegate.setLocale(this, locale)
}
override fun applyOverrideConfiguration(overrideConfiguration: Configuration?) {
super.applyOverrideConfiguration(overrideConfiguration)
}
open fun updateWelcomeActivityLocale(locale: Locale)
{
localeDelegate.setWelcomeActivityLocale(this, locale)
}
}
还有我实现应用程序的 App 类
class App : Application()
{
private val localeAppDelegate = LocaleHelperApplicationDelegate()
override fun onCreate() {
super.onCreate()
// Unique initialization of Cache library to allow saving into device
CacheLibrary.init(this)
// Unique initialization of Dependency Injection library to allow the use of application context
startKoin { androidContext(this@App) }
Preferences.init(this)
}
override fun attachBaseContext(base: Context) {
super.attachBaseContext(localeAppDelegate.attachBaseContext(base))
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
localeAppDelegate.onConfigurationChanged(this)
}
【问题讨论】:
标签: android kotlin configuration localization