Jesway / flutter_translate

Flutter Translate is a fully featured localization / internationalization (i18n) library for Flutter.
MIT License
403 stars 118 forks source link

Question about Chinese support #51

Closed ThrowJojo closed 4 years ago

ThrowJojo commented 4 years ago

Hey there,

First of all thank you for this package it is great and was really helpful when refactoring the localizations for one of my projects. I tried a few different localization packages and this one was definitely the best and easiest to use.

I spent a couple of hours trying to figure out Chinese localization today(Simplified and Traditional). I also ended up cloning the flutter_device_locale package and testing it out on an iOS and Android simulator.

For iOS I found that:

  1. When the language was set to Simplified Chinese getCurrentLocale would return zh_Hans
  2. When the language was set to Traditional Chinese getCurrentLocale would return zh_Hant

For Android I found that:

  1. When the language was set to Simplified Chinese(China) getCurrentLocale would return zh_CN
  2. When the language was set to Traditional Chinese(Taiwan) getCurrentLocale would return zh_TW

What I want to know is, will I have to make 4 translation files to support all of these situations(zh_Hans.json, zh_Hant.json, zh_CN.json, zh_TW.json)? Or is there some other way, like using localeResolutionCallback, to only use two files(ex: only zh_Hans.json and zh_Hant.json) and force one of the platforms(iOS or Android) to follow that specific pattern?

Thanks again for this awesome package!

ThrowJojo commented 4 years ago

Just wanted to update this incase someone else runs into the same issue.

I've only tested it lightly but this seems to work for me:

localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) {
    if (locale == null) return supportedLocales.first;

    if (locale.languageCode == "zh") {
        if (locale.toString().contains("TW") || locale.toString().contains("Hant")) {
            return supportedLocales.firstWhere((element) => element.countryCode == "Hant", orElse: () => supportedLocales.first);
        }

        if (locale.toString().contains("CN") || locale.toString().contains("Hans")) {
            return supportedLocales.firstWhere((element) => element.countryCode == "Hans", orElse: () => supportedLocales.first);
        }
    }

    return localizationDelegate.currentLocale;
}

You have to get rid of this line in MaterialApp for this to work:

locale: localizationDelegate.currentLocale

It's kind of sloppy but I'm running on not much sleep. The reason this is necessary is because like I wrote above the locales on Android are recognized as zh_TW and zh_CN respectively, which causes the fallback here to kick in - this only checks the languageCode so it will choose the first Chinese(zh) option in your supportedLocales.

It's probably also worth mentioning that in the default Flutter locales Hans and Hant are considered to be script codes rather than country codes.

I'll close this issue for now but update it if I find a cleaner option in the future.

ThrowJojo commented 4 years ago

I finally got around to implementing this and I found that what I wrote above was only working on iOS. Here's what I changed localeResolutionCallback to to get it working on Android as well:

localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) {
    if (locale == null) return localizationDelegate.fallbackLocale;

    if (locale.languageCode == "zh") {
        if (locale.toString().contains("TW") || locale.toString().contains("Hant")) {
            return supportedLocales.firstWhere((element) => element.countryCode == "Hant" || element.countryCode == "TW", orElse: () => localizationDelegate.fallbackLocale);
        }
    }

    return localizationDelegate.currentLocale;
}

Just thought I'd update incase this issue was relevant to anybody else 👍.