2010-09-23 11 views
38

Las implementaciones de los principales navegadores parecen tener problemas con text-transform: uppercase con caracteres turcos. Hasta donde yo sé (no soy turco), hay cuatro caracteres diferentes i: ı i I İ donde los dos últimos son las representaciones en mayúsculas de los dos anteriores.CSS: text-transform no funciona correctamente para caracteres turcos

Sin embargo aplicando text-transform:uppercase-ı i, los navegadores (controladas IE, Firefox, Chrome y Safari) se traduce en I I lo cual no es correcto y pueden cambiar el significado de las palabras hasta el punto de que se conviertan en insultos. (Eso es lo que me han dicho)

Como mi investigación para soluciones no reveló ninguna, mi pregunta es: ¿hay soluciones para este problema? La primera solución podría ser eliminar text-transform: uppercase por completo, pero eso es una especie de último recurso.

Lo curioso es que el W3C tiene pruebas para este problema en su sitio, pero carece de más información sobre este tema. http://www.w3.org/International/tests/tests-html-css/tests-text-transform/generate?test=5

Agradezco cualquier ayuda y en espera de sus respuestas :-)

He aquí una codepen

+0

¿Se puede mostrar un trabajo, er, el ejemplo de su caso que no funciona? – Tim

+0

Claro, eche un vistazo a http://malax.de/turkish-css-text-transform.html – Malax

+0

El enlace ya no funciona, FYI. –

Respuesta

56

puede añadir lang atributo y establezca su valor en tr de resolver esto:

<html lang="tr"> o <div lang="tr">

Here is working example.

+1

Esta debería ser la respuesta aceptada hoy. – gok

+1

Tengo problemas con esto. Funciona perfectamente en el escritorio tanto con Chrome como con Safari. Sin embargo, los navegadores iOS parecen ignorar esta etiqueta. No funciona en Chrome para dispositivos móviles y Safari móvil, ¿alguna idea? – gok

+0

bien, al parecer, es problemático con iOS 7 ~, funciona en iOS 8 ~ – gok

0

La causa principal de este problema debe ser el manejo incorrecto de estos caracteres turcos por la biblioteca Unicode utilizado en todos estos navegadores. Así que dudo que haya una solución para eso.

Alguien tiene que informar este problema a los desarrolladores de estas librerías Unicode, y se solucionará en algunas semanas/meses.

+0

Es por eso que estoy pidiendo soluciones, no soluciones.;-) – Malax

+0

No los están manejando de forma incorrecta, simplemente no tienen forma de saber que debe ser turco. – tdammers

+0

semanas/meses? Pruebe años/décadas. Encontré errores para esto para Firefox y Safari: https://bugzilla.mozilla.org/show_bug.cgi?id=231162 https://bugs.webkit.org/show_bug.cgi?id=21312 – gtd

0

Si no puede confiar en la transformación de texto y en los navegadores, deberá renderizar el texto en mayúsculas usted mismo en el servidor (espero que no esté aplicando mayúscula al texto cuando el usuario lo escriba). Debe tener un mejor soporte para la internacionalización allí.

0

Este trabajo requiere un poco de Javascript. Si no quiere hacer eso, pero tiene algo del lado del servidor que puede preprocesar el texto, esta idea también funcionará allí (creo).

En primer lugar, detectar si se está ejecutando en turco. Si es así, luego escanee lo que va a mayúsculas para ver si contiene los caracteres problemáticos. Si lo hacen, reemplace todos esos caracteres con la versión en mayúsculas de ellos. Luego aplica el CSS en mayúsculas. Dado que los personajes problemáticos ya están en mayúsculas, debería ser un trabajo totalmente perfecto (gueto). Para Javascript, imagino tener que lidiar con algunos .innerHTML en los elementos afectados.

Avíseme si necesita detalles de implementación, tengo una buena idea de cómo hacer esto en Javascript utilizando los métodos de manipulación de cadenas de Javascript. Esta idea general debe conseguir que la mayor parte del camino (y esperemos que conseguirme una recompensa!)

-Brian J. Stinar-

14

He aquí un ejemplo de solución rápida y sucia - es más rápido de lo que pensaba (probado en un documento con 2400 etiquetas -> sin demora).Pero veo que js soluciones no son la mejor solución

<html> 
<head> 
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-3"> 
</head> 
<body> 
<div style="text-transform:uppercase">a b c ç d e f g ğ h ı i j k l m n o ö p r s ş t u ü v y z (source)</div> <div>A B C Ç D E F G Ğ H I İ J K L M N O Ö P R S Ş T U Ü V Y Z (should be like this)</div> 

<script> 
    function getStyle(element, style) { 
     var result; 

     if (document.defaultView && document.defaultView.getComputedStyle) { 
      result = document.defaultView.getComputedStyle(element, '').getPropertyValue(style); 
     } else if(element.currentStyle) { 
      style = style.replace(/\-(\w)/g, function (strMatch, p1) { 
       return p1.toUpperCase(); 
      }); 
      result = element.currentStyle[style]; 
     } 
     return result; 
    } 

    function replaceRecursive(element) { 
     if (element && element.style && getStyle(element, 'text-transform') == 'uppercase') { 
      element.innerHTML = element.innerHTML.replace(/ı/g, 'I'); 
      element.innerHTML = element.innerHTML.replace(/i/g, 'İ'); // replaces 'i' in tags too, regular expression should be extended if necessary 
     } 

     if (!element.childNodes || element.childNodes.length == 0) return; 

     for (var n in element.childNodes) { 
      replaceRecursive(element.childNodes[n]); 
     } 
    } 

    window.onload = function() { // as appropriate 'ondomready' 
     alert('before...'); 
     replaceRecursive(document.getElementsByTagName('body')[0]); 
     alert('...after'); 
    } 
</script> 

</body> 
</html> 
+0

Me gusta su implementación de simplemente aplicar todos los contenidos en lugar de reemplazar los caracteres específicos y confiar en CSS como sugerí. Sin embargo, tengo una pregunta sobre su reemplazo recursivo y .innerHTML, principalmente porque no entiendo este atributo lo suficientemente bien. Si he anidado los elementos

contents
, y llamo a su replaceRecursive(), ¿se identificará el ID? Gracias por ayudarme a entender tu implementación. –

+5

Es posible que desee agregar pruebas para 'lang =" tr "', y definitivamente no debería usar 'for ... in' para iterar a través de objetos' NodeList': https://developer.mozilla.org/En/DOM/ NodeList. De lo contrario, +1 –

+0

Buenos puntos Yi, también esto no funciona con nodos secundarios mixtos elemento/texto (como cuando tiene una etiqueta que envuelve un cuadro de entrada y su descripción). Solucioné todos estos problemas y tengo una solución que estoy usando en producción, que compartiré como una respuesta separada. – gtd

7

Aquí está mi versión mejorada del código de Alex que estoy usando en la producción:

(function($) { 
    function getStyle(element, style) { 
    var result; 

    if (document.defaultView && document.defaultView.getComputedStyle) { 
     result = document.defaultView.getComputedStyle(element, '').getPropertyValue(style); 
    } else if(element.currentStyle) { 
     style = style.replace(/\-(\w)/g, function (strMatch, p1) { 
     return p1.toUpperCase(); 
     }); 
     result = element.currentStyle[style]; 
    } 
    return result; 
    } 

    function replaceRecursive(element, lang) { 
    if(element.lang) { 
     lang = element.lang; // Maintain language context 
    } 

    if (element && element.style && getStyle(element, 'text-transform') == 'uppercase') { 
     if (lang == 'tr' && element.value) { 
     element.value = element.value.replace(/ı/g, 'I'); 
     element.value = element.value.replace(/i/g, 'İ'); 
     } 

     for (var i = 0; i < element.childNodes.length; ++i) { 
     if (lang == 'tr' && element.childNodes[i].nodeType == Node.TEXT_NODE) { 
      element.childNodes[i].textContent = element.childNodes[i].textContent.replace(/ı/g, 'I'); 
      element.childNodes[i].textContent = element.childNodes[i].textContent.replace(/i/g, 'İ'); 
     } else { 
      replaceRecursive(element.childNodes[i], lang); 
     } 
     } 
    } else { 
     if (!element.childNodes || element.childNodes.length == 0) return; 

     for (var i = 0; i < element.childNodes.length; ++i) { 
     replaceRecursive(element.childNodes[i], lang); 
     } 
    } 
    } 

    $(document).ready(function(){ replaceRecursive(document.getElementsByTagName('html')[0], ''); }) 
})(jQuery); 

Tenga en cuenta que estoy usando jQuery aquí sólo para el ready() función. El contenedor de compatibilidad jQuery también es una forma conveniente de espacio de nombres de las funciones. Aparte de eso, las dos funciones no dependen de jQuery para poder sacarlas.

En comparación con la versión original de Alex éste resuelve un par de problemas:

  • Se realiza un seguimiento del atributo lang, ya que recursivamente a través, ya que si se han mezclado turco y otro tipo de contenido latino obtendrá transformaciones impropias en el no turco sin él. De acuerdo con esto, paso el elemento base html, no el body. Puede pegar lang="en" en cualquier etiqueta que no sea turca para evitar mayúsculas incorrectas.

  • Aplica la transformación solo a TEXT_NODES porque el método anterior innerHTML no funcionaba con nodos mixtos de texto/elemento como etiquetas con texto y casillas de verificación dentro de ellos.

Si bien tener algunas deficiencias notables en comparación con una solución del lado del servidor, sino que también tiene algunas ventajas importantes, el principal de los cuales está garantizada la cobertura sin la del lado del servidor que tiene que ser consciente de qué estilos se aplican a qué contenido . Si alguno de los contenidos se indexa y se muestra en los resúmenes de Google (por ejemplo), es mucho mejor si se mantiene en minúscula cuando se sirve.

+0

¡Gracias por publicar esto! :) – Malax

+1

Gracias por pedirlo un año antes de que lo necesitara :) – gtd

4

La próxima versión de Firefox Nightly (que debería convertirse en Firefox 14) tiene una solución para este problema y debe manejar el caso sin ningún truco (como lo solicitan las especificaciones de CSS3).

Los detalles morbosos están disponibles en ese error: https://bugzilla.mozilla.org/show_bug.cgi?id=231162

También arreglaron el problema de font-variant pienso (Para los que no conocen lo font-variant hace, ver https://developer.mozilla.org/en/CSS/font-variant, aún no arriba-hasta la fecha con el cambio, pero el documento es independiente del navegador y un wiki, así que ...)

+0

¡Buen seguimiento, gracias! – Malax

0

Puede resolver esto con javascript aswell orígenes:

Here is also its gist.

String.prototype.turkishToLower = function(){ 
 
    var string = this; 
 
    var letters = { "İ": "i", "I": "ı", "Ş": "ş", "Ğ": "ğ", "Ü": "ü", "Ö": "ö", "Ç": "ç" }; 
 
    string = string.replace(/(([İIŞĞÜÇÖ]))/g, function(letter){ return letters[letter]; }) 
 
    return string.toLowerCase(); 
 
} 
 

 
String.prototype.turkishToUpper = function(){ 
 
    var string = this; 
 
    var letters = { "i": "İ", "ş": "Ş", "ğ": "Ğ", "ü": "Ü", "ö": "Ö", "ç": "Ç", "ı": "I" }; 
 
    string = string.replace(/(([iışğüçö]))/g, function(letter){ return letters[letter]; }) 
 
    return string.toUpperCase(); 
 
} 
 

 
var text = 'iii'; 
 
text = text.turkishToUpper(); 
 
console.log(text);

Cuestiones relacionadas