首页 > 代码库 > Android Building Multi-Language Supported App

Android Building Multi-Language Supported App

使用 Android 的人越来越多,每天都在增加。因此,当你想把你的应用成功地全球化时,通常的方法就是使应用程序本地化。

虽然本地化,你可以考虑使用依靠区域和国家适当的文字,音频,货币,数字和图形。但是,本文只涉及本地化的字符串,例如支持多国语言(multiple languages)。Localizing with Resources 说明了,当本地化应用程序时,应该考虑的其他事情。

本文我们创建一个支持 French、Deutsch(German)、Hindi 和 Japanese 语言的 app。

字符串本地化的原理


默认情况下,Android 把英语作为主要语言,并从 res?values?strings.xml 中加载字符串资源。当你想添加支持其他语言时,你需要创建相应的文件夹(通过追加一个连字符和 ISO 语言代码)。例如,如果你想添加支持法语,你应该创建一个名为“values-fr”的文件夹,并保持 strings.xml 中的所有字符串都翻译成法文。

简单来说,本地化的原理如下:

  • 1. 当用户通过“设置 ? 语言和输入”改变设备语言时,android 操作系统自己会检查应用程序中相应的语言资源。假设用户选择了 French——法语。
  • 2. 如果 app 支持选择的语言,android 会在项目中的“values-(ISO 语言编码)”文件夹内查找字符串资源。对于法语,会从 values-fr/string.xml 中加载。
  • 3. 如果支持的语言 strings.xml 字符串有缺失,android 总是从默认的 values/strings.xml 中加载缺失的字符串。

因此,默认的 stings.xml 文件应包含应用程序使用的所有字符串的值,这是强制性的。其他明智的应用程序将崩溃,并强制关闭的错误。Other wise the app will crash with Force Close error.

可以按如下方式:

当你想要 app 支持多语言时,最好采用下面方式定义字符串。总是在 strings.xml  声明字符串。

<string name="note_email">Enter your email address</string>
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>

当在布局 XML 文件中引用时,使用 @strings 注解:

<TextView ...   android:text="@string/note_email"  />
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>

在后台,可以使用 R.string

emailNote.setText(R.string.note_email);
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>

但不能:

Never hard code the string in xml or in java code which make the translation difficult.

<TextView ...   android:text="Enter your email address"  />
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>

以及

emailNote.setText("Enter your email address");  
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>

下面创建一个项目,演示让android 支持多语言。

创建新项目


  • 1. 在 values 文件夹下创建  colors.xml

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="white">#ffffff</color>
    <color name="bg_gradient_start">#b21331</color>
    <color name="bg_gradient_end">#820d2a</color>
    <color name="bg_button_login">#380813</color>
</resources>
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>
  • 2. 在 drawable 文件下创建三个名为 bg_button_rounded.xmlbg_form_rounded.xmlbg_gradient.xml 文件。这些文件与支持多语言无关,只是给出了漂亮的渐变背景和圆角按钮,输入框。

bg_button_rounded.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
  
    <!-- view background color -->
    <solid
        android:color="@color/bg_button_login" >
    </solid>
  
    <!-- If you want to add some padding -->
    <padding
        android:left="5dp"
        android:top="5dp"
        android:right="5dp"
        android:bottom="5dp"    >
    </padding>
  
    <!-- Here is the corner radius -->
    <corners
        android:radius="6dp"   >
    </corners>
  
</shape>
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>

bg_form_rounded.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
  
    <!-- view background color -->
    <solid
        android:color="@color/white" >
    </solid>
  
    <!-- If you want to add some padding -->
    <padding
        android:left="5dp"
        android:top="5dp"
        android:right="5dp"
        android:bottom="5dp"    >
    </padding>
  
    <!-- Here is the corner radius -->
    <corners
        android:radius="6dp"   >
    </corners>
  
</shape>
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>

bg_gradient.xml

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >
 
    <gradient
        android:gradientRadius="750"
        android:endColor="@color/bg_gradient_end"
        android:startColor="@color/bg_gradient_start"
        android:type="radial" />
</shape>
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>
  • 3. 在 values/strings.xml 添加如下字符串。这是默认英文的字符串。

strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
 
    <string name="app_name">Multi Language App</string>
    <string name="action_settings">Settings</string>
     
    <string name="welcome">Welcome!</string>
    <string name="email">Email Address</string>
    <string name="password">Password</string>
    <string name="login">Login</string>
    <string name="signup">Don\‘t have account? Sign Up</string>
 
</resources>
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>
  • 4. 在 res 文件夹下创建四个名为 values-devalues-frvalues-hivalues-ja 的文件夹,以及在每个文件夹中创建相应的 strings.xml 文件。创建完成后,大概如下所示:

1

现在,把字符串翻译成相关的语言,并放到相应的 strings.xml 文件中。

另外,针对我的真机,支持三种语言:中文,英文和韩语,因此,再增加一个韩语。翻译是用 google 翻译的,对不对我也不知道。

values-de/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
     
    <string name="welcome">Willkommen!</string>
    <string name="email">Email Addresse</string>
    <string name="password">passowrd</string>
    <string name="login">Login</string>
    <string name="signup">müssen nicht angemeldet? Anmeldung</string>
 
</resources>

values-fr/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
     
    <string name="welcome">accueil</string>
    <string name="email">adresse e-mail</string>
    <string name="password">mot de passe</string>
    <string name="login">connexion</string>
    <string name="signup">Ne pas avoir un compte? signer</string>
 
</resources>
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>

values-hi/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
     
    <string name="welcome">???????</string>
    <string name="email">???? ???</string>
    <string name="password">???????</string>
    <string name="login">?????</string>
    <string name="signup">???? ???? ??? ???? ?? ????</string>
 
</resources>
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>

values-ja/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
     
    <string name="welcome">歓迎</string>
    <string name="email">電子メールアドレス</string>
    <string name="password">パスワード</string>
    <string name="login">ログイン</string>
    <string name="signup">アカウントをお持ちでない場合は?サインアップ</string>
 
</resources>

values-ko/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    
    <string name="welcome">??</string>
    <string name="email">???</string>
    <string name="password">??</string>
    <string name="login">???</string>
    <string name="signup">??</string>
 
</resources>
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>
  • 5. 创建布局 activity_main.xml,包含一个 title 和登录框。

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bg_gradient"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >
 
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:gravity="center"
        android:orientation="vertical" >
 
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="40dp"
            android:text="@string/welcome"
            android:textColor="@color/white"
            android:textSize="45dp"
            android:textStyle="bold" />
 
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_form_rounded"
            android:orientation="vertical" >
 
            <EditText
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dp"
                android:background="@null"
                android:hint="@string/email"
                android:padding="5dp"
                android:singleLine="true" />
 
            <EditText
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:background="@null"
                android:hint="@string/password"
                android:inputType="textPassword"
                android:padding="5dp" />
        </LinearLayout>
 
        <Button
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="25dp"
            android:background="@drawable/bg_button_rounded"
            android:text="@string/login"
            android:textColor="@color/white" />
    </LinearLayout>
 
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="25dp"
        android:gravity="center_horizontal"
        android:text="@string/signup"
        android:textColor="@color/white" />
 
</RelativeLayout>
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>
  • 6. 创建 MainActivity.java。

MainActivity.java

public class MainActivity extends Activity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        getActionBar().hide();
    }
 
    @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;
    }
 
}
<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>

1

图 1 Android 多语言——英文

测试其他语言


In order to see the app in other languages follow below steps or check the above demo video.

1. 在设备上进入“设置 ? 语言和输入”

2. 选择你设备支持的语言。

 

Android 本地化语言 ISO 编码


Below table give you ISO languages codes for all the languages that android supports.

Language   

Locale   

values/strings.xml

German        devalues-de/strings.xml
Chinese     zh   values-zh/strings.xml
Czech        csvalues-cs/strings.xml
Dutch        nlvalues-nl/strings.xml
French        frvalues-fr/strings.xml
Italian        itvalues-it/strings.xml
Japanese        javalues-ja/strings.xml
Korean        kovalues-ko/strings.xml
Polish       pl values-pl/strings.xml
Russian        ruvalues-ru/strings.xml
Spanish        esvalues-es/strings.xml
Arabic        arvalues-ar/strings.xml
Bulgarian        bgvalues-bg/strings.xml
Catalan       ca values-ca/strings.xml
Croatian        hrvalues-hr/strings.xml
Danish        davalues-da/strings.xml
Finnish        fivalues-fi/strings.xml
Greek        elvalues-el/strings.xml
Hebrew        iwvalues-iw/strings.xml
Hindi        hivalues-hi/strings.xml
Hungarian        huvalues-hu/strings.xml
Indonesian       invalues-in/strings.xml
Latvian        lvvalues-lv/strings.xml
Lithuanian       lt values-lt/strings.xml
Norwegian        nbvalues-nb/strings.xml
Portuguese        ptvalues-pt/strings.xml
Romanian        rovalues-ro/strings.xml
Serbian        srvalues-sr/strings.xml
Slovak        skvalues-sk/strings.xml
Slovenian        slvalues-sl/strings.xml
Swedish        svvalues-sv/strings.xml
Tagalog        tlvalues-tl/strings.xml
Thai        thvalues-th/strings.xml
Turkish        trvalues-tr/strings.xml
Ukrainian        ukvalues-uk/strings.xml
Vietnamese        vivalues-vi/strings.xml

Source: http://bit.ly/1qYfHDL

Translation Services


Right now I used Google Translate service to translate the strings into other languages. But if you want more accurate and meaningful translation always go for professional services like Professional translations through Google Play

Finally Localization Checklist gives you list of things to be verified before the app goes live when localization considered.









 

 

 

<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>

Android Building Multi-Language Supported App