You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

孟加拉语字符短信计数异常:首字符计为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));

核心修复点

  1. Unicode字符遍历:用Array.from(text)将字符串转换为Unicode码点数组,确保每个视觉字符(包括代理对、组合字符)被当作单个元素处理,避免拆分计数。
  2. 码点判断逻辑:用char.codePointAt(0)获取字符的实际Unicode码点,替代charCodeAt(),避免代理对的单个代码单元干扰isUnicode的判断。
  3. 代码精简:将calculateSmsMaxLength中的条件判断简化为三元表达式,不影响逻辑但提升可读性。

为什么部分在线工具也有同样问题?

这类工具大多采用了和你原脚本相同的错误处理逻辑:直接遍历UTF-16代码单元而非Unicode码点,导致无法正确处理非BMP(超出U+FFFF)的Unicode字符,出现计数异常。

内容的提问来源于stack exchange,提问作者Nazmul Hossain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 07:05:01