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

Java/Kotlin Normalizer无法归一化部分带重音字母问题问询

Java/Kotlin Normalizer 保留非ASCII字母的原因及替代方案

这不是Bug

Java/Kotlin的Normalizer核心作用是Unicode规范化——比如将带重音的组合字符(如é)分解为基础字符加重音标记(e + ´),但它的设计目标从来不是将所有非ASCII字母转换为等价的ASCII字符。

你测试中遇到的Ł、Æ等字符,本身是Unicode中独立的字母,没有对应的"基础ASCII字符+附加标记"的分解形式,因此Normalizer.normalize(..., NFD)不会对它们做拆分或转换,这是符合其设计逻辑的正常行为。

实现非ASCII到ASCII映射的方法

如果需要将Ł转为L、Æ转为AE这类转换,可以用以下两种方案:

方案1:使用ICU4J库的Transliterator

ICU4J提供了强大的字符转换功能,支持将Unicode字符转成ASCII等价形式:

import com.ibm.icu.text.Transliterator

fun main() {
    val transliterator = Transliterator.getInstance("Any-Latin; Latin-ASCII")
    println(transliterator.transliterate("Łódź")) // 输出 "Lodz"
    println(transliterator.transliterate("Æble")) // 输出 "AEble"
}

规则Any-Latin; Latin-ASCII会先将任意Unicode字符转为拉丁字母形式,再进一步转成ASCII等价字符。

方案2:自定义字符映射表

如果只需要处理特定字符,也可以手动创建映射表进行替换:

fun main() {
    val charMap = mapOf(
        'Ł' to 'L',
        'ł' to 'l',
        'Æ' to "AE",
        'æ' to "ae",
        'Ø' to "O",
        'ø' to "o"
        // 可根据需求添加更多字符映射
    )
    
    fun convertToAscii(input: String): String {
        val sb = StringBuilder()
        input.forEach { c ->
            sb.append(charMap.getOrDefault(c, c))
        }
        return sb.toString()
    }
    
    println(convertToAscii("Łódź")) // 输出 "Lodz"
    println(convertToAscii("Æble")) // 输出 "AEble"
}

这种方式更轻量,不需要引入外部库,但需要手动维护需要处理的字符集合。

内容的提问来源于stack exchange,提问作者Gideon Av

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 22:19:24