You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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());
}

问题根源分析

  1. Locale设置API兼容性问题:旧版updateConfiguration方法在Android 7.0+已被废弃,部分厂商定制系统对该API的支持存在差异,导致Locale未被正确应用到资源加载。
  2. 语言判断逻辑依赖BuildConfig:DateFormatter中通过BuildConfig.FLAVOR判断是否为匈牙利语版本,而非基于当前应用的实际Locale,若Flavor与Locale不匹配(比如多语言版本而非单独匈牙利语Flavor),会导致逻辑错误。
  3. 资源加载优先级差异:部分设备的系统资源加载机制可能优先使用系统默认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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 05:06:28