CSS: text-transform nie działa poprawnie dla znaków tureckich

Implementacje głównych przeglądarek wydają się mieć problemy z text-transform: uppercase z tureckimi znakami. Z tego co wiem (nie jestem Turkiem.) istnieją cztery różne znaki i: ı i I İ gdzie dwa ostatnie są wielkimi reprezentacjami dwóch poprzednich.

Jednak stosowanie text-transform:uppercase do ı i, przeglądarek (sprawdzonych IE, Firefox, Chrome i Safari) powoduje I I, co nie jest poprawne i może zmienić znaczenie słów tak bardzo, że stają się obelgami. (That 's what I' ve been told)

Ponieważ moje badania nad rozwiązaniami nie ujawniły żadnego, moje pytanie brzmi: Czy istnieją obejścia tego problemu? Pierwszym obejściem może być całkowite usunięcie text-transform: uppercase, ale jest to jakaś ostatnia deska ratunku.

Zabawne, W3C ma testy na ten problem na swojej stronie, ale brak dalszych informacji na ten temat. http://www.w3.org/International/tests/tests-html-css/tests-text-transform/generate?test=5

Doceniam każdą pomoc i czekam z niecierpliwością na Wasze odpowiedzi: -)

Oto codepen

Author: Asim K T, 2010-09-23

8 answers

Możesz dodać atrybut lang i ustawić jego wartość na tr, aby rozwiązać ten problem:

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

Oto przykład pracy.

 64
Author: Hkan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-19 15:15:02

Oto szybki i brudny przykład obejścia problemu - jest szybszy niż myślałem (testowany w dokumencie z tagami 2400 -> bez opóźnień). Ale widzę, że obejścia js nie są najlepszym rozwiązaniem

<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>
 14
Author: alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-03 09:10:55

Oto moja ulepszona wersja kodu Alexa, którego używam w produkcji:]}

(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);

Zauważ, że używam jQuery tylko dla funkcji ready(). Opakowanie kompatybilności jQuery jest również wygodnym sposobem na Przestrzeń nazw funkcji. Poza tym, te dwie funkcje w ogóle nie polegają na jQuery, więc można je wyciągnąć.

W porównaniu do oryginalnej wersji Alexa ten rozwiązuje kilka problemów:

  • Śledzi atrybut lang, ponieważ rekursuje, ponieważ jeśli zmieszałeś turecką i inną łacińską treść, otrzymasz niewłaściwe transformacje na nie-Tureckiej bez niej. Zgodnie z tym przekazuję w bazie html element, a nie body. Możesz przykleić lang="en" na dowolnym znaczniku, który nie jest Turecki, aby zapobiec niewłaściwej kapitalizacji.

  • Stosuje transformację tylko do TEXT_NODES, ponieważ poprzednia metoda innerHTML nie działała z pomieszanymi węzłami tekstu / elementu, takimi jak etykiety z tekstem i pola wyboru wewnątrz oni.

Chociaż ma pewne znaczące braki w porównaniu do rozwiązania po stronie serwera, ma również kilka głównych zalet, z których głównym jest Gwarantowany zasięg bez konieczności bycia świadomym, jakie style są stosowane do jakiej treści. Jeśli którakolwiek z Treści jest indeksowana i wyświetlana w podsumowaniach Google (na przykład), o wiele lepiej, jeśli pozostanie mała litera po serwowaniu.

 7
Author: gtd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-16 13:46:01

Następna wersja Firefoksa Nightly (która powinna stać się Firefoksem 14) ma poprawkę na ten problem i powinna obsłużyć sprawę bez żadnych włamań(zgodnie z wymaganiami specyfikacji CSS3).

Szczegóły są dostępne w tym Bugu: https://bugzilla.mozilla.org/show_bug.cgi?id=231162

Naprawili również problem dla font-variant, jak sądzę (dla tych, którzy nie wiedzą, co robi font-variant, zobacz https://developer.mozilla.org/en/CSS/font-variant , jeszcze nieaktualne z zmiana, ale doc jest przeglądarkowy i wiki, więc...)

 4
Author: teoli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-29 20:21:40

Główną przyczyną tego problemu musi być Nieprawidłowa obsługa tych tureckich znaków przez Bibliotekę unicode używaną we wszystkich tych przeglądarkach. Więc wątpię, żeby było na to rozwiązanie front-end-side.

Ktoś musi zgłosić ten problem programistom tych bibliotek unicode i zostanie on naprawiony w ciągu kilku tygodni/miesięcy.

 0
Author: BarsMonster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-28 15:27:34

Jeśli nie możesz polegać na text-transform i przeglądarkach, będziesz musiał renderować swój tekst wielkimi literami na serwerze (mam nadzieję, że nie piszesz wielkich liter, gdy użytkownik go wpisuje). Powinieneś mieć tam lepsze poparcie dla internacjonalizacji.

 0
Author: Jakub Konecki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-29 15:44:11

To obejście wymaga trochę Javascript. Jeśli nie chcesz tego robić, ale masz coś po stronie serwera, co może wstępnie przetworzyć tekst, ten pomysł też zadziała (myślę).

Najpierw sprawdź, czy używasz języka tureckiego. Jeśli tak, zeskanuj to, co zamierzasz zrobić wielkimi literami, aby sprawdzić, czy zawiera znaki problemu. Jeśli tak, Zastąp wszystkie te znaki wielkimi literami. Następnie zastosuj CSS z dużymi literami. Ponieważ znaki problemowe są już Wielkie Litery, to powinno być całkiem dobrze (Getto) praca wokół. Dla Javascript, wyobrażam sobie, że muszę sobie z niektórymi poradzić .innerHTML na Twoich elementach.

Daj mi znać, jeśli potrzebujesz szczegółów implementacji, mam dobry pomysł, jak to zrobić w Javascript za pomocą Javascript string manipulacji metod. Ten ogólny pomysł powinien dać ci większość drogi tam (i mam nadzieję, że zdobędę nagrodę!)

-Brian J. Stinar -

 0
Author: Brian Stinar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-29 20:58:45

Możesz rozwiązać to za pomocą natywnego javascript jak również:

Tutaj jest również jego sedno.

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);
 -1
Author: Barlas Apaydin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-22 16:08:27