在 Android 开发中,切换应用语言(即本地化/国际化) 有多种实现方式。以下是几种主流、可靠的方法,适用于不同 Android 版本和项目需求:
✅ 一、系统级语言切换(推荐用于 Android 7.0+)
从 Android 7.0(API 24) 开始,Google 推荐使用 Configuration + Context.createConfigurationContext() 的方式,并结合 AppCompatDelegate 实现应用内语言切换。
步骤:
- 在
Application或BaseActivity中设置语言 - 重启 Activity 或重新创建 Context
示例(Kotlin):
kotlin
// 工具类:LanguageManager.kt
object LanguageManager {
fun setAppLanguage(context: Context, languageCode: String) {
val locale = Locale(languageCode)
Locale.setDefault(locale)
val config = Configuration()
config.setLocale(locale)
// 保存到 SharedPreferences(可选)
context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE)
.edit().putString("language", languageCode).apply()
// 更新上下文
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
context.createConfigurationContext(config)
} else {
context.resources.updateConfiguration(config, context.resources.displayMetrics)
}
}
fun getSavedLanguage(context: Context): String? {
return context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE)
.getString("language", null)
}
}
在 Application 中初始化:
kotlin
class MyApplication : Application() {
override fun attachBaseContext(base: Context) {
super.attachBaseContext(updateBaseContextLocale(base))
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
updateBaseContextLocale(this)
}
private fun updateBaseContextLocale(context: Context): Context {
val language = LanguageManager.getSavedLanguage(context) ?: "en"
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
updateResourcesLocale(context, Locale(language))
} else {
updateResourcesLocaleLegacy(context, Locale(language))
}
}
@TargetApi(Build.VERSION_CODES.N)
private fun updateResourcesLocale(context: Context, locale: Locale): Context {
val configuration = context.resources.configuration
configuration.setLocale(locale)
return context.createConfigurationContext(configuration)
}
private fun updateResourcesLocaleLegacy(context: Context, locale: Locale): Context {
val resources = context.resources
val configuration = resources.configuration
configuration.locale = locale
resources.updateConfiguration(configuration, resources.displayMetrics)
return context
}
}
✅ 优点:兼容新旧版本,支持后台切换后生效
❗ 注意:切换后需重启当前 Activity (如
recreate())才能立即看到效果
✅ 二、使用 AppCompatDelegate.setApplicationLocales()(Android 13+ 官方推荐)
从 Android 13(API 33) 起,Google 提供了更标准的 API:AppCompatDelegate.setApplicationLocales()
示例(Kotlin):
kotlin
val localeList = LocaleListCompat.forLanguageTags("zh-Hans") // 简体中文
AppCompatDelegate.setApplicationLocales(localeList)
- 无需手动处理
Configuration - 自动持久化,下次启动自动生效
- 仅适用于 targetSdkVersion ≥ 33 且使用 AppCompat 1.6.0+
📌 Gradle 依赖:
gradle
implementation 'androidx.appcompat:appcompat:1.6.1'
✅ 最简单、最官方的方式(未来趋势)
⚠️ 低版本 Android 不支持,需配合降级方案
✅ 三、强制重启整个应用(不推荐,但简单)
适用于快速原型或简单场景:
kotlin
fun restartApp(context: Context) {
val intent = context.packageManager.getLaunchIntentForPackage(context.packageName)
intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
context.startActivity(intent)
(context as? Activity)?.finishAffinity()
Runtime.getRuntime().exit(0) // 强制退出(谨慎使用)
}
❌ 缺点:用户体验差,可能丢失状态
✅ 四、动态切换字符串资源(不改系统语言)
如果你只是想临时显示另一种语言的文案(比如多语言客服界面),可以:
- 手动加载对应
strings.xml的资源(通过Context.createConfigurationContext) - 或将多语言文本存入数据库/JSON,不依赖 Android 资源系统
适用于轻量级多语言,但维护成本高
🔧 补充:如何组织多语言资源?
在 res/ 目录下创建对应语言的资源文件夹:
res/
├── values/ → 默认(如英文)
│ └── strings.xml
├── values-zh/ → 简体中文
│ └── strings.xml
├── values-zh-rTW/ → 繁体中文(台湾)
├── values-es/ → 西班牙语
└── ...
✅ 最佳实践建议
| 场景 | 推荐方案 |
|---|---|
| 目标 Android 13+ | AppCompatDelegate.setApplicationLocales() |
| 兼容 Android 5.0 ~ 12 | 自定义 Application + attachBaseContext + recreate() |
| 需要即时生效 | 切换后调用 activity.recreate() |
| 避免重启 | 使用 ContextWrapper 动态创建带语言的 Context(复杂) |
📱 用户体验提示
- 切换语言后,应刷新当前界面 (
recreate()或finish() + startActivity()) - 提供语言选择列表(如
"en","zh","es"对应用户可读名称) - 默认语言建议跟随系统:
Locale.getDefault().language
提供一个示例
我们将创建以下文件:
- MainActivity.java - 主界面,包含语言选择的按钮。
- LanguageHelper.java - 工具类,用于保存和设置语言偏好。
- MyApplication.java - 应用程序类,用于初始化语言设置。
代码示例
1. MainActivity.java
java
package com.example.languagechanger;
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(LanguageHelper.onAttach(newBase));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnChangeToEnglish = findViewById(R.id.btn_change_to_english);
Button btnChangeToChinese = findViewById(R.id.btn_change_to_chinese);
btnChangeToEnglish.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LanguageHelper.setLocale(MainActivity.this, "en");
restartActivity();
}
});
btnChangeToChinese.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LanguageHelper.setLocale(MainActivity.this, "zh");
restartActivity();
}
});
}
private void restartActivity() {
Intent intent = getIntent();
finish();
startActivity(intent);
}
}
2. LanguageHelper.java
java
package com.example.languagechanger;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import java.util.Locale;
public class LanguageHelper {
private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
public static Context onAttach(Context context) {
String lang = getPersistedData(context, Locale.getDefault().getLanguage());
return setLocale(context, lang);
}
public static String getLanguage(Context context) {
return getPersistedData(context, Locale.getDefault().getLanguage());
}
public static Context setLocale(Context context, String language) {
persist(context, language);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language);
}
return updateResourcesLegacy(context, language);
}
private static String getPersistedData(Context context, String defaultLanguage) {
SharedPreferences preferences = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE);
return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
}
private static void persist(Context context, String language) {
SharedPreferences.Editor editor = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE).edit();
editor.putString(SELECTED_LANGUAGE, language);
editor.apply();
}
@TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);
return context.createConfigurationContext(configuration);
}
@SuppressWarnings("deprecation")
private static Context updateResourcesLegacy(Context context, String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLayoutDirection(locale);
}
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}
}
3. MyApplication.java
java
package com.example.languagechanger;
import android.app.Application;
public class MyApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LanguageHelper.onAttach(base));
}
}
4. activity_main.xml
确保你的布局文件中有两个按钮用于切换语言:
xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_change_to_english"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Change to English" />
<Button
android:id="@+id/btn_change_to_chinese"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="切换到中文" />
</LinearLayout>
5. 配置资源文件
请确保你已经为不同的语言准备了相应的 strings.xml 文件,例如 values/strings.xml(默认英语)和 values-zh/strings.xml(简体中文)。
注意事项
- 确保你的
AndroidManifest.xml中声明了MyApplication类:
xml
<application
android:name=".MyApplication"
... >
...
</application>
- 根据需要调整语言代码(如
"en"对应英语,"zh"对应简体中文)。如果需要支持更多语言,请相应地添加更多的语言资源文件夹和字符串资源。