Niaz
Niaz

Reputation: 564

What is the best way to add second language to the app

All texts in my app are in res\values\strings.xml.
I should add a second language.
The app should detect the language of Android and then select the appropriate language.
Is it possible to add a language avoiding changing references to strings.xml, such as below:

sensor.client.R.string.operationResult_communicationError

or

<TextView
    android:text="@string/common_please_wait"

Any advice please?

Upvotes: 1

Views: 4079

Answers (3)

Vid
Vid

Reputation: 1012

There is a default "values" folder in the res which contains string.xml, right. Now, if you want your app to support other language then create some other "values" folders.

Example:

If you want your app to support "Rusian language", then create folder with the name "values-ru" which will also contain string.xml. And make sure whatever the string name you are using in values folder's string.xml the same name you have to use in values-ru folder's string.xml file.

e.g.

In values folder's : <string name="submit">Submit</string> In values-ru folder's : <string name="submit">Представить</string>

And see this class now

public class LanguageActivity extends Activity implements OnClickListener
{
    private static String TAG = LanguageActivity.class.getSimpleName();

    ListView lvLanguage;
    ImageButton btnDone;

    String langCode = "";
    ArrayList<Language> listLanguages = new ArrayList<Language>();

    // ListAdapter lsAdapter;
    SharedPreferences preferences;
    Editor editor;

    Intent intent = null;
    LanguageAdapter languageAdapter;

    String fromWhere;
    private String selectedLanguage = "";
    private String selectedLanguageCode = "";

    boolean isFirstTime = true;

    /**
     * Locale object to know language set on device.
     */
    private Locale localeDevice;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_language);
        initView();
        initParameters();
    }

    private void initParameters()
    {
        preferences = PreferenceManager.getDefaultSharedPreferences(this);
        editor = preferences.edit();

        Log.i(TAG, "isFirstTime: " + isFirstTime);
        fromWhere = getIntent().getStringExtra(Constants.FROM_WHERE);
        selectedLanguage = preferences.getString(Constants.LANGUAGE_NAME, "English");
        selectedLanguageCode = preferences.getString(Constants.LANGUAGE_CODE, "en");
        isFirstTime = preferences.getBoolean(Constants.IS_FIRST_TIME, true);
        prepareLanguageList();
    }

    private void initView()
    {
        lvLanguage = (ListView) findViewById(R.id.activity_language_lv);
        btnDone = (ImageButton) findViewById(R.id.activity_language_btn_done);
        btnDone.setVisibility(View.VISIBLE);
        btnDone.setOnClickListener(this);
    }

    @Override
    public void onClick(View v)
    {
        switch (v.getId())
        {
        case R.id.activity_language_btn_done:
            Util.setAppLanguage(selectedLanguage, this);

            editor.putString(Constants.LANGUAGE_NAME, selectedLanguage);
            editor.putString(Constants.LANGUAGE_CODE, selectedLanguageCode);
            editor.putBoolean(Constants.IS_FIRST_TIME, false);
            editor.commit();

            LanguageActivity.this.finish();
            Intent intent = new Intent(LanguageActivity.this, LoginActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            if (fromWhere != null && fromWhere.equals("SettingsActivity"))
            {
                LanguageActivity.this.finish();
                intent = new Intent(LanguageActivity.this, SettingsActivity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            }
            startActivity(intent);
            break;

        default:
            break;
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        finish();
    }

    class Language
    {
        String name = "";
        String languageCode = "";
        boolean isSelected = false;

        /**
         * @return the name
         */
        public String getName()
        {
            return name;
        }

        /**
         * @param name
         *            the name to set
         */
        public void setName(String name)
        {
            this.name = name;
        }

        /**
         * @return the languageCode
         */
        public String getLanguageCode()
        {
            return languageCode;
        }

        /**
         * @param languageCode
         *            the languageCode to set
         */
        public void setLanguageCode(String languageCode)
        {
            this.languageCode = languageCode;
        }

        /**
         * @return the isSelected
         */
        public boolean isSelected()
        {
            return isSelected;
        }

        /**
         * @param isSelected
         *            the isSelected to set
         */
        public void setSelected(boolean isSelected)
        {
            this.isSelected = isSelected;
        }
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        finish();
    }

    /**
     * LanguageAdapter : ArrayAdapter class which prepares view for list of
     * languages.
     * 
     * @author MindBowser
     */
    class LanguageAdapter extends ArrayAdapter<Language>
    {
        LanguageAdapter(Context context, ArrayList<Language> list)
        {
            super(context, R.layout.row_language, R.id.row_language_tv, list);
        }

        public View getView(int position, View convertView, ViewGroup parent)
        {
            View row = super.getView(position, convertView, parent);
            LanguageViewHolder holder = (LanguageViewHolder) row.getTag();
            if (holder == null)
            {
                holder = new LanguageViewHolder(row);
                row.setTag(holder);
            }

            final Language language = getLanguage(position);

            holder.tvLanguage.setText(language.getName());
            holder.btnSelect.setBackgroundResource(language.isSelected() ? R.drawable.ic_checked_radio : R.drawable.ic_unchecked_radio);
            holder.btnSelect.setOnClickListener(new OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    for (Language languageS : listLanguages)
                    {
                        if (language.getName().equals(languageS.getName()))
                        {
                            languageS.setSelected(true);
                            Log.i(TAG, "Selected language : " + language.getName());
                            selectedLanguage = language.getName();
                            selectedLanguageCode = language.getLanguageCode();
                        } else
                            languageS.setSelected(false);
                    }
                    notifyDataSetChanged();
                }
            });

            return row;
        }
    }

    class LanguageViewHolder
    {
        public TextView tvLanguage;

        public Button btnSelect;

        public LanguageViewHolder(View base)
        {
            this.tvLanguage = (TextView) base.findViewById(R.id.row_language_tv);
            this.btnSelect = (Button) base.findViewById(R.id.row_language_btn);
        }

    }

    /**
     * @param position
     * @return Language object from specified position
     */
    private Language getLanguage(int position)
    {
        return (Language) languageAdapter.getItem(position);
    }

    /**
     * Prepare list of <b>Language</b> from string array.
     */
    void prepareLanguageList()
    {
        listLanguages = new ArrayList<Language>();
        localeDevice = getResources().getConfiguration().locale;
        Log.i(TAG, "displayLanguage : " + Locale.getDefault().getDisplayLanguage());
        Log.i(TAG, "Language : " + Locale.getDefault().getLanguage());
        Log.i(TAG, "localeDevice : " + localeDevice);
        String[] arrayLanguages = getResources().getStringArray(R.array.languages);
        int noOfLanguages = arrayLanguages.length;

        for (int i = 0; i < noOfLanguages; i++)
        {
            String strLang = arrayLanguages[i];
            String[] splitLang = strLang.split(":");
            Language language = new Language();
            language.setName(splitLang[0]);
            language.setLanguageCode(splitLang[1]);

            Log.i(TAG, "selectedLanguageCode : " + selectedLanguageCode);
            Log.i(TAG, "selectedLanguage : " + selectedLanguage);
            Log.i(TAG, "strLang : " + strLang);

            // On first time arrival of user we will set the device's default
            // language.
            // Otherwise set the language selected by user.
            if ((isFirstTime && localeDevice.toString().contains(splitLang[1])) || selectedLanguageCode.equals(splitLang[1]))
            {
                language.setSelected(true);
                selectedLanguage = language.getName();
                selectedLanguageCode = language.getLanguageCode();
            }
            // else if (selectedLanguageCode.equals(splitLang[1]))
            // {
            // language.setSelected(true);
            // selectedLanguage = language.getName();
            // selectedLanguageCode = language.getLanguageCode();
            // }

            listLanguages.add(language);
        }

        for (Language language : listLanguages)
        {
            Log.i(TAG, "" + language.getName() + " : " + language.isSelected());
        }

        Log.i(TAG, "selectedLanguageCode : " + selectedLanguageCode);
        Log.i(TAG, "selectedLanguage : " + selectedLanguage);

        Util.setAppLanguage(selectedLanguage, this);

        languageAdapter = new LanguageAdapter(this, listLanguages);
        lvLanguage.setAdapter(languageAdapter);
        languageAdapter.notifyDataSetChanged();
    }
}

public static void setAppLanguage(String language, Context context) {
        Resources resources = context.getResources();
        DisplayMetrics displayMetrics = resources.getDisplayMetrics();
        Configuration configuration = resources.getConfiguration();
        Log.i(TAG, "language: " + language);

        if (language.equals("Chinese")) {
            configuration.locale = Locale.CHINESE;
        } else if (language.equals("Japanese")) {
            configuration.locale = Locale.JAPANESE;
        } else if (language.equals("Malay")) {
            configuration.locale = new Locale("ms");
        } else if (language.equals("Vietnam")) {
            configuration.locale = new Locale("vi");
        } else if (language.equals("Danish")) {
            configuration.locale = new Locale("da");
        } else if (language.equals("French")) {
            configuration.locale = new Locale("fr");
        } else if (language.equals("Hungarian")) {
            configuration.locale = new Locale("hu");
        } else if (language.equals("Swedish")) {
            configuration.locale = new Locale("sv");
        } else if (language.equals("Korean")) {
            configuration.locale = new Locale("ko");
        } else if (language.equals("Russian")) {
            configuration.locale = new Locale("ru");
        } else if (language.equals("Spanish")) {
            configuration.locale = new Locale("es");
        } else {
            configuration.locale = Locale.ENGLISH;
        }
        resources.updateConfiguration(configuration, displayMetrics);
    }

Upvotes: 2

You need values-xx folders for each language and then strings.xml file in each of these folders. In eclipse, all these values-xx folders are shown separately in /res folder. In android studio, you click on values and it will show you all the values-xx folders. step by step tutorial: https://www.youtube.com/watch?v=og3BqpZMw7Q

Upvotes: 1

user5283155
user5283155

Reputation:

Take a look at this link. In short, you should provide multiple strings.xml for each language you will support in your app.

Upvotes: 2

Related Questions