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
相关产品推荐
相关产品推荐

