Ariyan
Ariyan

Reputation: 15158

How to convert a String to another locale?

I need to convert Arabic/Persian Numbers to its English equal (for example convert "۲" to "2")

How can I do this?

Upvotes: 32

Views: 23106

Answers (14)

sujith s
sujith s

Reputation: 914

This code will work with decimal points also:

public class mainsupport {
public static void main(String args[]){
//  String Numtoconvert="15.3201" ;
//  String Numtoconvert="458" ;
    String Numtoconvert="٨٧٫٥٩٨" ; // integer value 87.598
    
      System.out.println(getUSNumber(Numtoconvert));
}
private static String getUSNumber(String Numtoconvert){
    
    NumberFormat formatter = NumberFormat.getInstance(Locale.US);
      try {
          if(Numtoconvert.contains("٫"))      
          Numtoconvert=formatter.parse(Numtoconvert.split("٫")[0].trim())+"."+formatter.parse(Numtoconvert.split("٫")[1].trim());
          else
              Numtoconvert=formatter.parse(Numtoconvert).toString();
      } catch (ParseException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
      return Numtoconvert;
}

This prints 87.598.

Upvotes: 3

Navas Basheer
Navas Basheer

Reputation: 960

I achived this by java.math.BigDecimal Class, Below is the code snippet

String arabicNumerals = "۴۲۴۲.۴۲";
String englishNumerals = new BigDecimal(arabic).toString();
System.out.println("Number In Arabic : "+arabicNumerals);
System.out.println("Number In English : "+englishNumerals);

Result

Number In Arabic : ۴۲۴۲.۴۲
Number In English : 4242.42

NB: The above code will not work if there are any characteors other than numeric digits in arabicNumerals, for example: ۴,۲۴۲.۴۲ will result in a java.lang.NumberFormatException, so you may remove other characters using Character.isDigit(char ch) in another logic and use the above code. All normal cases are working.

Upvotes: 27

Mahsa Alamdari
Mahsa Alamdari

Reputation: 62

Try this for converting Persian/Arabic numbers to English:

public static String convertToEnglish(String arabicNumber) {
    for (int i = 0; i <= 9; i++) {
        arabicNumber= arabicNumber.replace((char) (1776 + i),
                (char) (48 + i));
    }
    return arabicNumber;
}

Upvotes: 0

Peter Lawrey
Peter Lawrey

Reputation: 533530

I suggest you have a ten digit lookup String and replace all the digits one at a time.

public static void main(String... args) {
    System.out.println(arabicToDecimal("۴۲"));
}
//used in Persian apps
private static final String extendedArabic = "\u06f0\u06f1\u06f2\u06f3\u06f4\u06f5\u06f6\u06f7\u06f8\u06f9";

//used in Arabic apps
private static final String arabic = "\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669";

private static String arabicToDecimal(String number) {
    char[] chars = new char[number.length()];
    for(int i=0;i<number.length();i++) {
        char ch = number.charAt(i);
        if (ch >= 0x0660 && ch <= 0x0669)
           ch -= 0x0660 - '0';
        else if (ch >= 0x06f0 && ch <= 0x06F9)
           ch -= 0x06f0 - '0';
        chars[i] = ch;
    }
    return new String(chars);
}

prints

42

The reason for using the strings as a lookup is that other characters such as . - , would be left as is. In fact a decimal number would be unchanged.

Upvotes: 38

Anonymous
Anonymous

Reputation: 86286

The following seems to me to be the simple and obvious solution. I don’t know why it hasn’t been posted before.

    Locale persian = Locale.forLanguageTag("fa");
    NumberFormat nf = NumberFormat.getIntegerInstance(persian);
    
    String persianIntegerString = "۲۱";
    
    int parsedInteger = nf.parse(persianIntegerString).intValue();

    System.out.println(parsedInteger);

Output is:

21

If we’ve got a string with a decimal point in it (or just one that may have that), use getInstance instead of getIntegerInstance. At the same time I am taking an Arabic string this time to demonstrate that this works too.

    Locale arabic = Locale.forLanguageTag("ar");
    NumberFormat nf = NumberFormat.getInstance(arabic);
    
    String arabicDecimalString = "٣٤٫٥٦";
    
    double parsedDouble = nf.parse(arabicDecimalString).doubleValue();

    System.out.println(parsedDouble);

34.56

In many cases the number formats can also parse numbers in other locales, but I doubt that it is always the case, so I would not want to rely on it.

Upvotes: 2

Sdghasemi
Sdghasemi

Reputation: 5598

While I was looking for the most performant solution I mixed Kishath and Sileria answers and came up with a clean and fast result:

public class StringLocalizer {
    private static final char[] ENGLISH_NUMBERS = {'\u0030', '\u0031', '\u0032', '\u0033', '\u0034', '\u0035', '\u0036', '\u0037', '\u0038', '\u0039'};
    private static final char[] PERSIAN_NUMBERS = {'\u06f0', '\u06f1', '\u06f2', '\u06f3', '\u06f4', '\u06f5', '\u06f6', '\u06f7', '\u06f8', '\u06f9'};
    private static final char[] ARABIC_NUMBERS = {'\u0660', '\u0661', '\u0662', '\u0663', '\u0664', '\u0665', '\u0666', '\u0667', '\u0668', '\u0669'};

    public static String on(String input) {
        String lang = Locale.getDefault().getLanguage();
        boolean isPersian = "fa".equals(lang) || "ur".equals(lang);
        boolean isArabic = "ar".equals(lang);
        if (isPersian) return input
                .replace(ENGLISH_NUMBERS[0], PERSIAN_NUMBERS[0])
                .replace(ENGLISH_NUMBERS[1], PERSIAN_NUMBERS[1])
                .replace(ENGLISH_NUMBERS[2], PERSIAN_NUMBERS[2])
                .replace(ENGLISH_NUMBERS[3], PERSIAN_NUMBERS[3])
                .replace(ENGLISH_NUMBERS[4], PERSIAN_NUMBERS[4])
                .replace(ENGLISH_NUMBERS[5], PERSIAN_NUMBERS[5])
                .replace(ENGLISH_NUMBERS[6], PERSIAN_NUMBERS[6])
                .replace(ENGLISH_NUMBERS[7], PERSIAN_NUMBERS[7])
                .replace(ENGLISH_NUMBERS[8], PERSIAN_NUMBERS[8])
                .replace(ENGLISH_NUMBERS[9], PERSIAN_NUMBERS[9]);
        else if (isArabic) return input
                .replace(ENGLISH_NUMBERS[0], ARABIC_NUMBERS[0])
                .replace(ENGLISH_NUMBERS[1], ARABIC_NUMBERS[1])
                .replace(ENGLISH_NUMBERS[2], ARABIC_NUMBERS[2])
                .replace(ENGLISH_NUMBERS[3], ARABIC_NUMBERS[3])
                .replace(ENGLISH_NUMBERS[4], ARABIC_NUMBERS[4])
                .replace(ENGLISH_NUMBERS[5], ARABIC_NUMBERS[5])
                .replace(ENGLISH_NUMBERS[6], ARABIC_NUMBERS[6])
                .replace(ENGLISH_NUMBERS[7], ARABIC_NUMBERS[7])
                .replace(ENGLISH_NUMBERS[8], ARABIC_NUMBERS[8])
                .replace(ENGLISH_NUMBERS[9], ARABIC_NUMBERS[9]);
        else return input
                .replace(PERSIAN_NUMBERS[0], ENGLISH_NUMBERS[0])
                .replace(PERSIAN_NUMBERS[1], ENGLISH_NUMBERS[1])
                .replace(PERSIAN_NUMBERS[2], ENGLISH_NUMBERS[2])
                .replace(PERSIAN_NUMBERS[3], ENGLISH_NUMBERS[3])
                .replace(PERSIAN_NUMBERS[4], ENGLISH_NUMBERS[4])
                .replace(PERSIAN_NUMBERS[5], ENGLISH_NUMBERS[5])
                .replace(PERSIAN_NUMBERS[6], ENGLISH_NUMBERS[6])
                .replace(PERSIAN_NUMBERS[7], ENGLISH_NUMBERS[7])
                .replace(PERSIAN_NUMBERS[8], ENGLISH_NUMBERS[8])
                .replace(PERSIAN_NUMBERS[9], ENGLISH_NUMBERS[9])
                .replace(ARABIC_NUMBERS[0], ENGLISH_NUMBERS[0])
                .replace(ARABIC_NUMBERS[1], ENGLISH_NUMBERS[1])
                .replace(ARABIC_NUMBERS[2], ENGLISH_NUMBERS[2])
                .replace(ARABIC_NUMBERS[3], ENGLISH_NUMBERS[3])
                .replace(ARABIC_NUMBERS[4], ENGLISH_NUMBERS[4])
                .replace(ARABIC_NUMBERS[5], ENGLISH_NUMBERS[5])
                .replace(ARABIC_NUMBERS[6], ENGLISH_NUMBERS[6])
                .replace(ARABIC_NUMBERS[7], ENGLISH_NUMBERS[7])
                .replace(ARABIC_NUMBERS[8], ENGLISH_NUMBERS[8])
                .replace(ARABIC_NUMBERS[9], ENGLISH_NUMBERS[9]);
    }
}

Note that here we assumed localizing is done between English and Persian or Arabic, so if you also need to include another language in replacing criteria just add the missing replace clauses.

Upvotes: 3

Flovettee
Flovettee

Reputation: 993

Character.getNumericValue(ch) saved my life, generic solution for any locale.

static String replaceNonstandardDigits(String input) {
    if (input == null || input.isEmpty()) {
        return input;
    }

    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < input.length(); i++) {
        char ch = input.charAt(i);
        if (Character.isDigit(ch) && !(ch >= '0' && ch <= '9')) {
            int numericValue = Character.getNumericValue(ch);
            if (numericValue >= 0) {
                builder.append(numericValue);
            }
        } else {
            builder.append(ch);
        }
    }
    return builder.toString();
}

Upvotes: 4

Sepehr Nozaryian
Sepehr Nozaryian

Reputation: 370

i think the best way is to change the Locale to what you want for example,
for double number :

NumberFormat fmt = NumberFormat.getNumberInstance(Locale.US);
d = Double.parseDouble(s);

for String :

NumberFormat.getNumberInstance(Locale.US).format(s);

or DecimalFormat:

double num;
DecimalFormat df = new DecimalFormat("###.###");
df.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US));
String s = df.format(num);

Upvotes: 3

Hend
Hend

Reputation: 36

Use Locale class to convert numbers.

 Locale locale = new Locale("ar");
 String formattedArabic = format(locale, "%d", value));

Upvotes: 1

Mehdi Khademloo
Mehdi Khademloo

Reputation: 2812

so trivial answer:

public static String convertNumbersToPersian(String str)
{
    String answer = str;
    answer = answer.replace("1","١");
    answer = answer.replace("2","٢");
    answer = answer.replace("3","٣");
    answer = answer.replace("4","٤");
    answer = answer.replace("5","٥");
    answer = answer.replace("6","٦");
    answer = answer.replace("7","٧");
    answer = answer.replace("8","٨");
    answer = answer.replace("9","٩");
    answer = answer.replace("0","٠");
    return answer;
}

and

public static String convertNumbersToEnglish(String str) {
    String answer = str;
    answer = answer.replace("١", "1");
    answer = answer.replace("٢", "2");
    answer = answer.replace("٣", "3");
    answer = answer.replace("٤", "4");
    answer = answer.replace("٥", "5");
    answer = answer.replace("٦", "6");
    answer = answer.replace("٧", "7");
    answer = answer.replace("٨", "8");
    answer = answer.replace("٩", "9");
    answer = answer.replace("٠", "0");
    return answer;
}

Upvotes: 5

Kishath
Kishath

Reputation: 5784

I found a simpler and faster way which includes the two arabic code pages too.

public static String convertToEnglishDigits(String value)
{
     String newValue = value.replace("١", "1").replace("٢", "2").replace("٣", "3").replace("٤", "4").replace("٥", "5")
             .replace("٦", "6").replace("7", "٧").replace("٨", "8").replace("٩", "9").replace("٠", "0")
             .replace("۱", "1").replace("۲", "2").replace("۳", "3").replace("۴", "4").replace("۵", "5")
             .replace("۶", "6").replace("۷", "7").replace("۸", "8").replace("۹", "9").replace("۰", "0");

     return newValue;
}

It will return the numbers in English format or vise versa if you change the replace from.
("۰", "0") to ("0","۰")

Upvotes: 14

Sileria
Sileria

Reputation: 15632

Try this guys:

/**
 * Utility class to detect arabic languages and convert numbers into arabic digits.
 *
 * @author Ahmed Shakil
 * @date 09-24-2012
 */
public final class ArabicUtil {

private static final char[] DIGITS = {'\u0660','\u0661','\u0662','\u0663','\u0664','\u0665','\u0666','\u0667','\u0668','\u0669'};

/**
 * Returns <code>true</code> if the provided language code uses arabic characters; othersise <code>false</code>.
 * @param lang ISO language code.
 * @return <code>true</code> if the provided language code uses arabic characters; othersise <code>false</code>
 */
public static boolean isArabic (String lang) {
    return "ar".equals(lang) || "fa".equals(lang) || "ur".equals(lang);
}

/**
 * Convert digits in the specified string to arabic digits.
 */
public static String convertDigits (String str) {
    if (str == null || str.length() == 0) return str;

    char[] s = new char[str.length()];
    for(int i =0;i<s.length;i++)
        s[i] = toDigit( str.charAt( i ) );

    return new String(s);
}

/**
 * Convert single digit in the specified string to arabic digit.
 */
public static char toDigit (char ch) {
    int n = Character.getNumericValue( (int)ch );
    return n >=0 && n < 10 ? ARABIC[n] : ch;
}

/**
 * Convert an int into arabic string.
 */
public static String toString (int num) {
    return convertDigits( Integer.toString( num ) );
}
}

BTW there is a difference between arabic digits vs. urdu/farsi: Arabic:

private static final char[] ARABIC     = {'\u0660', '\u0661', '\u0662', '\u0663', '\u0664', '\u0665', '\u0666', '\u0667', '\u0668', '\u0669'};

Urdu or Farsi:

private static final char[] URDU_FARSI = {'\u06f0', '\u06f1', '\u06f2', '\u06f3', '\u06f4', '\u06f5', '\u06f6', '\u06f7', '\u06f8', '\u06f9'};

Upvotes: 9

Paŭlo Ebermann
Paŭlo Ebermann

Reputation: 74760

I think instead of replacing the digits one by one (which would only work for decimal numbers), you should parse your number with a persian NumberFormat to a number, and then (if necessary) use a english NumberFormat to format it again.

Upvotes: -3

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340743

First make it work, then make it look nice ;-)

public static char persianDigitToEnglish(char persianDigit) {
    return (char) (((int)persianDigit) - ((int)'۲' - (int)'2'));
}

Works for 2, unfortunately I don't know other Persian digits, could You give it a try?

assertThat(persianDigitToEnglish('۲')).isEqualTo('2');

EDIT: (based on Peter Lawrey String version, but uses StringBuilder)

public static String persianDigitToEnglish(String persianNumber) {
    StringBuilder chars = new StringBuilder(persianNumber.length());
    for (int i = 0; i < persianNumber.length(); i++)
        chars.append(persianDigitToEnglish(persianNumber.charAt(i)));
    return chars.toString();
}

private static char persianDigitToEnglish(char persianDigit) {
    return (char) (((int)persianDigit) - ((int)'۲' - (int)'2'));
}

Upvotes: 5

Related Questions