<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">L10NTest</string> <string name="action_settings">Settings</string> <string name="hello_world">Hello world!</string> <string name="I_love_you">I love you.</string> </resources>
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">国际化测试</string> <string name="action_settings">设置</string> <string name="hello_world">世界,你好!</string> <string name="I_love_you">我爱你.</string> </resources>
<LinearLayout 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:gravity="center" android:orientation="vertical" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/country" tools:ignore="ContentDescription" /> <!-- tools:ignore="ContentDescription",屏蔽掉对View设置备注说明的提示 --> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" android:textSize="20sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/I_love_you" android:textSize="20sp" /> </LinearLayout>
在android ADT 16.0以后的控件中,没有文本描述的view如果不加android:contentDescription="@string/……"的话就会有黄 色的下划线,提示“[Accessibility] Missing contentDescription attribute on image”。加“ tools:ignore="ContentDescription"“便是屏蔽掉该提示。这句代码不加也没什么影响,在界面上不会有其他效果,当然也可以写一些字符串数据做提示,方便他人阅读。或者直接写成:
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:contentDescription="@null" android:src="@drawable/country" />
import java.util.Locale; public class Test { public static void main(String[] args) { //调用Locale类的getAvailableLocales方法获取,该方法返回一个数组,其中包含JAVA支持的语言和国家 Locale[] localeList = Locale.getAvailableLocales(); //依次获取所支持的国家和语言 for (int i = 0; i < localeList.length; i++) { System.out.println(localeList[i].getDisplayCountry() + "=" + localeList[i].getCountry() + "" + localeList[i].getDisplayLanguage() + "=" + localeList[i].getLanguage()); } } }
输出结果如下(有些国家可能会使用多种语言):
马来西亚=MY马来文=ms 卡塔尔=QA阿拉伯文=ar 冰岛=IS冰岛文=is 芬兰=FI芬兰文=fi =波兰文=pl 马耳他=MT英文=en 瑞士=CH意大利文=it 比利时=BE荷兰文=nl 沙特阿拉伯=SA阿拉伯文=ar 伊拉克=IQ阿拉伯文=ar 波多黎哥=PR西班牙文=es 智利=CL西班牙文=es =芬兰文=fi 奥地利=AT德文=de =丹麦文=da 英国=GB英文=en 巴拿马=PA西班牙文=es =塞尔维亚文=sr 也门=YE阿拉伯文=ar 马其顿王国=MK马其顿文=mk =马其顿文=mk 加拿大=CA英文=en 越南=VN越南文=vi 荷兰=NL荷兰文=nl 美国=US西班牙文=es 中国=CN中文=zh 洪都拉斯=HN西班牙文=es 美国=US英文=en =法文=fr =泰文=th =阿拉伯文=ar 摩洛哥=MA阿拉伯文=ar =拉托维亚文(列托)=lv =德文=de 印度尼西亚=ID印度尼西亚文=in =克罗地亚文=hr 南非=ZA英文=en 韩国=KR朝鲜文=ko 突尼斯=TN阿拉伯文=ar =印度尼西亚文=in =日文=ja 塞尔维亚=RS塞尔维亚文=sr 白俄罗斯=BY白俄罗斯文=be 台湾地区=TW中文=zh 苏丹=SD阿拉伯文=ar =葡萄牙文=pt =冰岛文=is 日本=JP日文=ja 玻利维亚=BO西班牙文=es 阿尔及利亚=DZ阿拉伯文=ar =马来文=ms 阿根廷=AR西班牙文=es 阿拉伯联合酋长国=AE阿拉伯文=ar 加拿大=CA法文=fr =斯洛文尼亚文=sl =西班牙文=es 立陶宛=LT立陶宛文=lt 黑山=ME塞尔维亚文=sr 叙利亚=SY阿拉伯文=ar 俄罗斯=RU俄文=ru 比利时=BE法文=fr 西班牙=ES西班牙文=es =保加利亚文=bg 以色列=IL希伯来文=iw =瑞典文=sv =英文=en =希伯来文=iw 丹麦=DK丹麦文=da 哥斯达黎加=CR西班牙文=es 香港=HK中文=zh =中文=zh 西班牙=ES加泰罗尼亚文=ca 泰国=TH泰文=th 乌克兰=UA乌克兰文=uk 多米尼加共和国=DO西班牙文=es 委内瑞拉=VE西班牙文=es 波兰=PL波兰文=pl 利比亚=LY阿拉伯文=ar 约旦=JO阿拉伯文=ar =意大利文=it =乌克兰文=uk 匈牙利=HU匈牙利文=hu =爱尔兰文=ga 危地马拉=GT西班牙文=es 巴拉圭=PY西班牙文=es 保加利亚=BG保加利亚文=bg 克罗地亚=HR克罗地亚文=hr 波斯尼亚和黑山共和国=BA塞尔维亚文=sr 罗马尼亚=RO罗马尼亚文=ro 卢森堡=LU法文=fr =挪威文=no =立陶宛文=lt 新加坡=SG英文=en 厄瓜多尔=EC西班牙文=es 波斯尼亚和黑山共和国=BA塞尔维亚文=sr 尼加拉瓜=NI西班牙文=es =斯洛伐克文=sk =俄文=ru =马耳他文=mt 萨尔瓦多=SV西班牙文=es =荷兰文=nl 印度=IN印地文=hi =爱沙尼亚文=et 希腊=GR希腊文=el 斯洛文尼亚=SI斯洛文尼亚文=sl 意大利=IT意大利文=it 日本=JP日文=ja 卢森堡=LU德文=de 瑞士=CH法文=fr 马耳他=MT马耳他文=mt 巴林=BH阿拉伯文=ar =阿尔巴尼亚文=sq =越南文=vi 黑山=ME塞尔维亚文=sr 巴西=BR葡萄牙文=pt 挪威=NO挪威文=no =希腊文=el 瑞士=CH德文=de 新加坡=SG中文=zh 科威特=KW阿拉伯文=ar 埃及=EG阿拉伯文=ar 爱尔兰=IE爱尔兰文=ga 秘鲁=PE西班牙文=es 捷克共和国=CZ捷克文=cs 土耳其=TR土耳其文=tr =捷克文=cs 乌拉圭=UY西班牙文=es 爱尔兰=IE英文=en 印度=IN英文=en 阿曼=OM阿拉伯文=ar 塞尔维亚及黑山=CS塞尔维亚文=sr =加泰罗尼亚文=ca =白俄罗斯文=be =塞尔维亚文=sr =朝鲜文=ko 阿尔巴尼亚=AL阿尔巴尼亚文=sq 葡萄牙=PT葡萄牙文=pt 拉脱维亚=LV拉托维亚文(列托)=lv 塞尔维亚=RS塞尔维亚文=sr 斯洛伐克=SK斯洛伐克文=sk 墨西哥=MX西班牙文=es 澳大利亚=AU英文=en 挪威=NO挪威文=no 新西兰=NZ英文=en 瑞典=SE瑞典文=sv =罗马尼亚文=ro 黎巴嫩=LB阿拉伯文=ar 德国=DE德文=de 泰国=TH泰文=th =土耳其文=tr 哥伦比亚=CO西班牙文=es 菲律宾=PH英文=en 爱沙尼亚=EE爱沙尼亚文=et 塞浦路斯=CY希腊文=el =匈牙利文=hu 法国=FR法文=fr
package com.example.l10ntest; public class ConstantBase { public String PUT_NAME; public String SAY_LOVE; public String NEXT; public String Second_Page; }
中英文的字符串类分别命名如下,中文:
package com.example.l10ntest; public class ConstantCH extends ConstantBase { public ConstantCH() { //此处定义需要的中文字符串 PUT_NAME = "请输入你的名字。"; SAY_LOVE = "我爱你"; NEXT = "下一页"; Second_Page = "第二页"; } }
英文:
package com.example.l10ntest; public class ConstantEN extends ConstantBase { public ConstantEN() { // 此处定义需要的英文字符串 PUT_NAME = "Please put your name."; SAY_LOVE = "I love you"; NEXT = "next"; Second_Page = "The second page"; } }
我在新创建的Constant类中写了本地语言的判断方法,该类如下:
package com.example.l10ntest; import java.util.Locale; public class Constant { public static ConstantBase string = produceConstant(); public static ConstantBase produceConstant() { if (isLocalLanguageZH()) { string = new ConstantCH(); } else { string = new ConstantEN(); } return string; } //判断本地语言是否是中文 public static boolean isLocalLanguageZH() { if (Locale.getDefault().getLanguage().contains("zh") && Locale.getDefault().getCountry().contains("CN")) { return true; } return false; } }
主类的XML文件做一下修改(暂时将ImageView屏蔽掉,后面增加了一个Button),如下:
<LinearLayout 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:gravity="center" android:orientation="vertical" > <!-- <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:contentDescription="@null" android:src="@drawable/country" /> --> <!-- tools:ignore="ContentDescription",屏蔽掉对View设置备注说明的提示 --> <TextView android:id="@+id/putName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@null" android:textSize="20sp" /> <TextView android:id="@+id/iloveyou" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@null" android:textSize="20sp" /> <Button android:id="@+id/next" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
在主类中,写如下代码:
((TextView) findViewById(R.id.putName)) .setText(Constant.string.PUT_NAME); ((TextView) findViewById(R.id.iloveyou)) .setText(Constant.string.SAY_LOVE);
package com.example.l10ntest; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((TextView) findViewById(R.id.putName)) .setText(Constant.string.PUT_NAME); ((TextView) findViewById(R.id.iloveyou)) .setText(Constant.string.SAY_LOVE); Button btn = (Button) findViewById(R.id.next); btn.setText(Constant.string.NEXT); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(MainActivity.this,SecondActivity.class)); } }); } }
第二个Activity(SecondActivity)我没有写XML布局,代码如下:
package com.example.l10ntest; import android.os.Bundle; import android.view.Gravity; import android.widget.TextView; public class SecondActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView textView = new TextView(this); textView.setGravity(Gravity.CENTER); textView.setText(Constant.string.Second_Page); textView.setTextSize(30); setContentView(textView); } }
事实上一个应用一般不会只有一个Activity的,我将两个Activity都继承了BaseActivity,在BaseActivity中对这两个Activity做统一管理,BaseActivity如下:
package com.example.l10ntest; import android.app.Activity; import android.os.Bundle; public class BaseActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Utils.addToList(this); } }
只调用了Utils类里的一个方法,在Activity创建后,将它添加到List里面。Utils类代码如下:
package com.example.l10ntest; import java.util.ArrayList; import java.util.Iterator; import android.app.Activity; import android.util.Log; public class Utils { private static String TAG = "Utils"; // 创建存放Activity的集合 private static ArrayList<Activity> activityList = new ArrayList<Activity>(); public static void addToList(Activity activity) { Log.i(TAG, "activity name:" + activity.getClass().getName()); activityList.add(activity); } public static void stopApp() { Iterator<Activity> itr = activityList.iterator(); Activity a = null; while (itr.hasNext()) { a = itr.next(); a.finish(); } Log.i(TAG, "stopApp end."); System.exit(0); } }
package com.example.l10ntest; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class AppExitReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent == null || intent.getAction() == null) return; if (intent.getAction().equals(Intent.ACTION_LOCALE_CHANGED)) { Utils.stopApp(); } } }
AndroidManifest.xml文件如下,配置了一个广播接收。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.l10ntest" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.l10ntest.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.example.l10ntest.SecondActivity" android:label="@string/app_name" > </activity> <receiver android:name="com.example.l10ntest.AppExitReceiver" > <intent-filter> <action android:name="android.intent.action.LOCALE_CHANGED" /> </intent-filter> </receiver> </application> </manifest>
作者:“皓轩”