android “Locale.getDefault()”和“getResources().getConfiguration().getLocales().get(0)”究竟是如何工作的?

gkl3eglg  于 2023-11-15  发布在  Android
关注(0)|答案(1)|浏览(208)

我的应用程序(Java 11,最小值:API 29,目标:API 30 = Android 11)目前支持两种语言:德语(默认)和英语
“build.gradle(Module:app)”文件包含resConfigs("de", "en"),并且有两个包含翻译的strings.xml文件。
根据官方文档,Locale.getDefault()应该返回:
此Java虚拟机示例的指定类别的默认区域设置的当前值。
如果我理解正确,那么这就是应用程序当前使用的Locale
getLocales()的文档只说:
获取语言环境列表。这是获取语言环境的首选方式(而不是使用直接访问器来访问语言环境,因为它只提供主要语言环境)。
.但根据多线程,这个函数也应该返回应用程序当前使用的Locale。我想知道这是哪种语言,所以我用下面的print做了一些测试:

Log.d(TAG,"1="+Locale.getDefault()+", 2="+getResources().getConfiguration().getLocales().get(0));

字符串

  • 将模拟器设置为“English(US)”->正确选择英语,打印“1=en_US,2=en_US”
  • 德语(CH)->德语选择正确,打印“1=de_CH,2=de_CH”
  • 德语+英语(美国)->德语选择正确,打印“1=de_CH,2=de_CH”
  • 丹麦语+德语(CH)->德语选择正确,打印“1=de_CH,2=de_CH”
  • 丹麦语+英语(美国)->英语选择正确,打印“1=en_US,2=en_US”
  • 正确选择丹麦语+意大利语->德语,打印“1=da_DK,2=da_DK”
  • 意大利语+西班牙语->德语选择正确,打印“1=in_IT,2=in_IT”

看起来它们要么设置为应用支持的语言,要么设置为用户在Android设置中选择的语言,或者如果应用不支持它们,则设置为用户选择的第一种语言。
我的应用程序有一个微调器,可以更改语言。调用例如Locale.setDefault(Locale.English)将所有内容切换为英语,但如果我从第一个Activity切换到第二个Activity,则此值将重置。例如:
德语+英语(美国)->德语自动选择(打印“1=de_CH,2=de_CH”)->切换到英语-> UI元素也切换->切换活动->在onCreateView中打印“1=de_CH,2=en”,而所有UI元素都是英语;使用丹麦语+意大利语时,它打印“1=da_DK,2=en”
我知道getResources().getConfiguration().getLocales().get(0)需要调用onConfigurationChanged才能更改,而Locale.setDefault()会立即应用更改,但为什么后者会突然重置?为什么我得到的是我在测试中得到的结果,而不是目前使用的Locale?如何获得应用程序实际使用的Locale的可靠结果(不可能只是this,对吧?)
或者更好:这两个函数实际上是如何工作的?它们只是有缺陷吗?
文档没有提到任何这一点,但只有如何Locale选择应用程序启动(here)和latest changes的语言偏好只适用于Android 13+。

xlpyo6sf

xlpyo6sf1#

我用我的语言Spinner做了一些测试(第一个练习中的菜单):

A. Locale.getDefault()返回应用选择使用的设备语言,每次切换Activity时都会重置(如果在片段之间切换,它似乎不会改变!)。在我的测试中,Locale.setDefault不会影响任何TextView s,EditText s或其他UI元素(除了:见下文)。
B. getResources().getConfiguration().getLocales().get(0)返回相同的语言,但您使用onConfigurationChanged应用的更改“粘滞”,即使在切换活动之后。它至少影响TextView s、EditText s、Switch es和Button s(同样,请参见下文),但是只有在膨胀视图之前调用它、在膨胀视图之后刷新视图或者覆盖onConfigureChanged时,更改才会应用。

听起来很简单,但事实并非如此。让我们看一个例子,让我们在等式中添加DatePickerTimePicker(在活动2中):

  • 该应用程序支持:德语和英语
  • Android设置中的语言:1.英语,2.德语
  • 应用程序以英语启动,因为这是用户的首选语言。A和B都打印“en_US”。
  • 切换到德语,使用第一个Activity中的微调器(带有onConfigurationChanged)。A和B都打印“de_CH”。
  • 切换到第二个Activity。A打印“en_US”,因为它被重置为用户的首选语言,而B保留我在第一个Activity中手动应用的更改并打印“de_CH”。所有TextView s都是德语,但DatePicker和TimePicker仍然是英语。

要更改两个pickers的语言,您必须在onCreateView的开始处使用A(例如Locale.setDefault(getResources().getConfiguration().getLocales().get(0))-看起来很容易,但还有另一个问题,见下文),甚至在膨胀视图之前,在调用例如datePicker = view.findViewById(R.id.datePicker)之前。之后A和B都再次打印“de_CH”,pickers是德语的。
如果Android设备被设置为丹麦语+英语,这也会以同样的方式工作:英语会自动选择,即使在第二个Activity中,B也会记得切换到德语。
我还没有能够让它完全工作与DatePickerDialog,但这是一个different problem
回到另一个更复杂的例子:丹麦语+意大利语
应用程序以德语正确启动,A和B都打印“da_DK”。在不使用微调器更改应用程序内的语言的情况下,Activity 2中的拾取器现在是丹麦语。如果我在切换Activity之前通过菜单更改语言,那么拾取器将使用所选的正确语言(因为微调器将B设置为特定语言,B记住了它)。

从这里拿走什么:

不要依赖A或B,除非你能绝对确定用户的手机使用至少一种你的应用支持的语言。可悲的是,似乎真的最好只使用建议的解决方案here:将包含该特定语言代码的键值对添加到本地化文件中,在应用程序启动后检查它,然后为该语言设置Locale,手动更改和更新它,在活动之间传递它,并在需要时使用它(例如,对于DatePicker)。

相关问题