I\'m developing a web application.
I need to display some decimal data correctly so that it can be copied and pasted into a certain GUI
application that
OK, I have something to show, more a proof of concept than a finished product, but because of lack of precise specifications, I leave it this way (or I will over-engineer it). I post in a separate message because it will be a bit long. I took the opportunity to try a bit more jQuery...
The 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);
}
}
An example of HTML page using the above 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>
Tested on Firefox 3.0, IE 6, Safari 3.1 and Opera 9.50, on Windows XP Pro SP3. It works without problem with the first two, on Safari I have a strange error after init() call:
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)
but it still works.
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.
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!
Similar to other answers, but compressed as a constant:
const decimal=.1.toLocaleString().substr(1,1); //returns "." in Canada
Also, to get the thousands separator:
const thousands=1234..toLocaleString().substr(1,1); //returns "," in Canada
Just place the code at the top of your JS and then call as required to return the symbol.
For example (where I live), to remove commas from "1,234,567"
:
console.log( "1,234,567".replaceAll(thousands,"") ); //prints "1234567" to console.
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;
}
Retrieving separators for the current or a given locale is possible using Intl.NumberFormat#formatToParts
.
function getDecimalSeparator(locale) {
const numberWithDecimalSeparator = 1.1;
return Intl.NumberFormat(locale)
.formatToParts(numberWithDecimalSeparator)
.find(part => part.type === 'decimal')
.value;
}
It only works for browsers supporting the Intl API. Otherwise it requires an Intl polyfill
Examples:
> getDecimalSeparator()
"."
> getDecimalSeparator('fr-FR')
","
Bonus:
We could extend it to retrieve either the decimal or group separator of a given locale:
function getSeparator(locale, separatorType) {
const numberWithGroupAndDecimalSeparator = 1000.1;
return Intl.NumberFormat(locale)
.formatToParts(numberWithGroupAndDecimalSeparator)
.find(part => part.type === separatorType)
.value;
}
Examples:
> getSeparator('en-US', 'decimal')
"."
> getSeparator('en-US', 'group')
","
> getSeparator('fr-FR', 'decimal')
","
> getSeparator('fr-FR', 'group')
" "
"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).