88

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

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

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

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

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

アップデート:

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

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

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

ソリューションは実装されて機能しますが、Accept-Language改善したいと思います。

アップデート2:

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

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

  1. DS としてカンマを持つロシア語の Windows (80%)。
  2. DS (15%) としてピリオドを持つ英語の Windows。
  3. 不十分に書かれた英語のアプリケーションを動作させるための DS としてのピリオドを持つロシア語の Windows (4%)。
  4. DS としてコンマを使用した英語版 Windows で、不十分に記述されたロシア語のアプリケーションが動作するようにします (1%)。

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

4

14 に答える 14

135

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

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

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

console.log('You use "' + whatDecimalSeparator() + '" as Decimal seprator');

これは役に立ちますか?

于 2009-08-20T19:53:00.727 に答える
22

を使用して、現在のロケールまたは特定のロケールのセパレータを取得できますIntl.NumberFormat#formatToParts

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

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

例:

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

ボーナス:

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

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')
" "
于 2018-07-18T21:41:17.907 に答える
11

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

追加するために編集:

デフォルトの設定を推測しても問題ないと思います。たとえば、95% の確率で問題なく動作します。私が言いたかったのは、ソフトウェアが行った推測をユーザーがオーバーライドできるべきだということです。ソフトウェアがあまりにも賢くしようとして、修正することができないとき、私はすでに何度も不満を感じてきました.

于 2009-07-02T14:59:59.710 に答える
8
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;
    }
于 2014-12-12T13:23:17.227 に答える
7

なぜだめですか

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

于 2015-10-23T21:13:06.067 に答える
5

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

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

于 2009-07-02T15:13:01.463 に答える
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 Pro SP3 上の Firefox 3.0、IE 6、Safari 3.1、および Opera 9.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の問題かもしれません.

于 2009-07-07T10:20:33.583 に答える
1

この「GUI アプリケーション」が実行されているロケールがわかっている場合でも、現在のロケールを取得する方法、小数点を決定する方法を理解する必要があります。

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

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

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

5,197,359,078

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

519-735-9078

もちろん、番号が口座番号を含む整数でない限り:

5197359078

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

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

于 2009-07-04T20:26:57.867 に答える
1

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

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

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

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

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

于 2009-07-02T15:05:59.480 に答える
0

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

サーバー側から。(.NET)によってシステムから小数点記号を取得できます

string x = CultureInfo.CurrentCulture.NumberFormat.NumberDsecimalSeparator;

残りの作業は、 csvエクスポートの場合のx カンマ (",") またはセミコロン (";")とは異なるエクスポート用の区切り記号のチェックです。

于 2021-08-20T07:54:23.690 に答える
-1

"Is there any way to do it on server side (preferably, so that I can collect statistics), or on client side?"

No you can't. That GUI is looking at some user or machine specific settings. First, you probably do not know at what settings this UI is looking. Second, with a webapplication you will probably not be able to check these settings (clientside --> Javacsript).

于 2009-07-02T14:31:58.160 に答える
-4

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

于 2009-07-02T15:21:18.700 に答える