В каких JS-двигателях, в частности, toLowerCase & toUpperCase зависит от локали?
В коде некоторых библиотек (например, AngularJS ссылка приводит к определенным строкам в коде), я вижу, что пользовательский вместо стандартных используются функции преобразования case. Это оправдано предположением, что в браузерах с турецким языком стандартные функции работают не так, как ожидалось:
console.log("SCRIPT".toLowerCase()); // "scrıpt"
console.log("script".toUpperCase()); // "SCRİPT"
Но действительно ли это или когда-либо было? Действительно ли браузеры ведут себя так? Если да, то кто из них? Как насчет node.js? Другие двигатели JS?
Существование методов toLocaleLowerCase
и toLocaleUpperCase
подразумевает, что toLowerCase
и toUpperCase
являются локально-инвариантными, не так ли?
Для каких браузеров команда Angular сохраняет эту проверку в коде: if ('i' !== 'I'.toLowerCase())...
?
Если ваш браузер (устройство) использует турецкий или азербайджанский язык, запустите этот фрагмент и напишите мне, если вы обнаружите, что проблема действительно существует.
if ('i' !== 'I'.toLowerCase()) {
document.write('Ooops! toLowerCase is locale-sensitive in your browser. ' +
'Please write your user-agent in the comments to this question: ' +
navigator.userAgent);
} else {
document.write('toLowerCase isn\'t locale-sensitive in your browser. ' +
'Everything works as expected!');
}
<html lang="tr">
Ответы
Ответ 1
Любые реализации JS, соответствующие стандарту ECMA-262 5.1, должны реализовывать String.prototype.toLocaleLowerCase
и String.prototype.toLocaleUpperCase
И в соответствии с стандартным toLocaleLowerCase
предполагается преобразовать строку в это строчное сопоставление в соответствии с конкретным языковым сопоставлением.
Где в качестве toLowerCase
преобразуется в строчную строку, как определено в unicode-сопоставлениях.
Для большинства языков toLocaleLowerCase
и toLowerCase
дается тот же результат. Но для некоторых языков, таких как turkish, отображение случаев не следует за отображением unicode, поэтому toLowerCase
и toLocaleLowerCase
дают разные результаты.
Библиотека/структура, которую вы используете (JQuery, Angular, Node все остальное) не имеет никакого значения. Это в какой реализации JS вы используете для запуска своих JS-библиотек, которые делают и меняют вещи.
Для всех практических целей точно следует, что Node/Angular или любые другие JS-библиотеки и фреймворки ведут себя одинаково при работе со строками (если они используются JS Engine, который реализует ECMA-262 3 и выше). Сказав это, я уверен, что многие фреймворки расширяют строковый объект, чтобы добавить больше функциональности, но основные свойства и функции определенные ECMA-262 5.1, всегда существуют и будут вести себя точно так же.
Чтобы узнать больше: http://www.ecma-international.org/ecma-262/5.1/#sec-15.5.4.17
Что касается браузеров, все современные браузеры реализуют стандарты ECMA-262 5.1 в своем JS-движке. Я не уверен в Node, но из того, что у меня есть с Node, я думаю, что они тоже используют JS, реализованный по стандарту ECMA-262 5.1.
Ответ 2
Примечание. Пожалуйста, обратите внимание, что я не смог проверить его.
По спецификация ECMAScript:
String.prototype.toLowerCase()
[...]
В целях этой операции 16-разрядные кодовые единицы Строки рассматриваются как кодовые точки в Unicode Basic Multilingual Самолет. Суррогатные коды передаются непосредственно из S в L без какого-либо отображения.
Результат должен быть получен в соответствии с отображением случая в База данных символов Юникода (это явно включает не только UnicodeData.txt, , а также файл SpecialCasings.txt, который сопровождает его в Unicode 2.1.8 и более поздних версиях).
[...]
String.prototype.toLocaleLowerCase()
Эта функция работает точно так же, как и для LowerCase, за исключением того, что ее результат предназначен для получения правильного результата для хоста среда текущего языка, а не результат, не зависящий от локали. В немногих случаях (например, турецких) будет только разница, где правила для этого языка конфликтуют с обычным Unicode случайные отображения.
[...]
И согласно Unicode Character Database Special Casing:
[...]
Формат
Записи в этом файле находятся в следующем машиночитаемом формате:
<code>; <lower>; <title>; <upper>; (<condition_list>;)? # <comment>
Безусловные сопоставления
[...]
Сохранять каноническую эквивалентность для я с точкой. Тюркский обрабатывается ниже.
0130; 0069 0307; 0130; 0130; # LATIN CAPITAL LETTER I WITH DOT ABOVE
[...]
Чувствительные к языку сопоставления Это символы, чьи отображения полного случая зависят от языка и, возможно, также контекст (какие символы появляются до или после). Чтобы получить больше информации см. заголовок этого файла и стандарт Unicode.
Литовская
Литовцы сохраняют точку в нижнем регистре, а затем акценты.
Удалите DOT ABOVE после "i" с верхней или заголовкой
0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE
Представьте явную точку выше, когда нижний индекс капитала я и J когда есть больше акцентов выше. (акцентов, используемых на литовском языке: тяжелая, острая, тильда выше и огонек)
0049; 0069 0307; 0049; 0049; lt More_Above; # LATIN CAPITAL LETTER I
004A; 006A 0307; 004A; 004A; lt More_Above; # LATIN CAPITAL LETTER J
012E; 012F 0307; 012E; 012E; lt More_Above; # LATIN CAPITAL LETTER I WITH OGONEK
00CC; 0069 0307 0300; 00CC; 00CC; lt; # LATIN CAPITAL LETTER I WITH GRAVE
00CD; 0069 0307 0301; 00CD; 00CD; lt; # LATIN CAPITAL LETTER I WITH ACUTE
0128; 0069 0307 0303; 0128; 0128; lt; #LATIN CAPITAL LETTER I WITH TILDE
Турецкий и азербайджанский
I и i-dotless; I-точка и я - пары случаев на турецком и азербайджанском языках Следующие правила обрабатывают эти случаи.
0130; 0069; 0130; 0130; tr; # LATIN CAPITAL LETTER I WITH DOT ABOVE
0130; 0069; 0130; 0130; az; # LATIN CAPITAL LETTER I WITH DOT ABOVE
При уменьшении размера снимите dot_above в последовательности я + dot_above, которая превратится в i. Это соответствует поведению канонического эквивалента I-dot_выше
0307; ; 0307; 0307; tr After_I; # COMBINING DOT ABOVE
0307; ; 0307; 0307; az After_I; # COMBINING DOT ABOVE
Когда нижняя шкала, если я не до точки dot_above, она превращается в бесчисленное i.
0049; 0131; 0049; 0049; tr Not_Before_Dot; # LATIN CAPITAL LETTER I
0049; 0131; 0049; 0049; az Not_Before_Dot; # LATIN CAPITAL LETTER I
При верхнем индексе я превращается в пунктирную столицу I
0069; 0069; 0130; 0130; tr; # LATIN SMALL LETTER I
0069; 0069; 0130; 0130; az; # LATIN SMALL LETTER I
Примечание. Следующий файл уже присутствует в файле UnicodeData.txt.
0131; 0131; 0049; 0049; tr; # LATIN SMALL LETTER DOTLESS I
EOF
Кроме того, согласно JavaScript для абсолютных начинающих (от Terry McNavage):
> "I".toLowerCase() // "i"
> "i".toUpperCase() // "I"
> "I".toLocaleLowerCase() // "<dotless-i>"
> "i".toLocaleUpperCase() // "<dotted-I>"
Примечание: toLocaleLowerCase()
и toLocaleUpperCase()
конвертировать фразу на основе настроек вашей ОС. Вам придется изменить эти настройки на турецкий, чтобы предыдущий образец работал. Или просто возьми мое слово за это!
И как bobince комментарий над Convert JavaScript String будет всем нижним регистром? вопрос:
Accept-Language
и navigator.language
являются двумя полностью раздельными Настройки. Accept-Language
отражает выбранные пользователем предпочтения для какие языки они хотят получать на веб-страницах (и этот параметр к сожалению, недоступным для JS). navigator.language
просто отражает которая была установлена локализацией веб-браузера, и должна вообще не используется ни для чего. Оба эти значения не связаны между собой к языку системы, который является битом, который решает, что toLocaleLowerCase() будет делать; , что параметр OS-уровня выходит за пределы области действия браузеров prefs.
Итак, установка lang="tr-TR"
на html
не будет соответствовать реальному тестовому примеру, так как это настройка ОС, которая должна воспроизводить специальный пример корпуса.
Я думаю, что только при использовании toLowerCase()
или toUpperCase()
только нижний штрих-пунктир-I или верхний индекс dotless-i был бы специфичным для локали.
В соответствии с этими достоверными/официальными источниками, я думаю, вы правы: 'i' !== 'I'.toLowerCase()
всегда будет оценивать значение false.
Но, как я уже сказал, я не смог проверить его здесь.