Live data from Hacker News

A bug that spoke Russian and crashed my app

imzaldih.com

1–10 of 22 posts

Re: A bug that spoke Russian and crashed my app

#2
> If the device is in Russian, Locale.getDefault() returns “русский”, and it seems that SQLite doesn’t like this for some reason.

> I did more tests, and it seems that out of the over 100 languages Android supports, only Russian encoding broke SQLite. Not even Chinese, which we typically think of as the most complicated (and also I tested changing to this language much earlier before trying the other).

Is this an issue?

Re: A bug that spoke Russian and crashed my app

#3

> If the device is in Russian, Locale.getDefault() returns “русский”, and it seems that SQLite doesn’t like this for some reason. > I did more tests, and it seems that out of the over 100 languages Android supports, only Russian encoding broke SQLite. Not even Chinese, which we typically think of as the most complicated (and also I tested changing to this language much earlier before trying the other). Is this an iss…

According to some people on the Internet [0][1], it is. Apparently, Java's (Android's?) Locale.getLanguage() is broken for Russian locale and instead of returning "ru" as the docs promise [2], it returns "русский".

[0] https://stackoverflow.com/questions/46916210/cannot-get-writ...

[1] https://github.com/google/ExoPlayer/issues/8251

[2] https://docs.oracle.com/javase/8/docs/api/java/util/Locale.h...

Re: A bug that spoke Russian and crashed my app

#4
post #3

> If the device is in Russian, Locale.getDefault() returns “русский”, and it seems that SQLite doesn’t like this for some reason. > I did more tests, and it seems that out of the over 100 languages Android supports, only Russian encoding broke SQLite. Not even Chinese, which we typically think of as the most complicated (and also I tested changing to this language much earlier before trying the other). Is this an iss…

According to some people on the Internet [0][1], it is. Apparently, Java's (Android's?) Locale.getLanguage() is broken for Russian locale and instead of returning "ru" as the docs promise [2], it returns "русский". [0] https://stackoverflow.com/questions/46916210/cannot-get-writ... [1] https://github.com/google/ExoPlayer/issues/8251 [2] https://docs.oracle.com/javase/8/docs/api/java/util/Locale.h...

Except that TFA is using `getDisplayLanguage`

    public void updateAppLanguage(Context context) {
        String languageCode = Locale.getDefault().getDisplayLanguage();
        Locale locale = new Locale(languageCode);
        Locale.setDefault(locale);
... which the JDK docs say:

>Returns a name for the locale's language that is appropriate for display to the user.

So maybe `getLanguage` is broken or maybe it isn't, but it seems wrong to use `getDisplayLanguage` for this purpose regardless.

(What even is the point of doing `Locale.setDefault()` with the same Locale that `Locale.getDefault()` returned? I don't know anything about Android.)

Re: A bug that spoke Russian and crashed my app

#5
This isn't fixed properly

The linked code is:

        String languageCode = Locale.getDefault().getDisplayLanguage();
        Locale locale = new Locale(languageCode);
        Locale.setDefault(locale);
But `getDisplayLanguage()` is defined as returning the display name, not the language code:

> if the locale is en_US and the default DISPLAY locale is fr_FR, getDisplayLanguage() will return "anglais"

https://developer.android.com/reference/java/util/Locale#get...()

----

This then proceeds to create a locale with a corrupt language code. The language parameter of `Locale` is not validated (besides a null check), and using a corrupt Locale in `Locale.setDefault()` will cause a number of bugs

Re: A bug that spoke Russian and crashed my app

#6
post #4
post #3

Earlier quoted context omitted.

According to some people on the Internet [0][1], it is. Apparently, Java's (Android's?) Locale.getLanguage() is broken for Russian locale and instead of returning "ru" as the docs promise [2], it returns "русский". [0] https://stackoverflow.com/questions/46916210/cannot-get-writ... [1] https://github.com/google/ExoPlayer/issues/8251 [2] https://docs.oracle.com/javase/8/docs/api/java/util/Locale.h...

Except that TFA is using `getDisplayLanguage` public void updateAppLanguage(Context context) { String languageCode = Locale.getDefault().getDisplayLanguage(); Locale locale = new Locale(languageCode); Locale.setDefault(locale); ... which the JDK docs say: >Returns a name for the locale's language that is appropriate for display to the user. So maybe `getLanguage` is broken or maybe it isn't, but it seems wrong to use…

> (What even is the point of doing `Locale.setDefault()` with the same Locale that `Locale.getDefault()` returned? I don't know anything about Android.)

The code intends to trim the country, variant and any extensions from the value returned from `Locale.getDefault()`

Example: "Chinese (Traditional) - Taiwan" to "Chinese"

Pseudocode:

`zh_Hant_TW` -> `zh`

It also normalizes to fix some Android internal mapping issues due to changes in ISO 639 (Hebrew can be `iw` or `he[b]`)

Re: A bug that spoke Russian and crashed my app

#7
post #4
post #3

Earlier quoted context omitted.

According to some people on the Internet [0][1], it is. Apparently, Java's (Android's?) Locale.getLanguage() is broken for Russian locale and instead of returning "ru" as the docs promise [2], it returns "русский". [0] https://stackoverflow.com/questions/46916210/cannot-get-writ... [1] https://github.com/google/ExoPlayer/issues/8251 [2] https://docs.oracle.com/javase/8/docs/api/java/util/Locale.h...

Except that TFA is using `getDisplayLanguage` public void updateAppLanguage(Context context) { String languageCode = Locale.getDefault().getDisplayLanguage(); Locale locale = new Locale(languageCode); Locale.setDefault(locale); ... which the JDK docs say: >Returns a name for the locale's language that is appropriate for display to the user. So maybe `getLanguage` is broken or maybe it isn't, but it seems wrong to use…

For language:

1. `getLanguage` should return the 2-letter ISO 3166-1 language code, or an empty string if missing. -- e.g. en, ru, fr, etc.

2. `getISO3Language` should return the 3-letter ISO 3166-1 language code, or an empty string if missing. -- e.g. eng, rus, fra, etc.

1. `getDisplayLanguage` should return the language display name in the current locale, or an empty string if missing. -- e.g. English, Russian, French, etc.

Re: A bug that spoke Russian and crashed my app

#8
post #7
post #4

Earlier quoted context omitted.

Except that TFA is using `getDisplayLanguage` public void updateAppLanguage(Context context) { String languageCode = Locale.getDefault().getDisplayLanguage(); Locale locale = new Locale(languageCode); Locale.setDefault(locale); ... which the JDK docs say: >Returns a name for the locale's language that is appropriate for display to the user. So maybe `getLanguage` is broken or maybe it isn't, but it seems wrong to use…

For language: 1. `getLanguage` should return the 2-letter ISO 3166-1 language code, or an empty string if missing. -- e.g. en, ru, fr, etc. 2. `getISO3Language` should return the 3-letter ISO 3166-1 language code, or an empty string if missing. -- e.g. eng, rus, fra, etc. 1. `getDisplayLanguage` should return the language display name in the current locale, or an empty string if missing. -- e.g. English, Russian, Fre…

Am I correct in understanding that `getDisplayLanguage` should return "Russian" if the current locale is US English but will return "Russe" if set to French?

Btw you have a formatting error. The third numbered point is listed as another '1.'.

Re: A bug that spoke Russian and crashed my app

#9

This isn't fixed properly The linked code is: String languageCode = Locale.getDefault().getDisplayLanguage(); Locale locale = new Locale(languageCode); Locale.setDefault(locale); But `getDisplayLanguage()` is defined as returning the display name, not the language code: > if the locale is en_US and the default DISPLAY locale is fr_FR, getDisplayLanguage() will return "anglais" https://developer.android.com/reference/…

I agree. Locale.getLanguage() returns the language code.

The specific Locale() constructor used in the code is documented as taking a parameter: "An ISO 639 alpha-2 or alpha-3 language code, or a language subtag up to 8 characters in length. See the Locale class description about valid language values."

I'd guess the app code lucked out on the string returned from getDisplayLanguage() getting mapped to the appropriate language in all the other cases that the app supports.

Now if getLanguage() had been renamed to getLanguageCode() then maybe a dev might have had the light bulb turn on, but random string returned from an API passed to another API passes the compile test and the app doesn't blow up, so we're good to go...

Searching for the offending incorrect code on the web doesn't return any matching "sample" code, so I'm not sure where the app got the bug from.

Re: A bug that spoke Russian and crashed my app

#10

This isn't fixed properly The linked code is: String languageCode = Locale.getDefault().getDisplayLanguage(); Locale locale = new Locale(languageCode); Locale.setDefault(locale); But `getDisplayLanguage()` is defined as returning the display name, not the language code: > if the locale is en_US and the default DISPLAY locale is fr_FR, getDisplayLanguage() will return "anglais" https://developer.android.com/reference/…

I agree. Locale.getLanguage() returns the language code. The specific Locale() constructor used in the code is documented as taking a parameter: "An ISO 639 alpha-2 or alpha-3 language code, or a language subtag up to 8 characters in length. See the Locale class description about valid language values." I'd guess the app code lucked out on the string returned from getDisplayLanguage() getting mapped to the appropriat…

For me the light bulb here is the word `display`. The method is called `getDisplayLanguage` because it's returning the language name for display to the user. Even if I didn't already know that, I'd be asking myself as I was typing the code: "wait, what does 'display' mean here? Why would they name it that? I'd better check the docs..."
Post reply on HN