В каких 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.

Но, как я уже сказал, я не смог проверить его здесь.