Android中阿拉伯文文本中的阿拉伯文数字

Android中阿拉伯文文本中的阿拉伯文数字,android,locale,arabic,Android,Locale,Arabic,编辑 我正在将我的应用程序移植到阿拉伯语语言环境。我有一些getString()参数,如: getString(R.string.distance, distance) 其中%1d km 要求是用阿拉伯语我应该这样显示:“2.3كم” 如果我设置为沙特阿拉伯(country=“sa”)或阿联酋(country=“ae”)的语言环境,则数字将以阿拉伯语东部显示,但我的客户希望它们以阿拉伯语西部显示 解决办法是在当地使用埃及作为一个国家,但这对我来说是不可能的 我试过: @TargetApi(Bu

编辑

我正在将我的应用程序移植到阿拉伯语语言环境。我有一些getString()参数,如:

getString(R.string.distance, distance)
其中
%1d km

要求是用阿拉伯语我应该这样显示:“2.3كم”

如果我设置为沙特阿拉伯(country=“sa”)或阿联酋(country=“ae”)的语言环境,则数字将以阿拉伯语东部显示,但我的客户希望它们以阿拉伯语西部显示

解决办法是在当地使用埃及作为一个国家,但这对我来说是不可能的

我试过:

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void setAppContextLocale(Locale savedLocale) {
    Locale.Builder builder = new Locale.Builder();
    builder.setLocale(savedLocale).setExtension(Locale.UNICODE_LOCALE_EXTENSION, "nu-latn");
    Locale locale = builder.build();
    Configuration config = new Configuration();
    config.locale = locale;
    config.setLayoutDirection(new Locale(savedLocale.getLanguage()));
    mAppContext.getResources().updateConfiguration(config, mContext.getResources().getDisplayMetrics());
}

如中所述,但之后将忽略国家/地区,因此SA和AE地区都使用默认文件中的字符串。

请按照以下阿拉伯语设置字体

Typeface font = Typeface.createFromAsset(getAssets(), "fonts/abcd.TTF");
abcd是阿拉伯语字体

textview.setTypeface(font);

谷歌的bugtracker中有这样一个问题:

如果由于某些客户的问题(我可以理解),特别是埃及语言环境无法工作,那么您可以将字符串格式化为任何其他西方语言环境。例如:

 NumberFormat nf = NumberFormat.getInstance(new Locale("en","US")); //or "nb","No" - for Norway
 String sDistance = nf.format(distance);
 distanceTextView.setText(String.format(getString(R.string.distance), sDistance));
如果使用新的
Locale
的解决方案根本不起作用,那么有一个难看的解决方法:

public String replaceArabicNumbers(String original) {
    return original.replaceAll("١","1")
                    .replaceAll("٢","2")
                    .replaceAll("٣","3")
                    .....;
}
(以及与Unicodes匹配的变体(U+0661、U+0662等)。请参阅更多类似想法)

Upd1: 为了避免到处逐个调用格式化字符串,我建议创建一个微型工具方法:

public final class Tools {

    static NumberFormat numberFormat = NumberFormat.getInstance(new Locale("en","US"));

    public static String getString(Resources resources, int stringId, Object... formatArgs) {
        if (formatArgs == null || formatArgs.length == 0) {
            return resources.getString(stringId, formatArgs);
        }

        Object[] formattedArgs = new Object[formatArgs.length];
        for (int i = 0; i < formatArgs.length; i++) {
            formattedArgs[i] = (formatArgs[i] instanceof Number) ?
                                  numberFormat.format(formatArgs[i]) :
                                  formatArgs[i];
        }
        return resources.getString(stringId, formattedArgs);
    }
}

....

distanceText.setText(Tools.getString(getResources(), R.string.distance, 24));

我希望这会有所帮助

默认区域设置是在运行时根据系统属性设置为应用程序进程静态构建的,因此它将表示启动应用程序时在该设备上选择的区域设置。通常,这很好,但这确实意味着,如果用户在应用程序进程运行后在设置中更改其区域设置,则getDefaultLocale()的值可能不会立即更新

如果出于某种原因需要在应用程序中捕获此类事件,则可以尝试从资源配置对象获取可用的区域设置,即

Locale current = getResources().getConfiguration().locale;
您可能会发现,如果应用程序需要更改设置,则此值在更改设置后更新得更快

        // please try below code
 double distance = 2.3; // ex. distance is 2.3
        Locale current = getResources().getConfiguration().locale; //get current locale
        Log.d("Locale", current + " ");


        if(current.toString().equals("ar_EG")){ //for arabic
            char[] arabicChars = {'٠','١','٢','٣','٤','٥','٦','٧','٨','٩'};
            StringBuilder builder = new StringBuilder();
            String str="2.3";
            for(int i =0;i<str.length();i++)
            {
                if(Character.isDigit(str.charAt(i)))
                {
                    builder.append(arabicChars[(int)(str.charAt(i))-48]);
                }
                else
                {
                    builder.append(str.charAt(i));
                }
            }
            Log.d("Locale"," " +builder.toString()+" كم"); // get distance in arabic كم ٢.٣
        }else if (current.toString().equals("en_US")){
            Log.d("Locale"," " +distance+" KM"); // get distance in us english 2.3 KM
        }
//请尝试下面的代码
双倍距离=2.3;//距离是2.3
当前语言环境=getResources().getConfiguration().Locale//获取当前区域设置
Log.d(“区域设置”,当前+”);
if(current.toString().equals(“ar_EG”){//表示阿拉伯语
char[]阿拉伯字母={'٠'、'١'、'٣'、'٤'、'٥'、'٧'、'٩'};
StringBuilder=新的StringBuilder();
字符串str=“2.3”;

对于(int i=0;i有一种简单的方法。使用整数并将其格式化为字符串,它将通过此方法对数字隐式应用本地化:

String YourNumberString = String.format("%d", YourNumberInteger);
所以123会变成١٣٣等等

有关更多信息,请参阅“格式编号”一节,网址为: 在JAVA中

String.format(Locale.US, getString(R.string.distance), distance)
在Kotlin中,我们可以添加扩展功能:

fun Resources.formatStringWithArabicNumbers(resId: Int, vararg args: Any?)
    = String.format(Locale.US, this.getString(resId), *args)
我们可以这样称呼它:

resource.formatStringWithArabicNumbers(R.string.distance, distance)

我使用String类的format方法解决了这个问题,效果非常好:

String correctLocaleTime = String.format(new Locale("en","US"),
            "%02d:%02d", 
            minutes, 
            seconds)
只需将一个局部实例变量传递到format方法的第一个参数中


此代码仅适用于希望了解我的解决方案上下文的人员:

 @Override
    public void onBindViewHolder(final RecordingsViewHolder holder, int position) {

        RecordingItem item = getItem(position);
        long itemDuration = item.getLength();

        long minutes = TimeUnit.MILLISECONDS.toMinutes(itemDuration);
        long seconds = TimeUnit.MILLISECONDS.toSeconds(itemDuration)
                - TimeUnit.MINUTES.toSeconds(minutes);

        holder.vLength.setText(String.format(new Locale("en","US"),
                "%02d:%02d",
                minutes,
                seconds));
}

你的意思是不使用阿拉伯语区域设置,只使用不同的字体吗?但这会破坏文本的RTL对齐方式只是澄清一下,数字0、1、2、3、4、5、6、7、8、9是阿拉伯语,数字的另一个形状是印地安语,为什么他们将印度数字与阿拉伯语区域设置一起使用?我怎么知道,在谷歌上查找man@s你不知道你在说什么。阿拉伯数字是:I1632£٢٣٤٥٦٧٨٩。至于这些0123456789,这是阿拉伯数字系统或数字,全世界都在使用。@simsim他们通常用什么符号来表示数字,例如说“2.3公里”?好的,这个解决方案需要更改我在字符串中使用数字的所有位置,这就是我试图避免使用数字的原因。但是感谢您提供有关旧Android问题的信息。@kingston您可以通过引入新类
TextView with arabicDigits extensed TextView
,其中
override
setText来简化它(CharSequence text,BufferType type)
并添加检查是否有任何错误的数字-在那里替换它们。然后你只需要使用带有阿拉伯数字的
TextView,而不是
TextView
。没有太多额外的代码。@kingston在我的答案中添加了建议。谢谢。我喜欢你的第二个解决方案(使用helper方法).让我们看看是否有更简单的问题…@kingston yep,事实上这是一个非常有趣的问题,干得好!让我们看看它将走向何方。但这仍然会显示“东阿拉伯”中的数字是吗?是的,这是一个选项,但在Konstantin Loginov answer中已经有了一些更干净的解决方案非常好的答案!是的,但问题是如何避免显示£٣٣,因为数字仍应显示为西方阿拉伯语数字。请继续!虽然问题没有发布语言,但显然不是Kotlin。请继续请用与中提出的问题相同的语言发布答案。
 @Override
    public void onBindViewHolder(final RecordingsViewHolder holder, int position) {

        RecordingItem item = getItem(position);
        long itemDuration = item.getLength();

        long minutes = TimeUnit.MILLISECONDS.toMinutes(itemDuration);
        long seconds = TimeUnit.MILLISECONDS.toSeconds(itemDuration)
                - TimeUnit.MINUTES.toSeconds(minutes);

        holder.vLength.setText(String.format(new Locale("en","US"),
                "%02d:%02d",
                minutes,
                seconds));
}