EDIT
I'm porting my app to Arabic locale. I have some getString() with parameters like:
getString(R.string.distance, distance)
where <string name="distance">%1d km</string>
The requirement is that in Arabic I should show it like this: "2.3 كم".
If I set as the locale for Saudi Arabia (country = "sa") or UAE (country = "ae") the number are shown in Eastern-Arabic but my client wants them in Western-Arabic.
The solution here is to use Egypt as a country in the locale but this is not possible for me.
I tried:
@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());
}
as suggested in this question but after that the country is ignored so both SA and AE locales use the strings in the default file.
Go to Tools > Options > click on the "Complex scripts" tab, then under General: Numeral select "Context". That way, numbers will appear Hindi (i.e. Arabic) when you're writing Arabic and Arabic (i.e. English) when you're writing English (as you probably know these numbers "1,2,3" are called Arabic numerals).
There's such issue in Google's bugtracker: Arabic numerals in arabic language intead of Hindu-Arabic numeral system
If particularly Egypt locale doesn't work due to some customer's issue(I can understand it), then you can format your string to any other western locales. For example:
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));
If solution with new Locale
doesn't work at all, there's an ugly workaround:
public String replaceArabicNumbers(String original) {
return original.replaceAll("١","1")
.replaceAll("٢","2")
.replaceAll("٣","3")
.....;
}
(and variations around it with Unicodes matching (U+0661,U+0662,...). See more similar ideas here)
Upd1: To avoid calling formatting strings one by one everywhere, I'd suggest to create a tiny Tool method:
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));
Or to override the default TextView
and handle it in 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;
}
}
I hope, it helps
There is an easy way. Taking your integer number and format it to string, and it will apply localization implicitly to numbers by this method:
String YourNumberString = String.format("%d", YourNumberInteger);
So 123 will become ١٢٣ and so on.
For more information see section "Format numbers" at: https://developer.android.com/training/basics/supporting-devices/languages
Set your TypeFace as per below for Arabic
Typeface font = Typeface.createFromAsset(getAssets(), "fonts/abcd.TTF");
abcd is Arabic font.
textview.setTypeface(font);
The default Locale is constructed statically at runtime for your application process from the system property settings, so it will represent the Locale selected on that device when the application was launched. Typically, this is fine, but it does mean that if the user changes their Locale in settings after your application process is running, the value of getDefaultLocale() probably will not be immediately updated.
If you need to trap events like this for some reason in your application, you might instead try obtaining the Locale available from the resource Configuration object, i.e.
Locale current = getResources().getConfiguration().locale;
You may find that this value is updated more quickly after a settings change if that is necessary for your application.
// 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
}
As the question title has the generic word "Android", I propose another Kotlin solution for Kotlin developers ending up here. This might not be the best solution regarding performance.
fun String.convertDigitsToWesternArabic() = this
// Replace Eastern Arabic numerals
.replace(Regex("[٠-٩]")) { match -> (match.value.single() - '٠').toString() }
// Replace Persian/Urdu numerals
.replace(Regex("[۰-۹]")) { match -> (match.value.single() - '۰').toString() }
val result = "۱۲۳ کم".convertDigitsToWesternArabic() // result: "123 کم"
See this Wikipedia article for difference between these numerals.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With