C# 消除波兰语中的变音符号

C# 消除波兰语中的变音符号,c#,.net,unicode,diacritics,polish,C#,.net,Unicode,Diacritics,Polish,我正试图用波兰语把变音字符从盘古文字中去掉。然而,我使用的代码来自Michael Kaplan的博客,但没有成功 考虑下面这句话:“普切尼·瓦托德·杰亚·卢布·奥塞姆·斯克钦菲格”(Pchnąćw tęłdźjeża lub ośm skrzyńfig.)。除了字母“ł”外,一切正常,我仍然得到“ł”。我想问题在于“ł”表示为单个unicode字符,并且没有以下非空格标记 你知道我如何修复它吗(不依赖于某些词典中的自定义映射-我正在寻找某种unicode转换)?本文采用的方法是删除带标记的非空格

我正试图用波兰语把变音字符从盘古文字中去掉。然而,我使用的代码来自Michael Kaplan的博客,但没有成功

考虑下面这句话:“普切尼·瓦托德·杰亚·卢布·奥塞姆·斯克钦菲格”(Pchnąćw tęłdźjeża lub ośm skrzyńfig.)。除了字母“ł”外,一切正常,我仍然得到“ł”。我想问题在于“ł”表示为单个unicode字符,并且没有以下非空格标记


你知道我如何修复它吗(不依赖于某些词典中的自定义映射-我正在寻找某种unicode转换)?

本文采用的方法是删除带标记的非空格字符。正如您正确指出的,“ł”不是由两个字符组成的(其中一个是Mark,nonspace),因此您看到的行为是预期的

我认为Unicode的结构不允许您完成完全自动的重新映射(您引用的文章的作者得出了相同的结论)


如果您只是对波兰语字符感兴趣,那么至少映射很小且定义良好(请参见示例的底部)。对于一般情况,我认为对于不是由标准字符加上标记、非空格字符组成的字符,不存在自动解决方案。

它位于,codepoint\u0142中。向下滚动到描述“带笔划的拉丁小写字母”,它没有列出任何分解。我对波兰语一无所知,但一个字母通常会有一个识别标记,使其成为自己的字母,而不是带有变音符号的基本字母。

有相当多的预合成字符没有有意义的分解

(也有少数可能有合理的分解,在大多数规范化形式中,这种分解是禁止的,因为这会导致版本之间的差异,这将使它们不再真正规范化)


ł就是其中之一。IIRC也不可能给不使用ł的字母赋予文化中立的转录。我认为德国人倾向于将其转录为w而不是l(或者可能是其他人),这是有道理的(听起来也不太正确,但它比l更接近)。

你必须手动替换这些(就像拉丁语-1中的ÆÐØÞßðþ一样)


其他人也有同样的问题,因此Unicode公共语言环境数据存储库“同意添加一个可以消除重音的音译器,即使对于重叠的重音也是如此。”()

下面是我对波兰语禁止列表的快速实现,其中包括波兰语变音符号的标准化

    class StopList
{
    private HashSet<String> set = new HashSet<String>();

    public void add(String word)
    {
        word = word.trim().toLowerCase();
        word = normalize(word);
        set.add(word);

    }

    public boolean contains(final String string)
    {
        return set.contains(string) || set.contains(normalize(string));
    }

    private char normalizeChar(final char c)
    {
        switch ( c)
        {
            case 'ą':
                return 'a';
            case 'ć':
                return 'c';
            case 'ę':
                return 'e';
            case 'ł':
                return 'l';
            case 'ń':
                return 'n';
            case 'ó':
                return 'o';
            case 'ś':
                return 's';
            case 'ż':
            case 'ź':
                return 'z';
        }
        return c;
    }

    private String normalize(final String word)
    {
        if (word == null || "".equals(word))
        {
            return word;
        }
        char[] charArray = word.toCharArray();
        char[] normalizedArray = new char[charArray.length];
        for (int i = 0; i < normalizedArray.length; i++)
        {
            normalizedArray[i] = normalizeChar(charArray[i]);
        }
        return new String(normalizedArray);
    }
}
类停止列表
{
私有HashSet=新HashSet();
公共空添加(字符串字)
{
word=word.trim().toLowerCase();
word=规范化(word);
set.add(word);
}
公共布尔包含(最终字符串)
{
返回set.contains(string)| set.contains(normalize(string));
}
私有字符规范化char(最终字符c)
{
开关(c)
{
“ą”案:
返回“a”;
案例'ć':
返回“c”;
“ę”案:
返回“e”;
案例“ł”:
返回“l”;
案例'n':
返回'n';
案例“ó”:
返回“o”;
案例“ś”:
返回's';
案例“ż”:
案例“ź”:
返回'z';
}
返回c;
}
私有字符串规范化(最终字符串字)
{
if(word==null | |“”.equals(word))
{
返回词;
}
char[]charArray=word.toCharArray();
char[]normalizedaray=新字符[charArray.length];
for(int i=0;i

我在网上找不到其他解决办法。因此,也许这对某些人会有帮助(?)

不久前,我遇到了这个解决方案,它似乎工作得很好:

    public static string RemoveDiacritics(this string s)
    {
        string asciiEquivalents = Encoding.ASCII.GetString(
                     Encoding.GetEncoding("Cyrillic").GetBytes(s)
                 );

        return asciiEquivalents;
    }

我找到了一个解决方案,这个解决方案也是“ł”

string RemoveDiacritics(string text)
    {
        var normalizedString = text.Normalize(NormalizationForm.FormD);
        var stringBuilder = new StringBuilder();

        foreach (var c in normalizedString)
        {
            var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
            if (unicodeCategory != UnicodeCategory.NonSpacingMark)
            {
                stringBuilder.Append(c);
            }
        }

        return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
    }

除了
ł
之外,所有这些字符都只有一个字符(我至少看到了ogonek、acute和dot),并且可以使用
Normalize
轻松地进行规范化。我建议将这两种方法结合起来。规范化是.NET库吗?很抱歉这是我Java代码中的一段:)和写“Net”时,我想到的是InterNet,而不是“.Net”。手动总是一个选项,但我应该写所有的组合吗?法语、德语、波兰语等?
System.ArgumentException:“西里尔字母”不是受支持的编码名称。
我还需要转换法语,我认为它无论如何都不起作用:(德语呢?