ブラウザで、オペレーティングシステムが使用している小数点を知るにはどうすればよいですか?


82

私はWebアプリケーションを開発しています。

GUI自分の管理下にない特定のアプリケーションにコピーして貼り付けることができるように、いくつかの10進データを正しく表示する必要があります。

GUIアプリケーションはロケールに依存し、システムに設定されている正しい小数点記号のみを受け入れます。

から小数点記号を推測できAccept-Language、95%の場合は推測が正しいですが、失敗することがあります。

サーバー側(できれば統計を収集できるようにするため)またはクライアント側でそれを行う方法はありますか?

更新:

タスクの要点はそれを自動的に行うことです。

実際、このWebアプリは、フォームに正しく入力するのに役立つレガシーGUIへの一種のオンラインインターフェイスです。

それを使用するユーザーの種類は、ほとんどの場合、小数点記号が何であるかを知りません。

Accept-Languageソリューションを実装して動作しますが、私はそれを改善したいと思います。

Update2:

非常に具体的な設定を取得する必要がありControl Panel / Regional and Language Options / Regional Options / Customizeます。に設定されている小数点。

私は4種類のオペレーティングシステムを扱っています。

  1. DSとしてコンマを使用したロシアのウィンドウ(80%)。
  2. DSとしての期間を持つ英語のWindows(15%)。
  3. 不十分に書かれた英語のアプリケーションを機能させるためのDSとしての期間を持つロシアのWindows(4%)。
  4. 不十分に記述されたロシア語アプリケーションを機能させるためのDSとしてのコンマ付きの英語ウィンドウ(1%)。

クライアントの100%はすべてロシアにあり、レガシーアプリケーションはロシア政府が発行したフォームを処理するため、国を要求するとロシア連邦の100%が生成され、GeoIPはロシア連邦の80%とその他の20%を生成します(不正解)答えます。

回答:


129

これは、この情報を返す単純なJavaScript関数です。Firefox、IE6、およびIE7でテスト済み。[コントロールパネル] / [地域と言語のオプション] / [地域のオプション] / [カスタマイズ]の設定を変更するたびに、ブラウザを閉じて再起動する必要がありました。ただし、コンマとピリオドだけでなく、文字「a」などの奇妙なカスタムのものも検出しました。

function whatDecimalSeparator() {
    var n = 1.1;
    n = n.toLocaleString().substring(1, 2);
    return n;
}

これは役に立ちますか?


3
これはFirefoxとIE8では機能しましたが、GoogleChromeでは機能しませんでした。私はOperaを持っていません。
マシュータルバート

@ Matthew-Chromeで働いてくれました。@ Quassnoi-最後のコメントの意味がわかりません。彼がその機能が機能しないと言っているなら、その人が何を知っているかは何が問題なのでしょうか?
matchu 2010年

気を付けて!Chromeでは、toLocaleStringは、Numberで直接呼び出された場合にのみ正しく機能します。私のシステムでは:[1.1,1.2] .toLocaleString()-> "1.1,1.2" | (1.1).toLocaleString()-> "1,1"
–TarnayKálmán 2013

1
関数は、DecimalSeparator(例,,)に複数の文字を使用するロケールで失敗します。WindowsLOCALE_SDECIMALでは、小数点記号に最大3文字を含めることができます。(それが私のPCで失敗する理由です)。Accept-Languageその場合はブラウザのを使用する方が良いでしょう。これはまだ自分自身を指定する能力を説明していませんDecimalSeparator例えば\o/
Ian Boyd

4
@IanBoydは、小数点記号として複数文字の文字列を使用するロケールについては正しいですが、それn = /^1(.+)1$/.exec(n.toLocaleString())[1]を実行し、Accept-Languageヘッダーを使用するよりも簡単です。
ygormutti 2014

16

現在または特定のロケールの区切り文字を取得するには、を使用しIntl.NumberFormat#formatToPartsます。

function getDecimalSeparator(locale) {
    const numberWithDecimalSeparator = 1.1;
    return Intl.NumberFormat(locale)
        .formatToParts(numberWithDecimalSeparator)
        .find(part => part.type === 'decimal')
        .value;
}

これは、IntlAPIをサポートするブラウザーでのみ機能します。それ以外の場合は、国際ポリフィルが必要です

例:

> getDecimalSeparator()
"."
> getDecimalSeparator('fr-FR')
","

ボーナス:

これを拡張して、特定のロケールの10進数またはグループ区切り文字を取得できます。

function getSeparator(locale, separatorType) {
        const numberWithGroupAndDecimalSeparator = 1000.1;
        return Intl.NumberFormat(locale)
            .formatToParts(numberWithGroupAndDecimalSeparator)
            .find(part => part.type === separatorType)
            .value;
    }

例:

> getSeparator('en-US', 'decimal')
"."
> getSeparator('en-US', 'group')
","
> getSeparator('fr-FR', 'decimal')
","
> getSeparator('fr-FR', 'group')
" "

現在、これはそのような情報を取得するための最も適切な方法です。ところでIntl、IE 11でもサポートされています:caniuse.com/#feat=internationalization
Konstantin Smolyanin 2018

3
formatToPartsがサポートされていないため、これはIE11では機能しません。
GajendraKumar19年

11

ユーザーに聞いてください、推測しないでください。Webアプリケーションで設定してください。

追加するために編集:

たとえば、95%の確率で正常に機能するデフォルト設定を推測しても問題ないと思います。私が言いたかったのは、ユーザーはソフトウェアが行った推測を上書きできるはずだということでした。ソフトウェアが賢くなりすぎて修正できないと、私はすでに何度もイライラしています。


おかしい、それは私の最初のアイデアでした、しかし私はそれを自動的に行う方法を探して船外に出ました...
PhiLho 2009

1
おそらくバックアップとして以外は、悪い考えです。ほとんどのユーザーは、文化に敏感ではなく、説明なしに「小数点」が何であるかさえ理解しません(そして、「誰もが知っている」何かを設定することを余儀なくされることに腹を立てます)。
Michael Borgwardt

2
@Iaalto:これは、「データベースサイズを最小化する(推奨)または検索機能を最大化する」とほぼ同じくらい大きな質問になります。
Quassnoi 2009

まあ、それはそれほど難しいことではないはずです。ユーザーに国を選択させてから、それに応じて乾燥セパレーターとその他のオプションを選択してください。

7
function getDecimalSeparator() {
    //fallback  
       var decSep = ".";

        try {
            // this works in FF, Chrome, IE, Safari and Opera
            var sep = parseFloat(3/2).toLocaleString().substring(1,2);
            if (sep === '.' || sep === ',') {
                decSep = sep;
            }
        } catch(e){}

        return decSep;
    }

1
「。」へのフォールバック。いくつかのあいまいなブラウザ...他の方法の場合には、それは...ほとんど同じことである
Dr.Oblak

7

何故なの

0.1.toLocaleString().replace(/\d/g, '')


2
奇妙なロケールが先頭のゼロをスキップする可能性がありますか?念のために、私はむしろそこにあるものが欲しいです。
Juanguiヨルダン

5

Accept-Languageから小数点記号を推測でき、95%の場合は推測が正しいですが、失敗することがあります。

これがIMOの最善の行動です。障害を処理するには、表示領域の横に手動で設定するためのリンクを追加します。


これはどのように行われますか?このようなブラウザライブラリを使用できることを理解していますgithub.com/dansingerman/jQuery-Browser-Language–
Lime

@William:OPが話すAcccept-Languageは、ブラウザーによって送信されるHTTPヘッダーであり、ユーザーが好む言語、通常はブラウザーのインストール言語またはOSをサーバーに通知します。
Michael Borgwardt 2017

4

他の人の回答を使用して、次の10進数と1000の区切り記号のユーティリティ関数をコンパイルしました。

var decimalSeparator = function() {
    return (1.1).toLocaleString().substring(1, 2);
};
var thousandSeparator = function() {
    return (1000).toLocaleString().substring(1, 2);
};

楽しい!


はい、サポートしていないブラウザformatToParts(SafariとIE)のポリフィルとしてこのメ​​ソッドを使用しました。
MarkoBonaci19年

1
一部のロケールでは、10000未満の千の区切り記号を使用しません。例(1000).toLocaleString("es-PE") # "1000"
Madacol 2020

1

ロケール設定を提供するには、JavaScriptに依存する必要があると思います。
しかし、どうやらJSはこの情報に直接アクセスできません。
私が見道場Toolkitは、それは例えば、アカウント設定の変更にはならないことがありますが、ロケール情報を見つけるために、外部のデータベースに依存しています。
私が見ているもう1つの回避策は、システムからこの情報をクエリする小さなサイレントJavaアプレットと、Javaから情報を取得するJavaScriptを用意することです。
あなたがそれをする方法を知らないならば、私はより多くの情報を与えることができます(もちろん、あなたがこの複雑なルートに行きたいならば)。

[編集] Javaでのローカリゼーションサポートの知識を更新しました...
当初考えていたのとは異なり、行区切り文字やパス区切り文字の場合のように、小数点記号や千単位の区切り文字を直接使用することはありません。代わりにJavaを使用します。指定した数値または日付をフォーマットするためのAPIを提供します。
どういうわけか、それは理にかなっています。ヨーロッパでは、数字の後に通貨記号を付けることがよくあります。一部の国(インド?)では、数字を区切るためのより複雑なルールがあります。

もう1つのこと:Javaはシステムから現在のロケールを正しく検出しますが、そこから情報を取得しません(おそらく上記の理由により)。代わりに、独自のルールセットを使用します。したがって、小数点記号を感嘆符に置き換えたスペイン語のロケールがある場合、Javaはそれを使用しません(ただし、とにかく、アプリケーションもおそらく使用しません...)。

そこで、サービス(関数)をJavaScriptに公開して、現在のロケールに数値をフォーマットできるアプレットを作成しています。JavaScriptを使用してブラウザで数値をフォーマットすることで、そのまま使用できます。または、サンプル番号をフィードしてそこからシンボルを抽出し、ローカルで使用するか、サーバーにフィードバックすることもできます。

アプレットを完成させてテストし、すぐにそこに投稿します。


@PhiLho:知っておくといいですね。このWebアプリは一種のヘルプシステムであるため、醜いハックでもかまいません。IE、Firefox、Operaで実行されている限り、エレガントである必要はありません。
Quassnoi 2009

1

OK、完成品よりも概念実証のようなものがありますが、正確な仕様が不足しているため、そのままにしておきます(または過剰に設計します)。少し長くなりますので、別のメッセージで投稿します。私はもう少しjQueryを試す機会を得ました...

Javaコード: GetLocaleInfo.java

import java.applet.*;
import java.util.Locale;
import java.text.*;

public class GetLocaleInfo extends Applet
{
  Locale loc;
  NumberFormat nf;
  NumberFormat cnf;
  NumberFormat pnf;

  // For running as plain application
  public static void main(String args[])
  {
    final Applet applet = new GetLocaleInfo();
    applet.init();
    applet.start();
  }

  public void init() // Applet is loaded
  {
    // Use current locale
    loc = Locale.getDefault();
    nf = NumberFormat.getInstance();
    cnf = NumberFormat.getCurrencyInstance();
    pnf = NumberFormat.getPercentInstance();
  }

  public void start() // Applet should start
  {
    // Following output goes to Java console
    System.out.println(GetLocaleInformation());
    System.out.println(nf.format(0.1));
    System.out.println(cnf.format(1.0));
    System.out.println(pnf.format(0.01));
  }

  public String GetLocaleInformation()
  {
    return String.format("Locale for %s: country=%s (%s / %s), lang=%s (%s / %s), variant=%s (%s)",
        loc.getDisplayName(),
        loc.getDisplayCountry(),
        loc.getCountry(),
        loc.getISO3Country(),

        loc.getDisplayLanguage(),
        loc.getLanguage(),
        loc.getISO3Language(),

        loc.getDisplayVariant(),
        loc.getVariant()
    );
  }

  public String FormatNumber(String number)
  {
    double value = 0;
    try
    {
      value = Double.parseDouble(number);
    }
    catch (NumberFormatException nfe)
    {
      return "!";
    }
    return nf.format(value);
  }

  public String FormatCurrency(String number)
  {
    double value = 0;
    try
    {
      value = Double.parseDouble(number);
    }
    catch (NumberFormatException nfe)
    {
      return "!";
    }
    return cnf.format(value);
  }

  public String FormatPercent(String number)
  {
    double value = 0;
    try
    {
      value = Double.parseDouble(number);
    }
    catch (NumberFormatException nfe)
    {
      return "!";
    }
    return pnf.format(value);
  }
}

上記のアプレットを使用したHTMLページの例: GetLocaleInfo.html

<!-- Header skipped for brevity -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.js"></script>
<script type="text/javascript">
var applet;
$(document).ready(function()
{
  applet = document.getElementById('LocaleInfo');
  $('#Results').text(applet.GetLocaleInformation());
});
</script>
<script type="text/javascript">
function DoFormatting()
{
  $('table.toFormat').each(function()
  {
    var table = $(this);
    $('td', table).each(function(cellId)
    {
      var val = $(this);
      if (val.is('.number'))
      {
        val.text(applet.FormatNumber(val.text()));
      }
      else if (val.is('.currency'))
      {
        val.text(applet.FormatCurrency(val.text()));
      }
      else if (val.is('.percent'))
      {
        val.text(applet.FormatPercent(val.text()));
      }
    });
  });
}
</script>
</head>
<body>
  <div id="Container">
    <p>Page to demonstrate how JavaScript can get locale information from Java</p>
    <div id="AppletContainer">
      <object classid="java:GetLocaleInfo.class"
          type="application/x-java-applet" codetype="application/java"
          name="LocaleInfo" id="LocaleInfo" width="0" height="0">
        <param name="code" value="GetLocaleInfo"/>
        <param name="mayscript" value="true"/>
        <param name="scriptable" value="true"/>
        <p><!-- Displayed if object isn't supported -->
          <strong>This browser does not have Java enabled.</strong>
          <br>
          <a href="http://java.sun.com/products/plugin/downloads/index.html" title="Download Java plug-in">
          Get the latest Java plug-in here
          </a> (or enable Java support).
        </p>
      </object>
    </div><!-- AppletContainer -->
    <p>
    Click on the button to format the table content to the locale rules of the user.
    </p>
    <input type="button" name="DoFormatting" id="DoFormatting" value="Format the table" onclick="javascript:DoFormatting()"/>
    <div id="Results">
    </div><!-- Results -->
<table class="toFormat">
<caption>Synthetic View</caption>
<thead><tr>
<th>Name</th><th>Value</th><th>Cost</th><th>Discount</th>
</tr></thead>
<tbody>
<tr><td>Foo</td><td class="number">3.1415926</td><td class="currency">21.36</td><td class="percent">0.196</td></tr>
<tr><td>Bar</td><td class="number">159263.14</td><td class="currency">33</td><td class="percent">0.33</td></tr>
<tr><td>Baz</td><td class="number">15926</td><td class="currency">12.99</td><td class="percent">0.05</td></tr>
<tr><td>Doh</td><td class="number">0.01415926</td><td class="currency">5.1</td><td class="percent">0.1</td></tr>
</tbody>
</table>
  </div><!-- Container -->
</body>
</html>

Windows XP ProSP3のFirefox3.0、IE 6、Safari 3.1、およびOpera9.50でテスト済み。最初の2つでは問題なく動作しますが、Safariではinit()呼び出し後に奇妙なエラーが発生します。

java.net.MalformedURLException: no protocol:
    at java.net.URL.<init>(Unknown Source)
    at java.net.URL.<init>(Unknown Source)
    at java.net.URL.<init>(Unknown Source)
    at sun.plugin.liveconnect.SecureInvocation.checkLiveConnectCaller(Unknown Source)
    at sun.plugin.liveconnect.SecureInvocation.access$000(Unknown Source)
    at sun.plugin.liveconnect.SecureInvocation$2.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.plugin.liveconnect.SecureInvocation.CallMethod(Unknown Source)

しかし、それでも機能します。

Operaで動作させることができません。Javaコンソールでinit()呼び出しのトレースを確認できるため、アプレットは正しくロードされます。JavaScriptがJava関数を呼び出すときにエラーは発生しません(メソッドを追加して呼び出す場合を除く)。不思議なことにJSObjectパラメータを取得していますが、Java関数は呼び出されません(呼び出しのトレースを追加しました)。
LiveconnectはOperaで動作すると思いますが、まだその方法がわかりません。もう少し調べてみます。
[更新]存在しないjarファイル(他のブラウザーを停止しない)への参照を削除し、呼び出しのトレースを取得しましたが、ページが更新されません。
うーん、もし私がalert(applet.GetLocaleInformation());情報を入手したので、それはjQueryの問題かもしれません。


@PhiLho:動作しますが、Windowsからセパレーターを正しく読み取れません。次のように表示される場合:Locale for русский (Россия): country=Россия (RU / RUS), lang=русский (ru / rus), variant= ()Windowsの設定でピリオドを使用してオーバーライドしたにもかかわらず、コンマを使用しています。
Quassnoi 2009

このシステムの制限についての私の最初のメッセージの私の更新を読んでください。おそらくいくつかのネイティブコードを使用することを除いて、Webブラウザからより良くできるかどうかはわかりません。
PhiLho 2009

1

この「GUIアプリケーション」がどのロケールで実行されているかを知っていたとしても、現在のロケールをどのよう取得しているか、そしてどのよう取得しているかを理解する必要があります。小数点区切りを決定されます。

Macでどのように行われるかはわかりませんが、Windowsアプリケーションでは、コントロールパネルを介して設定されたユーザーの設定を問い合わせる必要があります。このミステリーアプリケーションがこれらの設定を無視し、代わりに独自の内部設定を使用している可能性は十分にあります。

あるいは、彼らは言われるのではなく、現在のロケールを取り、残りを推測しているのかもしれません。

それでも、英語では、数字は3桁のグループで示され、グループはコンマで区切られます。すなわち:

5,197,359,078

番号が電話番号を含む整数でない限り:

519-735-9078

もちろん、番号がアカウント番号を含む整数でない限り:

5197359078

その場合、ハードコードされたオーバーライドされたロジックに戻ります。

編集:通貨には独自のフォーマットルールがあるため、通貨の例を削除しました。


0

他の回答と同様ですが、定数として圧縮されています:

const decimal=.1.toLocaleString().substr(1,1);      //returns "." in Canada

また、千単位の区切り文字を取得するには:

const thousands=1234..toLocaleString().substr(1,1);   //returns "," in Canada

JSの上部にコードを配置し、必要に応じて呼び出してシンボルを返します。


たとえば(私が住んでいる場所)、コンマを削除するには"1,234,567"

console.log( "1,234,567".replaceAll(thousands,"") ); //prints "1234567" to console.  

-1

「サーバー側(できれば統計を収集できるようにするため)またはクライアント側でそれを行う方法はありますか?」

いいえ、できません。そのGUIは、いくつかのユーザーまたはマシン固有の設定を調べています。まず、このUIがどの設定で表示されているかがわからない可能性があります。次に、Webアプリケーションでは、これらの設定を確認できない可能性があります(クライアント側-> Javacsript)。


@RWC:GUIアプリがどこを探しているか知っています:Windowsの地域設定。
Quassnoi 2009

-4

別の可能な解決策:GeoIP(PHPの例)のようなものを使用して、ユーザーの場所を特定し、これらの情報に基づいて決定することができます。


1
ただし、ユーザーがこれをオーバーライドできるようにする必要があります。私の友人はイギリス南部で働いています。彼が働いている会社は、スペインのプロキシサーバーを介してすべてのインターネットアクセスをルーティングしているため、GeoIPは常に彼が実際の場所から何百マイルも離れていることを示しています。
NickFitz 2009
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.