Change locale in android app (onto Hindi)

2019-06-06 22:53发布

问题:

Creating multi languages support for the app with possibility to change language in App settings.

As for now everything works fine for English, Spanish, Franch, Russian languages, but doesn't work for Hindi and Chineese.

1) I specify the language name in original language but in the app instead of हिन्दी I can see "Hindi".

\res\values-hi\arrays.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string-array name="languages">
        <item name="english">English</item>
        <item name="russian">Русский</item>
        <item name="spanish">Espagnol</item>
        <item name="russian">Français</item>
        <item name="chineese">中国</item>
        <item name="hindi">हिन्दी</item>
    </string-array>
    <string-array name="languagesValues">
         <item name="english">en</item>
        <item name="russian">ru</item>
        <item name="spanish">es</item>
        <item name="russian">fr</item>
        <item name="chineese">zh-CN</item>
        <item name="hindi">hi</item>
    </string-array>

</resources>

2) End after selecting "Hindi" - actually default (English) is being selected.
\res\values-hi\strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">लकी बीनने</string>
    <string name="score">0000</string>
    <string name="settings">सेटिंग</string>
    <string name="start_button">प्रारंभ</string>
    <string name="about_button">के बारे में</string>
    <string name="about">लियोनिद द्वारा बनाया गया</string>
    <string name="feedback">प्रतिक्रिया भेजें </string>
    <string name="high_score">उच्च स्कोर के</string>
    <string name="score_set">स्कोर निर्धारित किया गया है \r\nमें:</string>
    <string name="game_over">खेल खत्म</string>

....

Saving locale in Preferences.

public class Settings extends PreferenceActivity {

    Locale myLocale;
    static boolean localeChanged;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);


        // language changing
        Preference langPreference = getPreferenceScreen().findPreference(
                "language");
        langPreference.setOnPreferenceChangeListener(languageChangeListener);
    }

    Preference.OnPreferenceChangeListener languageChangeListener = new OnPreferenceChangeListener() {

        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {

            switch (newValue.toString()) {
            case "en":
                setLocale("en");
                break;

            case "ru":
                setLocale("ru");
                break;

            case "fr":
                setLocale("fr");
                break;

            case "es":
                setLocale("es");
                break;

            case "zh-CN":
                setLocale("zh-CN");
                break;

            case "hi":
                setLocale("hi");
                break;

            }

            localeChanged = true;
            return true;
        }
    };

    // * manually changing locale/
    public void setLocale(String lang) {
        myLocale = new Locale(lang);
        Resources res = getResources();
        DisplayMetrics dm = res.getDisplayMetrics();
        Configuration conf = res.getConfiguration();
        conf.locale = myLocale;
        res.updateConfiguration(conf, dm);
        Intent refresh = new Intent(this, Settings.class);
        startActivity(refresh);
        finish();
    }

What is wrong? Is something wrong in my code, or in my device?

回答1:

It depends on the device. Also, please check whether your device supports Hindi and Chinese languages by going to Settings --> Language & input.



回答2:

I. First thing first:

Your post has lots of logical and spelling mistakes. Lint will report errors and warnings for such, and code will not compile.

Please see the corrections:

Creating multi languages support for the app with possibility to change language in App settings.

As for now everything works fine for English, Spanish, French, Russian languages, but doesn't work for Hindi and Chinese.

1) I specify the language name in original language but in the app instead of हिन्दी I can see "Hindi".

\res\values-hi\arrays.xml

<string-array name="languages">
    <item name="english">English</item>
    <item name="russian">Русский</item>
    <item name="spanish">Espagnol</item>
    <item name="french">Français</item>
    <item name="chinese">中国</item>
    <item name="hindi">हिन्दी</item>
</string-array>
<string-array name="languagesValues">
     <item name="english">en</item>
    <item name="russian">ru</item>
    <item name="spanish">es</item>
    <item name="french">fr</item>
    <item name="chinese">zh-CN</item>
    <item name="hindi">hi</item>
</string-array>

[COMMENTS]

  1. Spelling mistakes: in the words chinese, french.

  2. Logical mistake: repetition in the key russian, in both the arrays, where on the second repeat, it should be french.

II. Improvements for @Chandrakanth's answer:

It depends on the device, and your device seems to be old one, while your code is correct. Giving you the reasons why:

Beginning with my answer, I want to quote from your question:

As for now everything works fine for English, Spanish, French, Russian    
languages, but doesn't work for Hindi and Chinese.

When you are using Chinese and Hindi, you are using following locales, as from your string resources:

<item name="chineese">zh-CN</item>
<item name="hindi">hi</item>

Please refactor it to:

<item name="chinese">zh</item>
<item name="hindi">hi</item>

So you should be using the values folders as:

values-zh and values-hi

If the above is correct then your application is not accepting or recognizing values-zh and values-hi in some old device.

  1. Please share your device make, manufacturer and model, so that more investigations can be done.

  2. Your code is OK, hence you can test your application in any other and newer device.

  3. Please call the method where it changes the locale, just before calling "setContentView" inside "onCreate" call back.

  4. Maybe you can check whether your device supports Hindi and Chinese language by going Settings --> Language & input.

I have devices that don't have Hindi and Chinese in the device settings, but still the locales hi and zh are recognized within the application, though I have to install corresponding fonts to prevent the fallback.

Please note that Hindi and Chinese are locales from different time zones, so most likely, they can not be found in the same devices settings.

Please see that your code is working on other new devices. If not, then you have to follow steps below. There are some basic understandings first:

Firstly, if you change locale in your device settings, it should have no effect on your application level locale settings. That is, if your device locale is set to Spanish, and your Application level locale preference is set to Hindi, Hindi should continue to show on every fragment/activity of your application if each one of these components are have the strings in them localized. Now if you change your locale from Spanish to Chinese, and your application or device is restarted, since zh is stored in your preferences, your method changes the locale to Chinese, on Application load and it continues to show text in Chinese.

Secondly, if your language depends upon font for example: since you have English, Hindi and Chinese locale support in your application, you have to have all TTF fonts in your asset folder and apply the Font-face to TextView, EditText, Radio Buttons, Check Box, Spinners etc. appropriately, when you change the language from your application settings. Here Hindi, and Chinese locales need TTF fonts to be there for each, in assets folder and has to be used in every component's font-face as mentioned above.

Thirdly, and most importantly, the best place to change your locale is just before setContentView(layout_id) of an activity is called in onCreate(Bundle restoreState) method. Therefore as soon as locale is changed, you have to send the control back to your dashboard/home screen so as to immediately see the effect.

Please see Android get hosting Activity from a view

You can also see How to use font assets using XML resources, in Android

and Using styles for your components in Android

Happy Coding :-)