7

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.

b2mob
  • 3,419
  • 2
  • 14
  • 22

2 Answers2

2

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

Milind Mevada
  • 3,145
  • 1
  • 14
  • 22
  • You seems to not understand the problem. App has only Polish language and strings are working correctly until you change android system language for other than Polish. It's look like system BUG. – b2mob Jul 31 '18 at 06:28
  • 1
    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` are in system default language – Milind Mevada Jul 31 '18 at 06:41
  • The above comment could be the answer for it if it would clearly state that system locale is more important than app, and it doesn't matter if your app has only one language. Whenever user change system language to other than your app have, then the other "plurals rule" will apply. – b2mob Jul 31 '18 at 09:15
  • Updated answer and provided the link as well. please go through – Milind Mevada Jul 31 '18 at 09:37
1

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.

b2mob
  • 3,419
  • 2
  • 14
  • 22