Android多设备匈牙利语本地化日期字符串显示异常求助
匈牙利语Locale下部分Android设备日期显示英文问题排查与解决
问题现象
应用设置为匈牙利语(HU)locale时,少数不同OS版本的Android设备上日期字符串仍显示为英文,所有Android版本模拟器均正常显示匈牙利语日期。
测试设备情况
- One Plus 8(Android 12):正常显示
- Google Pixel 5(Android 12):正常显示
- Galaxy S10(Android 12):日期字符串显示英文
- One Plus 5t(Android 10):日期字符串显示英文
- 另一台One Plus 5t(Android 10):正常显示
相关代码
strings.xml
<string-array name="months_name"> <item>Jan</item> <item>Feb</item> <item>Mar</item> <item>Apr</item> <item>May</item> <item>Jun</item> <item>Jul</item> <item>Aug</item> <item>Sep</item> <item>Oct</item> <item>Nov</item> <item>Dec</item> </string-array> <string-array name="full_months_name"> <item>January</item> <item>February</item> <item>March</item> <item>April</item> <item>May</item> <item>June</item> <item>July</item> <item>August</item> <item>September</item> <item>October</item> <item>November</item> <item>December</item> </string-array> <string name="st">st</string> <string name="nd">nd</string> <string name="rd">rd</string> <string name="th">th</string>
strings-hu.xml
<string-array name="months_name"> <item>Jan</item> <item>Febr</item> <item>Márc</item> <item>Ápr</item> <item>Máj</item> <item>Jún</item> <item>Júl</item> <item>Aug</item> <item>Szept</item> <item>Okt</item> <item>Nov</item> <item>Dec</item> </string-array> <string-array name="full_months_name"> <item>január</item> <item>február</item> <item>március</item> <item>április</item> <item>Lehet</item> <item>június</item> <item>július</item> <item>augusztus</item> <item>szeptember</item> <item>október</item> <item>November</item> <item>December</item> </string-array> <string name="st"></string> <string name="nd"></string> <string name="rd"></string> <string name="th"></string>
DateFormatter.java
package app.util; import android.content.Context; import java.text.NumberFormat; import java.util.Calendar; import java.util.Locale; public class DateFormatter { private static Integer date; private static Integer month; private static Integer year; private static String[] monthArray; private static String[] shortMonthArray; public static String formatDate(long milliseconds, Context context) { init(milliseconds, context); if (!BuildConfig.FLAVOR.equals(BuildConfig.Flavor_Hungarian)) { return getDateString(date, context) + " " + getMonth(month, true) + " " + numberFormatBasedOnLanguage(year); } else { return numberFormatBasedOnLanguage(year) + " " + getMonth(month, true) + " " + getDateString(date, context); } } public static String formatDateMonthAndYear(long milliseconds, Context context) { init(milliseconds, context); if (!BuildConfig.FLAVOR.equals(BuildConfig.Flavor_Hungarian)) { return getDateString(date, context) + "-" + getMonth(month, true) + "-" + numberFormatBasedOnLanguage(year); } else { return numberFormatBasedOnLanguage(year) + ". " + getMonth(month, true) + " " + getDateString(date, context); } } public static String formatDateAndMonth(long milliseconds, Context context, boolean suffixRequired) { init(milliseconds, context); if (suffixRequired) { if (!BuildConfig.FLAVOR.equals(BuildConfig.Flavor_Hungarian)) { return getDateString(date, context) + " " + getMonth(month, true); } else { return getMonth(month, true) + " " + numberFormatBasedOnLanguage(date); } } else if (!BuildConfig.FLAVOR.equals(BuildConfig.Flavor_Hungarian)) { return numberFormatBasedOnLanguage(date) + " " + getMonth(month, true); } else { return getMonth(month, true) + " " + numberFormatBasedOnLanguage(date); } } public static String formatToDDMMMY(long milliseconds, Context context) { init(milliseconds, context); if (!BuildConfig.FLAVOR.equals(BuildConfig.Flavor_Hungarian)) { return numberFormatBasedOnLanguage(date) + " " + getMonth(month, false) + " " + numberFormatBasedOnLanguage(year); } else { return numberFormatBasedOnLanguage(year) + ". " + getMonth(month, true) + " " + getDateString(date, context); } } public static String formatToDDMMMYYYY(long milliseconds, Context context) { init(milliseconds, context); return numberFormatBasedOnLanguage(date) + "-" + (getMonth(month, false)).toUpperCase(Constants.LANGUAGE) + "-" + numberFormatBasedOnLanguage(year); } public static String numberFormatBasedOnLanguage(long value){ if(BuildConfig.IS_NUMBER_FORMAT_ENABLED){ NumberFormat nf= NumberFormat.getInstance(new Locale(Locale.getDefault().getLanguage())); nf.setGroupingUsed(false); return nf.format(value); }else{ return ""+value; } } public static String numberFormatBasedOnLanguage(String value){ if(BuildConfig.IS_NUMBER_FORMAT_ENABLED){ NumberFormat nf= NumberFormat.getInstance(new Locale(Locale.getDefault().getLanguage())); nf.setGroupingUsed(false); return nf.format(Integer.parseInt(value)); }else{ return ""+value; } } public static String numberFormatGlobalBasedOn(String value){ if(BuildConfig.IS_NUMBER_FORMAT_ENABLED){ NumberFormat nf= NumberFormat.getInstance(new Locale(Constants.GLOBAL)); nf.setGroupingUsed(false); return nf.format(Integer.parseInt(value)); }else{ return ""+value; } } private static void init(long milliseconds, Context context) { monthArray = context.getResources().getStringArray( R.array.full_months_name); shortMonthArray = context.getResources().getStringArray( R.array.months_name); Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(milliseconds); date = cal.get(Calendar.DATE); month = cal.get(Calendar.MONTH); year = cal.get(Calendar.YEAR); Log.d("DateFormatter", "date:" + date + " month:" + month + " year" + year); } private static String getDateString(Integer date, Context context) { String extension = ""; if (BuildConfig.FLAVOR.equals(BuildConfig.Flavor_Hungarian)) { return DateFormatter.numberFormatBasedOnLanguage(date) + extension; } if (date == 1 || date == 21 || date == 31) { extension = context.getString(R.string.st); } else if (date == 2 || date == 22) { extension = context.getString(R.string.nd); } else if (date == 3 || date == 23) { extension = context.getString(R.string.rd); } else if (date == 4 || (date > 4 && date < 21) || (date > 23 && date < 31)) { extension = context.getString(R.string.th); } return DateFormatter.numberFormatBasedOnLanguage(date) + extension; } private static String getMonth(Integer month, boolean fullMonth) { if (fullMonth) { return monthArray[month]; } return shortMonthArray[month]; } }
SplashScreenActivity.java(语言设置代码)
/** * This method is to set the locale language. */ private void setLocale(String language) { Locale locale = new Locale(language); Locale.setDefault(locale); Configuration config = new Configuration(); config.locale = locale; getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics()); }
问题根源分析
- Locale设置API兼容性问题:旧版
updateConfiguration方法在Android 7.0+已被废弃,部分厂商定制系统对该API的支持存在差异,导致Locale未被正确应用到资源加载。 - 语言判断逻辑依赖BuildConfig:
DateFormatter中通过BuildConfig.FLAVOR判断是否为匈牙利语版本,而非基于当前应用的实际Locale,若Flavor与Locale不匹配(比如多语言版本而非单独匈牙利语Flavor),会导致逻辑错误。 - 资源加载优先级差异:部分设备的系统资源加载机制可能优先使用系统默认Locale资源,而非应用内的自定义资源。
解决方案
1. 修复Locale设置逻辑,适配全版本Android
替换旧的setLocale方法,使用兼容API 17到最新版本的实现:
private void setLocale(String language) { Locale locale = new Locale(language); Locale.setDefault(locale); Resources resources = getBaseContext().getResources(); Configuration config = resources.getConfiguration(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { config.setLocale(locale); Context context = createConfigurationContext(config); resources.updateConfiguration(config, resources.getDisplayMetrics()); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { config.setLocale(locale); resources.updateConfiguration(config, resources.getDisplayMetrics()); } else { config.locale = locale; resources.updateConfiguration(config, resources.getDisplayMetrics()); } }
2. 修改DateFormatter的语言判断逻辑
将基于BuildConfig.FLAVOR的判断替换为基于当前应用Locale的判断,确保逻辑与实际应用语言一致:
// 替换所有BuildConfig.FLAVOR.equals(BuildConfig.Flavor_Hungarian)的判断 boolean isHungarian = context.getResources().getConfiguration().getLocales().get(0).getLanguage().equals("hu");
例如修改formatDate方法:
public static String formatDate(long milliseconds, Context context) { init(milliseconds, context); boolean isHungarian = context.getResources().getConfiguration().getLocales().get(0).getLanguage().equals("hu"); if (!isHungarian) { return getDateString(date, context) + " " + getMonth(month, true) + " " + numberFormatBasedOnLanguage(year); } else { return numberFormatBasedOnLanguage(year) + " " + getMonth(month, true) + " " + getDateString(date, context); } }
3. 优化资源加载(可选)
使用Android系统自带的日期格式化API替代自定义月份数组,减少手动维护成本,同时利用系统的Locale适配能力:
// 示例:使用SimpleDateFormat格式化匈牙利语日期 SimpleDateFormat sdf = new SimpleDateFormat("yyyy MMMM dd", new Locale("hu")); String hungarianDate = sdf.format(new Date(milliseconds));
4. 确认资源文件结构
确保strings-hu.xml放置在res/values-hu/目录下,目录结构正确,避免资源未被正确识别。
内容的提问来源于stack exchange,提问作者chutwik
相关产品推荐
相关产品推荐

