在C#中将阿拉伯语单词转换为Unicode格式

3

我正在设计一个API,该API用户需要以Unicode格式返回阿拉伯文本。为此,我尝试了以下方法:

public static class StringExtensions
{
    public static string ToUnicodeString(this string str)
    {
        StringBuilder sb = new StringBuilder();
        foreach (var c in str)
        {
            sb.Append("\\u" + ((int)c).ToString("X4"));
        }
        return sb.ToString();
    }
}

上述代码的问题在于,它返回字母的Unicode,而不考虑其在单词中的位置。
例如:假设我们有以下单词:
"سمير",由以下组成:
'س'写作'سـ',因为它是单词的第一个字母。
'م'写作'ـمـ',因为它在单词中间。
'ي'写作'ـيـ',因为它在单词中间。
'ر'写作'ـر',因为它是单词的最后一个字母。
上述代码返回{ 'س','م','ي','ر'}的Unicode,即:
"\u0633\u0645\u064A\u0631"
而不是{ 'سـ','ـمـ','ـيـ','ـر'},即:
"\uFEB3\uFEE4\uFEF4\uFEAE"
有什么想法可以更新代码以获取正确的Unicode吗?

有用的 链接

2个回答

3

这个字符串只是一个Unicode代码点的序列,它并不知道阿拉伯语的规则。您得到的数据恰好就是您输入的数据;如果您想要不同的输出数据,则需要输入不同的数据!

试试这个:

Console.WriteLine("\u0633\u0645\u064A\u0631");
Console.WriteLine("\u0633\u0645\u064A\u0631".ToUnicodeString());
Console.WriteLine("\uFEB3\uFEE4\uFEF4\uFEAE");
Console.WriteLine("\uFEB3\uFEE4\uFEF4\uFEAE".ToUnicodeString());

预计输出结果为:
سمير
\u0633\u0645\u064A\u0631
ﺳﻤﻴﺮ
\uFEB3\uFEE4\uFEF4\uFEAE

这两个Unicode代码点序列在浏览器中呈现相同,但它们是不同的序列。如果您想写出第二个序列,请不要传入第一个序列。


当我传递“ﺳﻤﻴﺮ”时,我期望得到的是\uFEB3\uFEE4\uFEF4\uFEAE,因为\u0633\u0645\u064A\u0631是س م ي ر的Unicode,而不是ﺳﻤﻴﺮ。请在此处检查表格:http://www.wikizeroo.net/index.php?q=aHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQXJhYmljX3NjcmlwdF9pbl9Vbmljb2Rl - Yahya Hussein
同样地,如果您将字符串“ВАСКЅІЕЅ”输入您的工具中,与输入“BACKSIES”时会得到不同的结果,因为它们是两个完全不同的字符串。(试试吧!从评论中复制并粘贴这些字符串,看看会发生什么。)在某些浏览器中它们看起来相同的事实是无关紧要的。字符的呈现方式并不重要,许多不同的字符在呈现时看起来相同。字符串中的字符就是字符串中的字符。 - Eric Lippert
谢谢您的澄清,但我仍然有点困惑,如果我正在构建一个浏览器,该如何知道何时呈现字母“م”,例如“م”、“مـ”、“ـمـ”或“ـم”? - Yahya Hussein
1
@YahyaHussein:嗯,你是一个阿拉伯语读者和计算机程序员,那么你告诉我:如果你被分配了这个问题,你会如何解决?这不是魔法;微软聘请了一群深入了解阿拉伯文字的人和一群深入了解代码的人——其中许多人当然都是两者的专家——他们编写了大量极其复杂的代码。然后这个过程在希腊语、西里尔字母、德语、丹麦语、韩语、日语和泰语中重复进行,嘿,软件很昂贵,但Windows已经本地化了。 - Eric Lippert
1
里面有太多历史了:D,我知道软件很贵,我只是想更好地理解我的问题,再次感谢! - Yahya Hussein
显示剩余4条评论

0

基于Eric的回答,我知道如何解决我的问题了,我在Github上创建了一个解决方案。

你会发现一个简单的工具可以在Windows上运行,如果你想在你的项目中使用代码,那么只需复制粘贴UnicodesTable.csUnshaper.cs

基本上,你需要为每个阿拉伯字母准备一个Unicode表,然后你就可以使用以下扩展方法之类的东西。

public static string GetUnShapedUnicode(this string original)
    {
        original = Regex.Unescape(original.Trim());
        var words = original.Split(' ');
        StringBuilder builder = new StringBuilder();
        var unicodesTable = UnicodesTable.GetArabicGliphes();
        foreach (var word in words)
        {
            string previous = null;
            for (int i = 0; i < word.Length; i++)
            {
                string shapedUnicode = @"\u" + ((int)word[i]).ToString("X4");
                if (!unicodesTable.ContainsKey(shapedUnicode))
                {
                    builder.Append(shapedUnicode);
                    previous = null;
                    continue;
                }
                else
                {
                    if (i == 0 || previous == null)
                    {
                        builder.Append(unicodesTable[shapedUnicode][1]);
                    }
                    else
                    {
                        if (i == word.Length - 1)
                        {
                            if (!string.IsNullOrEmpty(previous) && unicodesTable[previous][4] == "2")
                            {
                                builder.Append(unicodesTable[shapedUnicode][0]);
                            }
                            else
                                builder.Append(unicodesTable[shapedUnicode][3]);
                        }
                        else
                        {
                            bool previouChar = unicodesTable[previous][4] == "2";
                            if (previouChar)
                                builder.Append(unicodesTable[shapedUnicode][1]);
                            else
                                builder.Append(unicodesTable[shapedUnicode][2]);
                        }
                    }
                }

                previous = shapedUnicode;
            }
            if (words.ToList().IndexOf(word) != words.Length - 1)
                builder.Append(@"\u" + ((int)' ').ToString("X4"));
        }

        return builder.ToString();
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接