18

一部のユーザーは、メール ヘッダーでエンコーディングなどが適切に設定されていても、Unicode に対応できない電子メール クライアントを使用しています。

彼らが受け取っているコンテンツを「正規化」したいと思います。私たちが抱えている最大の問題は、ユーザーが Microsoft Word から Web アプリケーションにコンテンツをコピーして貼り付けることです。これにより、そのコンテンツが電子メールで転送されます。これには、分数、スマート クォート、および Word が便利に挿入する他のすべての拡張 Unicode 文字が含まれます。 .

これには明確な解決策はないと思いますが、座って大きなルックアップ テーブルを書き始める前に、何か組み込みのメソッドを使って作業を開始できますか?

基本的に 3 つのフェーズが関係しています。

まず、そうでなければ通常の文字からアクセントを取り除きます - これに対する解決策はここにあります

This paragraph contains “smart quotes” and áccénts and ½ of the problem is fractions

に行く

This paragraph contains “smart quotes” and accents and ½ of the problem is fractions

次に、単一の Unicode 文字を同等の ASCII 文字に置き換えると、次のようになります。

This paragraph contains "smart quotes" and accents and ½ of the problem is fractions

これは、自分で実装する前に解決策があることを望んでいる部分です。最後に、特定の文字を適切な ASCII シーケンス (½ から 1/2 など) に置き換えることは、どの種類の Unicode マジックでもネイティブにサポートされていないことは確かですが、誰かが適切なルックアップ テーブルを作成した可能性があります。再利用。

何か案は?

4

4 に答える 4

24

非常に有益な回答をありがとうございました。実際の質問は「Unicode文字をASCIIフォールバックに変換するにはどうすればよいですか」ではなく、「顧客が不満を言っているUnicode文字をASCIIフォールバックに変換するにはどうすればよいですか」ということです。

言い換えれば、汎用ソリューションは必要ありません。英語を話す顧客がWordや他のWebサイトからアプリケーションに英語のコンテンツを貼り付けるために、99%の時間で機能するソリューションが必要です。そのために、次のテストを使用して、システムを介して送信された8年分のメッセージを分析し、ASCIIエンコードで表現できない文字を探しました。

///<summary>Determine whether the supplied character is 
///using ASCII encoding.</summary>
bool IsAscii(char inputChar) {
    var ascii = new ASCIIEncoding();
    var asciiChar = (char)(ascii.GetBytes(inputChar.ToString())[0]);
    return(asciiChar == inputChar);
}

次に、結果として得られた表現できない文字のセットを調べ、適切な置換文字列を手動で割り当てました。ロット全体が拡張メソッドにバンドルされているため、myString.Asciify()を呼び出して、文字列を適切なASCIIエンコード近似に変換できます。

public static class StringExtensions {
    private static readonly Dictionary<char, string> Replacements = new Dictionary<char, string>();
    /// <summary>Returns the specified string with characters not representable in ASCII codepage 437 converted to a suitable representative equivalent.  Yes, this is lossy.</summary>
    /// <param name="s">A string.</param>
    /// <returns>The supplied string, with smart quotes, fractions, accents and punctuation marks 'normalized' to ASCII equivalents.</returns>
    /// <remarks>This method is lossy. It's a bit of a hack that we use to get clean ASCII text for sending to downlevel e-mail clients.</remarks>
    public static string Asciify(this string s) {
        return (String.Join(String.Empty, s.Select(c => Asciify(c)).ToArray()));
    }

    private static string Asciify(char x) {
        return Replacements.ContainsKey(x) ? (Replacements[x]) : (x.ToString());
    }

    static StringExtensions() {
        Replacements['’'] = "'"; // 75151 occurrences
        Replacements['–'] = "-"; // 23018 occurrences
        Replacements['‘'] = "'"; // 9783 occurrences
        Replacements['”'] = "\""; // 6938 occurrences
        Replacements['“'] = "\""; // 6165 occurrences
        Replacements['…'] = "..."; // 5547 occurrences
        Replacements['£'] = "GBP"; // 3993 occurrences
        Replacements['•'] = "*"; // 2371 occurrences
        Replacements[' '] = " "; // 1529 occurrences
        Replacements['é'] = "e"; // 878 occurrences
        Replacements['ï'] = "i"; // 328 occurrences
        Replacements['´'] = "'"; // 226 occurrences
        Replacements['—'] = "-"; // 133 occurrences
        Replacements['·'] = "*"; // 132 occurrences
        Replacements['„'] = "\""; // 102 occurrences
        Replacements['€'] = "EUR"; // 95 occurrences
        Replacements['®'] = "(R)"; // 91 occurrences
        Replacements['¹'] = "(1)"; // 80 occurrences
        Replacements['«'] = "\""; // 79 occurrences
        Replacements['è'] = "e"; // 79 occurrences
        Replacements['á'] = "a"; // 55 occurrences
        Replacements['™'] = "TM"; // 54 occurrences
        Replacements['»'] = "\""; // 52 occurrences
        Replacements['ç'] = "c"; // 52 occurrences
        Replacements['½'] = "1/2"; // 48 occurrences
        Replacements['­'] = "-"; // 39 occurrences
        Replacements['°'] = " degrees "; // 33 occurrences
        Replacements['ä'] = "a"; // 33 occurrences
        Replacements['É'] = "E"; // 31 occurrences
        Replacements['‚'] = ","; // 31 occurrences
        Replacements['ü'] = "u"; // 30 occurrences
        Replacements['í'] = "i"; // 28 occurrences
        Replacements['ë'] = "e"; // 26 occurrences
        Replacements['ö'] = "o"; // 19 occurrences
        Replacements['à'] = "a"; // 19 occurrences
        Replacements['¬'] = " "; // 17 occurrences
        Replacements['ó'] = "o"; // 15 occurrences
        Replacements['â'] = "a"; // 13 occurrences
        Replacements['ñ'] = "n"; // 13 occurrences
        Replacements['ô'] = "o"; // 10 occurrences
        Replacements['¨'] = ""; // 10 occurrences
        Replacements['å'] = "a"; // 8 occurrences
        Replacements['ã'] = "a"; // 8 occurrences
        Replacements['ˆ'] = ""; // 8 occurrences
        Replacements['©'] = "(c)"; // 6 occurrences
        Replacements['Ä'] = "A"; // 6 occurrences
        Replacements['Ï'] = "I"; // 5 occurrences
        Replacements['ò'] = "o"; // 5 occurrences
        Replacements['ê'] = "e"; // 5 occurrences
        Replacements['î'] = "i"; // 5 occurrences
        Replacements['Ü'] = "U"; // 5 occurrences
        Replacements['Á'] = "A"; // 5 occurrences
        Replacements['ß'] = "ss"; // 4 occurrences
        Replacements['¾'] = "3/4"; // 4 occurrences
        Replacements['È'] = "E"; // 4 occurrences
        Replacements['¼'] = "1/4"; // 3 occurrences
        Replacements['†'] = "+"; // 3 occurrences
        Replacements['³'] = "'"; // 3 occurrences
        Replacements['²'] = "'"; // 3 occurrences
        Replacements['Ø'] = "O"; // 2 occurrences
        Replacements['¸'] = ","; // 2 occurrences
        Replacements['Ë'] = "E"; // 2 occurrences
        Replacements['ú'] = "u"; // 2 occurrences
        Replacements['Ö'] = "O"; // 2 occurrences
        Replacements['û'] = "u"; // 2 occurrences
        Replacements['Ú'] = "U"; // 2 occurrences
        Replacements['Œ'] = "Oe"; // 2 occurrences
        Replacements['º'] = "?"; // 1 occurrences
        Replacements['‰'] = "0/00"; // 1 occurrences
        Replacements['Å'] = "A"; // 1 occurrences
        Replacements['ø'] = "o"; // 1 occurrences
        Replacements['˜'] = "~"; // 1 occurrences
        Replacements['æ'] = "ae"; // 1 occurrences
        Replacements['ù'] = "u"; // 1 occurrences
        Replacements['‹'] = "<"; // 1 occurrences
        Replacements['±'] = "+/-"; // 1 occurrences
    }
}

そこにはかなり奇妙なフォールバックがあることに注意してください-このように:

Replacements['³'] = "'"; // 3 occurrences
Replacements['²'] = "'"; // 3 occurrences

これは、ユーザーの1人がオープン/クローズのスマートクォートを²と³に変換するプログラムを持っていて(たとえば、彼は²hello³と言った)、べき乗を表すためにそれらを使用したことがないためです。 。

于 2011-05-29T09:06:48.270 に答える
6

Word で最初に作成された文字列のリストを使用している間、私はこれにいくつかの問題を抱えていました。"String".replace(current char/string, new char/string)簡単なコマンドを使用すると完全に機能することがわかりました。私が使用した正確なコードは、スマート クォート用でした。正確には、左 "、右 "、左 '、および右 ' は次のとおりです。

StringName = StringName.Replace(ChrW(8216), "'")     ' Replaces any left ' with a normal '
StringName = StringName.Replace(ChrW(8217), "'")     ' Replaces any right ' with a normal '
StringName = StringName.Replace(ChrW(8220), """")    ' Replace any left " with a normal "
StringName = StringName.Replace(ChrW(8221), """")    ' Replace any right " with a normal "

これがまだこの問題を抱えている人に役立つことを願っています!

于 2012-10-15T19:56:56.943 に答える
1

私を始めるための組み込みメソッドはありますか?

最初に試したいのは、Normalize on strings メソッドを使用して、テキストを NFKD正規化形式に変換することです。この提案は、リンクした質問への回答に記載されていますが、NFKD では不要なタイポグラフィの区別 (NBSP → スペース、ℂ → C など) が削除されるため、NFKD の代わりに NFKD を使用することをお勧めします。

Unicode カテゴリで一般的な置換を行うこともできます。たとえば、Pd は に置き換えられ-、Nd は対応する0-9数字に置き換えられ、Mn は空の文字列に置き換えられます (アクセントを削除するため)。

しかし、誰かが私が再利用できる適切なルックアップ テーブルを書いているかもしれません。

Unidecode プログラムまたはCLDRのデータを使用してみてください。

編集:ここに巨大な置換チャートがあります。

于 2011-05-29T06:51:54.653 に答える
-1

Unicode を ASCII に変換しようとしないでください。解決するよりも多くの問題が発生することになります。

1,114,112 コードポイント (Unicode 6.0) を 128 文字に収めようとするようなものです。

あなたは成功すると思いますか?

ところで、あなたが言及したものだけでなく、Unicodeには多くの引用符があります。また、変換を行いたい場合は、変換がロケールに依存することを覚えておいてください。

最も完全な Unicode 変換ルーチンが含まれているICUを確認してください。

于 2011-05-28T18:41:20.443 に答える