b2mob
b2mob

Reputation: 3449

Android plurals not working properly when you change system language

My application has only polish strings, it's default language of an app. Here you can see example plurals placed under res/vaules:

<plurals name="number_of_vouchers">
    <item quantity="one">%d kupon</item>
    <item quantity="few">%d kupony</item>
    <item quantity="many">%d kuponów</item>
    <item quantity="other">%d kuponów</item>
</plurals>

Here you have test activity class:

class DevTest : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_dev_test)

    val stb = StringBuilder()
    for (j in 1..30) {
        stb.append(resources.getQuantityString(R.plurals.number_of_vouchers, j, j) + "\n")
    }
    testTV.text = stb.toString()
}
}

This how example test looks like on system settings with Polish language set as default (works as it supposed to): enter image description here

This how example test looks like on system settings with English language set as default (doesn't work even if app has only Polish language): enter image description here

You can see that for English system language it's omits

<item quantity="few">%d kupony</item>

even if app has only one language, and it's not English.

Upvotes: 7

Views: 2233

Answers (2)

Milind Mevada
Milind Mevada

Reputation: 3285

As per Android official documentation here

few : When the language requires special treatment of "small" numbers (as with 2, 3, and 4 in Czech; or numbers ending 2, 3, or 4 but not 12, 13, or 14 in Polish).

So, In the Polish. If the numbers are ending with 2,3,4 (But not 12,13,14) it is taking plural of few.

--- EDITED --

For your app, polish is the only language.(under res/values). Now when your system language is polish. These plurals will be treated as Polish. So it's displaying as per my ans. Now when you change the system language to English. The same plurals will be treated as English. Hence no change in at 22,23,24. That's because res/values behaves as per system default language when no specific resource type is defined.

Also check the official documentation How Android finds the best-matching resource

Upvotes: 2

b2mob
b2mob

Reputation: 3449

Fix for this is for example to wrap context with overridden locale. For example:

companion object {
    fun wrap(context: Context?, language: String): ContextWrapper {
        if(context == null)
            return CustomContextWrapper(context)
        val config = context.resources.configuration
        val sysLocale: Locale = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            getSystemLocale(config)
        } else {
            getSystemLocaleLegacy(config)
        }
        if (language.isNotEmpty() && !sysLocale.language.equals(language)) {
            val locale = Locale(language)
            Locale.setDefault(locale)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                setSystemLocale(config, locale)
            } else {
                setSystemLocaleLegacy(config, locale)
            }
            return CustomContextWrapper(context.createConfigurationContext(config))
        }
        return CustomContextWrapper(context)
    }

    private fun getSystemLocaleLegacy(config: Configuration): Locale {
        return config.locale
    }

    @TargetApi(Build.VERSION_CODES.N)
    private fun getSystemLocale(config: Configuration): Locale {
        return config.locales.get(0)
    }

    private fun setSystemLocaleLegacy(config: Configuration, locale: Locale) {
        config.locale = locale
    }

    @TargetApi(Build.VERSION_CODES.N)
    private fun setSystemLocale(config: Configuration, locale: Locale) {
        config.setLocale(locale)
    }
}

And called within Activity like:

override fun attachBaseContext(newBase: Context?) {
    super.attachBaseContext(CustomContextWrapper.wrap(newBase, "pl"))
}

Resolved thanks to original fix link

I couldn't find that issue on google's bug tracker so I assume that it works as it should.

Upvotes: 1

Related Questions