Validación de JavaScript, el problema con los caracteres internacionales

Utilizamos la excelente validador plugin para jQuery aquí en Stack Overflow para hacer validaciones del lado del cliente de la entrada antes de que se la envía al servidor.

Que en general funciona bien, sin embargo, éste nos ha rascado la cabeza.

La siguiente validador método se utiliza en la pregunta/respuesta del formulario para el campo de nombre de usuario (tenga en cuenta que debe ser la sesión ver este campo en el sitio en vivo; está en cada /question página y la /ask página)

$.validator.addMethod("validUserName",
  function(value, element) {
  return this.optional(element) || 
  /^[\w\-\s\dÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜäëïöüçÇßØøÅåÆæÞþÐð]+$/.test(value); },
  "Can only contain A-Z, 0-9, spaces, and hyphens.");  

Ahora esta expresión parece raro, pero es bastante simple:

  • coincide con el inicio de la cadena (^)
  • coincidir con alguno de estos..
    • carácter de palabra (\w)
    • guión (-)
    • espacio (\s)
    • dígitos (\d)
    • loco de la luna caracteres de idioma (àèìòù etc)
  • ahora coincide con el final de la cadena ($)

Sí, nos encontramos con el Internacionalizado Expresiones Regulares problema. JavaScript es la definición de la palabra «de carácter» no incluye caracteres internacionales.. en todo.

Aquí está lo más raro: a pesar de que hemos ido a los problemas de adición manual de toneladas de la validez de los caracteres internacionales para la expresión regular, se no funciona. Usted no puede ingresar estos caracteres internacionales en el cuadro de entrada para el nombre de usuario sin tener el..

Sólo puede contener A-Z, 0-9, espacios y guiones

.. validación de regreso!

Obviamente la validación es de trabajo para las otras partes de la regex.. así que.. ¿por qué?

El otro raro es que esta validación funciona en el navegador de la consola de JavaScript, pero no cuando se ejecuta como parte de nuestro estándar *.js incluye.

/^[\w\sÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûãñõãñõäëïöüäëïöüççßøøååææþþðð]+$/
.de prueba(‘ÓBill de hÓra’) === true

Nos hemos quedado en algo realmente extraño carácter internacional problemas en el código JavaScript antes, lo que en algunos muy, muy desagradable hacks. Nos gustaría entender lo que está pasando aquí y por qué. Por favor, que nos ilumine!

  • Este podría ser un problema de codificación de caracteres? I. e., un loco de la luna «Ä» desde el usuario no es un «Ä» en su expresión regular?
  • No sé la respuesta, pero esa es una buena manera de escribir una pregunta.
  • Jeff siempre defiende pedir bien las preguntas por escrito, así que mejor estar haciendo eso mismo, también 🙂 Pero estás en lo cierto.
  • é no es un personaje de la luna idioma, pokémon está en el alfabeto inglés ¿no? Compruebe también que mi comentario Jorn respuesta
InformationsquelleAutor Jeff Atwood | 2009-07-02

7 Kommentare

  1. 36

    Creo que el correo electrónico y url de validación de métodos son una buena referencia aquí, por ejemplo. el método de correo electrónico:

    email: function(value, element) {
        return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
    },

    La secuencia de comandos para compilar que regex.

    En otras palabras, la sustitución de su arbitraria lista de «los locos de la luna» personajes con esto podría ayudar a:

    [\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]

    Básicamente esto evita la codificación de caracteres problemas que tiene en otros lugares mediante la sustitución de las necesidades de codificación de caracteres con más definiciones generales. Aunque no necesariamente más legible, de modo que ahora es más corta que su lista completa.

    • Solo para aclarar sobre el por qué de esto funcionó. Si su .archivo js está enconded en una codificación de caracteres todos los caracteres dentro de regex expresiones dentro de ella estarán representados en esa codificación, incluso si su sitio web utiliza otra codificación. En mis proyectos, yo simplemente codificar TODO lo que puede contener internacional de cadenas de caracteres en UTF-8. Este incluye .js archivos. Lo que probablemente sucedió a Jeff era que su .js archivos se han codificado en un conjunto de caracteres y su página se ha analizado con otro juego de caracteres, sus peticiones HTTP/respuesta probablemente codificados con el mismo juego de caracteres como el de la página. Esto explica por qué se trabajó en el depurador.
    • Otra cosa, intente alert(«áéíóú») si se muestra a la derecha de su archivo javascript está codificado en la misma codificación que la página. Sin embargo, otra solución es simplemente incluir su código javascript con: <script src=»myscripts.js» charset=»ISOsomething» /> donde ISOsomething es la codificación .archivo js. Este es un error común, porque la mayoría de los IDEs crear .js archivos en su defecto codificación, que es casi nunca UTF-8 por defecto.
    • De los dos enlaces en la respuesta están rotos.
    • esto me ayudó, admite i18n caracteres y SIN comillas: ^[[email protected]#$%^~&*/?:'\,\\|{}()-_+\s\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*$`
  2. 14

    Esta no es realmente una respuesta, pero no tengo 50 rep sin embargo, para agregar un comentario… puede sin duda ser atribuidos a problemas de codificación.

    Sí «ECMA no debería de atención acerca de la codificación…» bla, bla, así que si estás en firefox, vaya a Ver > Codificación de Caracteres > Occidental (ISO-8859-1), a continuación, pruebe a utilizar el Nombre de campo.

    Funciona muy bien para mí después de cambiar la codificación manualmente (concedido por el resto de la página no le gusta la codificación interruptor, :P)

    (en IE8 puede ir a Página > Codificación > Europeo Occidental (Windows) para obtener el mismo efecto)

    • él está en lo correcto, esto por arte de magia hace que el Nombre de: trabajo de validación (!)
  3. 3

    ¿Qué es la codificación de caracteres del archivo JS?

    Para XML QNames yo uso este RegExp:

    /**
     * Definition of an XML Name
     */
    var NameStartChar = "A-Za-z:_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D"+
                        "\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF"+
                        "\uF900-\uFDCF\uFDF0-\uFFFD\u010000-\u0EFFFF";
    var NameChar = NameStartChar+"\\-\\.0-9\u00B7\u0300-\u036F\u203F-\u2040";
    var Name = "^["+NameStartChar+"]["+NameChar+"]*$";
    RegExp (Name).test (value);

    Funciona como un encanto también con internacionalizado caracteres. Nota los caracteres de escape. Debido a que soy capaz de restringir el archivo JS para ASCII sólo caracteres. Por lo tanto no me meto en problemas al tratar con ISO-8859 vs UTF-8 tipos de caracteres.

    Esto no es más cierto, si el uso de las codificaciones de caracteres ASCII no es real subconjunto (como, por ejemplo, en Asia UTF-16).

    Saludos,

    • Por lo que he entendido, el validador de reglas en un archivo JS externo. Entonces yo apuesto a que el archivo que se está en la codificación incorrecta (es decir, no UTF-8).
    • Estoy abriendo el archivo en el disco en el Notepad2 y nos parece correcto — idéntico a lo que ves arriba en la norma ANSI y cuando me cambie a Unicode, UTF-8 codificación, también idéntico.
    • Eso no puede ser. Una ANSI ‘Ä’ (==ISO-8859-1) tiene un único byte representación ‘C4’, mientras que el UTF-8 ‘Ä’ se ve en un editor hexadecimal como ‘C3 84’. ¿A qué te refieres con ‘switch’? ¿Es real la conversión entre codificaciones?
    • bueno, yo voy a abrir la .archivo js desde el propio servidor en Notepad2 y cambiar el archivo de codificaciones a través del menú desplegable. No veo diferencias en ninguna de ellas para la expresión de cadena. Es completamente posible que yo estoy haciendo algo mal..
    • extrañamente, esto coincide con verdadero en una cadena que contiene un «<«. Aparentemente debido a que el último bit de la NameStartChar «\u010000-\u0EFFFF», aunque < es \u003C y no en ese rango. Del mismo modo @, ?, =, y otros caracteres entre el ‘9’ y ‘Un’. pensamientos sobre ¿por qué?
    • Hm, puede ser que tu JS cortes de motor después de los primeros 4 dígitos. Pero entonces, \u0100 todavía no contenga los <. Extraño, de hecho.
    • He creado una biblioteca de javascript para hacer algunas de estas cosas, no está seguro de cómo corregir o óptimo es, pero echar un vistazo: code.google.com/p/charfunk

  4. 2

    internacional de los personajes mencionados son parte de ASCII extendido. los que añadió por que son sin duda no.

  5. 2

    Ver como la declaración de las obras en la consola, puede esto tener que ver la forma en que su .js archivos se guardan (es decir, ascii o UTF-8), y que el navegador se carga de esa manera y en el proceso convierte los caracteres?

    • JS no sabe nada acerca de la codificación UTF-8, incluso si la codificación se establece así.
    • Pero el navegador que hace, ¿no? Lo que si se carga el archivo como UTF-8 y el JS motor del navegador interpreta los personajes, erróneamente, debido a que el navegador carga el archivo de forma incorrecta ?
    • Sí, el navegador le importa. Si guarda un «Ä» como no-Unicode, que se traducirá en un inválido UTF-8 flujo de bytes. Por lo tanto, nunca puede coincidir con un UTF-8 flujo de bytes correspondientes a la «Ä».
    • s navegador/preocupa/navegador y por lo tanto el motor de JS cares/
  6. 2

    Usar algo como Fiddler o Charles (no Firebug Neto del panel, o de cualquier otra cosa que, de hecho, dentro del navegador) para examinar lo que realmente viene a través del cable. Es casi ciertamente un problema de codificación: el archivo ha sido guardado en algunas de Microsoft conjunto de caracteres y está siendo enviado como UTF-8, o tal vez al revés.

    En el caso de JS Regex puede, como Boldewyn señala, evitar estos problemas, especificando el punto de código Unicode para los caracteres que desea que se encuentran fuera del intervalo de US-ASCII. Todavía sería así para asegurarse de que usted no mezclar las codificaciones entre el lugar donde se guarda el archivo y el lugar donde se sirve, sin embargo.

    • gzip sobre el alambre, tan difícil de hacer
    • Tanto el Violinista y Charles puede lidiar con eso. IIRC Fiddler (al menos en la versión 2) le ofrecemos un botón de Respuesta en el área de visualización que permiten ver la ungzipped contenido.
  7. 2

    Tarde para el juego aquí, pero acabo de utilizar esta expresión y pareció funcionar bien para mí. Parece ser bastante completa y relativamente simple:

    JS:

    var re = /^[A-zÀ-ÿ\s\d-]*$/g; 
    var str1 = 'casa-me,pois 99 estou farto! Eis a lista:uma;duas;três';
    var str2 = 'casa-me pois 99 estou farto Eis a lista uma duas três';
    
    alert(re.test(str1));
    alert(re.test(str2));

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea