web-dev-qa-db-fra.com

Conversion de symboles et de lettres d’accent en alphabet anglais

Le problème est que, comme vous le savez, il y a des milliers de caractères dans le graphique Unicode et je veux convertir tous les caractères similaires en lettres qui sont en alphabet anglais.

Par exemple, voici quelques conversions:

ҥ->H
Ѷ->V
Ȳ->Y
Ǭ->O
Ƈ->C
tђє Ŧค๓เℓy --> the Family
...

et j'ai vu qu'il y avait plus de 20 versions de la lettre A/a. et je ne sais pas comment les classer. Ils ressemblent à des aiguilles dans la botte de foin.

La liste complète des caractères unicode se trouve à http://www.ssec.wisc.edu/~tomw/Java/unicode.html ou http://unicode.org/charts/ charindex.html . Essayez simplement de faire défiler la liste et de voir les variations des lettres.

Comment puis-je convertir tout cela avec Java? Aidez-moi, s'il vous plaît :(

124
AhmetB - Google

Republier ma publication de Comment puis-je supprimer les signes diacritiques (accents) d'une chaîne dans .NET?

Cette méthode fonctionne bien avec Java ) (uniquement dans le but de supprimer les marques diacritiques, à savoir les accents) .

Il convertit fondamentalement tous les caractères accentués en leurs équivalents décents, suivis de la combinaison de leurs signes diacritiques. Maintenant, vous pouvez utiliser une regex pour éliminer les signes diacritiques.

import Java.text.Normalizer;
import Java.util.regex.Pattern;

public String deAccent(String str) {
    String nfdNormalizedString = Normalizer.normalize(str, Normalizer.Form.NFD); 
    Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
    return pattern.matcher(nfdNormalizedString).replaceAll("");
}
192
hashable

C'est une partie de Apache Commons Lang à partir de ver. 3.0.

org.Apache.commons.lang3.StringUtils.stripAccents("Añ");

retourne An

Voir aussi http://www.drillio.com/fr/software-development/Java/removing-accents-diacritics-in-any-language/

71
Ondra Žižka

Tenter de "les convertir tous" n’est pas la bonne approche du problème.

Tout d'abord, vous devez comprendre les limites de ce que vous essayez de faire. Comme d'autres l'ont souligné, les signes diacritiques ont une raison: ils sont essentiellement des lettres uniques dans l'alphabet de cette langue, avec leur propre signification/son, etc.: supprimer ces marques revient à remplacer des lettres aléatoires dans un mot anglais. C’est avant même d’envisager les langues cyrilliques et d’autres textes basés sur des scripts tels que l’arabe, qui ne peuvent tout simplement pas être "convertis" en anglais.

Si vous devez, pour une raison quelconque, convertissez des caractères, le seul moyen sensé de l'aborder consiste à réduire dans un premier temps la portée de la tâche à accomplir. Considérez la source de l'entrée - si vous codez une application pour "le monde occidental" (pour utiliser une phrase aussi bonne que toute autre), il serait peu probable que vous ayez besoin d'analyser les caractères arabes. De même, le jeu de caractères Unicode contient des centaines de symboles mathématiques et graphiques: les utilisateurs ne peuvent pas (facilement) entrer directement ces éléments. Vous pouvez donc en déduire qu'ils peuvent être ignorés.

En prenant ces mesures logiques, vous pouvez réduire le nombre de caractères à analyser au point où une opération de recherche/remplacement basée sur un dictionnaire est réalisable. Cela devient alors une petite quantité de travail légèrement ennuyeux créant les dictionnaires, et une tâche triviale pour effectuer le remplacement. Si votre langue prend en charge les caractères Unicode natifs (comme le fait Java)) et optimise correctement les structures statiques, la recherche et le remplacement ont tendance à être extrêmement rapides.

Cela vient de l’expérience d’avoir travaillé sur une application qui devait permettre aux utilisateurs finaux de rechercher des données bibliographiques contenant des caractères diacritiques. Les tableaux de recherche (comme dans notre cas) prenaient peut-être un jour par homme pour couvrir tous les signes diacritiques de toutes les langues d'Europe occidentale.

19
Ian

Étant donné que l'encodage qui transforme "la famille" en "t ℓ" est effectivement aléatoire et ne suit aucun algorithme pouvant être expliqué par les informations des points de code Unicode impliqués, il n'existe aucun moyen général de résoudre cet algorithme.

Vous devrez construire le mappage des caractères Unicode en caractères latins auxquels ils ressemblent. Vous pouvez probablement le faire avec une machine intelligente à apprendre sur les glyphes représentant les points de code Unicode. Mais je pense que l'effort pour cela serait plus grand que de construire manuellement cette cartographie. Surtout si vous avez une bonne quantité d'exemples à partir desquels vous pouvez construire votre cartographie.

Pour clarifier: quelques-unes des substitutions peuvent en réalité être résolues via les données Unicode (comme le montrent les autres réponses), mais certaines lettres n’ont tout simplement aucune association raisonnable avec les caractères latins auxquels elles ressemblent.

Exemples:

  • "ђ" (U + 0452 LETTRE MINUSCULE CYRILLIQUE DJE) est plus lié à "d" qu'à "h", mais est utilisé pour représenter "h".
  • "Ŧ" (U + 0166 LETTRE MAJUSCULE LATINE T AVEC STROKE) est un peu lié à "T" (comme son nom l'indique) mais est utilisé pour représenter "F".
  • "ค" (U + 0E04 CARACTÈRE THAI KHO KHWAI) n'est associé à aucun caractère latin et, dans votre exemple, est utilisé pour représenter "un"
16
Joachim Sauer

La demande initiale a déjà été traitée.

Cependant, je publie la réponse ci-dessous pour ceux qui pourraient être à la recherche d'un code générique de translittération pour translittérer n'importe quel jeu de caractères en latin/anglais en Java.

Signification naïve de la traduction: La chaîne traduite dans sa forme finale/le jeu de caractères cible sonne comme la chaîne dans sa forme originale. Si nous voulons translittérer n’importe quel jeu de caractères en latin (alphabets anglais), alors ICU4 (bibliothèque ICU4J dans Java) fera le travail.

Voici l'extrait de code en Java:

    import com.ibm.icu.text.Transliterator; //ICU4J library import

    public static String TRANSLITERATE_ID = "NFD; Any-Latin; NFC";
    public static String NORMALIZE_ID = "NFD; [:Nonspacing Mark:] Remove; NFC";

    /**
    * Returns the transliterated string to convert any charset to latin.
    */
    public static String transliterate(String input) {
        Transliterator transliterator = Transliterator.getInstance(TRANSLITERATE_ID + "; " + NORMALIZE_ID);
        String result = transliterator.transliterate(input);
        return result;
    }
7
Dayanand Gowda

Corde testée: ÁÂÄÄÇÇÉÉËËÏÎÑÐÑÒÓÔÕÖØÙÚÛÜÝß

Testé:

  • Sortie de Apache Commons Lang : AAAAAÆCEEEEIIIIÐNOOOOOØUUUUUYß
  • Sortie de ICU4j : AAAAAÆCEEEEIIIIÐNOOOOOØUUUUUYß
  • Sortie de JUnidecode : AAAAAAECEEEEIIIIDNOOOOOOUUUUUUUss (problème avec et un autre numéro )
  • Sortie de nidecode : AAAAAAECEEEEIIIIDNOOOOOOUOUUUUYss

Le dernier choix est le meilleur.

7
cactuschibre

S'il est nécessaire de convertir "òéışöç-> oeisoc", vous pouvez l'utiliser comme point de départ:

public class AsciiUtils {
    private static final String PLAIN_ASCII =
      "AaEeIiOoUu"    // Grave
    + "AaEeIiOoUuYy"  // acute
    + "AaEeIiOoUuYy"  // circumflex
    + "AaOoNn"        // tilde
    + "AaEeIiOoUuYy"  // umlaut
    + "Aa"            // ring
    + "Cc"            // cedilla
    + "OoUu"          // double acute
    ;

    private static final String UNICODE =
     "\u00C0\u00E0\u00C8\u00E8\u00CC\u00EC\u00D2\u00F2\u00D9\u00F9"             
    + "\u00C1\u00E1\u00C9\u00E9\u00CD\u00ED\u00D3\u00F3\u00DA\u00FA\u00DD\u00FD" 
    + "\u00C2\u00E2\u00CA\u00EA\u00CE\u00EE\u00D4\u00F4\u00DB\u00FB\u0176\u0177" 
    + "\u00C3\u00E3\u00D5\u00F5\u00D1\u00F1"
    + "\u00C4\u00E4\u00CB\u00EB\u00CF\u00EF\u00D6\u00F6\u00DC\u00FC\u0178\u00FF" 
    + "\u00C5\u00E5"                                                             
    + "\u00C7\u00E7" 
    + "\u0150\u0151\u0170\u0171" 
    ;

    // private constructor, can't be instanciated!
    private AsciiUtils() { }

    // remove accentued from a string and replace with ascii equivalent
    public static String convertNonAscii(String s) {
       if (s == null) return null;
       StringBuilder sb = new StringBuilder();
       int n = s.length();
       for (int i = 0; i < n; i++) {
          char c = s.charAt(i);
          int pos = UNICODE.indexOf(c);
          if (pos > -1){
              sb.append(PLAIN_ASCII.charAt(pos));
          }
          else {
              sb.append(c);
          }
       }
       return sb.toString();
    }

    public static void main(String args[]) {
       String s = 
         "The result : È,É,Ê,Ë,Û,Ù,Ï,Î,À,Â,Ô,è,é,ê,ë,û,ù,ï,î,à,â,ô,ç";
       System.out.println(AsciiUtils.convertNonAscii(s));
       // output : 
       // The result : E,E,E,E,U,U,I,I,A,A,O,e,e,e,e,u,u,i,i,a,a,o,c
    }
}

Le JDK 1.6 fournit la classe Java.text.Normalizer qui peut être utilisée pour cette tâche.

Voir un exemple ici

6
RealHowTo

Le problème de la "conversion" en Unicode arbitraire en ASCII) est que la signification d'un caractère dépend de la culture. Par exemple, "ß" en une personne de langue allemande devrait être converti en "ss". alors qu'un anglophone le convertirait probablement en "B".

Ajoutez à cela le fait qu'Unicode possède plusieurs points de code pour les mêmes glyphes.

Le résultat est que le seul moyen de le faire est de créer une table volumineuse avec chaque caractère Unicode et le caractère ASCII que vous souhaitez convertir. Vous pouvez utiliser un raccourci en normalisant les caractères accentués. forme de normalisation KD, mais tous les caractères ne sont pas normalisés au format ASCII. De plus, Unicode ne définit pas les parties d'un glyphe qui sont des "accents".

Voici un petit extrait d'une application qui fait ceci:

switch (c)
{
    case 'A':
    case '\u00C0':  //  À LATIN CAPITAL LETTER A WITH Grave
    case '\u00C1':  //  Á LATIN CAPITAL LETTER A WITH ACUTE
    case '\u00C2':  //  Â LATIN CAPITAL LETTER A WITH CIRCUMFLEX
    // and so on for about 20 lines...
        return "A";
        break;

    case '\u00C6'://  Æ LATIN CAPITAL LIGATURE AE
        return "AE";
        break;

    // And so on for pages...
}
4
Dour High Arch

Il n’existe aucun moyen simple ou général de faire ce que vous voulez, c’est votre opinion subjective que ces lettres ressemblent aux lettres latines que vous voulez convertir. Ce sont en fait des lettres séparées avec leurs propres noms et sons distincts qui ressemblent superficiellement à une lettre latine.

Si vous souhaitez cette conversion, vous devez créer votre propre table de traduction en fonction des lettres latines auxquelles vous pensez que les lettres non latines doivent être converties.

(Si vous souhaitez uniquement supprimer les marques diacritiales, il existe des réponses à cette discussion: Comment puis-je supprimer les signes diacritiques (accents) d'une chaîne dans .NET? Cependant, vous décrivez un problème plus général)

4
JacquesB

Vous pouvez essayer d'utiliser unidecode, qui est disponible sous la forme Ruby gem et module Perl sur cpan . Pour l’essentiel, cela fonctionne comme une énorme table de recherche, où chaque point de code unicode se rapporte à un caractère ou à une chaîne ascii.

4
Daniel Vandersluis

Je suis en retard au parti, mais après avoir affronté ce problème aujourd'hui, j'ai trouvé cette réponse très bonne:

String asciiName = Normalizer.normalize(unicodeName, Normalizer.Form.NFD)
    .replaceAll("[^\\p{ASCII}]", "");

Référence: https://stackoverflow.com/a/1628386

4
Francisco Junior

Suivre le cours fait le tour:

org.Apache.lucene.analysis.miscellaneous.ASCIIFoldingFilter
2
TomWolk