How to replace numbers in body to Persian numbers?
Asked Answered
A

14

29

I want to convert every number in the html content to Persian numerals without other effects on page elements.

For example:

<div style='color: #c2c2c2'>
  text number 1
  <span>text number 2</span>
  <div>
    text number 3
    <b>text number 4</b>
    <a href='#page2'>text number 5</a>
  </div>
</div>

be converted to:

<div style='color: #c2c2c2'>
  text number ۱
  <span>text number ۲</span>
  <div>
    text number ۳
    <b>text number ۴</b>
    <a href='#page2'>text number ۵</a>
  </div>
</div>
let persian = array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹');
let english = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');

Thanks.

Augusto answered 6/3, 2013 at 12:29 Comment(2)
Why would you do that client-side (as your tags imply), instead of generating the desired content when producing the HTML document in the first place?Backstop
I know do it server side is simpler but i have to do it client side with javascriptAugusto
I
34

You can use this method: (http://jsfiddle.net/A4NfG/1/)

persian={0:'۰',1:'۱',2:'۲',3:'۳',4:'۴',5:'۵',6:'۶',7:'۷',8:'۸',9:'۹'};
function traverse(el){
    if(el.nodeType==3){
        var list=el.data.match(/[0-9]/g);
        if(list!=null && list.length!=0){
            for(var i=0;i<list.length;i++)
                el.data=el.data.replace(list[i],persian[list[i]]);
        }
    }
    for(var i=0;i<el.childNodes.length;i++){
        traverse(el.childNodes[i]);
    }
}
Invincible answered 6/3, 2013 at 13:26 Comment(1)
It works in chrome but in firefox it changes nothing...is there a way to make it work in firefox too?Dunkle
J
8

There is this findAndReplaceDOMText.js that may help you. It walks through all nodes in the document (as opposed to all elements) and replaces the text when the nodeType argument equals 3, which is TEXT_NODE.

This example will replace numbers in the whole page:

function walkNode(node) { 
    if (node.nodeType == 3) {
        // Do your replacement here
        node.data = node.data.replace(/\d/g,convert);
    }
        
    // Also replace text in child nodes
    for (var i = 0; i < node.childNodes.length; i++) {
        walkNode(node.childNodes[i]); 
    }
}
    
walkNode(document.getElementsByTagName('body')[0]);

function convert(a){
    return ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'][a];
}

See JavaScript String.replace documentation here.

Juneberry answered 6/3, 2013 at 13:5 Comment(0)
S
5

If you want to select some elements by a selector, you can use this simple code (JsFiddle):

persian={0:'۰',1:'۱',2:'۲',3:'۳',4:'۴',5:'۵',6:'۶',7:'۷',8:'۸',9:'۹'};
$(".persian-digit").each(function(){
    for(var i=0;i<=9;i++) {
        var re = new RegExp(i,"g");
        $(this).html($(this).html().replace(re,persian[i]));
    }
});

Then for use it:

<span class="persian-digit">This span contains persian digits (0123456789),</span>
<span>and this one contains english digits (0123456789).</span>
Spangle answered 10/1, 2015 at 13:42 Comment(0)
U
5

I wrote this short and simple code.

// ES6
const regex = /[۰-۹]/g
let str = '۰۱۲۳۵۴۸۹۰۷۸۹۰۱۲';
let result = str.replace(regex, function (w) {
    return String.fromCharCode(w.charCodeAt(0) - 1728)
  }
)

console.log(result);
Untoward answered 14/11, 2016 at 22:15 Comment(0)
S
4

ES6 one-liner

Functions based on @mcrunix's answer:

fa2enDigits Returns string with Persian digits replaced with English digits:

const fa2enDigits = s => s.replace(/[۰-۹]/g, w => String.fromCharCode(w.charCodeAt(0) - 1728) )

en2faDigits Returns string with English digits replaced with Persian digits:

const en2faDigits = s => s.replace(/[0-9]/g, w => String.fromCharCode(w.charCodeAt(0) + 1728) )

examples:

const fa2enDigits = s => s.replace(/[۰-۹]/g, w => String.fromCharCode(w.charCodeAt(0) - 1728) )

const en2faDigits = s => s.replace(/[0-9]/g, w => String.fromCharCode(w.charCodeAt(0) + 1728) )


console.log('Tel: ۰۹۱۲', '=>' , fa2enDigits('Tel: ۰۹۱۲') );
console.log('Tel: 0912', '=>' , en2faDigits('Tel: 0912') );
Sentimental answered 10/9, 2021 at 6:41 Comment(0)
H
2
<script>

    function en2fa(num){
        let arr = [];
        persian = {0:'۰',1:'۱',2:'۲',3:'۳',4:'۴',5:'۵',6:'۶',7:'۷',8:'۸',9:'۹'};
        num.split('').map((number,index)=>{
            arr[index] = (persian[number]);
        });
        return arr.join('');
    }

    console.log(en2fa("86598231452"));

</script>

test this code in codepen

https://codepen.io/bashirpour/pen/JvgeYy

Harmonic answered 27/5, 2018 at 13:2 Comment(0)
B
1

If you wanna use it on a specific element or selector, this might help :

var persian = Array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹');
   function replaceDigits(selector) {

      for(i=0;i<10;i++){

         var regex=eval("/"+i+"/g");

         $(selector).html($(selector).html().replace(regex,persian[i]));

      }

   }

replaceDigits(".selected");

Worked for me!

Beggary answered 7/5, 2014 at 11:34 Comment(0)
F
1

You can use Number.toLocaleString() to convert and format a single number.

let myNumberStr = "123456.7890";
let myNumber = Number(myNumberStr); // Convert from string to number
let persian = myNumber.toLocaleString("fa"); // OR "fa-IR" for IRAN

The more advanced and complete answer (convert all numbers in page)

localizeNumbers(document.getElementsByTagName('body')[0]);

function localizeNumbers(node) { 
    if (node.nodeType == Node.TEXT_NODE) {
        // Use this if target numbers may contain comma as thousands separators
        node.data = node.data.replace(/([,\d]*\.?\d+)/g, localize);
        // Use this if you do not want to treat comma as thousands separator
        // node.data = node.data.replace(/(\d*\.?\d+)/g, localize);
    }
    // Also, replace numbers in child nodes
    node.childNodes.forEach(localizeNumbers);
}

function localize(numberString) {
  // Convert from string to number
  // Use this if target numbers may contain comma as thousands separators
  let number = Number(numberString.replace(/[^\d.]/g, ""));
  // Use this if you do not want to treat comma as thousands separator
  // let number = Number(numberString);

  // Could also have used "fa-IR" for IRAN
  let persian = number.toLocaleString("fa", { maximumFractionDigits: 10 });
  // Could also have used "en-US" for USA
  let english = number.toLocaleString("en", { maximumFractionDigits: 10 });
  // Could also have used "ar" (which seems to use western digits). "EG" is for Egypt
  let arabic = number.toLocaleString("ar-EG", { maximumFractionDigits: 10 });

  console.log(`Persian: ${persian}`);
  console.log(`English: ${english}`);
  console.log(`Arabic: ${arabic}\n`);

  return persian;
}

localizeNumbers(document.getElementsByTagName('body')[0]);

function localizeNumbers(node) { 
  if (node.nodeType == Node.TEXT_NODE) {
    node.data = node.data.replace(/([,\d]*\.?\d+)/g, localize);
  }
  node.childNodes.forEach(localizeNumbers);
}

function localize(numberString) {
  let number = Number(numberString.replace(/[^\d.]/g, ""));
  let persian = number.toLocaleString("fa", { maximumFractionDigits: 10 });
  let english = number.toLocaleString("en", { maximumFractionDigits: 10 });
  let arabic = number.toLocaleString("ar-EG", { maximumFractionDigits: 10 });

  console.log(`Persian: ${persian}`);
  console.log(`English: ${english}`);
  console.log(`Arabic: ${arabic}\n`);

  return persian;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Test</title>
<script src="script.js" defer></script>
</head>
<body>


  <div style='color: #c2c2c2'>
    text number 1
    <span>text number 2</span>
    <div>
      text number 3
      <b>text number 4</b>
      <a href='#page2'>text number 5</a>
    </div>
  </div>


  1234
  <div>
    1234
    <p>1234</p>
  </div>
  <p>1234</p>
  <p>1,234</p>
  <p>1234.5678</p>
  <p>1,234.5678</p>
  <p>0.1234</p>
  <p>.1234</p>
  <p>abc1234</p>
  <p>abc1,234</p>
  <p>abc1234def</p>
  <p>abc1,234def</p>
  <p>abc 1234def</p>
  <p>abc 1,234def</p>
  <p>abc 1234 def</p>
  <p>abc 1,234 def</p>
  <p>abc1234.567</p>
  <p>abc1,234.567</p>
  <p>abc1234.567def</p>
  <p>abc1,234.567def</p>
  <p>abc 1234.567def</p>
  <p>abc 1,234.567def</p>
  <p>abc 1234.567 def</p>
  <p>abc 1,234.567 def</p>
</body>
</html>

Notes

  1. The solution will treat numbers as Numbers not as Strings. If you do not specify the maximumFractionDigits in the options object of toLocaleString, the formatted number my be rounded. See this post.

  2. To omit thousands separators in the formatted number, add useGrouping: false in the options object of toLocaleString. Refer to MDN Web Docs: Intl.NumberFormat() and W3Schools: JavaScript Number toLocaleString() to see all the other available options.

  3. The solution will format the number with correct Persian thousands separator and decimal separator (called momayyez). With the default browser fonts and some other fonts, both of those characters may look similar to a Latin comma (,) but they are actually three different characters with three different Unicode values:

    Name Unicode value Rendered
    Latin comma U+002C ,
    Arabic/Persian thousands separator U+066C ٬
    Arabic/Persian decimal separator U+066B ٫
  4. The code assumes that all the original numbers in the HTML are in English format (which uses comma for thousands separator and dot for decimal separator).

I used a modified version of Sjoerd answer here. Thanks to him for his answer.

For a list of different common numerals see this Wikipedia article. Also, see this post and this post. You could also use persian.js library to do this all.

Fluorocarbon answered 23/12, 2021 at 21:36 Comment(0)
F
1

just put it in a span or p tag with specific class and change the font of that class to a persian font like 'B yekan'. i've tested.worked.

Fuel answered 31/8, 2022 at 9:50 Comment(3)
Please explain your answerToast
obvious. we put our numbers in <span>(or another tag, according to need) and change font of <span> to an persian font.Fuel
I should have been clearer, my comment was to get you to make your answer better. It is always better with an example.Toast
P
0

Another Simple way:

String.prototype.toEnglishDigits = function () {
     var charCodeZero = '۰'.charCodeAt(0);

     return this.replace(/[0-9]/g, function (w) {
         return String.fromCharCode(parseInt(w) + charCodeZero);
      });
}
Patellate answered 1/5, 2018 at 19:43 Comment(0)
O
0

all of the ways are not confident because lots of Persian users, use Arabic keyboard and Arabic chars are different with Persian numbers.

it's better to replace Arabic chars too.

for example this is zero char in Persian: ۰ and this is zero char in Arabic: ٠

as you see, both are the same but their Unicode are not the same. if you use Persian in your project, i recommend you persian.js, it's just 5 KB.

or if you don't want to use this library you can use this code:

function convertToPersianNumber(value) {
  const arabicNumbers = ['٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'];
  const persianNumbers = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];
  const englishNumbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

  let confidentValue = value;
  for (var i = 0; i < value.length; i++) {
    const inArabicIndex = arabicNumbers.indexOf(value[i]);
    if (inArabicIndex > -1) {
    confidentValue = confidentValue.replace(
      value[i],
      englishNumbers[inArabicIndex]
    );
  }

  const inPersianIndex = persianNumbers.indexOf(value[i]);
  if (inPersianIndex > -1) {
      confidentValue = confidentValue.replace(
        value[i],
        englishNumbers[inPersianIndex]
      );
    }
  }
  return confidentValue;
}
Olvan answered 12/11, 2018 at 12:39 Comment(0)
P
0
  try {
    if (!enDigit &&  !enDigit.toString().length)
      return "";

  let enDigitString = typeof enDigit === 'number' ? enDigit.toString() : enDigit;

  var newValue="";
  for (var i=0;i<enDigitString.length;i++)
  {
      var ch=enDigitString.charCodeAt(i);
      if (ch>=48 && ch<=57)
      {
          // european digit range
          var newChar=ch+1728;
          newValue=newValue+String.fromCharCode(newChar);
      }
      else
          newValue=newValue+String.fromCharCode(ch);
  }
  return newValue;

  }catch (e) {
    return "";
  }
Pizzicato answered 24/11, 2018 at 13:15 Comment(0)
D
0

Just a bit more clear snippet:

function numbersToPersian (el) {
    ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'].forEach((num, index) => {
        el.textContent = el.textContent.replace(new RegExp(index, 'g'), num);
    });
};

function traverseToLeaf (el) {
    if (el.childNodes.length === 0) return;

    el
        .childNodes
        .forEach(node => {
            if (node.nodeType === 3) {
                numbersToPersian(node);
                } else {
                traverseToLeaf(node);
            }
        });
};

// just write your element class or ID instead of '.primary' in line below
traverseToLeaf(document.querySelector('.primary'));
Dynah answered 29/12, 2018 at 1:57 Comment(0)
A
0
function persianNumber(string) {
    return string.split('0').join('۰')
    .split('1').join('۱')
    .split('2').join('۲')
    .split('3').join('۳')
    .split('4').join('۴')
    .split('5').join('۵')
    .split('6').join('۶')
    .split('7').join('۷')
    .split('8').join('۸')
    .split('9').join('۹')
}
Avictor answered 23/1, 2019 at 7:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.