86 votes

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

Je suis en train de développer une application web.

J'ai besoin d'afficher correctement des données décimales pour qu'elles puissent être copiées et collées dans un fichier de données. GUI application qui n'est pas sous mon contrôle.

L'application GUI est sensible à la locale et n'accepte que le séparateur décimal correct qui est défini dans le système.

Je peux deviner le séparateur décimal à partir de Accept-Language et l'estimation sera correcte dans 95% des cas, mais parfois elle échoue.

Y a-t-il un moyen de le faire du côté serveur (de préférence, pour pouvoir collecter des statistiques), ou du côté client ?

Mise à jour :

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

En fait, cette application web est une sorte d'interface en ligne d'une interface graphique traditionnelle qui aide à remplir correctement les formulaires.

Les utilisateurs qui l'utilisent n'ont généralement aucune idée de ce qu'est un séparateur décimal.

El Accept-Language La solution est implémentée et fonctionne, mais j'aimerais l'améliorer.

Mise à jour2 :

J'ai besoin de retrouver un paramètre très spécifique : le séparateur de décimales défini en Control Panel / Regional and Language Options / Regional Options / Customize .

Je m'occupe de quatre types de systèmes d'exploitation :

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

La totalité des clients se trouvent en Russie et l'ancienne application traite des formulaires émis par le gouvernement russe. Ainsi, la demande d'un pays donnera 100 % de la Fédération de Russie, et GeoIP donnera 80 % de la Fédération de Russie et 20 % d'autres réponses (incorrectes).

132voto

Chris Nielsen Points 7492

Voici une fonction JavaScript simple qui renverra ces informations. Testée 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 détecté non seulement la virgule et le point, mais aussi des éléments personnalisés 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 vous aide-t-il ?

4 votes

Cela a fonctionné pour moi dans Firefox et IE8, mais pas dans Google Chrome. Je n'ai pas Opera.

0 votes

@Matthew - cela a fonctionné pour moi dans Chrome. @Quassnoi - Je ne comprends pas le sens de ce dernier commentaire. S'il dit que la fonction ne fonctionne pas, alors quelle importance a ce que la personne sait ?

0 votes

Attention ! Dans Chrome, toLocaleString ne fonctionne correctement que s'il est appelé directement sur un numéro. Sur mon système : [1.1,1.2].toLocaleString() -> "1.1,1.2" | (1.1).toLocaleString() -> "1,1".

11voto

laalto Points 50581

Demandez à l'utilisateur, ne devinez pas. Prévoyez un paramètre à cet effet dans votre application Web.

Modifié pour ajouter :

Je pense que c'est normal de deviner le par défaut un réglage qui fonctionne bien, disons, 95 % du temps. Ce que j'ai voulu dire, c'est que l'utilisateur devrait toujours être en mesure d'ignorer les suppositions du logiciel. J'ai déjà été frustré trop souvent quand un logiciel essaie d'être trop intelligent et ne permet pas d'être corrigé.

0 votes

C'est drôle, c'était ma première idée, mais je me suis emballé en cherchant comment le faire automatiquement...

1 votes

Mauvaise idée, sauf peut-être comme sauvegarde. La plupart des utilisateurs sont culturellement insensibles et ne comprendront même pas ce qu'est un "séparateur décimal" sans explication (et seront ensuite furieux d'être obligés de définir quelque chose que "tout le monde connaît").

2 votes

@Iaalto : cela ferait une question presque aussi géniale que "Minimiser la taille de la base de données (recommandé) ou Maximiser les capacités de recherche ?".

5voto

Michael Borgwardt Points 181658

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

C'est, à mon avis, la meilleure façon de procéder. Afin de gérer les échecs, ajoutez un lien pour le régler manuellement à côté de la zone d'affichage.

0 votes

Comment cela se passe-t-il ? Je comprends que vous pouvez utiliser une bibliothèque de navigateur comme celle-ci github.com/dansingerman/jQuery-Browser-Language

0 votes

@William : L'Acccept-Language dont parle le PO est un en-tête HTTP envoyé par le navigateur qui indique au serveur la langue préférée de l'utilisateur, généralement la langue d'installation du navigateur ou du système d'exploitation.

1voto

PhiLho Points 23458

OK, j'ai quelque chose à montrer, plus une preuve de concept d'un produit fini, mais en raison de l'absence d'un cahier des charges précis, je laisse cela de cette façon (ou je vais sur-conception). Je poste un autre message, parce que ce sera un peu long. J'ai eu l'occasion d'essayer un peu plus de 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 à l'aide de 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, c'est à dire 6, Safari 3.1 et Opera 9.50, sur Windows XP Pro SP3. Il fonctionne sans problème avec les deux premières, sur Safari, j'ai une erreur étrange après init() de l'appel:

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 il fonctionne encore.

Je ne peux pas le faire fonctionner avec de l'Opéra: l'applet se charge correctement, que je puisse voir la trace de init() de l'appel dans la console Java, je n'ai pas d'erreurs lors de JavaScript appelle la Java des fonctions (sauf si j'ajoute et appeler une méthode de l'obtention d'un JSObject paramètre, curieusement), mais le Java fonctions ne sont pas appelés (j'ai ajouté trace des appels).
Je crois Liveconnect travaille à l'Opéra, mais je ne vois pas encore comment. Je recherche un peu plus.
[Mise à jour] j'ai supprimé les références à la non-existant fichier jar (qui n'empêche pas les autres navigateurs) et j'ai eu une trace des appels, mais il n'a pas de mise à jour de la page.
Mmm, si je n' alert(applet.GetLocaleInformation()); j'ai eu l'information, de sorte qu'il pourrait être un jQuery problème.

0 votes

@PhiLho : cela fonctionne, mais ne lit toujours pas le séparateur correctement depuis Windows. Quand il voit ce qui suit : Locale for (): country= (RU / RUS), lang= (ru / rus), variant= () il utilise une virgule alors que je l'ai remplacée par un point dans les paramètres de Windows.

0 votes

Veuillez lire la mise à jour de mon premier message concernant les limites de ce système. Je ne sais pas si on peut faire mieux à partir d'un navigateur Web, sauf peut-être en utilisant du code natif.

1voto

PhiLho Points 23458

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

[EDIT] J'ai donc mis à jour mes connaissances sur le support de la localisation en Java...
Contrairement à ce que je pensais au départ, vous n'aurez pas à utiliser directement les caractères du séparateur décimal ou du séparateur de milliers, comme vous le feriez avec le séparateur de ligne ou le séparateur de chemin : au lieu de cela, Java propose des API pour formater les nombres ou les dates que vous fournissez.
D'une certaine manière, c'est logique : en Europe, on met souvent le symbole de la monnaie après le chiffre, certains pays (l'Inde ?) ont une règle plus complexe pour séparer les chiffres, etc.

Autre chose : Java trouve correctement la locale actuelle du système, mais ne prend pas d'informations de là (peut-être pour les raisons ci-dessus). Il utilise plutôt son propre ensemble de règles. Ainsi, 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 pas votre application, de toute façon...).

J'écris donc une applet exposant un service (fonctions) à JavaScript, permettant de formater les nombres selon la locale courante. Vous pouvez l'utiliser comme tel, en utilisant JavaScript pour formater les nombres sur le navigateur. Ou vous pouvez simplement lui fournir un exemple de nombre et en extraire les symboles, les utiliser localement ou les renvoyer au serveur.

Je termine et teste mon applet et la poste ici bientôt.

0 votes

@PhiLho : ce serait bien de le savoir. Cette webapp est une sorte de système d'aide, donc n'importe quel hack moche fera l'affaire, il n'a pas besoin d'être élégant tant qu'il fonctionne sur IE, Firefox et Opera.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X