Estoy desarrollando una aplicación web.
Necesito mostrar algunos datos decimales correctamente para que se puedan copiar y pegar en una determinada GUI
aplicación que no esté bajo mi control.
La aplicación GUI es sensible a la configuración regional y solo acepta el separador decimal correcto que está configurado en el sistema.
Puedo adivinar el separador decimal de Accept-Language
y la suposición será correcta en el 95% de los casos, pero a veces falla.
¿Hay alguna forma de hacerlo en el lado del servidor (preferiblemente, para que pueda recopilar estadísticas) o en el lado del cliente?
Actualizar:
El objetivo de la tarea es hacerlo automáticamente.
De hecho, esta aplicación web es una especie de interfaz en línea para una GUI heredada que ayuda a completar los formularios correctamente.
El tipo de usuarios que lo usan en su mayoría no tienen idea de qué es un separador decimal.
La Accept-Language
solución está implementada y funciona, pero me gustaría mejorarla.
Actualización2:
Necesito recuperar una configuración muy específica: separador decimal establecido Control Panel / Regional and Language Options / Regional Options / Customize
.
Me ocupo de cuatro tipos de sistemas operativos:
- Windows ruso con una coma como DS (80%).
- Inglés Windows con un punto como DS (15%).
- Windows ruso con un período como DS para hacer que las aplicaciones en inglés mal escritas funcionen (4%).
- Windows en inglés con una coma como DS para que las aplicaciones rusas mal escritas funcionen (1%).
El 100% de los clientes están en Rusia y la aplicación heredada se ocupa de los formularios emitidos por el gobierno ruso, por lo que solicitar un país arrojará el 100% de la Federación de Rusia, y GeoIP generará el 80% de la Federación de Rusia y el 20% de otros (incorrecto) respuestas.
fuente
DecimalSeparator
(ej,,
.). WindowsLOCALE_SDECIMAL
permite que un separador decimal contenga hasta tres caracteres. (Por eso falla en mi PC). Es mejor usar elAccept-Language
del navegador en ese caso. Lo que todavía no tiene en cuenta la capacidad de especificar los suyos propios,DecimalSeparator
por ejemplo\o/
n = /^1(.+)1$/.exec(n.toLocaleString())[1]
lo haría, y es más fácil que usar elAccept-Language
encabezado.Es posible recuperar separadores para la configuración regional actual o determinada mediante
Intl.NumberFormat#formatToParts
.function getDecimalSeparator(locale) { const numberWithDecimalSeparator = 1.1; return Intl.NumberFormat(locale) .formatToParts(numberWithDecimalSeparator) .find(part => part.type === 'decimal') .value; }
Solo funciona para navegadores compatibles con la API de Intl . De lo contrario, requiere un polyfill Intl
Ejemplos:
> getDecimalSeparator() "." > getDecimalSeparator('fr-FR') ","
Prima:
Podríamos extenderlo para recuperar el separador decimal o de grupo de una configuración regional determinada:
function getSeparator(locale, separatorType) { const numberWithGroupAndDecimalSeparator = 1000.1; return Intl.NumberFormat(locale) .formatToParts(numberWithGroupAndDecimalSeparator) .find(part => part.type === separatorType) .value; }
Ejemplos:
> getSeparator('en-US', 'decimal') "." > getSeparator('en-US', 'group') "," > getSeparator('fr-FR', 'decimal') "," > getSeparator('fr-FR', 'group') " "
fuente
Intl
se admite incluso en IE 11: caniuse.com/#feat=internationalizationPregunte al usuario, no adivine. Tenga una configuración para ello en su aplicación web.
Editado para agregar:
Creo que está bien adivinar la configuración predeterminada que funciona bien, digamos, el 95% del tiempo. Lo que quise decir es que el usuario debería poder anular cualquier conjetura que haya hecho el software. Ya me he sentido frustrado muchas veces cuando un software intenta ser demasiado inteligente y no permite que se corrija.
fuente
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; }
fuente
Por qué no
0.1.toLocaleString().replace(/\d/g, '')
fuente
Este es en mi opinión el mejor curso de acción. Para manejar las fallas, agregue un enlace para configurarlo manualmente junto al área de visualización.
fuente
Usando las respuestas de otras personas, compilé las siguientes funciones de utilidad de separadores decimales y de miles:
var decimalSeparator = function() { return (1.1).toLocaleString().substring(1, 2); }; var thousandSeparator = function() { return (1000).toLocaleString().substring(1, 2); };
¡Disfrutar!
fuente
formatToParts
(Safari e IE).(1000).toLocaleString("es-PE") # "1000"
Creo que debe confiar en JavaScript para obtener la configuración regional.
Pero aparentemente JS no tiene acceso directo a esta información.
Veo que Dojo Toolkit se basa en una base de datos externa para encontrar la información de la configuración regional, aunque es posible que no tenga en cuenta los cambios de configuración de la cuenta, por ejemplo.
Otra solución que veo es tener un pequeño subprograma de Java silencioso que consulta esta información del sistema y JavaScript para sacarla de Java.
Puedo darte más información si no sabes cómo hacerlo (si quieres seguir este camino complicado, por supuesto).
[EDITAR] Así que actualicé mi conocimiento del soporte de localización en Java ...
A diferencia de lo que pensé originalmente, no tendrá directamente el separador decimal o miles de caracteres separadores directamente, como lo haría con el separador de línea o el separador de ruta: en lugar de Java ofrece API para formatear los números o las fechas que proporcione.
De alguna manera, tiene sentido: en Europa, a menudo se coloca el símbolo de la moneda después del número, algunos países (¿India?) Tienen una regla más compleja para separar dígitos, etc.
Otra cosa: Java encuentra correctamente la configuración regional actual del sistema, pero no toma información de allí (quizás por las razones anteriores). En su lugar, utiliza su propio conjunto de reglas. Entonces, si tiene una configuración regional en español donde reemplazó el separador decimal con un signo de exclamación, Java no lo usará (pero quizás tampoco su aplicación, de todos modos ...).
Así que estoy escribiendo un subprograma que expone un servicio (funciones) a JavaScript, lo que permite formatear números en la configuración regional actual. Puede usarlo como tal, usando JavaScript para formatear números en el navegador. O simplemente puede alimentarlo con algún número de muestra y extraer los símbolos de allí, utilizándolos localmente o devolviéndolos al servidor.
Termino y pruebo mi applet y lo publico allí pronto.
fuente
De acuerdo, tengo algo que mostrar, más una prueba de concepto que un producto terminado, pero debido a la falta de especificaciones precisas, lo dejo así (o lo sobre-diseñaré). Publico en un mensaje separado porque será un poco largo. Aproveché para probar un poco más de jQuery ...
El código 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 ejemplo de página HTML usando el subprograma anterior: 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>
Probado en Firefox 3.0, IE 6, Safari 3.1 y Opera 9.50, en Windows XP Pro SP3. Funciona sin problema con los dos primeros, en Safari tengo un error extraño después de llamar a 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)
pero todavía funciona.
No puedo hacer que funcione con Opera: el subprograma se carga correctamente, ya que puedo ver el rastro de la llamada init () en la consola de Java, no tengo errores cuando JavaScript llama a las funciones de Java (excepto si agrego y llamo a un método obteniendo un parámetro JSObject, curiosamente), pero las funciones de Java no son llamadas (agregué rastro de las llamadas).
Creo que Liveconnect funciona en Opera, pero todavía no veo cómo. Investigaré un poco más.
[Actualización] Eliminé las referencias a un archivo jar no existente (que no detiene otros navegadores) y obtuve un rastro de las llamadas, pero no actualiza la página.
Mmm, si lo hago
alert(applet.GetLocaleInformation());
, obtuve la información, por lo que podría ser un problema de jQuery.fuente
Locale for русский (Россия): country=Россия (RU / RUS), lang=русский (ru / rus), variant= ()
usa una coma a pesar de que la he anulado con un punto en la configuración de Windows.Incluso si usted supiera lo que esta configuración regional "Aplicación GUI" se está ejecutando bajo, usted todavía tiene que encontrar la manera que está recibiendo la localización actual, y cómo se está determinando el separador decimal.
No sé cómo se hace en una Mac, pero se supone que las aplicaciones de Windows interrogan las preferencias del usuario establecidas a través del Panel de control. Es muy posible que esta aplicación misteriosa ignore esas configuraciones y use su propia configuración interna en su lugar.
O tal vez están tomando la ubicación actual e infiriendo el resto, en lugar de que se les diga.
Incluso entonces, en inglés, los números se dan en grupos de 3 dígitos, con una coma separando los grupos. es decir:
5,197,359,078
A menos que el número sea un número entero que contenga un número de teléfono :
519-735-9078
A menos que, por supuesto, el número sea un número entero que contenga un número de cuenta :
5197359078
En cuyo caso, vuelve a la lógica anulada codificada.
Editar: ejemplo de moneda eliminado, ya que la moneda tiene sus propias reglas de formato.
fuente
Similar a otras respuestas, pero comprimido como una constante :
const decimal=.1.toLocaleString().substr(1,1); //returns "." in Canada
Además, para obtener el separador de miles :
const thousands=1234..toLocaleString().substr(1,1); //returns "," in Canada
Simplemente coloque el código en la parte superior de su JS y luego llame según sea necesario para devolver el símbolo.
Por ejemplo (donde vivo), para quitar las comas de
"1,234,567"
:console.log( "1,234,567".replaceAll(thousands,"") ); //prints "1234567" to console.
fuente
No, no puedes. Esa GUI está mirando algunas configuraciones específicas de usuario o máquina. Primero, probablemente no sepa en qué configuración se ve esta interfaz de usuario. En segundo lugar, con una aplicación web probablemente no podrá verificar estas configuraciones (lado del cliente -> Javacsript).
fuente
Otra posible solución: podría usar algo como GeoIP (ejemplo en PHP) para determinar la ubicación del usuario y decidir en base a esta información.
fuente