Welcome, Buddy… In this android tutorials we demonstrate, Build a multi-language support in the android application. As per Android best practice, Application should be kept culture-specific resource. So that resource to be translated to the language based on current locale. In android term, it is called Internationalization and Localization

Localization is play very important role for app reach and user experience (especially GUI). Multi-language support increases your audience reach and provides a better user interface based on locale. Let’s make your Android app more usable and comfortable so more and more audience can use it

How do Internationalization and Localization work in android?

In, Android you can specify resources to the culture of the targeted audience. All content related resource is held in drawable and value folder in Android Project. In this tutorials as will give support of 3 languages Spanish, Hindi (hi_IN)and English(en_US)

1. Let’s build a sample app in 4 step

1.1 In the Create New Project, enter the following values:

Application Name: “Multi-Language App”// Replace name with your application
Company Domain: “com.androidwave.multilangauge” // replace package name here

Go Next and select target device, keep the default values and click Finish.
In Android, the project structure seems like below figure.

How locale work in android.
Locale Manager in Android

1.2 Add new resource file strings.xml for the Hindi language

Go to value resource folder and right click on got to the Value resource file.
Select locale from available qualifier clicks the right arrow. Select language and specific region (the region is not mandatory). Check below figure

Multi Language support in android
Android tutorials, android developer

Similarly create file for Spanish locale.

<resources>
    <string name="app_name">Multi Language App</string>
    <string name="navigation_drawer_open">Open navigation drawer</string>
    <string name="navigation_drawer_close">Close navigation drawer</string>
    <string name="nav_header_title">Android Wave</string>
    <string name="nav_header_subtitle">androidwave.com</string>
    <string name="nav_header_desc">Android &amp; iOS Developer Blog</string>
    <string name="action_settings">Settings</string>
    <string name="description_androidwave">We demonstrate android &amp; iOS app development tutorials for Firebase, Camera2 API, Exo Player, Youtube API, Dagger2, RxJava, MVVM, MVP, Realm, and more.</string>
    <string name="text_hindi" translatable="false">हिंदी</string>
    <string name="text_english" translatable="false">English</string>
    <string name="text_spanish" translatable="false">" Español"</string>

    <!-- Navigation Menu-->
    <string name="title_import">Import</string>
    <string name="title_gallery">Gallery</string>
    <string name="title_slideshow">Slideshow</string>
    <string name="title_tools">Tools</string>
    <string name="title_communication">Communicate</string>
    <string name="title_share">Share</string>
    <string name="title_send">Send</string>
</resources>

For Hindi

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">बहु भाषा ऐप</string>
    <string name="navigation_drawer_open">नेविगेशन ड्रावर को खोले</string>
    <string name="navigation_drawer_close">नेविगेशन ड्रावर को बंद करें </string>
    <string name="nav_header_title">एंड्रॉइड वेव</string>
    <string name="nav_header_subtitle">androidwave.com</string>
    <string name="nav_header_desc">एंड्रॉइड और आईओएस डेवलपर ब्लॉग</string>
    <string name="action_settings">सेटिंग</string>
    <string name="description_androidwave">हम फायरबेस, कैमरा 2 एपीआई, एक्सो प्लेयर, यूट्यूब एपीआई, डैगर 2, आरएक्सजेवा, एमवीवीएम, एमवीपी, दायरे, आदि के लिए एंड्रॉइड और आईओएस ऐप डेवलपमेंट ट्यूटोरियल का प्रदर्शन करते हैं।</string>
    <!-- Navigation Menu-->
    <string name="title_import">आयात</string>
    <string name="title_gallery">गैलरी</string>
    <string name="title_slideshow">स्लाइड शो</string>
    <string name="title_tools">उपकरण</string>
    <string name="title_communication">संवाद</string>
    <string name="title_share">शेयर</string>
    <string name="title_send">भेजना</string>
</resources>

For Spanish

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">Aplicación multi idioma</string>
    <string name="navigation_drawer_open">Cajón de navegación abierto.</string>
    <string name="navigation_drawer_close">Cerrar el cajon de navegacion</string>
    <string name="nav_header_title">Android Wave</string>
    <string name="nav_header_subtitle">androidwave.com</string>
    <string name="nav_header_desc">Android &amp; Blog del desarrollador de iOS</string>
    <string name="action_settings">Ajustes</string>
    <string name="description_androidwave">Demostramos android &amp; Tutoriales de desarrollo de aplicaciones iOS para Firebase, Camera2 API, Exo Player, Youtube API, Dagger2, RxJava, MVVM, MVP, Realm y más</string>
    <!-- Navigation Menu-->
    <string name="title_import">Importar</string>
    <string name="title_gallery">Galería</string>
    <string name="title_slideshow">Diapositivas</string>
    <string name="title_tools">Herramientas</string>
    <string name="title_communication">Comunicar</string>
    <string name="title_share">Compartir</string>
    <string name="title_send">Enviar</string>
</resources>
The complete project hierarchy looks like this figure
Android Developer

3. Now build LocalManager.java utilities.

3.1. Define some specific constant key
    /**
     * For english locale
     */
    public static final String LANGUAGE_KEY_ENGLISH = "en";
    /**
     * for hindi locale
     */
    public static final String LANGUAGE_KEY_HINDI = "hi";
    /***
     * // for spanish locale
     */

    public static final String LANGUAGE_KEY_SPANISH = "es";
    /**
     *  SharedPreferences Key
     */
    private static final String LANGUAGE_KEY = "language_key";
3.2. Save locale preference in PreferenceManager

Build Getter and Setter of local, It’s Setter responsible for persisting data in SharedPreferences and Getter is responsible for pulling data from SharedPreferences.

/**
     * Get saved Locale from SharedPreferences
     * @param mContext current context
     * @return current locale key by default return english locale
     */
    public static String getLanguagePref(Context mContext) {
        SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
        return mPreferences.getString(LANGUAGE_KEY, LANGUAGE_KEY_ENGLISH);
    }

    /**
     *  set pref key
      * @param mContext
     * @param localeKey
     */
    private static void setLanguagePref(Context mContext, String localeKey) {
        SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
        mPreferences.edit().putString(LANGUAGE_KEY, localeKey).commit();
    }

Now set locale and update the resource in android.
 /**
     * update resource
     * @param context
     * @param language
     * @return
     */
    private static Context updateResources(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(locale);
        Resources res = context.getResources();
        Configuration config = new Configuration(res.getConfiguration());
        if (Build.VERSION.SDK_INT >= 17) {
            config.setLocale(locale);
            context = context.createConfigurationContext(config);
        } else {
            config.locale = locale;
            res.updateConfiguration(config, res.getDisplayMetrics());
        }
        return context;
    }

Finally the complete utilites class looks like below java class

package com.androidwave.multilanguage;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.preference.PreferenceManager;

import java.util.Locale;

public class LocaleManager {
    /**
     * For english locale
     */
    public static final String LANGUAGE_KEY_ENGLISH = "en";
    /**
     * for hindi locale
     */
    public static final String LANGUAGE_KEY_HINDI = "hi";
    /***
     * // for spanish locale
     */

    public static final String LANGUAGE_KEY_SPANISH = "es";
    /**
     *  SharedPreferences Key
     */
    private static final String LANGUAGE_KEY = "language_key";

    /**
     * set current pref locale
     * @param mContext
     * @return
     */
    public static Context setLocale(Context mContext) {
        return updateResources(mContext, getLanguagePref(mContext));
    }

    /**
     * Set new Locale with context
     * @param mContext
     * @param mLocaleKey
     * @return
     */
    public static Context setNewLocale(Context mContext, String mLocaleKey) {
        setLanguagePref(mContext, mLocaleKey);
        return updateResources(mContext, mLocaleKey);
    }

    /**
     * Get saved Locale from SharedPreferences
     * @param mContext current context
     * @return current locale key by default return english locale
     */
    public static String getLanguagePref(Context mContext) {
        SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
        return mPreferences.getString(LANGUAGE_KEY, LANGUAGE_KEY_ENGLISH);
    }

    /**
     *  set pref key
      * @param mContext
     * @param localeKey
     */
    private static void setLanguagePref(Context mContext, String localeKey) {
        SharedPreferences mPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
        mPreferences.edit().putString(LANGUAGE_KEY, localeKey).commit();
    }

    /**
     * update resource
     * @param context
     * @param language
     * @return
     */
    private static Context updateResources(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(locale);
        Resources res = context.getResources();
        Configuration config = new Configuration(res.getConfiguration());
        if (Build.VERSION.SDK_INT >= 17) {
            config.setLocale(locale);
            context = context.createConfigurationContext(config);
        } else {
            config.locale = locale;
            res.updateConfiguration(config, res.getDisplayMetrics());
        }
        return context;
    }

    /**
     * get current locale
     * @param res
     * @return
     */
    public static Locale getLocale(Resources res) {
        Configuration config = res.getConfiguration();
        return Build.VERSION.SDK_INT >= 24 ? config.getLocales().get(0) : config.locale;
    }
}

5. Locale Configration

Few minor configration have to need in activity and application class.

package com.androidwave.multilanguage;

import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;

import static android.content.pm.PackageManager.GET_META_DATA;

public class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        resetTitles();
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleManager.setLocale(base));
    }

    protected void resetTitles() {
        try {
            ActivityInfo info = getPackageManager().getActivityInfo(getComponentName(), GET_META_DATA);
            if (info.labelRes != 0) {
                setTitle(info.labelRes);
            }
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
    }

}

6. Implement Locale Configration in Application class

package com.androidwave.multilanguage;

import android.app.Application;
import android.content.Context;
import android.util.Log;

public class MultiLanguageApp extends Application {

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(LocaleManager.setLocale(base));
    }

    @Override
    public void onConfigurationChanged(android.content.res.Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        LocaleManager.setLocale(this);
    }
}

Above all locale configration is complete and LocaleManager utilities is ready to use. In conclusion, just wrtie a single line code for change locale of application

 
    // For English
      LocaleManager.setNewLocale(this, LocaleManager.LANGUAGE_KEY_ENGLISH);
   // For Hindi
        LocaleManager.setNewLocale(this, LocaleManager.LANGUAGE_KEY_HINDI);
   // For Spanish
      LocaleManager.setNewLocale(this, LocaleManager.LANGUAGE_KEY_SPANISH);

For instance, for simple utities uses example.

package com.androidwave.multilanguage;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.NavigationView;
import android.support.design.widget.Snackbar;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

public class MainActivity extends BaseActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
    }


    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        switch (id) {
            case R.id.local_english:
                LocaleManager.setNewLocale(this, LocaleManager.LANGUAGE_KEY_ENGLISH);
                recreate();
                return true;
            case R.id.local_hindi:
                LocaleManager.setNewLocale(this, LocaleManager.LANGUAGE_KEY_HINDI);
                recreate();
                return true;

            case R.id.local_spanish:
                LocaleManager.setNewLocale(this, LocaleManager.LANGUAGE_KEY_SPANISH);
                recreate();
                return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();
        switch (id) {
            case R.id.nav_camera:
                break;
            case R.id.nav_gallery:
                break;
            case R.id.nav_slideshow:
                break;
            case R.id.nav_manage:
                break;
            case R.id.nav_share:
                break;
            case R.id.nav_send:
                break;

            default:
                break;
        }
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

}

Download Sample Project- Android Multi Language Support Best Practices

 
If you have any query, feel free to connect us.

Author

Write A Comment