如何将正文中的数字替换为波斯数字?

29
我希望将HTML内容中的每个数字转换为波斯数字,而不影响页面元素。
例如:
<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>

被转换为:

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

谢谢。


你为什么要在客户端这样做(正如你的标签所示),而不是在生成HTML文档时就产生所需的内容呢? - Jukka K. Korpela
我知道在服务器端做这件事更简单,但我必须使用JavaScript在客户端完成它。 - Alireza
14个回答

34
你可以使用这个方法:(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]);
    }
}

1
它在Chrome中可以工作,但在Firefox中没有任何变化...有没有办法让它在Firefox中也能工作? - Sara Nikta Yousefi

8
有一个名为 findAndReplaceDOMText.js 的工具可以帮助您。它遍历文档中的所有节点(而不是所有元素),并在 nodeType 参数等于 3(即 TEXT_NODE)时替换文本内容。
以下示例将替换整个页面中的数字:
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];
}

查看此处的 JavaScript String.replace 文档


5

如果您想通过 选择器 选择一些元素,您可以使用以下简单代码 (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]));
    }
});

然后用它的方法如下:
<span class="persian-digit">This span contains persian digits (0123456789),</span>
<span>and this one contains english digits (0123456789).</span>

5

我写了这段简短而简单的代码。

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

console.log(result);


4

ES6一行代码

@mcrunix回答的函数:

fa2enDigits 将波斯数字替换为英文数字并返回字符串:

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

en2faDigits 返回一个字符串,其中英文数字被波斯数字替换:

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

例子:

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


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>

请在Codepen中测试此代码

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


1
你可以使用 Number.toLocaleString() 来转换和格式化单个数字。
let myNumberStr = "123456.7890";
let myNumber = Number(myNumberStr); // Convert from string to number
let persian = myNumber.toLocaleString("fa"); // OR "fa-IR" for IRAN

更高级和完整的答案(将页面中所有数字转换)
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>

注意事项

  1. 该解决方案将数字视为 Number 而不是 String。如果在 toLocaleString选项对象中未指定 maximumFractionDigits,则格式化的数字可能会四舍五入。请参考此帖子

  2. 要在格式化的数字中省略千位分隔符,请在 toLocaleString 的选项对象中添加 useGrouping: false。请参考MDN Web Docs:Intl.NumberFormat()W3Schools:JavaScript Number toLocaleString() 以查看所有其他可用选项。

  3. 该解决方案将使用正确的波斯语千位分隔符小数点分隔符(称为 momayyez)。对于默认的浏览器字体和其他一些字体,这两个字符可能看起来类似于拉丁逗号 (,),但它们实际上是三个具有三个不同 Unicode 值的不同字符:

  4. 代码假定 HTML 中的所有原始数字都使用英文格式(使用逗号作为千位分隔符,使用点作为小数点分隔符)。

我在这里使用了Sjoerd的答案的修改版本。感谢他的回答。
有关不同常见数字的列表,请参见此维基百科文章。 此外,还请参见此帖子此帖子。您也可以使用persian.js库来完成所有这些操作。

1

只需将其放入具有特定类的span或p标签中,并将该类的字体更改为波斯语字体,例如'B yekan'。

我已经测试过了。有效。


请解释您的答案。 - Rohit Gupta
我们将数字放入<span>标签中(或根据需要选择其他标签),并将<span>的字体更改为波斯语字体。 - hossein shirkavand
我应该表达得更清楚,我的评论是为了让你的回答更好。有例子的话总是更好。 - Rohit Gupta

1

如果你想在特定元素或选择器上使用它,这可能会有所帮助:

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

对我很有用!


0

另一种简单的方法:

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

     return this.replace(/[0-9]/g, function (w) {
         return String.fromCharCode(parseInt(w) + charCodeZero);
      });
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接