5

I'm building a software that takes integers from users and does some calculations and then outputs the result. The thing is that I want to take users numbers using English numbers(0, 1, 2, etc.) and I want to present the numbers using Persian numbers(like Arabic) in the output. I've read some topics on Unicode conversion and things like replace() and charCodeAt() but I can't understand the code.

Here's a piece of code.(It converts Persian numbers into English numbers but I want to do the opposite.)

 var yas ="٠١٢٣٤٥٦٧٨٩";
 yas = Number(yas.replace(/[٠١٢٣٤٥٦٧٨٩]/g, function (d) {
     return d.charCodeAt(0) - 1632;                
     }).replace(/[۰۱۲۳۴۵۶۷۸۹]/g, function (d) { return d.charCodeAt(0) - 1776; })
 );
assembler
  • 3,098
  • 12
  • 43
  • 84
Amirhosein Al
  • 470
  • 6
  • 18
  • Pardon my ignorance, but do you really have two separate glyphs for 4 and 6? ٤ and ۴, and ٦ and ۶? If so, when going from English to Persian, which do you want to use? – T.J. Crowder Nov 08 '17 at 15:20
  • @T.J.Crowder I looked it up. The first set is Arabic numbers, the second is Persian numbers. – Klas Lindbäck Nov 08 '17 at 15:35

2 Answers2

3

That Persian-to-English script seems unnecessarily complicated, which makes me wonder if I'm missing something.

Basically, with such a limited data set, the simplest thing is to give yourself a map either way:

// The "Persian" here aren't just Persian, nor are the English just English.
// Both numeral sets are used in multiple languages...

// One time setup
var persian ="٠١٢٣٤٥٦٧٨٩";
var mapPtoE = Object.create(null);
var mapEtoP = Object.create(null);
persian.split("").forEach(function(glyph, index) {
  mapPtoE[glyph] = index;
  mapEtoP[index] = glyph;
});
// Convert one char "Persion" => "English"
function charPtoE(ch) {
  return mapPtoE[ch] || ch;
}
// Convert one char "English" => "Persion"
function charEtoP(ch) {
  return mapEtoP[ch] || ch;
}
// Convert the "Persian" digits in a string to "English"
function strPToE(s) {
  return s.replace(/[٠١٢٣٤٥٦٧٨٩]/g, charPtoE);
}
// Convert the "English" digits in a string to "Persian"
function strEToP(s) {
  return s.replace(/\d/g, charEtoP);
}

// Demonstrate converting "Persian" to "English"
console.log("Test A ٠١٢٣", "=>", strPToE("Test A ٠١٢٣"));
console.log("Test B ٦٥٤", "=>",  strPToE("Test B ٦٥٤"));
console.log("Test C ٧٨٩", "=>",  strPToE("Test C ٧٨٩"));

// Demonstrate converting "English" to "Persian"
console.log("Test A 0123", "=>", strEToP("Test A 0123"));
console.log("Test B 654", "=>",  strEToP("Test B 654"));
console.log("Test C 789", "=>",  strEToP("Test C 789"));

From your question it looks like there can be more than one form for 4 and 6 (pardon my ignorance); if so, you'll want to adjust the above to handle that in the "Persian" to "English" conversion, and pick one to use going the other way.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    More elegant than mine. Knowing that the context is Farsi but that the provided example is Arabic is interesting. The numbers provided by OP in the example are Arabic. The second alternative you found is traditional Farsi. 5 also differs between writing systems, and can be written ۵ (almost like an upside-down heart, compared with the more circular Arabic ٥). – msanford Nov 08 '17 at 15:34
  • I think you got it wrong! the strings(۰۱۲۳۴۵۶۷۸۹) are just an example. More accurately, I want to take numbers from the user (Persian strings), convert them to integers(obviously English integers), do some calculations, then return them to the user(in Persian strings). Since I'm planning to deploy my app in Persian I don't want to have English strings presented to the user. (and the code above isn't mine.) @t-j-crowder – Amirhosein Al Nov 08 '17 at 21:28
  • Usually ۴ and ۶ are used in Persian. @t-j-crowder – Amirhosein Al Nov 08 '17 at 21:37
  • As I can see your code breaks if I change the strings because it just simply maps the characters to each other. @t-j-crowder – Amirhosein Al Nov 08 '17 at 21:45
  • @AmirhoseinAl: You wouldn't change the *map*. But you can pass any string through that you want. I've edited to make that clearer (and to put the bits handling entire strings into functions). – T.J. Crowder Nov 09 '17 at 07:29
  • It's obviously a prefect piece of code that works like a shine. I appreciate your time. Thank you! @t-j-crowder – Amirhosein Al Nov 09 '17 at 10:52
  • @AmirhoseinAl: LOL, that's going a *bit* far... :-) – T.J. Crowder Nov 09 '17 at 10:53
2

It looks like the code you posted handles both Arabic and Persian digits. To convert back you can use either

var yas ="1234567890";

// To Arabic digits
yas = yas.replace(/[0-9]/g, function (d) {
    return d.charCodeAt(0) + 1632;    // 1632 == '٠' - '0'           
});

or

// To Persian digits
yas = yas.replace(/[0-9]/g, function (d) {
    return d.charCodeAt(0) + 1776;  // 1776 == '۰' - '0' 
});

depending on which set you want to use.

The numbers 1632 and 1776 is the difference between the codepoints for regular digits and the codepoints for the Arabic and Persian digits.

Klas Lindbäck
  • 33,105
  • 5
  • 57
  • 82