Ich entwickle eine Webanwendung.
Ich muss einige Dezimaldaten korrekt anzeigen, damit sie kopiert und in eine bestimmte GUI
Anwendung eingefügt werden können, die nicht unter meiner Kontrolle steht.
Die GUI-Anwendung ist vom Gebietsschema abhängig und akzeptiert nur das korrekte Dezimaltrennzeichen, das im System festgelegt ist.
Ich kann das Dezimaltrennzeichen von Accept-Language
erraten und die Vermutung wird in 95% der Fälle korrekt sein, aber manchmal schlägt es fehl.
Gibt es eine Möglichkeit, dies auf der Serverseite (vorzugsweise, damit ich Statistiken sammeln kann) oder auf der Clientseite zu tun?
Aktualisieren:
Der springende Punkt der Aufgabe ist es, sie automatisch zu erledigen.
Tatsächlich ist diese Webanwendung eine Art Online-Schnittstelle zu einer älteren Benutzeroberfläche, mit deren Hilfe die Formulare korrekt ausgefüllt werden können.
Die Art der Benutzer, die es verwenden, hat meistens keine Ahnung, was ein Dezimaltrennzeichen ist.
Die Accept-Language
Lösung ist implementiert und funktioniert, aber ich möchte sie verbessern.
Update2:
Ich muss eine ganz bestimmte Einstellung abrufen: Dezimaltrennzeichen gesetzt in Control Panel / Regional and Language Options / Regional Options / Customize
.
Ich beschäftige mich mit vier Arten von Betriebssystemen:
- Russisches Windows mit einem Komma als DS (80%).
- Englisch Windows mit einem Zeitraum als DS (15%).
- Russisches Windows mit einem Zeitraum als DS, damit schlecht geschriebene englische Anwendungen funktionieren (4%).
- Englisches Windows mit einem Komma als DS, damit schlecht geschriebene russische Anwendungen funktionieren (1%).
Alle 100% der Kunden sind in Russland und der Legacy-Antrag befasst sich mit Formularen, die von der russischen Regierung ausgestellt wurden. Wenn Sie also nach einem Land fragen, erhalten Sie 100% der Russischen Föderation und GeoIP 80% der Russischen Föderation und 20% der anderen (falsch). Antworten.
quelle
DecimalSeparator
(z,,
. B. ) verwenden. In WindowsLOCALE_SDECIMAL
kann ein Dezimaltrennzeichen bis zu drei Zeichen enthalten. (Deshalb schlägt es auf meinem PC fehl). Verwenden SieAccept-Language
in diesem Fall besser den Browser. Was immer noch nicht die Fähigkeit erklärt, ihre eigenen zu spezifizieren,DecimalSeparator
zB\o/
n = /^1(.+)1$/.exec(n.toLocaleString())[1]
würde dies jedoch tun und ist einfacher als die Verwendung desAccept-Language
Headers.Das Abrufen von Trennzeichen für das aktuelle oder ein bestimmtes Gebietsschema ist mit möglich
Intl.NumberFormat#formatToParts
.function getDecimalSeparator(locale) { const numberWithDecimalSeparator = 1.1; return Intl.NumberFormat(locale) .formatToParts(numberWithDecimalSeparator) .find(part => part.type === 'decimal') .value; }
Es funktioniert nur für Browser, die die Intl-API unterstützen . Andernfalls ist eine Intl-Polyfüllung erforderlich
Beispiele:
> getDecimalSeparator() "." > getDecimalSeparator('fr-FR') ","
Bonus:
Wir könnten es erweitern, um entweder das Dezimal- oder das Gruppentrennzeichen eines bestimmten Gebietsschemas abzurufen :
function getSeparator(locale, separatorType) { const numberWithGroupAndDecimalSeparator = 1000.1; return Intl.NumberFormat(locale) .formatToParts(numberWithGroupAndDecimalSeparator) .find(part => part.type === separatorType) .value; }
Beispiele:
> getSeparator('en-US', 'decimal') "." > getSeparator('en-US', 'group') "," > getSeparator('fr-FR', 'decimal') "," > getSeparator('fr-FR', 'group') " "
quelle
Intl
wird sogar in IE 11 unterstützt: caniuse.com/#feat=internationalizationFragen Sie den Benutzer, raten Sie nicht. Nehmen Sie eine Einstellung dafür in Ihrer Webanwendung vor.
Bearbeitet, um hinzuzufügen:
Ich denke, es ist in Ordnung, die Standardeinstellung zu erraten , die beispielsweise in 95% der Fälle in Ordnung ist . Was ich damit meinte war, dass der Benutzer immer noch in der Lage sein sollte, alle Vermutungen der Software zu überschreiben. Ich war schon zu oft frustriert, als eine Software versucht, zu intelligent zu sein und nicht korrigiert werden kann.
quelle
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; }
quelle
Warum nicht
0.1.toLocaleString().replace(/\d/g, '')
quelle
Dies ist IMO die beste Vorgehensweise. Um die Fehler zu beheben, fügen Sie einen Link hinzu, um ihn manuell neben dem Anzeigebereich festzulegen.
quelle
Unter Verwendung der Antworten anderer Personen habe ich die folgenden Dienstprogramme für Dezimal- und Tausendertrennzeichen zusammengestellt:
var decimalSeparator = function() { return (1.1).toLocaleString().substring(1, 2); }; var thousandSeparator = function() { return (1000).toLocaleString().substring(1, 2); };
Genießen!
quelle
formatToParts
(Safari und IE).(1000).toLocaleString("es-PE") # "1000"
Ich denke, Sie müssen sich auf JavaScript verlassen, um die Gebietsschemaeinstellungen zu erhalten.
Aber anscheinend hat JS keinen direkten Zugriff auf diese Informationen.
Ich sehe, dass Dojo Toolkit auf eine externe Datenbank angewiesen ist, um die Gebietsschemainformationen zu finden, obwohl beispielsweise Änderungen an den Einstellungen möglicherweise nicht berücksichtigt werden.
Eine andere Problemumgehung, die ich sehe, besteht darin, ein kleines stilles Java-Applet zu haben, das diese Informationen vom System abfragt, und JavaScript, um sie aus Java herauszuholen.
Ich kann weitere Informationen geben, wenn Sie nicht wissen, wie es geht (wenn Sie diesen verschlungenen Weg gehen möchten, natürlich).
[BEARBEITEN] Also habe ich mein Wissen über die Lokalisierungsunterstützung in Java aktualisiert ...
Im Gegensatz zu dem, was ich ursprünglich dachte, haben Sie nicht direkt das Dezimaltrennzeichen oder tausend Trennzeichen direkt, wie Sie es mit dem Zeilen- oder Pfadtrennzeichen tun würden: stattdessen Java bietet APIs zum Formatieren der von Ihnen angegebenen Zahlen oder Daten.
Irgendwie macht es Sinn: In Europa setzt man oft das Währungssymbol nach der Zahl, einige Länder (Indien?) Haben eine komplexere Regel zum Trennen von Ziffern usw.
Eine andere Sache: Java findet das aktuelle Gebietsschema korrekt aus dem System, nimmt jedoch keine Informationen von dort entgegen (möglicherweise aus den oben genannten Gründen). Stattdessen verwendet es seine eigenen Regeln. Wenn Sie also ein spanisches Gebietsschema haben, in dem Sie das Dezimaltrennzeichen durch ein Ausrufezeichen ersetzt haben, wird Java es nicht verwenden (aber vielleicht auch nicht Ihre Anwendung ...).
Ich schreibe also ein Applet, das einen Dienst (Funktionen) für JavaScript verfügbar macht und es ermöglicht, Zahlen für das aktuelle Gebietsschema zu formatieren. Sie können es als solches verwenden, indem Sie JavaScript verwenden, um Zahlen im Browser zu formatieren. Oder Sie füttern es einfach mit einer Probennummer und extrahieren die Symbole von dort, verwenden sie lokal oder geben sie an den Server zurück.
Ich beende und teste mein Applet und poste es bald dort.
quelle
OK, ich habe etwas zu zeigen, eher einen Proof of Concept als ein fertiges Produkt, aber wegen des Mangels an genauen Spezifikationen lasse ich es so (oder ich werde es überentwickeln). Ich poste in einer separaten Nachricht, weil es ein bisschen lang sein wird. Ich nutzte die Gelegenheit, um ein bisschen mehr jQuery zu probieren ...
Der Java-Code: 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); } }
Ein Beispiel für eine HTML-Seite mit dem obigen Applet: 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>
Getestet unter Firefox 3.0, IE 6, Safari 3.1 und Opera 9.50 unter Windows XP Pro SP3. Es funktioniert problemlos mit den ersten beiden, auf Safari habe ich nach dem Aufruf von init () einen seltsamen Fehler:
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)
aber es funktioniert immer noch.
Ich kann es nicht mit Opera zum Laufen bringen: Das Applet wird korrekt geladen, da ich die Ablaufverfolgung des Aufrufs init () in der Java-Konsole sehen kann. Ich habe keine Fehler, wenn JavaScript die Java-Funktionen aufruft (außer wenn ich eine Methode hinzufüge und aufrufe seltsamerweise einen JSObject-Parameter erhalten), aber die Java-Funktionen werden nicht aufgerufen (ich habe eine Ablaufverfolgung der Aufrufe hinzugefügt).
Ich glaube, Liveconnect funktioniert in Opera, aber ich sehe noch nicht, wie. Ich werde ein bisschen mehr recherchieren.
[Update] Ich habe Verweise auf nicht vorhandene JAR-Dateien entfernt (was andere Browser nicht stoppt) und habe eine Spur der Aufrufe erhalten, aber die Seite wird nicht aktualisiert.
Mmmm, wenn ich das tue, habe
alert(applet.GetLocaleInformation());
ich die Informationen, also könnte es ein jQuery-Problem sein.quelle
Locale for русский (Россия): country=Россия (RU / RUS), lang=русский (ru / rus), variant= ()
angezeigt wird : Es wird ein Komma verwendet, obwohl ich es in den Windows-Einstellungen mit einem Punkt überschrieben habe.Auch wenn Sie wissen , was diese „GUI - Anwendung“ locale unter ausgeführt wird , müssen Sie noch herausfinden , wie es ist , die aktuelle locale bekommen, und wie es ist , das Dezimaltrennzeichen zu bestimmen.
Ich weiß nicht, wie es auf einem Mac gemacht wird, aber unter Windows sollen Anwendungen die über die Systemsteuerung festgelegten Benutzereinstellungen abfragen. Es ist durchaus möglich, dass diese mysteriöse Anwendung diese Einstellungen ignoriert und stattdessen ihr eigenes internes Setup verwendet.
Oder vielleicht nehmen sie das aktuelle Gebietsschema und schließen auf den Rest, anstatt es zu erfahren.
Selbst dann werden auf Englisch Zahlen in dreistelligen Gruppen angegeben, wobei ein Komma die Gruppen trennt. dh:
5,197,359,078
Es sei denn, die Nummer war eine Ganzzahl, die eine Telefonnummer enthält :
519-735-9078
Es sei denn natürlich, die Nummer war eine Ganzzahl, die eine Kontonummer enthält :
5197359078
In diesem Fall kehren Sie zur fest codierten überschriebenen Logik zurück.
Bearbeiten: Währungsbeispiel entfernt, da die Währung ihre eigenen Formatierungsregeln hat.
quelle
Ähnlich wie bei anderen Antworten, jedoch als Konstante komprimiert :
const decimal=.1.toLocaleString().substr(1,1); //returns "." in Canada
Um das Tausendertrennzeichen zu erhalten :
const thousands=1234..toLocaleString().substr(1,1); //returns "," in Canada
Platzieren Sie einfach den Code oben in Ihrem JS und rufen Sie nach Bedarf auf, um das Symbol zurückzugeben.
Zum Beispiel (wo ich wohne), um Kommas zu entfernen von
"1,234,567"
:console.log( "1,234,567".replaceAll(thousands,"") ); //prints "1234567" to console.
quelle
Nein, kannst du nicht. Diese GUI betrachtet einige benutzer- oder maschinenspezifische Einstellungen. Erstens wissen Sie wahrscheinlich nicht, nach welchen Einstellungen diese Benutzeroberfläche sucht. Zweitens können Sie mit einer Webanwendung diese Einstellungen wahrscheinlich nicht überprüfen (clientseitig -> Javacsript).
quelle
Eine andere mögliche Lösung: Sie könnten etwas wie GeoIP (Beispiel in PHP) verwenden, um den Standort des Benutzers zu bestimmen und basierend auf diesen Informationen zu entscheiden.
quelle