孟加拉语字符短信计数异常:首字符计为91个的问题求助
问题分析与解决方案
问题出在JavaScript对Unicode字符的处理逻辑上:孟加拉语的部分字符属于UTF-16代理对(占2个UTF-16代码单元)或组合字符序列,而你的脚本通过text[charPos]和charCodeAt()遍历的是UTF-16代码单元,而非实际的Unicode字符,导致单个视觉字符被拆分成多个单元计数,进而触发异常的长度统计。
修复后的完整脚本
(function ($) { $.fn.smsArea = function (options) { var e = this, cutStrLength = 0, s = $.extend({ cut: true, maxSmsNum: 5, interval: 400, counters: { message: $('#smsCount'), character: $('#smsLength') }, calculateSmsMaxLength: function (isUnicode, writtenSmsNb) { if (isUnicode) { return writtenSmsNb === 0 ? 70 : (70 * (writtenSmsNb + 1)) - ((writtenSmsNb + 1) * 3); } else { return writtenSmsNb === 0 ? 160 : (160 * (writtenSmsNb + 1)) - ((writtenSmsNb + 1) * 7); } } }, options); e.keyup(function () { clearTimeout(this.timeout); this.timeout = setTimeout(function () { var smsType, smsLength = 0, smsCount = -1, charsLeft = 0, text = e.val(), isUnicode = false; // 关键修复:按Unicode码点遍历,正确处理代理对和组合字符 const codePoints = Array.from(text); for (const char of codePoints) { switch (char) { case "\n": case "[": case "]": case "\\": case "^": case "{": case "}": case "|": case "€": smsLength += 2; break; default: smsLength += 1; } const codePoint = char.codePointAt(0); if (codePoint > 127 && char !== "€") { isUnicode = true; } } for (var sCount = 0; sCount < s.maxSmsNum; sCount++) { smsType = s.calculateSmsMaxLength(isUnicode, sCount); cutStrLength = smsType; if (smsLength <= smsType) { smsCount = sCount + 1; charsLeft = smsType - smsLength; break; } } if (s.cut) e.val(text.substring(0, cutStrLength)); if (smsCount === -1) { smsCount = s.maxSmsNum; charsLeft = 0; } s.counters.message.html(smsCount); s.counters.character.html(charsLeft); }, s.interval); }).keyup(); } }(jQuery));
核心修复点
- Unicode字符遍历:用
Array.from(text)将字符串转换为Unicode码点数组,确保每个视觉字符(包括代理对、组合字符)被当作单个元素处理,避免拆分计数。 - 码点判断逻辑:用
char.codePointAt(0)获取字符的实际Unicode码点,替代charCodeAt(),避免代理对的单个代码单元干扰isUnicode的判断。 - 代码精简:将
calculateSmsMaxLength中的条件判断简化为三元表达式,不影响逻辑但提升可读性。
为什么部分在线工具也有同样问题?
这类工具大多采用了和你原脚本相同的错误处理逻辑:直接遍历UTF-16代码单元而非Unicode码点,导致无法正确处理非BMP(超出U+FFFF)的Unicode字符,出现计数异常。
内容的提问来源于stack exchange,提问作者Nazmul Hossain
相关产品推荐
相关产品推荐

