本文内容
- 字符串本地化原理
- 环境
- 创建项目
- 测试其他语言
- Android 本地化语言 ISO 编码
- 参考资料
使用 Android 的人越来越多,每天都在增加。因此,当你想把你的应用成功地全球化时,通常的方法就是使应用程序本地化。
虽然本地化,你可以考虑使用依靠区域和国家适当的文字,音频,货币,数字和图形。但是,本文只涉及本地化的字符串,例如支持多国语言(multiple languages)。Localizing with Resources 说明了,当本地化应用程序时,应该考虑的其他事情。
本文我们创建一个支持 French、Deutsch(German)、Hindi 和 Japanese 语言的 app。
下载 Demo
字符串本地化原理
默认情况下,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 文件应包含应用程序使用的所有字符串的值,这是强制性的。否则,app 会强制关闭错误而崩溃。
可以按如下方式:
当你想要 app 支持多语言时,最好采用下面方式定义字符串。总是在 strings.xml 声明字符串。
<string name="note_email">Enter your email address</string>
.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; }
当在布局 XML 文件中引用时,使用 @strings 注解:
<TextView ... android:text="@string/note_email" />
.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; }
在后台,可以使用 R.string:
emailNote.setText(R.string.note_email);
.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; }
但不能:
Never hard code the string in xml or in java code which make the translation difficult.
<TextView ... android:text="Enter your email address" />
.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; }
以及
emailNote.setText("Enter your email address");
.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; }
下面创建一个项目,演示让android 支持多语言。
环境
- Windows 2008 R2 64 位
- Eclipse ADT V22.6.2,Android 4.4.2(API 19)
- SAMSUNG GT-8618,Android OS 4.1.2
创建项目
图 1 项目结构
- 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>
.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; }
- 2. 在 drawable 文件下创建三个名为 bg_button_rounded.xml、bg_form_rounded.xml、bg_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>
.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; }
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>
.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; }
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>
.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; }
- 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>
.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; }
- 4. 在 res 文件夹下创建四个名为 values-de、values-fr、values-hi、values-ja 的文件夹,以及在每个文件夹中创建相应的 strings.xml 文件。创建完成后,大概如下所示:
现在,把字符串翻译成相关的语言,并放到相应的 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>
.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; }
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>
.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; }
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>
.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; }
- 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>
.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; }
- 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;
}
}
.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; }
图 2 Android 多语言——英文
测试其他语言
按下面步骤测试一下app对其他语言的支持:
1. 在设备上进入“设置 ⇒ 语言和输入”
2. 选择你设备支持的语言。
图 3 SAMSUNG GT-8618 语言和输入
图 4 Android 多语言——韩语
Android 本地化语言 ISO 编码
下表给出 Android 支持的 ISO 语言编码。
表 1 Android 支持的 ISO 语言编码
Language |
Locale |
values/strings.xml |
German | de | values-de/strings.xml |
Chinese | zh | values-zh/strings.xml |
Czech | cs | values-cs/strings.xml |
Dutch | nl | values-nl/strings.xml |
French | fr | values-fr/strings.xml |
Italian | it | values-it/strings.xml |
Japanese | ja | values-ja/strings.xml |
Korean | ko | values-ko/strings.xml |
Polish | pl | values-pl/strings.xml |
Russian | ru | values-ru/strings.xml |
Spanish | es | values-es/strings.xml |
Arabic | ar | values-ar/strings.xml |
Bulgarian | bg | values-bg/strings.xml |
Catalan | ca | values-ca/strings.xml |
Croatian | hr | values-hr/strings.xml |
Danish | da | values-da/strings.xml |
Finnish | fi | values-fi/strings.xml |
Greek | el | values-el/strings.xml |
Hebrew | iw | values-iw/strings.xml |
Hindi | hi | values-hi/strings.xml |
Hungarian | hu | values-hu/strings.xml |
Indonesian | in | values-in/strings.xml |
Latvian | lv | values-lv/strings.xml |
Lithuanian | lt | values-lt/strings.xml |
Norwegian | nb | values-nb/strings.xml |
Portuguese | pt | values-pt/strings.xml |
Romanian | ro | values-ro/strings.xml |
Serbian | sr | values-sr/strings.xml |
Slovak | sk | values-sk/strings.xml |
Slovenian | sl | values-sl/strings.xml |
Swedish | sv | values-sv/strings.xml |
Tagalog | tl | values-tl/strings.xml |
Thai | th | values-th/strings.xml |
Turkish | tr | values-tr/strings.xml |
Ukrainian | uk | values-uk/strings.xml |
Vietnamese | vi | values-vi/strings.xml |