在仍然使用Android资源的情况下,是否可能通过编程方式更改应用程序的语言?
如果不行,是否可能以特定语言请求资源?
我希望允许用户从应用程序中更改应用程序的语言。
在仍然使用Android资源的情况下,是否可能通过编程方式更改应用程序的语言?
如果不行,是否可能以特定语言请求资源?
我希望允许用户从应用程序中更改应用程序的语言。
是可以做到的。您可以设置区域设置。然而,我不建议这样做。我们早期尝试过,基本上这是在与系统作斗争。
我们有更改语言的相同要求,但决定接受UI应该与手机UI相同的事实。通过设置区域设置可以工作,但存在太多错误。并且从我的经验来看,您必须每次进入活动(每个活动)时设置它。如果您仍需要此代码,则以下是代码(再次强调,我不建议这样做)
Resources res = context.getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.setLocale(new Locale(language_code.toLowerCase())); // API 17+ only.
// Use conf.locale = new Locale(...) if targeting lower versions
res.updateConfiguration(conf, dm);
如果您有特定语言的内容,可以根据设置进行更改。
2020年3月26日更新
public static void setLocale(Activity activity, String languageCode) {
Locale locale = new Locale(languageCode);
Locale.setDefault(locale);
Resources resources = activity.getResources();
Configuration config = resources.getConfiguration();
config.setLocale(locale);
resources.updateConfiguration(config, resources.getDisplayMetrics());
}
Context.createConfigurationContext()
,它可以用于使用特定于语言环境的配置包装默认上下文,然后在不必更新资源对象本身的配置的情况下在其上调用getResources
。 - JABconf.setLayoutDirection(locale)
的语句,你可以将conf.locale = new Locale(...)
替换为conf.setLocale(new Locale(...))
。它会在内部调用setLayoutDirection
。 - Ted Hopp这段代码确实有效:
fa代表波斯语,en代表英语
在languageToLoad
变量中输入您的语言代码:
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
public class Main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String languageToLoad = "fa"; // your language
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
this.setContentView(R.layout.main);
}
}
2021年6月更新(Kotlin):
class Main : Activity() {
// Called when the activity is first created.
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val config = resources.configuration
val lang = "fa" // your language code
val locale = Locale(lang)
Locale.setDefault(locale)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
config.setLocale(locale)
else
config.locale = locale
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
createConfigurationContext(config)
resources.updateConfiguration(config, resources.displayMetrics)
this.setContentView(R.layout.main)
}
}
Resources.updateConfiguration
方法的第二个参数。我缩进了代码以使其更清晰。 - Czechnologyif (Build.VERSION.SDK_INT >= 17) {
config.setLocale(locale);
} else {
config.locale = locale;
}
这将确保您的应用程序在不同版本的 Android 上正确设置语言环境。 - roghayeh hosseini我正在寻找一种以编程方式更改系统语言的方法。虽然我充分理解普通应用程序永远不应该这样做,而应该:
但是,确实有必要以编程方式真正更改系统语言。
这是未经记录的API,因此不应用于市场/最终用户应用程序!
无论如何,这是我找到的解决方案:
Locale locale = new Locale(targetLocaleAsString);
Class amnClass = Class.forName("android.app.ActivityManagerNative");
Object amn = null;
Configuration config = null;
// amn = ActivityManagerNative.getDefault();
Method methodGetDefault = amnClass.getMethod("getDefault");
methodGetDefault.setAccessible(true);
amn = methodGetDefault.invoke(amnClass);
// config = amn.getConfiguration();
Method methodGetConfiguration = amnClass.getMethod("getConfiguration");
methodGetConfiguration.setAccessible(true);
config = (Configuration) methodGetConfiguration.invoke(amn);
// config.userSetLocale = true;
Class configClass = config.getClass();
Field f = configClass.getField("userSetLocale");
f.setBoolean(config, true);
// set the locale to the new value
config.locale = locale;
// amn.updateConfiguration(config);
Method methodUpdateConfiguration = amnClass.getMethod("updateConfiguration", Configuration.class);
methodUpdateConfiguration.setAccessible(true);
methodUpdateConfiguration.invoke(amn, config);
如果您想在整个应用程序中保持语言更改,您需要执行两个操作。
首先,创建一个基础 Activity,并使所有的活动都继承自此 Activity:
public class BaseActivity extends AppCompatActivity {
private Locale mCurrentLocale;
@Override
protected void onStart() {
super.onStart();
mCurrentLocale = getResources().getConfiguration().locale;
}
@Override
protected void onRestart() {
super.onRestart();
Locale locale = getLocale(this);
if (!locale.equals(mCurrentLocale)) {
mCurrentLocale = locale;
recreate();
}
}
public static Locale getLocale(Context context){
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
String lang = sharedPreferences.getString("language", "en");
switch (lang) {
case "English":
lang = "en";
break;
case "Spanish":
lang = "es";
break;
}
return new Locale(lang);
}
}
请注意,我将新语言保存在sharedPreference中。
其次,创建一个Application的扩展,如下所示:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
setLocale();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setLocale();
}
private void setLocale() {
final Resources resources = getResources();
final Configuration configuration = resources.getConfiguration();
final Locale locale = getLocale(this);
if (!configuration.locale.equals(locale)) {
configuration.setLocale(locale);
resources.updateConfiguration(configuration, null);
}
}
}
请注意,getLocale()与上面的相同。
就这些! 我希望这可以帮助某人。
Application
是什么以及如何使用它。https://www.mobomo.com/2011/05/how-to-use-application-object-of-android/ - Siweiconfiguration.locate
已被弃用,setLocale需要API 17+,updateConfiguration也已被弃用。 - Zoe stands with UkraineLocaleHelper.java
文件。
MyApplication
的类,继承Application
。attachBaseContext()
方法来更新语言。在清单文件中注册该类。
public class MyApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
}
}
<application
android:name="com.package.MyApplication"
.../>
创建BaseActivity
,并重写onAttach()
方法以更新语言。 在Android 6及以上版本中需要。
public class BaseActivity extends Activity {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base));
}
}
使您的应用程序中的所有活动都继承自BaseActivity
。public class LocaleHelper {
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 Context onAttach(Context context, String defaultLanguage) {
String lang = getPersistedData(context, defaultLanguage);
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 = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
}
private static void persist(Context context, String language) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.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;
}
}
Application
的类,并创建一个静态方法。然后,在所有活动中的 setContentView()
之前调用此方法。public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
}
public static void setLocaleFa (Context context){
Locale locale = new Locale("fa");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
context.getApplicationContext().getResources().updateConfiguration(config, null);
}
public static void setLocaleEn (Context context){
Locale locale = new Locale("en_US");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
context.getApplicationContext().getResources().updateConfiguration(config, null);
}
}
在活动中的使用:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyApp.setLocaleFa(MainActivity.this);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
}
我只想额外添加一个让我困扰的细节。
虽然其他回答中使用 "de" 是可以的,例如
String lang = "de";
Locale locale = new Locale(lang);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
上面的方法无法与例如"fr_BE"
区域设置一起使用,因此它将使用values-fr-rBE
文件夹或类似文件夹。"fr_BE"
一起使用。String lang = "fr";
//create a string for country
String country = "BE";
//use constructor with country
Locale locale = new Locale(lang, country);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
activity.recreate()
。 - To Kraandroid.content.res.Configuration conf = res.getConfiguration();
而不是创建一个新的 Configuration
实例怎么样?使用全新实例有什么好处吗? - Bianca DaniciuclayoutDirection='locale'
怎么样? - nAkhmedovLocale.getDefault().country
/context.resources.configuration.locales[0].language
,您将得到空白的响应。
这是什么原因?有解决办法吗? - SaurabhG我为我的应用启动自身而更改了德语语言。
这是我的正确代码。任何人想要使用相同的代码可以参考以下内容。 (如何在Android中以编程方式更改语言)
我的代码:
Configuration config ; // variable declaration in globally
// this part is given inside onCreate Method starting and before setContentView()
public void onCreate(Bundle icic)
{
super.onCreate(icic);
config = new Configuration(getResources().getConfiguration());
config.locale = Locale.GERMAN ;
getResources().updateConfiguration(config,getResources().getDisplayMetrics());
setContentView(R.layout.newdesign);
}
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 android.preference.PreferenceManager;
import java.util.Locale;
/**
* This class is used to change your application locale and persist this change for the next time
* that your app is going to be used.
* <p/>
* You can also change the locale of your application on the fly by using the setLocale method.
* <p/>
* Created by gunhansancar on 07/10/15.
*/
public class LocaleHelper {
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 Context onAttach(Context context, String defaultLanguage) {
String lang = getPersistedData(context, defaultLanguage);
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 = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
}
private static void persist(Context context, String language) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.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;
}
}
您需要覆盖attachBaseContext并调用LocaleHelper.onAttach()来初始化应用程序中的语言环境设置。
import android.app.Application;
import android.content.Context;
import com.gunhansancar.changelanguageexample.helper.LocaleHelper;
public class MainApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base, "en"));
}
}
你所要做的就是添加
LocaleHelper.onCreate(this, "en");
在你想要更改地区设置的任何地方。
createConfigurationContext
,这非常有帮助。 - jacoballenwood需要更新了。
首先,API中已经弃用的列表如下:
configuration.locale
(API 17)updateConfiguration(configuration, displaymetrics)
(API 17)最近没有一个问题得到正确回答的是新方法的使用方式。
createConfigurationContext
是 updateConfiguration
的新方法。
有些人将其独立地使用,像这样:
Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
createConfigurationContext(overrideConfiguration);
但是那样做并不起作用。为什么呢?该方法返回一个上下文,然后用于处理Strings.xml翻译和其他本地化资源(图像,布局等)。
正确的用法如下:
Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
//the configuration can be used for other stuff as well
Context context = createConfigurationContext(overrideConfiguration);
Resources resources = context.getResources();
如果你将它复制粘贴到IDE中,可能会看到一个警告,API要求你以API17或更高版本为目标。你可以通过将其放入方法并添加注释@TargetApi(17)
来解决这个问题。
但是等等,旧的API怎么办?
你需要创建另一个方法,使用updateConfiguration而不带TargetApi注释。
Resources res = YourApplication.getInstance().getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.locale = new Locale("th");
res.updateConfiguration(conf, dm);
这里不需要返回上下文。
现在,管理这些内容可能会很困难。在API 17+中,您需要创建上下文(或从创建的上下文中获取资源)以根据本地化获取适当的资源。如何处理呢?
嗯,这是我处理的方式:
/**
* Full locale list: https://dev59.com/92sz5IYBdhLWcg3wVGLJ
* @param lang language code (e.g. en_US)
* @return the context
* PLEASE READ: This method can be changed for usage outside an Activity. Simply add a COntext to the arguments
*/
public Context setLanguage(String lang/*, Context c*/){
Context c = AndroidLauncher.this;//remove if the context argument is passed. This is a utility line, can be removed totally by replacing calls to c with the activity (if argument Context isn't passed)
int API = Build.VERSION.SDK_INT;
if(API >= 17){
return setLanguage17(lang, c);
}else{
return setLanguageLegacy(lang, c);
}
}
/**
* Set language for API 17
* @param lang
* @param c
* @return
*/
@TargetApi(17)
public Context setLanguage17(String lang, Context c){
Configuration overrideConfiguration = c.getResources().getConfiguration();
Locale locale = new Locale(lang);
Locale.setDefault(locale);
overrideConfiguration.setLocale(locale);
//the configuration can be used for other stuff as well
Context context = createConfigurationContext(overrideConfiguration);//"local variable is redundant" if the below line is uncommented, it is needed
//Resources resources = context.getResources();//If you want to pass the resources instead of a Context, uncomment this line and put it somewhere useful
return context;
}
public Context setLanguageLegacy(String lang, Context c){
Resources res = c.getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();//Utility line
android.content.res.Configuration conf = res.getConfiguration();
conf.locale = new Locale(lang);//setLocale requires API 17+ - just like createConfigurationContext
Locale.setDefault(conf.locale);
res.updateConfiguration(conf, dm);
//Using this method you don't need to modify the Context itself. Setting it at the start of the app is enough. As you
//target both API's though, you want to return the context as you have no clue what is called. Now you can use the Context
//supplied for both things
return c;
}
这段代码的工作原理是有一个方法根据API调用适当的方法。我已经使用了许多不同的弃用调用(包括Html.fromHtml)。您有一个方法接收所需的参数,然后将其分成两个(或三个或更多)方法,并根据API级别返回适当的结果。它很灵活,因为您不必多次检查,“entry”方法会为您完成。这里的入口方法是setLanguage
您需要使用获取资源时返回的上下文。为什么?我已经看到其他答案在此处使用createConfigurationContext并且没有使用它返回的上下文。要使它像那样工作,必须调用updateConfiguration。这已被弃用。使用该方法返回的上下文来获取资源。
示例用法:
构造函数或类似位置:
ctx = getLanguage(lang);//lang is loaded or generated. How you get the String lang is not something this answer handles (nor will handle in the future)
然后,无论您想要获取资源的地方都可以执行以下操作:
String fromResources = ctx.getString(R.string.helloworld);
使用其他上下文(理论上)会破坏此功能。
AFAIK,您仍然需要使用活动上下文来显示对话框或Toast。为此,您可以使用活动的实例(如果在外部)
最后,使用recreate()
在活动上刷新内容。这是不必创建意图以刷新的快捷方式。