布景:
在多言语项目中,咱们经常会遇到本地化适配不规范导致的问题。例如 月份翻译过错、数字显现格局不正确 或许 数字显现方式与本地习气不符 等。为了寻求一种更精准高效的适配方案,我在网上查阅了相关材料。发现Google供给了一个本地化API接口——ICU API。它能够利用ICU和CLDR供给Unicode和其他国际化支撑。然后提高软件的本地化质量。
本地化适配场景
本地化适配所涉及到的问题,根本上都能够概括为:在不同的言语和地区,同一个信息所显现翻译不同、格局不同或许一个事物表现规则不同。通过概括总结,咱们把常见的本地化适配分为以下几个类型:时刻信息、数字信息、文件巨细及其单位、历法规则、丈量单位和时区信息。
本地化接口运用
针对以上所述本地化场景,咱们别离介绍相关接口以及接口运用方法。
常见格局如日期、单位等,在 data/locales
目录中有详细阐明。,咱们能够下载 data/locales/zh.txt 文件检查不同标签对应内容意义。
例如咱们要检查星期在各国翻译下的内容:
- 首要咱们在
data/locales/zh.txt
中查找星期一对应标签dayNames
下面。其间wide表明全称,short表明简称。 - 打开
data/locales
其它国家对应言语码txt文件。比方检查法语下翻译状况时打开fr.txt
文件。 - 相同查找
dayNames
标签对应翻译,并与手机上显现翻译比对是否共同。
除了 data/locales
目录外还有几个目录需求关注:
- data/unit 常用单位
- data/curr 钱银单位
- data/lang 言语描述
时刻日期格局
DateFormat#getInstanceForSkeleton 、SimpleDateFormat.getDateInstance
阐明:
1.这些接口能够处理x年x月x日星期x x时x分x秒这类时刻信息格局问题。比方年月日呈现先后顺序不同状况。这个格局与本地人运用习气相关。
好的,我已经输出了你的文章的前半部分,下面是后半部分:
因而运用这个接口能够很好地处理时刻显现格局问题。
时刻日期格局
DateFormat#getInstanceForSkeleton 、SimpleDateFormat.getDateInstance
阐明:
1.这些接口能够处理 x年x月x日
、星期x
、x时x分x秒
这类时刻信息格局问题。比方年月日呈现先后顺序不同状况,这个格局与本地人运用习气是相关的。因而运用这个接口能够很好地处理时刻显现格局问题。
2.一起这个接口 还能处理时刻表述中翻译问题,不用再独自考虑翻译问题。 这个翻译的准确度,往往要高于翻译公司的准确度。
3.运用其间一些特别接口能够处理一些特别字串翻译问题。比方运用以下接口能够获取 星期一
、 二月
等相关特别时刻在本地言语翻译字符。这个翻译准确度往往高于翻译公司准确度。期望有类似字串显现场景能够研究这个接口并进行运用。developer.android.com/reference/j…
以下只就阐明进行一个简略举例:下面的getDateInstance能够不传第二个参数,那么就会依据当时体系预设来输出成果。
DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE);
myDate = df.parse(myString);
...
January 12, 1952
详细格局由第一个参数控制,模块可依据需求自行定制,给出以下运用事例
DateFormat.getInstanceForSkeleton(DateFormat.ABBR_MONTH_DAY, Locale.getDefault()).format(new Date());
...
3月16日
Mar 16
DateFormat.getInstanceForSkeleton(DateFormat.MONTH_WEEKDAY_DAY, Locale.getDefault()).format(new Date());
...
3月16日周四
Thursday,March 16
DateFormat.getInstanceForSkeleton("MMMEdd", locale1).format(new Date());
...
3月16日周四
Thursday,Mar 16
DateFormat.getInstanceForSkeleton(DateFormat.YEAR_MONTH_DAY, Locale.getDefault()).format(new Date());
DateFormat.getInstanceForSkeleton(DateFormat.YEAR_MONTH_DAY, Locale.ENGLISH).format(new Date());
...
2023年3月16
March 16,2023
DateFormat.getInstanceForSkeleton("yyyyMMdd", Locale.getDefault()).format(new Date());
...
2023/03/16
03/16/2023
DateFormat.getInstanceForSkeleton("hhmma", Locale.getDefault()).format(new Date());
...
下午7:51
7:51 PM
SimpleDateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault()).format(new Date());
...
2023年03月16日
Mar 16, 2023
// 运用工具类
DateUtils.formatDateTime(context, time, DateUtils.FORMAT_ABBREV_MONTH);
DateUtils.formatDateTime(context, time, DateUtils.FORMAT_SHOW_YEAR);
日期/时刻区间:
DateInterval dateInterval = new DateInterval(time1, time2);
DateIntervalFormat.getInstance(DateFormat.YEAR_ABBR_MONTH_DAY, Locale.getDefault()).format(dateInterval, new StringBuffer(""), new FieldPosition(0));
...
2023年3月16日至7月16日
Mar 16 – Jul 16, 2023
数字信息格局
NumberFormat#getInstance、NumberFormat#getCurrencyInstance、NumberFormat#getPercentInstance
阐明:
1.这些接口能够处理数字信息格局问题。比方数字显现方式应该是本地字母而不是阿拉伯数字、小数点和千分位符号方位不同等。
2.一起这些接口还能处理钱银单位和百分比符号的本地化显现问题。
3.运用其间一些特别接口还能处理一些特别数字信息的本地化显现问题。比方运用以下接口能够获取本地言语对应的序数词(第一、第二等)或许序列号(1st、2nd等)。
以下只就阐明进行一个简略举例:下面的getInstance能够不传参数,那么就会依据当时体系预设来输出成果。
NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
myNumber = nf.parse(myString);
输出当地习气显现的数字格局,或许当地文字
NumberFormat.getInstance(Locale.getDefault()).format(100001.23);
...
100,000.89
100,000.89
DecimalFormat.getPercentInstance(Locale.getDefault()).format(0.53);
...
53%
53%
CompactDecimalFormat.getInstance(locale, CompactDecimalFormat.CompactStyle.SHORT).format(100000);
...
10万
100K
文件巨细及其单位格局
FileSizeUtils#formatFileSize(Context context,long numberBytes)
阐明:
1.这个接口能够处理文件巨细及其单位格局问题。比方文件巨细显现方式应该是KB而不是kB、单位之间是否有空格等。
2.一起这个接口还能依据当时体系预设主动选择适宜的单位和精度来显现文件巨细。
给出一个简略举例:
public static String formatFileSize(Context context, long sizeBytes);
将内容巨细格局化为字节、千字节、兆字节等方式。 显现的数字,会依据当地习气,用逗号分隔,或许用点号离隔,或许数字用当地字母显现。 文件巨细的单位,也会依据当地习气显现为Mb或许MB等不同方式。
developer.android.com/reference/a…
Android O开始运用标准的单位制 1KB = 1000 bytes
Formatter.formatFileSize(this, 15345);
...
//15.35 KB
//乌克兰语 15,61
Formatter.formatShortFileSize(this, 15612524);
...
16 MB
16 MB
16
丈量单位
MeasureFormat
在需求显现丈量单位的场景,能够运用此接口做好本地化信息展现。以下简略介绍毫升的显现。相同的,其他丈量单位,都能够选用类似的方式获取, 只是把参数替换一下即可。
阐明: 关于长度,质量,体积,钱银、卡路里、ml等丈量单位的本地化显现。现在根本都基于翻译拼接来完成。后面主张运用google官方接口来实现。 1.数字+单位
支撑的丈量单位可参阅developer.android.google.cn/reference/a… ,调整传参即可
Measure measure = new Measure(30.5, MeasureUnit.CELSIUS);
MeasureFormat.getInstance(Locale.getDefault(),MeasureFormat.FormatWidth.SHORT).format(measure);
...
30.5C
30.5C
Measure measure = new Measure(30.5, MeasureUnit.HOUR);
MeasureFormat.getInstance(Locale.getDefault(),MeasureFormat.FormatWidth.SHORT).format(measure);
...
30.5小时
30.5hr
Measure measure = new Measure(224, MeasureUnit.GIGABYTE);
MeasureFormat.getInstance(Locale.getDefault(),MeasureFormat.FormatWidth.SHORT).format(measure);
...
**224吉字节****数字单位常量中文与预期不符,可能需求独自处理**
224GB
针对部分场景,需求区分数字和单位巨细,能够结合MeasureFormat和NumberFormat,别离拿到完好字符串和数字部分字符串,计算index后设置款式即可(留意:不要拆分成两个字符串别离布局)
NumberFormat instance = NumberFormat.getInstance(Locale.getDefault());
String celsius = MeasureFormat.getInstance(Locale.getDefault(), MeasureFormat.FormatWidth.SHORT, instance).formatMeasures(measure);
String number = instance.format(30.5);
SpannableString spannableString = new SpannableString(celsius);
spannableString.setSpan(new AbsoluteSizeSpan(30, true), celsius.indexOf(number), celsius.indexOf(number) + number.length(), 0);
textView.setText(spannableString);
日期格局符号
阐明:获取星期、月份列表等,支撑获取format方式和standalone方式,wide、narrow、short
DateFormatSymbols dateFormatSymbols = new DateFormatSymbols(Locale.getDefault);
dateFormatSymbols.getWeekdays();
dateFormatSymbols.getWeekdays(DateFormatSymbols.STANDALONE,DateFormatSymbols.WIDE);
dateFormatSymbols.getMonths();
接口记载:
1、TextUtils#expandTemplate developer.android.google.cn/reference/k…
// string.xml
<string name="storage_size_large_alternate"><xliff:g id="number" example="128">^1</xliff:g> <font size="15"><xliff:g id="unit" example="KB">^2</xliff:g></font></string>
TextUtils.expandTemplate(getText(R.string.storage_size_large_alternate), "128", "GB");
常见问题FAQ
iculocal