program tip

브라우저에서 운영 체제가 사용하는 소수 구분 기호를 어떻게 알 수 있습니까?

radiobox 2020. 10. 29. 07:59
반응형

브라우저에서 운영 체제가 사용하는 소수 구분 기호를 어떻게 알 수 있습니까?


웹 애플리케이션을 개발 중입니다.

내가 제어 할 수 GUI없는 특정 응용 프로그램에 복사하여 붙여 넣을 수 있도록 소수 데이터를 올바르게 표시해야합니다 .

GUI 응용 프로그램은 로케일에 민감하며 시스템에 설정된 올바른 소수점 구분자 만 허용합니다.

소수점 구분 기호를 Accept-Language추측 할 수 있고 추측은 95 %의 경우 정확하지만 때로는 실패합니다.

서버 측 (가급적이면 통계를 수집 할 수 있도록) 또는 클라이언트 측에서 수행 할 수있는 방법이 있습니까?

최신 정보:

작업의 요점은 자동으로 수행하는 것입니다.

실제로이 웹앱은 양식을 올바르게 채우는 데 도움이되는 레거시 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 %를 산출하고 GeoIP는 러시아 연방의 80 %, 기타의 20 %를 산출합니다 (잘못된). 대답.


다음은이 정보를 반환하는 간단한 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');

도움이 되나요?


사용자에게 물어보고 추측하지 마십시오. 웹 애플리케이션에 설정이 있습니다.

추가하기 위해 편집 :

95 %의 경우 정상적으로 작동 하는 기본 설정 을 추측하는 것이 좋습니다. 제가 의미 한 것은 사용자가 소프트웨어가 추측 한 모든 것을 무시할 수 있어야한다는 것입니다. 나는 소프트웨어가 너무 똑똑해 지려고 시도하고 수정을 허용하지 않을 때 이미 너무 많이 좌절했습니다.


을 사용하여 현재 또는 지정된 로케일에 대한 구분 기호를 검색 할 수 있습니다 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 polyfill 이 필요합니다.

예 :

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

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;
    }

왜 안돼

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


Accept-Language의 소수 구분 기호를 추측 할 수 있으며 추측은 95 %의 경우 정확하지만 때로는 실패합니다.

이것은 IMO가 최선의 조치입니다. 오류를 처리하려면 표시 영역 옆에 수동으로 설정하는 링크를 추가하십시오.


로케일 설정을 제공하려면 JavaScript에 의존해야한다고 생각합니다.
그러나 분명히 JS는이 정보에 직접 액세스 할 수 없습니다. Dojo Toolkit 이 로케일 정보를 찾기 위해 외부 데이터베이스에 의존한다는
것을 알았습니다 . 예를 들어 계정 설정 변경 사항을 고려하지 않을 수도 있습니다. 내가 보는 또 다른 해결 방법은 시스템에서이 정보를 쿼리하는 작은 자동 Java 애플릿과 Java에서 가져 오는 JavaScript입니다. 방법을 모르는 경우 더 많은 정보를 제공 할 수 있습니다 (물론이 복잡한 경로를 가고 싶다면).

[편집] 그래서 Java에서 현지화 지원에 대한 지식을 업데이트했습니다.
원래 생각했던 것과는 달리 줄 구분 기호 또는 경로 구분 기호를 사용하는 것처럼 직접 소수점 구분 기호 나 천 구분 문자를 직접 사용하지 않습니다. 대신 Java 제공하는 숫자 또는 날짜의 형식을 지정하는 API를 제공합니다.
어떻게 든 의미가 있습니다. 유럽에서는 숫자 뒤에 통화 기호를 넣는 경우가 많으며 일부 국가 (인도?)는 숫자를 구분하는 더 복잡한 규칙이 있습니다.

또 다른 한가지 : Java는 시스템에서 현재 로케일을 올바르게 찾지 만 여기에서 정보를 가져 오지 않습니다 (아마 위의 이유로). 대신 자체 규칙 집합을 사용합니다. 따라서 소수점 구분 기호를 느낌표로 대체 한 스페인어 로케일이있는 경우 Java는이를 사용하지 않습니다 (어쨌든 응용 프로그램이 아닐 수도 있습니다 ...).

그래서 저는 서비스 (기능)를 JavaScript에 노출하는 애플릿을 작성하여 숫자를 현재 로케일로 형식화 할 수 있습니다. 브라우저에서 숫자 형식을 지정하는 데 JavaScript를 사용하여 그대로 사용할 수 있습니다. 또는 샘플 번호를 제공하고 거기에서 기호를 추출하여 로컬에서 사용하거나 서버로 다시 공급할 수 있습니다.

애플릿을 완료하고 테스트 한 후 곧 게시합니다.


좋아, 나는 완성품보다 개념 증명에 더 많은 것을 보여줄 것이 있지만, 정확한 사양이 없기 때문에 나는 이것을 그대로 두거나 오버 엔지니어링 할 것이다. 조금 길기 때문에 별도의 메시지로 게시합니다. 나는 조금 더 jQuery를 시도 할 기회를 가졌다.

자바 코드 : 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에서 테스트되었습니다. 처음 두 가지 문제없이 작동합니다. 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)

하지만 여전히 작동합니다.

I can't get it work with Opera: the applet loads correctly, as I can see the trace of init() call in the Java console, I have no errors when JavaScript calls the Java functions (except if I add and call a method getting a JSObject parameter, curiously), but the Java functions are not called (I added trace of the calls).
I believe Liveconnect works in Opera, but I don't see yet how. I will research a bit more.
[Update] I removed references to non-existing jar file (which doesn't stop other browsers) and I got a trace of the calls, but it doesn't update the page.
Mmm, if I do alert(applet.GetLocaleInformation()); I got the information, so it might be a jQuery issue.


Even if you knew what locale this "GUI Application" is running under, you still have to figure out how it is getting the current locale, and how it is determining the decimal separator.

i don't know how it is done on a Mac, but on Windows applications are supposed to interrogte the user's preferences set via the Control Panel. It's quite possible this mystery applicaiton is ignoring those settings, and using their own internal setup instead.

Or perhaps they're taking the current locale, and inferring the rest, rather than being told.

Even then, in english, numbers are given in groups of 3 digits, with a comma separating the groups. i.e.:

5,197,359,078

Unless the number was an integer that contains a phone number:

519-735-9078

Unless of course the number was an integer that contains an account number:

5197359078

In which case, you're back to hard-coded overridden logic.

Edit: Removed currency example, since currency has its own formatting rules.


Using other people answers I compiled the following decimal and thousand separators utility functions:

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

Enjoy!


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


또 다른 가능한 해결책 : GeoIP (PHP의 예) 와 같은 것을 사용 하여 사용자의 위치를 ​​확인하고 이러한 정보를 기반으로 결정할 수 있습니다.

참고 URL : https://stackoverflow.com/questions/1074660/with-a-browser-how-do-i-know-which-decimal-separator-does-the-operating-system

반응형