27

文字コードを変更せずにアラビア数字のバリエーションを設定するにはどうすればよいですか?

Eastern Arabic      ۰   ۱   ۲   ۳   ٦   ٥   ٤   ۷   ۸   ۹
Persian variant     ۰   ۱   ۲   ۳   ۴   ۵   ۶   ۷   ۸   ۹
Western Arabic      0   1   2   3   4   5   6   7   8   9 
(And other numeral systems)

サンプルコードは次のとおりです。

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
</head>
<body>

<div lang="fa">0123456789</div>
<div lang="ar">0123456789</div>
<div lang="en">0123456789</div>

</body>
</html>

HTMLクライアント側のテクノロジ( 、、CSS)のみを使用してこれを行うにはどうすればよいJSですか?
このソリューションは、ページのSEOスコアに悪影響を与えることはありません。

Windowsのテキストボックス(実行など)では、周囲のテキストの言語に応じて数字が正しく表示されることに注意してください。

参照:デスクトップアプリケーションでの番号のローカリゼーション

注:このPHPパッケージhttps://github.com/salarmehr/cosmopolitanを使用すると、バックエンドで番号のローカリゼーションが非常に簡単になります。

4

9 に答える 9

16

コードシフトを使用したアプローチは次のとおりです。

// Eastern Arabic (officially "Arabic-Indic digits")
"0123456789".replace(/\d/g, function(v) {
    return String.fromCharCode(v.charCodeAt(0) + 0x0630);
});  // "٠١٢٣٤٥٦٧٨٩"

// Persian variant (officially "Eastern Arabic-Indic digits (Persian and Urdu)")
"0123456789".replace(/\d/g, function(v) {
    return String.fromCharCode(v.charCodeAt(0) + 0x06C0);
});  // "۰۱۲۳۴۵۶۷۸۹"

デモ:http: //jsfiddle.net/bKEbR/

ここでは、Unicodeシフトを使用します。これは、Unicodeグループの数字がlatinグループ(つまり)と同じ順序で配置されるため[0x0030 ... 0x0039]です。したがって、たとえば、アラビア語-インド数字のグループシフトは0x0630です。

注意:東部文字を区別するのは難しいので、間違えた場合(Unicodeには東部文字のさまざまなグループがあります)、オンラインのUnicodeテーブルを使用してシフトをいつでも計算できます。公式のUnicode文字コードチャートまたはUnicodeOnlineChartableのいずれかを使用できます。

于 2012-12-09T11:35:36.383 に答える
6

これが外見の問題なのか、それとも変容の問題なのかを判断する必要があります。また、これが文字レベルのセマンティクスまたは数字表現を含む質問であるかどうかを判断する必要があります。これが私の考えです:


Unicodeが数字のコードを分離していなかった場合、質問のセマンティクスはまったく異なります。次に、必要に応じてさまざまなグリフを表示するには、適切なフォントを使用するだけです。一方、フォントを変更せずに、以下のように単純に異なる文字を書き出すことはできなかったでしょう。(フォントは必ずしも32ビットUnicodeセットはもちろん、16ビットUnicodeセットの全範囲をカバーしているわけではないため、状況は完全ではありません。)

9, ٩ (Arabic), ۹ (Urdu), &#29590; (Chinese, complex), ๙ (Thai), ௯ (Tamil) etc.  

ここで、Unicodeセマンティクスを受け入れると仮定すると、つまり「9」、「٩」、および「۹」は別個の文字であると仮定すると、問題は外観(CSSの範囲内にあったもの)ではなく、変換-これについては後でいくつか考えますが、今のところ、これが当てはまると仮定しましょう。文字レベルのセマンティクスに焦点を当てる場合、状況はアルファベットや文字で起こることとそれほど異ならない。たとえば、ラテン語のアルファベットはEuboeaで使用されているギリシャ語のアルファベットとほぼ同じですが、ギリシャ語の「α」とラテン語の「a」は別個のものと見なされます。おそらくさらに劇的なことに、対応する大文字のバリエーションである「Α」(ギリシャ語)と「A」(ラテン語)は、両方のスクリプトをサポートする実質的にすべてのフォントで視覚的に同一です。

基本ルールを述べたので、それらを無視することによって、特に(文字レベルの)Unicodeセマンティクスを無視することによって、質問にどのように答えることができるかを見てみましょう。

(恐ろしく、厄介で、下位互換性がありません)解決策: 「0」から「9」を目的のグリフにマップするフォントを使用します。私はそのようなフォントを知りません。あなたは@font-faceとあなたが望むことをするために適切にハッキングされたいくつかのフォントを使わなければならないでしょう。

言うまでもなく、私はこのソリューションが特に好きではありません。ただし、サーバー側またはクライアント側のいずれかで「文字コードを変更せずに」質問が行うことを実行するのは、私が知っている唯一の単純なソリューションです。(技術的に言えば、以下で提案するCufonソリューションは文字コードも変更しませんが、テキストをキャンバスに描画することは非常に複雑であり、オープンソースコードを微調整する必要があります)。


注: 変換ソリューション、つまりDOMを変更し、「0」から「9」の範囲の文字を置き換えるソリューション。たとえば、アラビア語に相当するものは、数字がDOMの元の形式で表示されることを期待するコードを壊します。もちろん、この問題は、フォームと入力について議論するときに最悪です。

変革的アプローチを採用した回答の例は次のとおりです。

  $("[lang='fa']").find("*").andSelf().contents().each(function() {
      if (this.nodeType === 3) 
     {
        this.nodeValue = this.nodeValue.replace(/\d/g, function(v) {
            return String.fromCharCode(v.charCodeAt(0) + 0x0630);
       });
    }
 });

注:VisioNの2番目のjsFiddleから取得したコード。これがあなたが好きなこの答えの唯一の部分であるならば、あなたが私のものではなく、VisioNの答えに賛成することを確認してください!!! :-)

これには2つの問題があります。

  1. これはDOMを混乱させ、その結果、「標準」形式の数字(数字の「0」から「9」を使用)が見つかると想定して機能していたコードを壊す可能性があります。ここで問題を参照してください:http://jsfiddle.net/bKEbR/10/ たとえば、ユーザーが入力した整数の合計を含むフィールドがある場合、その値を取得しようとすると驚かれるかもしれません。 ..
  2. 要素の内部input(および)で何が起こっているのかという問題には対処していません。textarea入力フィールドがたとえば「42」で初期化されている場合、その値が小売りされます。これは簡単に修正できますが、実際の入力の問題があります...文字が来たら変更したり、変更したときに値を変換したりすることもできます。このような変換を行う場合は、クライアント側とサーバー側の両方で、さまざまな種類の数字を処理できるように準備する必要があります。Javascript、jQuery、さらにはGlobalize(クライアント側)、ASP.NET、PHPなど(サーバー側)の箱から出てくるものは、非標準形式の数字を入力すると壊れます...

もう少し包括的な解決策(input / textarea要素、それらの初期値とユーザー入力の両方にも注意を払う)は次のようになります。

//before the DOM change, test1 holds a numeral parseInt can understand
alert("Before: test holds the value:" +parseInt($("#test1").text()));

function convertNumChar(c) {
   return String.fromCharCode(c.charCodeAt(0) + 0x0630);
}

function convertNumStr(s) {
    return s.replace(/\d/g, convertNumChar);
}

//the change in the DOM
$("[lang='fa']").find("*").andSelf().contents()
    .each(function() {
        if (this.nodeType === 3)        
           this.nodeValue = convertNumStr(this.nodeValue);      
    })
    .filter("input:text,textarea")
    .each(function() {
         this.value = convertNumStr(this.value)
     })
     .change(function () {this.value = convertNumStr(this.value)});      

//test1 now holds a numeral parseInt cannot understand
alert("After: test holds the value:" +parseInt($("#test1").text()))

jsFiddle全体はここで見つけることができます:http://jsfiddle.net/bKEbR/13/

言うまでもなく、これは前述の問題を部分的にしか解決しません。クライアント側および/またはサーバー側のコードは、非標準の数字を認識し、それらを標準形式または実際の値に適切に変換する必要があります。

これは、数行のjavascriptで解決できる単純な問題ではありません。そして、これは、ある形式の数字から別の形式に移行するために適用する必要がある単純な文字から文字へのマッピングがあるため、このような可能な変換の最も単純なケースにすぎません。


もう1つは、外観ベースのアプローチです。

Cufonベースのソリューション(過剰な、下位互換性がない(キャンバスが必要)など): Cufonのようなライブラリを比較的簡単に調整して、想定されていることを実行できます。Cufonはその機能を実行し、キャンバスオブジェクトにグリフを描画できます。ただし、要素に特定のプロパティがある場合、通常選択されているグリフの代わりに目的のグリフが使用されるように調整します。Cufonやその他の種類のライブラリは、DOMに要素を追加し、既存の要素の外観を変更する傾向がありますが、テキストには触れないため、変換アプローチの問題は適用されません。実際、(微調整された)Cufonは、DOM全体に関する限り、明らかに変革的なアプローチを提供しますが、その精神性に関する限り、外観ベースのソリューションであることに注意してください。私はそれをハイブリッドソリューションと呼んでいます。

代替ハイブリッドソリューション: アラビア語のコンテンツを使用して新しいDOM要素を作成し、古い要素を非表示にしますが、IDとコンテンツはそのままにします。アラビア語のコンテンツ要素を、対応する非表示の要素と同期します。


ボックスの外側を考えてみましょう(ボックスは現在のWeb標準です)。

特定の文字が一意であるという事実は、それらが無関係であることを意味するものではありません。また、必ずしも外観の違いであるとは限りません。たとえば、「a」と「A」は同じ文字です。ある文脈ではそれらは同じであると見なされ、他の文脈では異なると見なされます。Unicode(およびその前のASCIIとISO-Latin-1など)の違いは、それを克服するためにいくらかの努力が必要であることを意味します。CSSは、大文字と小文字をすばやく簡単に変更する方法を提供します。たとえばbody {text-transform:uppercase}、ページ本文のテキスト内のすべての文字を大文字に変換します。これは、変換ではなく外観変更の場合でもあることに注意してください。body要素のDOMは変更されず、レンダリング方法だけが変更されます。

注: CSSがそのようなものをサポートしていればnumerals-transform: 'ar'、それが表現されていたので、おそらくその質問に対する理想的な答えだったでしょう。

ただし、CSS委員会にこの機能を追加するように急ぐ前に、それが何を意味するのかを検討することをお勧めします。ここでは、小さな問題に取り組んでいますが、全体像に対処する必要があります。

出力:この数字変換機能は、「10」(2文字)を10(中国語、単純)、15(中国語、複雑)、X(ラテン)(すべて1文字)などとして表示できるようにしますか? 'ar'の、適切な引数が与えられましたか?

入力:この数字変換機能は、「十」(中国語、単純)をアラビア語に相当するものに変更しますか、それとも単に「10」をターゲットにしますか?「MMXI」(2012年のラテン数字)が単語ではなく数字であることをどういうわけか巧みに検出し、それに応じて変換しますか?

数の表現の問題は、この質問を見ただけで想像できるほど単純ではありません。


だから、これはどこに私たちを残しますか?

  1. 単純なプレゼンテーションベースのソリューションはありません。将来登場する場合、下位互換性はありません。
  2. 今ここに変革の「解決策」があるかもしれませんが、これが私が行ったようにフォーム要素でも機能するようにされたとしても(http://jsfiddle.net/bKEbR/13/)、サーバー側と使用される非標準形式のクライアント側の認識。
  3. 複雑なハイブリッドソリューションが存在する可能性があります。それらは複雑ですが、場合によってはプレゼンテーションベースのアプローチのいくつかの利点を提供します。

CSSソリューションは素晴らしいでしょうが、実際には、他の数値システム(標準システムとの間の変換が簡単ではない)、小数点、符号などを含む全体像を見ると、問題は大きく複雑です。

結局のところ、現実的で下位互換性があると私が考えるソリューションは、Globalize(およびサーバー側の同等のもの)の拡張であり、ユーザー入力を処理するための追加のコードが含まれている可能性があります。これは文字レベルでは問題ではなく(全体像を考えれば問題ではないため)、千と小数点の違いが処理されたのと同じように処理する必要があるという考え方です。フォーマット/解析の問題として。

于 2012-12-16T03:30:07.047 に答える
2

最善の方法は、aを使用して、別の数値セットを必要とするdivにregexpaを追加することにより、変更する必要のある数字を検索することだと思います。class name

これは、jQueryを使用してかなり簡単に行うことができます。

jsfiddleデモ


編集:そして、変数を使用したくない場合は、この改訂されたデモを参照してください:

jsfiddleデモ2

于 2012-12-09T09:16:04.723 に答える
2

私は、数字だけではない一般的なWebページのローカリゼーション手法に取り組んできました(.poファイルに似ています)。

ローカリゼーションファイルは単純です(文字列には必要に応じてhtmlを含めることができます)

/* Localization file - save as document_url.lang.js ... index.html.en.js: */
items=[
{"id":"string1","value":"Localized text of string1 here."},
{"id":"string2", "value":"۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ "}
];
rtl=false; /* set to true for rtl languages */

この形式は、翻訳者(またはMechanical Turk)を分離するのに役立ちます

と基本的なページテンプレート

<html><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<head><title>My title</title>
<style>.txt{float:left;margin-left:10px}</style>
</head>
<body onload='setLang()'>
<div id="string1" class="txt">This is the default text of string1.</div>
<div id="string2" class="txt">0 1 2 3 4 5 6 7 8 9 </div>
</body></html>
<script>
   function setLang(){
      for(var i=0;i<items.length;i++){
         term=document.getElementById(items[i].id)
         if(term)term.innerHTML=items[i].value
         if(rtl){  /* for rtl languages */ 
            term.style.styleFloat="right"
            term.style.cssFloat="right"
            term.style.textAlign="right"
         }
      }
   }
   var lang=navigator.userLanguage || navigator.language;
   var script=document.createElement("script");
   script.src=document.URL+"-"+lang.substring(0,2)+".js"
   var head = document.getElementsByTagName('head')[0]
   head.insertBefore(script,head.firstChild)
</script>

私はそれをかなりシンプルに保とうとしましたが、できるだけ多くのロケールをカバーするので、追加のcssが必要になる可能性があります(rtl言語への露出が不足していることを認める必要があるため、さらに多くのスタイルを設定する必要があります)

どのフォントが文字コードをサポートしているかを知っていると便利なフォントチェックコードがあります

function hasFont(f){
    var s=document.createElement("span")
    s.style.fontSize="72px"
    s.innerHTML="MWMWM"
    s.style.visibility="hidden"
    s.style.fontFamily=[(f=="monospace")?'':'monospace','sans-serif','serif']
    document.body.appendChild(s)
    var w=s.offsetWidth
    s.style.fontFamily=[f,'monospace','sans-serif','serif']
    document.body.lastChild=s
    return s.offsetWidth!=w
}

利用方法:if(hasFont("myfont"))myelement.style.fontFamily="myfont"

于 2012-12-14T20:56:50.593 に答える
1

あなたはこれを試すことができます:これはCSSソースコードです:

@font-face
 {
   font-family: A1Tahoma;
    src: url(yourfont.eot) format('eot')
    , url(yourfont.ttf) format('truetype')
   , url(yourfont.woff) format('woff')
    , url(yourfont.svg) format('svg');
}

p{font-family:A1Tahoma; font-size:30px;}  

そしてこれはHTMLコードです:

<p>سلام به همه</p>

<p>1234567890</p>  

そして最後に、結果が表示されます。IE、FIREFOXなどのブラウザでは4つのフォントタイプが使用されることを忘れないでください。
"salam reza、to mituni in karo anjam bedi ta un fonte dekhaheto be siteezafekoni。"

于 2012-12-09T10:16:10.650 に答える
1

新しい(現在までの)単純なJSソリューションは、Intl.NumberFormatを使用することです。数字のローカリゼーション、フォーマットのバリエーション、および現地通貨をサポートしています(その他の例についてはドキュメントを参照してください)。

MDNのものと非常によく似た例を使用するには:

const val = 1234567809;
console.log('Eastern Arabic (Arabic-Egyptian)', new Intl.NumberFormat('ar-EG').format(val));
console.log('Persian variant (Farsi)',new Intl.NumberFormat('fa').format(val));
console.log('English (US)',new Intl.NumberFormat('en-US').format(val));

Intl.NumberFormatは文字列の数値もサポートしているようで、ローカル言語の数値でない場合も示します。

const val1 = '456';
const val2 = 'Numeric + string example, 123';
console.log('Eastern Arabic', new Intl.NumberFormat('ar-EG').format(val1));
console.log('Eastern Arabic', new Intl.NumberFormat('ar-EG').format(val2));
console.log('Persian variant',new Intl.NumberFormat('fa').format(val1));
console.log('Persian variant',new Intl.NumberFormat('fa').format(val2));
console.log('English',new Intl.NumberFormat('en-US').format(val1));
console.log('English', new Intl.NumberFormat('en-US').format(val2));

ロケール識別子(ロケールを示すコンストラクターに渡される文字列)についてはNumberFormat、上記の値を試してみましたが、問題ないように見えました。考えられるすべての値のリストを見つけてみましたが、MDNを通じて、このドキュメントこのリストが役立つ可能性があります。

私はSEOに精通していないので、これが質問のその部分にどのように答えるかわかりません。

于 2021-04-29T20:15:30.983 に答える
0

西アラビア数字を東アラビア数字に変換できるjqueryプラグインを作成しました(ペルシア語のみ)。ただし、数値を任意の記数法に変換するように拡張できます。私のjQueryプラグインには2つの利点があります。

  1. 子ノードで数値を適切に検出して変換します。
  2. ポイント文字を適切に検出して変換します。

このプラグインはgithubから複製できます。私のプラグインコード:

(function( $ ){
  $.fn.persiaNumber = function() {
      var groupSelection = this;
      for(i=0; i< groupSelection.length ; i++){
          var htmlTxt = $(groupSelection[i]).html();
          var trueTxt = convertDecimalPoint(htmlTxt);
          trueTxt = convertToPersianNum(trueTxt);
          $(groupSelection[i]).html(trueTxt);
      }
function convertToPersianNum(htmlTxt){
          var otIndex = htmlTxt.indexOf("<");
          var ctIndex = htmlTxt.indexOf(">");
          if(otIndex == -1 && ctIndex == -1 && htmlTxt.length > 0){
            var trueTxt = htmlTxt.replace(/1/gi, "۱").replace(/2/gi, "۲").replace(/3/gi, "۳").replace(/4/gi, "۴").replace(/5/gi, "۵").replace(/6/gi, "۶").replace(/7/gi, "۷").replace(/8/gi, "۸").replace(/9/gi, "۹").replace(/0/gi, "۰");
            return trueTxt;
          }
              var tag = htmlTxt.substring(otIndex,ctIndex + 1);
              var str = htmlTxt.substring(0,otIndex);
              str = convertDecimalPoint(str);
              str = str.replace(/1/gi, "۱").replace(/2/gi, "۲").replace(/3/gi, "۳").replace(/4/gi, "۴").replace(/5/gi, "۵").replace(/6/gi, "۶").replace(/7/gi, "۷").replace(/8/gi, "۸").replace(/9/gi, "۹").replace(/0/gi, "۰");
              var refinedHtmlTxt = str + tag;
              var htmlTxt = htmlTxt.substring(ctIndex + 1, htmlTxt.length);
              if(htmlTxt.length > 0 && otIndex != -1 || ctIndex != -1){
                  var trueTxt = refinedHtmlTxt;
                  var trueTxt =  trueTxt + convertToPersianNum(htmlTxt); 
              }else{
                    return refinedHtmlTxt+ htmlTxt;
              }
              return trueTxt;         

    }
function convertDecimalPoint(str){
    for(j=1;j<str.length - 1; j++){
        if(str.charCodeAt(j-1) > 47 &&  str.charCodeAt(j-1) < 58 && str.charCodeAt(j+1) > 47 &&  str.charCodeAt(j+1) < 58 && str.charCodeAt(j) == 46)
            str = str.substring(0,j) + '٫' + str.substring(j+1,str.length);
    }
    return str;
}
};
})( jQuery );

http://jsfiddle.net/VPWmq/2/

于 2012-12-09T15:51:37.840 に答える
0

この方法で数値を変換できます。

const persianDigits = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];
const number = 44653420;

convertedNumber = String(number).replace(/\d/g, function(digit) {
    return persianDigits[digit]
})
console.log(convertedNumber) // ۴۴۶۵۳۴۲۰
于 2019-07-21T07:58:33.233 に答える
0

このコードシフト方式を使用してバングラ番号にローカライズすることを探している人がいる場合:

    $("[lang='bang']").text(function(i, val) {
        return val.replace(/\d/g, function(v) {
            return String.fromCharCode(v.charCodeAt(0) + 0x09B6);
        });
    });

こちらにアクセスして、ベンガル語のASCII16進コードのUNICODEを確認することもできます。

于 2020-12-13T12:22:16.830 に答える