международные символы подсчета смс

Я нашел Подсчет символов/смс с использованием jQuery, но он не поддерживает международные символы, такие как Китайский, японский, тайский и т.д.

var $remaining = $('#remaining'),
    $messages = $remaining.next();

$('#message').keyup(function(){
    var chars = this.value.length,
        messages = Math.ceil(chars / 160),
        remaining = messages * 160 - (chars % (messages * 160) || messages * 160);

    $remaining.text(remaining + ' characters remaining');
    $messages.text(messages + ' message(s)');
});

Вот несколько примеров неправильного подсчета символов:

您好,請問你吃飯了嗎? ‹‹ 11 символов

สวัสดีคุณกินหรือ? ‹‹ 17 символов

こんにちは、あなたは食べていますか? ‹‹ 18 символов

안녕하세요, 당신이 먹는 거죠? ‹‹ 17 символов

हैलो, आप खाते हैं? ‹‹ 18 символов

Добры дзень, вы ясьце? ‹‹ 22 символа

Как я могу заставить это работать с символами, отличными от ASCII?


person Ironman    schedule 28.03.2011    source источник
comment
Кажется, по большей части считается нормально. 您好,請問你吃飯了嗎? имеет 11 символов, а числа для японского, корейского и русского языков также подходят. Каких цифр вы ожидаете? Только тайский и хинди могут быть отключены, но я не знаю, как там учитываются символы.   -  person deceze♦    schedule 28.03.2011
comment
Да, как вы сказали, тайский и хинди - это разница, ดี - это уже 2 символа, поэтому, как указано выше, jquery я нашел, как заставить его поддерживать международный китайский, тайский, японский, корейский, хинди, русский...   -  person Ironman    schedule 28.03.2011
comment
Да, но 您 — это один символ UTF-8. Очевидно, вы хотите считать байты, а не символы?   -  person deceze♦    schedule 28.03.2011


Ответы (1)


Вы не можете рассчитывать на «персонажей» здесь. Согласно статье SMS в Википедии, для SMS используется одна из трех различных кодировок (7-битный GSM, 8-битный). бит GSM и UTF-16). Итак, сначала вам нужно знать/решить, какую кодировку вы будете использовать.

Если вы знаете, что всегда будете использовать UTF-16, вы можете подсчитать количество 16-битных единиц кода будет занимать строка. Стандартное SMS может состоять из 70 16-битных кодовых единиц. Но это также ограничит сообщения латинскими символами до 70. Поэтому, если вы хотите использовать полные 160 символов (с 7-битной кодировкой) или 140 символов (с 8-битной кодировкой) для латинских символов, вам нужно различать эти три случая.

Пример подсчета единиц 16-битного кода UTF-16:

var message = "您好,請問你吃飯了嗎?";

var utf16codeUnits = 0;

for (var i = 0, len = message.length; i < len; i++) {
  utf16codeUnits += message.charCodeAt(i) < 0x10000 ? 1 : 2;
}

Кстати, это будет показывать те же числа, которые вы указали как "неправильные", поэтому вам нужно будет объяснить, почему вы считаете их неверными.


ИЗМЕНИТЬ

Несмотря на то, что меня уже приняли, я быстро взломал функцию, которая правильно (насколько я могу судить) вычисляет 7-битный GSM (если возможно) и UTF-16 размеры SMS-сообщения: http://jsfiddle.net/puKJb/

person RoToRa    schedule 28.03.2011
comment
Как насчет использования Math.ceil(Math.log(message.charCodeAt(i))/Math.log(2<<bits)) с bits вместо 7 или 8? - person Gumbo; 28.03.2011
comment
@Gumbo: я не думаю, что это применимо здесь. Кодировка GSM 7 и 8 бит не основана на кодовой точке Unicode (которую возвращает charCodeAt). - person RoToRa; 28.03.2011
comment
Я думаю стандарт SMS указывает UCS-2, а не UTF-16. Таким образом, только 2-байтовые символы и никаких символов за пределами BMP. - person Craig McQueen; 15.08.2011
comment
@RoToRa в коде jsfiddle gsm7bitUnits не работает для символов с диакритическими знаками, таких как á, которые распространены в испанском языке. - person kzfabi; 12.08.2013
comment
@RoToRa только что исследовал больше и обнаружил, что такие символы, как á, не являются GSM, поэтому максимальная длина SMS-сообщения, содержащего их, составляет 70, и эти символы считаются за 1 единицу. - person kzfabi; 12.08.2013