CSS: преобразование текста не работает должным образом для турецких символов - PullRequest
49 голосов
/ 23 сентября 2010

Реализация основных браузеров, похоже, имеет проблемы с text-transform: uppercase с турецкими символами.Насколько я знаю (я не турецкий.) Есть четыре разных символа i: ı i I İ, где последние два - это заглавные представления первых двух.

Однако применяется text-transform:uppercase кı i, браузеры (проверенные IE, Firefox, Chrome и Safari) приводят к I I, что неверно и может настолько изменить смысл слов, что они станут оскорблениями.(Это то, что мне сказали)

Поскольку мое исследование решений не выявило никаких вопросов, мой вопрос: есть ли обходные пути для этой проблемы?Первый обходной путь может состоять в том, чтобы полностью удалить text-transform: uppercase, но это своего рода последнее средство.

Забавно, у W3C есть тесты для этой проблемы на их сайте, но нет дополнительной информации об этой проблеме.http://www.w3.org/International/tests/tests-html-css/tests-text-transform/generate?test=5

Я ценю любую помощь и с нетерпением жду ваших ответов: -)

Вот кодекс

Ответы [ 8 ]

74 голосов
/ 24 марта 2014

Вы можете добавить атрибут lang и установить его значение на tr, чтобы решить это:

<html lang="tr"> или <div lang="tr">

Здесь работаетпример.

15 голосов
/ 01 октября 2010

Вот пример быстрого и грязного обходного пути - он быстрее, чем я думал (проверено в документе с 2400 тегами -> без задержки).Но я вижу, что обходные пути JS - не самое лучшее решение

<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>
7 голосов
/ 05 января 2012

Вот моя расширенная версия кода alex, которую я использую в производстве:

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

Обратите внимание, что здесь я использую jQuery только для функции ready(). Оболочка совместимости с jQuery также является удобным способом для пространства имен функций. Кроме этого, две функции вообще не зависят от jQuery, так что вы можете их извлечь.

По сравнению с оригинальной версией Алекса эта проблема решает пару проблем:

  • Он отслеживает атрибут lang во время его повторения, поскольку, если вы смешали турецкий и другой латинский контент, вы получите неправильные преобразования для нетурецкого без него. В соответствии с этим я передаю базовый элемент html, а не body. Вы можете прикрепить lang="en" к любому тегу, который не является турецким, чтобы предотвратить неправильную капитализацию.

  • Применяет преобразование только к TEXT_NODES, поскольку предыдущий метод innerHTML не работал со смешанными узлами текста / элемента, такими как метки с текстом и флажки внутри них.

Несмотря на некоторые заметные недостатки по сравнению с серверным решением, оно также имеет ряд существенных преимуществ, главным из которых является гарантированное покрытие без необходимости знать на стороне сервера, какие стили применяются к какому контенту. Если какой-либо контент индексируется и показывается в сводках Google (например), гораздо лучше, если он будет отображаться в нижнем регистре.

4 голосов
/ 30 марта 2012

Следующая версия Firefox Nightly (которая должна стать Firefox 14) имеет исправление для этой проблемы и должна обрабатывать случай без какого-либо взлома (как этого требуют спецификации CSS3).

Подробная информация доступна в этой ошибке: https://bugzilla.mozilla.org/show_bug.cgi?id=231162

Они также исправили проблему для варианта шрифта, я думаю (для тех, кто не знает, что делает вариант шрифта, см. https://developer.mozilla.org/en/CSS/font-variant, еще не в курсе изменений, но документ не зависит от браузера. и вики, так что ...)

0 голосов
/ 22 ноября 2015

Вы можете решить эту проблему с помощью javascript aswell:

Вот также его суть.

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);
0 голосов
/ 29 сентября 2010

Этот обходной путь требует некоторого JavaScript.Если вы не хотите этого делать, но имеете что-то на стороне сервера, которое может предварительно обработать текст, эта идея также будет работать там (я думаю).

Сначала определите, работаете ли вы на турецком языке.Если да, то отсканируйте все, что вы собираетесь в верхнем регистре, чтобы увидеть, содержит ли он проблемные символы.Если это так, замените все эти символы на заглавные версии.Затем примените прописные буквы CSS.Поскольку проблемные символы уже в верхнем регистре, это должно быть вполне нормально (гетто).Что касается Javascript, я предполагаю, что придется иметь дело с некоторыми .innerHTML для ваших затронутых элементов.

Дайте мне знать, если вам нужны какие-либо подробности реализации, у меня есть хорошая идея, как сделать это в Javascript, используя методы манипуляции со строками Javascript.,Эта общая идея должна помочь вам пройти большую часть пути (и, надеюсь, получить мне награду!)

-Брайан Дж. Стинар-

0 голосов
/ 29 сентября 2010

Если вы не можете полагаться на преобразование текста и браузеры, вам придется отображать текст в верхнем регистре самостоятельно на сервере (надеюсь, вы не будете вводить верхний регистр текста, когда пользователь его набирает). У вас должна быть лучшая поддержка интернационализации там.

0 голосов
/ 28 сентября 2010

Основной причиной этой проблемы должна быть неправильная обработка этих турецких символов библиотекой юникода, используемой во всех этих браузерах.Поэтому я сомневаюсь, что для этого есть внешнее исправление.

Кто-то должен сообщить об этой проблеме разработчикам этих библиотек Unicode, и она будет исправлена ​​через несколько недель / месяцев.

...