Подтвердить что ты не робот

Может ли .NET конвертировать Unicode в ASCII для удаления "умных кавычек" и т.д.?

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

Я хочу "нормализовать" контент, который они получают. Самая большая проблема, с которой мы сталкиваемся, - это копирование пользователями контента из 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 до 1/2 и т.д., Что, я уверен, не поддерживается какой-либо маской Unicode, но кто-то мог написать подходящую таблицу поиска, которую я могу повторное использование.

Любые идеи?

4b9b3361

Ответ 1

Спасибо всем за очень полезные ответы. Я понимаю, что фактический вопрос заключается не в том, "как я могу преобразовать любой символ Юникода в его резервную копию ASCII" - вопрос заключается в том, "как я могу преобразовать символы Unicode , которые мои клиенты жалуются на в их резервные копии ASCII" )?

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

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

Ответ 2

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

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

Ответ 3

Есть ли встроенный метод, который начать меня?

The first thing I'd try is to convert the text to NFKD normalization form, with the Normalize on strings method. This suggestion is mentioned in the answer to the question you linked, but я recommend using NFKD instead of NFD because NFKD will remove unwanted typographical distinctions (e.g., NBSP → space, or ℂ → C).

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

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

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

Изменить: здесь огромный график замещения здесь.

Ответ 4

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

Это похоже на попытку установить 1111112 кодовых точек (Unicode 6.0) всего на 128 символов.

Как вы думаете, вы добьетесь успеха?

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

Отметьте ICU - содержащий наиболее полные процедуры преобразования Юникода.