С помощью браузера, Как узнать, какой десятичный разделитель использует операционная система?
Я разрабатываю веб-приложения.
мне нужно правильно отобразить некоторые десятичные данные, чтобы их можно было скопировать и вставить в определенный GUI
приложение, которое не находится под моим контролем.
приложение GUI чувствительно к локали, и оно принимает только правильный десятичный разделитель, который установлен в системе.
Я могу угадать десятичный разделитель от Accept-Language
и думаю, будет правильно в 95% случаев, но иногда это не удается.
Is есть ли способ сделать это на стороне сервера (желательно, чтобы я мог собирать статистику) или на стороне клиента?
обновление:
весь смысл задачи делает это автоматически.
на самом деле, это веб-приложение является своего рода онлайн-интерфейс к наследию GUI, который помогает правильно заполнить формы.
вид пользователей, которые используют его в основном понятия не имеют о том, что такое десятичный разделитель.
The решение и работает, но я хотел бы улучшить его.
обновление 2:
мне нужно повторить очень конкретную настройку: десятичный разделитель установлен в Control Panel / Regional and Language Options / Regional Options / Customize
.
Я имею дело с четырьмя видами операционных систем:
- Русские окна с запятой как DS (80%).
- английские окна с периодом как DS (15%).
- Русские окна с периодом как DS, чтобы сделать плохо написанные английские приложения работают (4%).
- английские окна с запятой в качестве DS, чтобы плохо написанные русские приложения работали (1%).
все 100% клиентов находятся в России, и приложение legacy имеет дело с российскими правительственными формами, поэтому запрос страны даст 100% Российской Федерации, а GeoIP даст 80% Российской Федерации и 20% других (неправильных) ответов.
12 ответов:
вот простая функция JavaScript, которая возвращает эту информацию. Протестировано в Firefox, IE6 и IE7. Мне пришлось закрыть и перезапустить браузер между каждым изменением настройки в разделе Панель управления / региональные и языковые параметры / региональные параметры / настройка. Однако он подобрал не только запятую и точку, но и странные пользовательские вещи, такие как буква "А".
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');
это поможет?
спросите пользователя, не угадайте. Есть настройки для него в вашем веб-приложении.
редактировать, чтобы добавить:
Я думаю, что это нормально, чтобы угадать по умолчанию установка, которая работает нормально, скажем, 95% времени. Я имел в виду, что пользователь все равно должен иметь возможность переопределить любые догадки, сделанные программным обеспечением. Я уже тоже много раз, когда программное обеспечение пытается быть слишком умным и не позволяет быть исправлены.
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; }
Я могу угадать десятичный разделитель от Принять-язык и догадка будет правильно в 95% случаев, но иногда неудачи.
Это ИМО лучший курс действий. Для обработки сбоев добавьте ссылку, чтобы установить ее вручную рядом с областью отображения.
получение разделителей для текущей или заданной локали возможно с помощью
Intl.NumberFormat#formatToParts
.function getDecimalSeparator(locale) { const numberWithDecimalSeparator = 1.1; return Intl.NumberFormat(locale) .formatToParts(numberWithDecimalSeparator) .find(part => part.type === 'decimal') .value; }
это работает только для браузеры, поддерживающие Intl API. В противном случае он требует Международный полифилл
примеры:
> getDecimalSeparator() "." > getDecimalSeparator('fr-FR') ","
бонус:
мы могли бы расширить его, чтобы получить либо decimal или группа разделитель данного локаль:
function getSeparator(locale, separatorType) { const numberWithGroupAndDecimalSeparator = 1000.1; return Intl.NumberFormat(locale) .formatToParts(numberWithGroupAndDecimalSeparator) .find(part => part.type === separatorType) .value; }
примеры:
> getSeparator('en-US', 'decimal') "." > getSeparator('en-US', 'group') "," > getSeparator('fr-FR', 'decimal') "," > getSeparator('fr-FR', 'group') " "
Я думаю, что вы должны полагаться на JavaScript, чтобы дать вам настройки локали.
Но, по-видимому, JS не имеет прямого доступа к этой информации.
Я вижу Dojo Toolkit использует внешнюю базу данных для поиска информации о локали, хотя она может не учитывать изменения настроек учетной записи, например.
Еще один обходной путь, который я вижу, должен иметь небольшой тихий Java-апплет, который запрашивает эту информацию из системы, и JavaScript, чтобы получить ее из Java.
Я могу дайте дополнительную информацию, если вы не знаете, как это сделать (если вы хотите пройти этот извилистый маршрут, Конечно).[редактирование] Поэтому я обновил свои знания о поддержке локализации на Java...
В отличие от того, что я думал изначально, у вас не будет непосредственно десятичного разделителя или тысячи символов разделителя напрямую, как вы бы сделали с разделителем строк или разделителем путей: вместо этого Java предлагает API для форматирования чисел или дат, которые вы предоставляете.
Так или иначе, это имеет смысл: в Европе вы часто ставят символ валюты после номера, некоторые страны (Индия?) есть более сложное правило для разделения цифр и т. д.другое дело: Java правильно находит текущую локаль из системы, но не берет оттуда информацию (возможно, по вышеуказанным причинам). Вместо этого он использует свой собственный набор правил. Поэтому, если у вас есть испанский язык, где вы заменили десятичный разделитель восклицательным знаком, Java не будет использовать его (но, возможно, ни ваше приложение, в любом случае...).
поэтому я пишу апплет, предоставляющий сервис (функции) JavaScript, позволяющий форматировать числа в текущую локаль. Вы можете использовать его как таковой, используя JavaScript для форматирования чисел в браузере. Или вы можете просто подать его с некоторым номером образца и извлечь символы оттуда, используя их локально или подавая их обратно на сервер.
Я заканчиваю и тестирую свой апплет и отправляю его туда в ближайшее время.
хорошо, у меня есть что-то показать, больше доказательство концепции, чем готовый продукт, но из-за отсутствия точных спецификаций я оставляю его таким образом (или я буду перепроектировать его). Я публикую в отдельном сообщении, потому что это будет немного долго. Я воспользовался возможностью, чтобы попробовать немного больше jQuery...
код 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); } }
пример HTML-страницы, используя выше апплет: 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>
протестировано на Firefox 3.0, IE 6, Safari 3.1 и Opera 9.50, на Windows XP Pro SP3. Он работает без проблем с первыми двумя, на Safari у меня есть странная ошибка после вызова 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.access0(Unknown Source) at sun.plugin.liveconnect.SecureInvocation.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at sun.plugin.liveconnect.SecureInvocation.CallMethod(Unknown Source)
но это все еще работает.
Я не могу заставить его работать с Opera: апплет загружается правильно, так как я вижу трассировку вызова init() в консоли Java, у меня нет ошибок при вызове функций Java JavaScript (Кроме если Я добавляю и вызываю метод, получающий параметр JSObject, любопытно), но функции Java не вызываются (я добавил трассировку вызовов).
Я считаю, что Liveconnect работает в Opera, но я пока не вижу, как это сделать. Я буду исследовать немного больше.
[Update] я удалил ссылки на несуществующий файл jar (который не останавливает другие браузеры), и я получил трассировку вызовов, но он не обновляет страницу.
МММ, если я это сделаюalert(applet.GetLocaleInformation());
я получил информацию, так что может быть проблема с jQuery.
даже если вы знали, что локаль это "GUI приложение" работает под, вы все равно должны выяснить, как это получает текущую локаль, и как это определяет десятичный разделитель.
Я не знаю, как это делается на Mac, но на Windows приложения должны опрашивать предпочтения пользователя, установленные с помощью Панели Управления. Вполне возможно, что это таинственное приложение игнорирует эти настройки и использует их собственную внутреннюю настройку вместо.
или, возможно, они берут текущую локаль и выводят остальное, а не говорят.
даже тогда, по-английски,цифры даны в группах из 3 цифр, с запятой, разделяющей группы. т. е.:
5,197,359,078
Если число не было целым числом, содержащим номер телефона:
519-735-9078
Если, конечно, число не было целым числом, содержащим аккаунт номер:
5197359078
в этом случае вы возвращаетесь к жестко закодированной переопределенной логике.
изменить: удален пример валюты, так как валюта имеет свои собственные правила форматирования.
используя ответы других людей, я скомпилировал следующие функции утилиты десятичных и тысячных разделителей:
var decimalSeparator = function() { return (1.1).toLocaleString().substring(1, 2); }; var thousandSeparator = function() { return (1000).toLocaleString().substring(1, 2); };
наслаждайтесь!
"есть ли способ, чтобы сделать это на сервере стороны (желательно, чтобы я мог сбор статистики), или на клиенте в сторону?"
нет, вы не можете. Тот GUI, глядя На некоторых пользователей или определенных параметров машины. Во-первых, вы, вероятно, не знаете, на какие настройки этот пользовательский интерфейс смотрит. Во-вторых, с помощью веб-приложения вы, вероятно, не сможете проверить эти настройки (clientside --> Javacsript).
другое возможное решение: вы могли бы использовать что-то вроде GeoIP (пример в PHP), чтобы определить местоположение пользователя и принять решение на основе этой информации.