返回

多语言字符串显示问题:解决方案和常见问题解答

Android

## 多语言字符串显示问题解决方案

前言

在构建多语言应用程序时,开发人员经常遇到字符串资源中显示文本值的问题。本文深入探讨了导致此问题的原因,并提供了详细的解决方案。

问题

当你使用第三方库或自定义代码实现多语言支持时,应用的语言和布局方向能够成功切换,但无法从第二语言的字符串资源中获取文本值。

## 解决步骤

要解决此问题,需要确保你的应用程序遵循以下步骤:

1. 正确加载语言设置

onAttach() 方法中,从 SharedPreferences 中加载保存的语言设置,并将其应用于 Locale.setDefault()

2. 更新上下文资源

使用 updateContextResources() 方法更新上下文的语言配置。这将导致重新加载资源,包括字符串资源。

3. 刷新活动

在设置语言后,重新创建活动以应用更新的资源。

代码示例

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 设置语言
        LocaleHelper.onAttach(this)

        // 刷新活动
        recreate()
    }
}

object LocaleHelper {
    private const val SELECTED_LANGUAGE = "Locale.Helper.Selected.Language"
    private const val SELECTED_COUNTRY = "Locale.Helper.Selected.Country"
    private var initialized = false

    fun onAttach(context: Context) {
        if (!initialized) {
            Locale.setDefault(load(context))
            initialized = true
        }
        updateContextResources(context, Locale.getDefault())
    }

    fun getLocale(context: Context): Locale = load(context)

    fun setLocale(context: Context, locale: Locale) {
        persist(context, locale)
        Locale.setDefault(locale)
        updateContextResources(context, locale)
    }

    fun isRTL(locale: Locale): Boolean = Locales.RTL.contains(locale.language)

    private fun getPreferences(context: Context): SharedPreferences =
        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)
            .putString(SELECTED_COUNTRY, locale.country)
            .apply()
    }

    private fun load(context: Context): Locale {
        val preferences = getPreferences(context)
        val default = Locale.getDefault()
        val language = preferences.getString(SELECTED_LANGUAGE, default.language) ?: return default
        val country = preferences.getString(SELECTED_COUNTRY, default.country) ?: return default
        return Locale(language, country)
    }

    private fun updateContextResources(context: Context, locale: Locale) {
        val resources = context.resources
        val configuration = resources.configuration
        configuration.setCurrentLocale(locale)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            configuration.setLayoutDirection(locale)
        }

        context.createConfigurationContext(configuration)
    }
}

其他提示

  • 确保在 strings.xml 中使用正确的语言代码和国家代码。
  • 检查应用是否正确获取语言环境,可以使用 Locale.getDefault() 方法来验证。
  • 尝试清理和重新编译应用,这可以解决某些缓存相关的问题。

## 结论

遵循本文中概述的步骤,你将能够在你的多语言应用程序中成功显示字符串资源的文本值。

## 常见问题解答

  1. 为什么需要更新上下文资源?

    更新上下文资源是必要的,因为这会重新加载字符串资源并应用所选语言的翻译。

  2. 刷新活动有什么作用?

    刷新活动确保应用的 UI 使用更新的资源重新创建。

  3. 如何确定正确的语言环境?

    你可以使用 Locale.getDefault() 方法获取当前语言环境。

  4. 如何使用不同的语言代码和国家代码?

    strings.xml 文件中,使用正确的语言代码和国家代码,例如 "en-US" 或 "es-MX"。

  5. 如何在 RTL 语言中设置布局方向?

    对于 RTL 语言,使用 updateContextResources() 方法来设置布局方向。