Convertisseur de casse

Convertissez du texte entre camelCase, snake_case, kebab-case, Title Case et plus, avec une casse selon la langue et des outils de lignes.

Texte

Formes d'écriture

  • UPPERCASE
    XMLHTTPREQUEST HANDLER FOR ISTANBUL CITY GUIDE
  • lowercase
    xmlhttprequest handler for istanbul city guide
  • Title Case
    Xmlhttprequest Handler For Istanbul City Guide
  • Sentence case
    Xmlhttprequest handler for istanbul city guide
  • camelCase
    xmlHttpRequestHandlerForIstanbulCityGuide
  • PascalCase
    XmlHttpRequestHandlerForIstanbulCityGuide
  • snake_case
    xml_http_request_handler_for_istanbul_city_guide
  • kebab-case
    xml-http-request-handler-for-istanbul-city-guide
  • CONSTANT_CASE
    XML_HTTP_REQUEST_HANDLER_FOR_ISTANBUL_CITY_GUIDE
  • dot.case
    xml.http.request.handler.for.istanbul.city.guide

Opérations sur les lignes

Résultat
XMLHttpRequest handler for istanbul city guide

Lignes : 1

Un seul découpage en mots, dix formes d'écriture

Changer la casse d'un texte semble la chose la plus simple qu'un programme puisse faire, et c'est la source d'un nombre étonnant de bugs bien réels. Une partie de l'explication tient à ce que « la casse » recouvre en fait deux problèmes distincts sous un même nom. Passer un texte en UPPERCASE ou en lowercase est une correspondance caractère par caractère définie par Unicode. Le passer en camelCase ou en snake_case est tout autre chose : il faut d'abord décider où sont les mots, et seulement ensuite recomposer et rassembler. Cet outil fait les deux, affiche tous les résultats d'un coup et, surtout, indique lesquelles de ces réponses dépendent d'un réglage de langue.

Les six formes de programmation découlent toutes du même découpage, elles ne peuvent donc jamais se contredire. Voici ses frontières :

  • Une minuscule suivie d'une majuscule commence un nouveau mot, ce qui transforme fooBar en foo et Bar.
  • Une suite de majuscules s'arrête là où commence le mot suivant, c'est-à-dire à la dernière majuscule avant une minuscule. XMLHttpRequest donne XML, Http et Request ; IOError donne IO et Error.
  • Un chiffre suivi d'une majuscule commence un nouveau mot, donc html5Parser donne html5 et Parser.
  • Tout ce qui n'est ni lettre, ni chiffre, ni signe combinant sépare les mots : espaces, tirets bas, traits d'union, points et signes de ponctuation.

Pour le reste, les chiffres restent attachés au mot qui les précède, et c'est pourquoi utf8 et address2 passent entiers. C'est un écart délibéré avec lodash, dont le découpeur traite chaque suite de chiffres comme un mot à part et transforme utf8 en utf_8 : techniquement cohérent, mais pas ce que voulait dire celui qui a nommé la variable.

Le découpage est écrit avec les propriétés Unicode et non avec une classe de caractères ASCII, il ne se limite donc pas à l'anglais. Un identifiant en cyrillique se découpe à ses frontières de casse exactement comme un identifiant latin. Une écriture sans casse — hébreu, arabe, chinois, japonais, coréen — n'a aucune frontière de ce type à trouver, ses mots se découpent donc uniquement sur les séparateurs, et c'est la bonne réponse et non une limite.

Les sigles : deux bonnes réponses

Une fois XMLHttpRequest découpé en XML, Http et Request, le recomposer en PascalCase pose une question sans réponse unique. Si l'on recompose chaque mot, on obtient XmlHttpRequest, ce que produit lodash et ce qu'exige le guide de style Java de Google : traiter un sigle comme un mot ordinaire pour que les frontières restent visibles dans des noms comme ParseXmlDocument. Si l'on conserve la suite de majuscules, on obtient XMLHttpRequest, le vrai nom de l'API du navigateur et la convention que suivent l'essentiel du DOM et une bonne part de ‎.NET.

Les deux existent dans de vraies bases de code, l'outil propose donc les deux et recompose par défaut. L'option ne touche que camelCase et PascalCase : les autres formes recomposent de toute façon le mot entier, donc XMLHttpRequest donne xml_http_request et XML_HTTP_REQUEST dans les deux cas.

Un détail est fixé et ne se choisit pas : le premier mot d'un nom en camelCase passe toujours entièrement en minuscules, même s'il s'agit d'un sigle. Le conserver donnerait du PascalCase, et le conserver à moitié donnerait xMLHttpRequest, une forme qu'aucun guide de style ne recommande et sur laquelle tout lecteur bute. Ainsi XMLHttpRequest donne xmlHttpRequest dans les deux cas, tandis que parseXMLDocument garde son sigle médian quand on le demande.

Le i turc, et pourquoi la langue est un choix

JavaScript possède deux méthodes de passage en majuscules, et la différence entre elles a fait tomber des systèmes en production. La méthode toUpperCase applique la correspondance Unicode indépendante de la langue : la lettre i devient I. La méthode toLocaleUpperCase applique les règles d'une langue donnée, et en turc comme en azéri la majuscule de i est İ, la capitale pointée, parce que ces alphabets comportent aussi un ı sans point dont la majuscule est I. Passez en majuscules la saisie d'un utilisateur turc avec sa propre langue, comparez-la à un mot-clé de protocole, et la comparaison échoue sur un caractère presque identique.

C'est le bug d'internationalisation le plus courant du traitement des chaînes, et il reste invisible jusqu'à ce qu'il vous arrive. Cet outil ne devine donc jamais. Sa valeur par défaut est la correspondance indépendante de la langue, celle dont ont besoin les identifiants, les jetons de protocole, les en-têtes HTTP et les clés de base de données. Choisir une langue bascule vers ses règles — et chaque fois que ce choix modifie un résultat, l'outil affiche à côté la réponse indépendante de la langue, pour que l'on voie exactement ce que la langue a fait.

'i'.toUpperCase()             // 'I'
'i'.toLocaleUpperCase('tr')   // 'İ'  dotted capital
'I'.toLocaleLowerCase('tr')   // 'ı'  dotless lowercase
'ISTANBUL'.toLocaleLowerCase('tr')  // 'ıstanbul'

Trois autres langues changent la réponse, et l'outil les propose toutes. Le lituanien conserve le point sur le i lorsqu'il met en minuscule une capitale portant un autre accent : Ì donne un i suivi d'un point combinant et d'un accent grave combinant, et non le seul ì précomposé. Le grec supprime le tonos au passage en majuscules, si bien que άνθρωπος donne ΑΝΘΡΩΠΟΣ et non ΆΝΘΡΩΠΟΣ, car le grec n'écrit pas l'accent sur les capitales. L'azéri partage avec le turc le i pointé et le i sans point.

Deux cas célèbres ne sont pas des règles de langue, et il vaut la peine de savoir lequel est lequel. Le ß allemand devient SS dans toutes les langues, parce qu'il s'agit d'une règle SpecialCasing d'Unicode et non d'une règle allemande — c'est aussi pourquoi la correspondance n'est pas réversible, SS redonnant ss. Et un sigma grec en fin de mot passe à la forme finale ς et non à σ, partout : c'est une condition contextuelle sur la position du caractère, pas un réglage de langue. Les deux se voient dans cet outil sans choisir aucune langue.

Title case et Sentence case sont ici mécaniques

Le Title Case de cet outil met en capitale la première lettre de chaque mot et en minuscule le reste. Le Sentence case met en capitale la première lettre du texte et celle de chaque phrase suivante, une phrase se terminant par un point, un point d'exclamation, un point d'interrogation ou des points de suspension suivis d'une espace. Les deux passent d'abord la saisie en minuscules, ce qui les rend utiles sur un texte arrivé EN CRIANT.

Ce sont des règles délibérément mécaniques, et l'alternative mérite d'être expliquée. Les guides de style anglais définissent la casse de titre par la liste des mots courts qui restent en minuscules — et ils se contredisent sur cette liste, sur la capitalisation du mot après un deux-points et sur les prépositions de quatre lettres ou plus. En appliquer un ici reviendrait à livrer des conventions de presse américaines à des lecteurs qui écrivent en hébreu, en japonais ou en turc, où la notion ne se transpose pas du tout. Capitaliser chaque mot est prévisible, explicable dans toutes les langues et facile à retoucher à la main.

La condition d'espace du Sentence case est ce qui empêche 3.5 metres de devenir 3.5 Metres, puisque le point y est suivi d'un chiffre. Elle ne règle pas les abréviations : e.g. this commence toujours une fausse phrase, car savoir que « e.g. » n'est pas une fin de phrase suppose une liste des abréviations de la langue. Une apostrophe à l'intérieur d'un mot n'en commence pas un nouveau non plus, donc it's est capitalisé une seule fois et donne It's et non It'S.

Trier : ordre alphabétique ou ordre des octets

Les outils de lignes rognent, suppriment les doublons, trient, inversent et numérotent, et le tri soulève la question de la langue une seconde fois. L'ordre alphabétique est une propriété d'une langue, pas d'Unicode. L'allemand classe ä près de a : a, ä, z. Le suédois en fait une lettre distincte en fin d'alphabet : a, z, ä. Les deux sont corrects chez eux, et l'outil utilise la langue choisie en haut de la page.

L'autre option est l'ordre par point de code, celui que l'on veut quand la réponse doit correspondre à autre chose. Comparer par point de code, c'est l'ordre des octets en UTF-8 : cela reproduit exactement ce que produisent LC_ALL=C sort, git et la comparaison de chaînes par défaut de la plupart des langages — toutes les majuscules avant toutes les minuscules, donc B avant a. Choisissez-le pour comparer avec la sortie d'un outil ; choisissez le tri par langue quand une personne va lire la liste.

L'ordre numérique naturel — item2 avant item10 et non après — est une fonction du tri par langue, il n'est donc disponible qu'avec la règle alphabétique. L'ordre des octets n'a aucune notion de nombre à l'intérieur d'une chaîne, pas plus que le tri qu'il imite ; proposer les deux ensemble promettrait ce que la sortie ne pourrait pas tenir.

Les opérations s'exécutent dans un ordre fixe, et cet ordre compte. Le rognage précède la suppression des doublons, de sorte que deux lignes ne différant que par une espace finale sont reconnues comme identiques. Le tri précède l'inversion, de sorte qu'inverser signifie toujours « inverse ce que je vois ». Le nombre de lignes vides et celui de doublons supprimés sont tous deux indiqués, car un décompte silencieux est précisément ce qui empêche de remarquer que la liste n'était pas celle que l'on croyait.

Où cela s'exécute

Tout se passe dans votre navigateur. Les correspondances de casse proviennent de l'implémentation Unicode du moteur JavaScript lui-même et le tri d'Intl.Collator, si bien que les réponses s'accordent avec l'environnement d'exécution qui traitera réellement vos chaînes, et non avec une table recopiée il y a des années. Rien de ce que vous collez n'est téléversé, stocké ni journalisé, ce qui rend l'outil sûr pour des noms, des lignes de journal et tout ce que vous préféreriez ne pas envoyer à un serveur juste pour en changer la casse.

Questions fréquentes

Mon texte est-il envoyé à un serveur ?
Non. Chaque conversion s'exécute dans votre navigateur à partir des correspondances de casse Unicode du moteur JavaScript lui-même, et rien de ce que vous collez n'est téléversé ni journalisé.
Pourquoi le choix du turc m'affiche-t-il deux résultats différents ?
Parce que le turc change la réponse. Son alphabet comporte un i pointé et un ı sans point, la majuscule de i est donc İ et non I. Chaque fois qu'une langue modifie un résultat, l'outil affiche à côté la réponse indépendante de la langue, celle dont ont besoin les identifiants et les jetons de protocole.
Dois-je utiliser la correspondance indépendante de la langue ou celle d'une langue ?
Utilisez la correspondance indépendante de la langue pour tout ce qu'une machine lira : identifiants, en-têtes HTTP, clés de base de données, jetons de protocole, noms de fichiers. Utilisez celle d'une langue pour un texte qu'une personne lira dans cette langue. Les confondre, c'est le bug classique du i turc.
Pourquoi XMLHttpRequest devient-il XmlHttpRequest ?
Parce que les sigles sont recomposés par défaut, comme le font lodash et plusieurs guides de style majeurs. Activez l'option des sigles pour conserver la suite de majuscules et retrouver XMLHttpRequest. Elle n'affecte que camelCase et PascalCase, les autres formes recomposant de toute façon chaque mot.
Pourquoi utf8 reste-t-il un seul mot alors que lodash le découpe ?
Parce qu'ici les chiffres s'attachent au mot qui les précède, donc utf8 et address2 passent entiers. Un chiffre suivi d'une majuscule commence bien un nouveau mot, et c'est ce qui découpe html5Parser en html5 et Parser.
Pourquoi Title Case met-il des capitales à des mots courts comme « of » et « the » ?
Parce que la règle est volontairement mécanique. Les guides de style anglais se contredisent sur les mots courts qui restent en minuscules, et leurs conventions ne se transposent pas aux autres langues de ce site. Capitaliser chaque mot est prévisible et facile à retoucher à la main.
Pourquoi ne puis-je pas utiliser l'ordre numérique naturel avec le tri par point de code ?
L'ordre naturel est une fonction du tri par langue. L'ordre par point de code est un ordre d'octets, sans notion de nombre à l'intérieur d'une chaîne — pas plus que le LC_ALL=C sort qu'il reproduit. Proposer les deux donnerait une sortie qui ne correspondrait plus à l'outil imité.
Pourquoi ß devient-il SS même sans langue sélectionnée ?
Parce que cette correspondance est une règle SpecialCasing d'Unicode et non une règle de l'allemand, elle s'applique donc partout. Elle n'est pas non plus réversible : SS donne ss et non ß. Le sigma final grec fonctionne de la même façon — il dépend de la position de la lettre, pas d'une langue.