Может ли .NET конвертировать Unicode в ASCII, чтобы удалить «умные кавычки» и т. Д.? - PullRequest
17 голосов
/ 28 мая 2011

Некоторые из наших пользователей используют почтовые клиенты, которые не справляются с Юникодом, даже если кодировка и т. Д. Правильно установлены в заголовках почты.

Я бы хотел «нормализовать»контент, который они получают.Самая большая проблема, с которой мы сталкиваемся, заключается в том, что пользователи копируют и вставляют контент из Microsoft Word в наше веб-приложение, которое затем пересылает этот контент по электронной почте, включая дроби, умные кавычки и все другие расширенные символы Юникода, которые Word любезно вставляет для вас..

Я предполагаю, что для этого определенно нет решения, но прежде чем я сижу и начинаю писать большие большие таблицы поиска, есть ли какой-нибудь встроенный метод, который поможет мне начать?

Там в основном три этапа.

Во-первых, удаление акцентов с обычных букв - решение для этого здесь

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 и т. Д., Которая, я уверен, не поддерживается изначально какой-либо магией Юникода, но кто-то мог бы написать подходящую таблицу поиска, которую я могуповторно использовать.

Есть идеи?

Ответы [ 4 ]

17 голосов
/ 29 мая 2011

Спасибо всем за некоторые очень полезные ответы.Я понимаю, что на самом деле вопрос не в том, «Как я могу преобразовать ЛЮБОЙ символ Unicode в его запасной вариант ASCII» - вопрос в том, «как я могу преобразовать символы Unicode , мои клиенты жалуются на в свои запасные варианты ASCII»?

Другими словами - нам не нужно универсальное решение;нам нужно решение, которое будет работать в 99% случаев, чтобы англоязычные клиенты вставляли англоязычный контент из Word и других веб-сайтов в наше приложение.С этой целью я проанализировал сообщения, отправленные через нашу систему за восемь лет в поисках символов, которые не могут быть представлены в кодировке 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

Это потому, что у одного из наших пользователей есть какая-то программа, которая преобразует умные кавычки открытия / закрытия в ² и ³ (например, он сказал «привет»), и никто никогда не использовал их дляпредставляет возведение в степень, так что это, вероятно, будет работать очень хорошо для нас, но YMMV.

5 голосов
/ 15 октября 2012

У меня были некоторые проблемы с этим, когда я использовал список строк, изначально встроенных в 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 "

Я надеюсь, что это поможет любому, у кого все еще есть этопроблема!

1 голос
/ 29 мая 2011

есть какой-то встроенный метод, который будет начать?

Первое, что я попробую, - это преобразовать текст в NFKD форму нормализации с помощью метода Normalize on strings. Это предложение упоминается в ответе на вопрос, который вы связали, но я рекомендую использовать NFKD вместо NFD, поскольку NFKD удалит нежелательные типографские различия (например, пробел NBSP или & # x2102; & rarr; C).

Вы также можете сделать общие замены на Юникод категории . Например, Pd можно заменить на -, Nd можно заменить на соответствующую цифру 0 - 9, а Mn можно заменить на пустую строку (для удаления акцентов).

но кто-то мог написать Подходящую таблицу поиска я могу использовать повторно.

Вы можете попробовать использовать данные из программы Unidecode или CLDR .

Редактировать : Здесь огромная таблица замещения .

0 голосов
/ 28 мая 2011

Вы никогда не должны пытаться конвертировать Unicode в ASCII, потому что у вас в конечном итоге будет больше проблем, чем решения.

Это все равно что пытаться вписать 1114112 кодовых точек (Unicode 6.0) в 128 символов.

Как вы думаете, у вас все получится?

Кстати, в Юникоде есть много цитат, не только упомянутых вами, но и если вы все равно захотите выполнить конвертацию, помните, что конверсии будут зависеть от локали.

Проверьте ICU - содержит самые полные процедуры преобразования Unicode.

...