Android

时间:2015-12-14 12:13:24

标签: android locale arabic

修改

我正在将我的应用移植到阿拉伯语区域设置。我有一些带有参数的getString():

getString(R.string.distance, distance)

其中<string name="distance">%1d km</string>

要求是在阿拉伯语中我应该这样表达:“2.3كم”。

如果我设置为沙特阿拉伯(country =“sa”)或阿联酋(country =“ae”)的区域设置,则该数字以东方阿拉伯语显示,但我的客户希望使用西方阿拉伯语。

解决方案 here 是将埃及用作语言环境中的国家/地区,但这对我来说是不可能的。

我试过了:

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

this question中建议但在此之后该国家被忽略,因此SA和AE区域设置都使用默认文件中的字符串。

6 个答案:

答案 0 :(得分:22)

谷歌的bugtracker中存在这样的问题:Arabic numerals in arabic language intead of Hindu-Arabic numeral system

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

 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,...)。查看更多类似的想法here

<强> 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));

或覆盖默认TextView并在setText(CharSequence text, BufferType type)

中处理
public class TextViewWithArabicDigits extends TextView {
    public TextViewWithArabicDigits(Context context) {
        super(context);
    }

    public TextViewWithArabicDigits(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void setText(CharSequence text, BufferType type) {
        super.setText(replaceArabicNumbers(text), type);
    }

    private String replaceArabicNumbers(CharSequence original) {
        if (original != null) {
            return original.toString().replaceAll("١","1")
                    .replaceAll("٢","2")
                    .replaceAll("٣","3")
                    ....;
        }

        return null;
    }
}

我希望,这有帮助

答案 1 :(得分:5)

有一种简单的方法。取整数并将其格式化为字符串,它将通过此​​方法隐式应用本地化:

   public async void Test1()
    {

        //Arrange

        Mock<IHostingEnvironment> hostingEnvironment = new Mock<IHostingEnvironment>();
        TelemetryClient telemetryClient = new TelemetryClient();
        Mock<ILogger<SearchController>> logger = new Mock<ILogger<SearchController>>();
        Mock<AppSettingsConfig> appSettings = new Mock<AppSettingsConfig>();

        Mock<IOptions<ConnectionStringsConfig>> connectionString = new Mock<IOptions<ConnectionStringsConfig>>();
        Mock<IOptions<AppSettingsConfig>> options = new Mock<IOptions<AppSettingsConfig>>();

        Mock<ILookupSearch> lookupSearch = new Mock<ILookupSearch>();
        Mock<IFullSearch> fullSearch = new Mock<IFullSearch>();
        Mock<IOneSoeUow> EmpUow = new Mock<IEmpUow>();

        //Act
        SearchController search = new SearchController(lookupSearch.Object, fullSearch.Object, oneSoeUow.Object, logger.Object, telemetryClient, hostingEnvironment.Object, connectionString.Object, options.Object);
        search.Test();

所以123会变成123,依此类推。

有关详细信息,请参阅以下位置的“格式编号”部分: https://developer.android.com/training/basics/supporting-devices/languages

答案 2 :(得分:2)

为阿拉伯语

设置您的TypeFace如下所示
Typeface font = Typeface.createFromAsset(getAssets(), "fonts/abcd.TTF");

abcd是阿拉伯字体。

textview.setTypeface(font);

答案 3 :(得分:1)

默认语言环境是在运行时为系统属性设置中的应用程序进程静态构建的,因此它将表示启动应用程序时在该设备上选择的语言环境。通常,这很好,但它确实意味着如果用户在应用程序进程运行后更改其设置中的Locale,则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
        }

答案 4 :(得分:0)

我通过使用 String 类的格式方法解决了此问题,效果很好:

String correctLocaleTime = String.format(new Locale("en","US"),
            "%02d:%02d", 
            minutes, 
            seconds)

只需将本地实例变量传递到format方法的 first 参数中即可。


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

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

答案 5 :(得分:-1)

在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)