bluesky-social / social-app

The Bluesky Social application for Web, iOS, and Android
https://bsky.app
MIT License
12.65k stars 1.61k forks source link

Fix display language not switching correctly to Chinese on native. #6621

Closed auroursa closed 3 days ago

auroursa commented 3 days ago

Why

In web development, language codes generally follow the RFC 1766 standard. In this standard, the language tag for Chinese is typically written as: zh-CN, zh-TW, zh-HK.

However, in Android and iOS, language codes follow the RFC 4646 standard, which further distinguishes Simplified Chinese (Hans) and Traditional Chinese (Hant). The language tags in this standard look like: zh-Hans-CN, zh-Hant-TW, zh-Hant-HK

When using getLocales().languageTag from expo-localization on an Android device (with system language set to Simplified Chinese), it will return this output:

[{"languageTag": "zh-Hans-CN"}]

This cannot be matched to existing AppLanguage, so it will rollback to English. Because AppLanguage naming follows RFC 1766, which is still widely used in browsers. Therefore, we cannot rename Chinese AppLanguage to following RFC 4646.

This patch is meant to solve this issue by converting the RFC 4646 output from the device into RFC 1766, just like how we handle incorrect languageCode on legacy Java devices (#4461).

With this patch, now using getLocales().languageTag will return the following output:

[{"languageTag": "zh-CN"}]

Based on #5384, the app can now correctly handle language tags with region codes. This allows it to match the existing zh-CN in AppLanguage and display Chinese when the app is opened for the first time, instead of rolling back to English.

It's hard to say RFC 1766 or RFC 4646 which standard is better, but both will likely coexist for a long time. Web development is unlikely to transition to RFC 4646, as it would break browser behavior, and W3C seem to prefer RFC 1766.

Always bear in mind that the golden rule is to keep your language tag as short as possible. Only add further subtags to your language tag if they are needed to distinguish the language from something else in the context where your content is used.

For now, Chinese is one of the few languages that requires mapping conversion. Most languages work as expected under either standard. So this patch only includes conversion mapping for Chinese. I prefer not to rewrite the logic in the later parts of the code.

Before:

https://github.com/user-attachments/assets/fc8dda1d-0099-47a7-a6c2-4772bbfe2cf3

After:

https://github.com/user-attachments/assets/8169186c-a71f-4a7d-91f1-d8845b1fc514

auroursa commented 3 days ago

Okay... There are so many variations of Chinese in the Android system language list.

For Simplified Chinese, there are zh-Hans-CN, zh-Hans-MO, zh-Hans-HK, and zh-Hans-SG. The previous exact match may not cover other Chinese variants, such as zh-Hans-SG. Please forgive me for using startsWith for fuzzy matching. To ensure no Chinese variant fallback to English.

Based on the reference, Android 7+ and iOS 9+ have started using zh-Hans / zh-Hant language codes, so this patch is also effective for iOS.

Reference: https://stackoverflow.com/questions/44714408/android-simplified-chinese-and-traditional-chinese-not-working https://developer.apple.com/library/archive/technotes/tn2418/_index.html