Я разрабатываю веб-приложение.
Мне нужно правильно отобразить некоторые десятичные данные, чтобы их можно было скопировать и вставить в определенное GUI
приложение, которое не находится под моим контролем.
Приложение с графическим интерфейсом зависит от языкового стандарта и принимает только правильный десятичный разделитель, установленный в системе.
Я могу предположить десятичный разделитель Accept-Language
и предположение будет правильным в 95% случаев, но иногда это не удается.
Есть ли способ сделать это на стороне сервера (желательно, чтобы я мог собирать статистику) или на стороне клиента?
Обновить:
Вся суть задачи в том, чтобы делать это автоматически.
Фактически, это веб-приложение представляет собой своего рода онлайн-интерфейс к устаревшему графическому интерфейсу, который помогает правильно заполнять формы.
Пользователи, которые его используют, в основном не имеют представления о том, что такое десятичный разделитель.
Accept-Language
Решение реализовано и работает, но я хотел бы, чтобы улучшить его.
Обновление2:
Мне нужно получить очень конкретную настройку: установленный десятичный разделитель Control Panel / Regional and Language Options / Regional Options / Customize
.
Я имею дело с четырьмя типами операционных систем:
- Русская винда с запятой как DS (80%).
- Английская Windows с точкой в DS (15%).
- Русская Windows с точкой в качестве DS для работы плохо написанных англоязычных приложений (4%).
- Английская Windows с запятой в качестве DS для работы плохо написанных русских приложений (1%).
Все 100% клиентов находятся в России, и устаревшее приложение связано с формами, выпущенными российским правительством, поэтому запрос страны даст 100% Российской Федерации, а GeoIP - 80% Российской Федерации и 20% других (неверных). ответы.
источник
DecimalSeparator
(например,,,
). WindowsLOCALE_SDECIMAL
позволяет десятичному разделителю содержать до трех символов. (Вот почему он не работает на моем ПК). В этом случае лучше использоватьAccept-Language
браузер. Что по-прежнему не учитывает возможность указывать свои собственные,DecimalSeparator
например\o/
n = /^1(.+)1$/.exec(n.toLocaleString())[1]
он сделает это, и это проще, чем использованиеAccept-Language
заголовка.Получение разделителей для текущего или заданного языкового стандарта возможно с помощью
Intl.NumberFormat#formatToParts
.function getDecimalSeparator(locale) { const numberWithDecimalSeparator = 1.1; return Intl.NumberFormat(locale) .formatToParts(numberWithDecimalSeparator) .find(part => part.type === 'decimal') .value; }
Он работает только для браузеров, поддерживающих Intl API . В противном случае требуется полифил Intl
Примеры:
> getDecimalSeparator() "." > getDecimalSeparator('fr-FR') ","
Бонус:
Мы могли бы расширить его, чтобы получить либо десятичный, либо групповой разделитель данной локали:
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') " "
источник
Intl
поддерживается даже в IE 11: caniuse.com/#feat=internationalizationСпросите пользователя, а не угадайте. Настройте его в своем веб-приложении.
Отредактировано для добавления:
Я думаю, что можно угадать настройку по умолчанию, которая работает нормально, скажем, в 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; }
источник
Почему бы и нет
0.1.toLocaleString().replace(/\d/g, '')
источник
Это лучший курс действий ИМО. Для обработки сбоев добавьте ссылку, чтобы установить ее вручную рядом с областью отображения.
источник
Используя ответы других людей, я скомпилировал следующие служебные функции десятичного разделителя и разделителя тысяч:
var decimalSeparator = function() { return (1.1).toLocaleString().substring(1, 2); }; var thousandSeparator = function() { return (1000).toLocaleString().substring(1, 2); };
Наслаждайтесь!
источник
formatToParts
(Safari и IE).(1000).toLocaleString("es-PE") # "1000"
Я думаю, вам нужно полагаться на JavaScript, чтобы получить настройки локали.
Но, видимо, у JS нет прямого доступа к этой информации.
Я вижу, что Dojo Toolkit полагается на внешнюю базу данных для поиска информации о локали, хотя, например, он может не учитывать изменения настроек учетной записи.
Другой обходной путь, который я вижу, - это иметь небольшой тихий Java-апплет, который запрашивает эту информацию из системы, и JavaScript, чтобы получить ее из Java.
Я могу дать больше информации, если вы не знаете, как это сделать (если, конечно, вы хотите пойти по этому запутанному маршруту).
[EDIT] Итак, я обновил свои знания о поддержке локализации в 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.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)
но он все еще работает.
Я не могу заставить его работать с Opera: апплет загружается правильно, так как я вижу трассировку вызова init () в консоли Java, у меня нет ошибок, когда JavaScript вызывает функции Java (кроме случаев, когда я добавляю и вызываю метод получение параметра JSObject, как ни странно), но функции Java не вызываются (я добавил трассировку вызовов).
Я считаю, что Liveconnect работает в Opera, но пока не понимаю, как это сделать. Я изучу еще немного.
[Обновление] Я удалил ссылки на несуществующий файл jar (который не останавливает другие браузеры), и я получил трассировку вызовов, но он не обновляет страницу.
Ммм, если я это сделаю,
alert(applet.GetLocaleInformation());
я получил информацию, так что это может быть проблема с jQuery.источник
Locale for русский (Россия): country=Россия (RU / RUS), lang=русский (ru / rus), variant= ()
он использует запятую, несмотря на то, что я заменил ее точкой в настройках Windows.Даже если вы знали, в какой локали работает это «приложение с графическим интерфейсом», вам все равно нужно выяснить, как она получает текущую локаль и как она определяет десятичный разделитель.
Я не знаю, как это делается на Mac, но в Windows приложения должны запрашивать настройки пользователя, установленные через панель управления. Вполне возможно, что это загадочное приложение игнорирует эти настройки и вместо этого использует свои собственные внутренние настройки.
Или, возможно, они берут текущую локаль и делают вывод об остальном, а не говорят.
Даже в этом случае на английском языке числа даются группами по 3 цифры, с запятой, разделяющей группы. то есть:
Если номер не был целым числом, содержащим номер телефона :
Если, конечно, это не целое число, содержащее номер счета :
В этом случае вы возвращаетесь к жестко запрограммированной переопределенной логике.
Изменить: удален пример валюты, так как у валюты есть собственные правила форматирования.
источник
Подобно другим ответам, но сжато как константа :
const decimal=.1.toLocaleString().substr(1,1); //returns "." in Canada
Кроме того, чтобы получить разделитель тысяч :
const thousands=1234..toLocaleString().substr(1,1); //returns "," in Canada
Просто разместите код в верхней части вашего JS, а затем вызовите по мере необходимости, чтобы вернуть символ.
Например (где я живу), чтобы удалить запятые из
"1,234,567"
:console.log( "1,234,567".replaceAll(thousands,"") ); //prints "1234567" to console.
источник
Нет, не можешь. Этот графический интерфейс смотрит на некоторые настройки пользователя или компьютера. Во-первых, вы, вероятно, не знаете, на какие настройки смотрит этот пользовательский интерфейс. Во-вторых, с веб-приложением вы, вероятно, не сможете проверить эти настройки (на стороне клиента -> Javacsript).
источник
Другое возможное решение: вы можете использовать что-то вроде GeoIP (пример в PHP), чтобы определить местоположение пользователя и принять решение на основе этой информации.
источник