Avec un navigateur, comment puis-je savoir quel séparateur décimal le système d'exploitation?

Je développe une application web.

J'ai besoin d'afficher certaines données décimales correctement afin qu'elles puissent être copiées et collées dans une certaine application GUI qui n'est pas sous mon contrôle.

L'application GUI est sensible aux paramètres régionaux et n'accepte que le séparateur décimal correct défini dans le système.

Je peux deviner le séparateur décimal de Accept-Language et la supposition sera correcte dans 95% des cas, mais parfois elle échoue.

Est-il un moyen de le faire sur le serveur côté (de préférence, afin que je puisse collecter des statistiques), ou du côté client?

Mise à Jour:

Tout le but de la tâche est de le faire automatiquement.

En fait, cette webapp est une sorte d'interface en ligne à une interface graphique héritée qui aide à remplir les formulaires correctement.

Le genre d'utilisateurs qui l'utilisent le plus souvent n'ont aucune idée de ce qu'est un séparateur décimal.

La solution Accept-Language est implémentée et fonctionne, mais je voudrais améliorer il.

Update2:

J'ai besoin de récupérer un paramètre très spécifique: séparateur décimal défini dans Control Panel / Regional and Language Options / Regional Options / Customize.

Je traite de quatre types de systèmes d'exploitation:

  1. fenêtres russes avec une virgule comme DS (80%).
  2. fenêtres en anglais avec un point en tant que DS (15%).
  3. Windows russe avec une période en tant que DS pour faire fonctionner des applications anglaises mal écrites (4%).
  4. Windows anglais avec une virgule comme un DS pour faire des applications russes mal écrites travail (1%).

Tous les 100% des clients sont en Russie et l'application existante traite des formulaires émis par le gouvernement russe, donc demander un pays donnera 100% de la Fédération de Russie, et GeoIP donnera 80% de la Fédération de Russie et 20% des autres réponses (incorrectes).

64
demandé sur Quassnoi 2009-07-02 18:19:45

12 réponses

Voici une simple fonction JavaScript qui retournera cette information. Testé dans Firefox, IE6 et IE7. J'ai dû fermer et redémarrer mon navigateur entre chaque modification du paramètre sous Panneau de configuration / Options régionales et linguistiques / Options régionales / personnaliser. Cependant, il a ramassé non seulement la virgule et la période, mais aussi des choses personnalisées bizarres, comme la lettre "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');

Cela aide-t-il?

104
répondu Chris Nielsen 2017-01-04 10:32:14

Demandez à l'utilisateur, ne devinez pas. Un paramètre dans votre application web.

Modifié pour ajouter:

Je pense qu'il est correct de deviner le paramètre par défaut qui fonctionne bien, disons, 95% du temps. Ce que je voulais dire, c'est que l'utilisateur devrait toujours être en mesure de remplacer tout ce qui devine le logiciel fait. J'ai été frustré trop de fois déjà quand un logiciel essaie d'être trop intelligent et ne permet pas d'être corrigé.

9
répondu laalto 2009-07-02 15:30:03
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;
    }
7
répondu Dr.Oblak 2014-12-12 13:23:17

Je peux deviner le séparateur décimal de Accepter-langue et la conjecture sera correct dans 95% des cas, mais parfois, il échouer.

C'est IMO le meilleur plan d'action. Afin de gérer les échecs, ajoutez un lien pour le définir manuellement à côté de la zone d'affichage.

5
répondu Michael Borgwardt 2009-07-02 15:13:01

Pourquoi pas

0.1.toLocaleString().replace(/\d/g, '')
5
répondu user3023011 2015-10-23 21:13:06

La récupération des séparateurs pour le courant ou une locale donnée est possible en utilisant Intl.NumberFormat#formatToParts.

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

Cela ne fonctionne que pour les navigateurs supportant L'API Intl . Sinon, il nécessite un Intl polyfill

Exemples:

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

Bonus:

On pourrait l'étendre à récupérer le décimal ou le groupe séparateur de paramètres régionaux:

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

Exemples:

> getSeparator('en-US', 'decimal')
"."
> getSeparator('en-US', 'group')
","
> getSeparator('fr-FR', 'decimal')
","
> getSeparator('fr-FR', 'group')
" "
3
répondu JBE 2018-07-18 21:41:17

Je pense que vous devez compter sur JavaScript pour vous donner les paramètres régionaux.
Mais apparemment, JS n'a pas d'accès direct à cette information.
Je vois Dojo Toolkit repose sur une base de données externe pour trouver les informations de paramètres régionaux, bien qu'il puisse ne pas prendre en compte les changements de paramètres, par exemple.
Une autre solution de contournement que je vois est d'avoir une petite applet Java silencieuse qui interroge ces informations à partir du système, et JavaScript pour les sortir de Java.
Je peux donner plus d'informations si vous ne savez pas comment le faire (si vous voulez suivre cette route alambiquée, bien sûr).

[modifier] J'ai donc mis à jour mes connaissances du support de localisation en Java...
Contrairement à ce que je pensais à l'origine, vous n'aurez pas directement le séparateur décimal ou le séparateur de milliers, comme vous le feriez avec le séparateur de ligne ou le séparateur de chemin: Java propose plutôt des API pour formater les nombres ou les dates que vous fournissez.
D'une certaine manière, il est logique: en Europe, vous mettez souvent le symbole monétaire après le nombre, certains pays (l'Inde?) ont une règle plus complexe pour séparer les chiffres, etc.

Une autre chose: Java trouve correctement les paramètres régionaux actuels du système, mais ne prend pas d'informations à partir de là (peut-être pour les raisons ci-dessus). Au lieu de cela, il utilise son propre ensemble de règles. Donc, si vous avez une locale espagnole où vous avez remplacé le séparateur décimal par un signe d'exclamation, Java ne l'utilisera pas (mais peut-être ni votre application, de toute façon...).

J'écris donc une applet exposant un service (fonctions) à JavaScript, permettant de formater les nombres à la locale actuelle. Vous pouvez l'utiliser en tant que tel, en utilisant JavaScript pour formater les numéros sur le navigateur. Ou vous pouvez simplement le nourrir avec un numéro d'échantillon et extraire les symboles à partir de là, en les utilisant localement ou en les renvoyant au serveur.

Je termine et teste mon applet et l'affiche bientôt.

1
répondu PhiLho 2009-07-04 19:40:22

OK, j'ai quelque chose à montrer, plus une preuve de concept qu'un produit fini, mais à cause du manque de spécifications précises, je le laisse de cette façon (ou je le sur-ingénieur). Je poste dans un message séparé parce que ce sera un peu long. J'en ai profité pour essayer un peu plus jQuery...

Le code 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);
  }
}

Un exemple de page HTML utilisant l'applet ci-dessus: 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>

Testé sur Firefox 3.0, IE 6, Safari 3.1 et Opera 9.50, sur Windows XP PRO SP3. Cela fonctionne sans problème avec les deux premiers, sur Safari j'ai une erreur étrange après l'appel 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)

Mais ça marche toujours.

Je ne peux pas le faire fonctionner avec Opera: L'applet se charge correctement, car je peux voir la trace de l'appel init() dans la console Java, je n'ai aucune erreur lorsque JavaScript appelle les fonctions Java (sauf si j'ajoute et appelle une méthode obtenant un paramètre jsobject, curieusement), mais les fonctions Java ne sont pas appelées (j'ai ajouté appel).
Je crois que Liveconnect fonctionne dans Opera, mais je ne vois pas encore comment. Je recherche un peu plus.
[Mise à jour] j'ai supprimé les références au fichier JAR non existant (ce qui n'arrête pas les autres navigateurs) et j'ai eu une trace des appels, mais il ne met pas à jour la page.
Mmm, si je fais alert(applet.GetLocaleInformation()); j'ai l'information, donc ce pourrait être un problème jQuery.

1
répondu PhiLho 2009-07-07 10:27:00

Même si vous saviez sous quelle locale Cette "Application GUI" s'exécute, vous devez toujours comprendre comment it obtient les paramètres régionaux actuels, et comment it détermine le séparateur décimal.

Je ne sais pas comment cela se fait sur un Mac, mais sur Windows, les applications sont censées interroger les préférences de l'utilisateur via le Panneau de configuration. Il est tout à fait possible que cette application mystérieuse ignore ces paramètres et utilise leur propre configuration interne à la place.

Ou peut-être qu'ils prennent les paramètres régionaux actuels, et infèrent le reste, plutôt que d'être dit.

, Même alors, en anglais, nombres sont donnés en groupes de 3 chiffres, avec une virgule séparant les groupes. c'est à dire:

5,197,359,078

, Sauf si le nombre est un entier qui contient un numéro de téléphone:

519-735-9078

À moins bien sûr que le nombre soit un entier contenant un numéro de compte :

5197359078

Auquel cas, vous êtes de retour à un code en dur remplacé logique.

Edit: exemple de devise supprimé, car la devise a ses propres règles de formatage.

1
répondu Ian Boyd 2010-05-11 01:21:48

En utilisant les réponses d'autres personnes, j'ai compilé les fonctions Utilitaires décimales et mille séparateurs suivantes:

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

Profitez!

0
répondu Juangui Jordán 2017-06-01 11:06:03

" est - il possible de le faire sur le serveur côté (de préférence, afin que je puisse recueillir des statistiques), ou sur le client côté?"

Non, vous ne pouvez pas. cette interface graphique regarde certains paramètres spécifiques à l'utilisateur ou à la machine. Tout d'abord, vous ne savez probablement pas à quels paramètres cette interface utilisateur est à la recherche. Deuxièmement, avec une application web, vous ne pourrez probablement pas vérifier ces paramètres (clientside - > Javacsript).

-1
répondu Ian Boyd 2009-07-04 20:18:28

Une autre solution possible: vous pouvez utiliser quelque chose comme GeoIP (Exemple en PHP) pour déterminer l'emplacement de l'utilisateur et décider en fonction de ces informations.

-4
répondu okoman 2011-11-13 18:03:28