Подтвердить что ты не робот

CSS: текстовое преобразование не работает должным образом для турецких персонажей

Реализации основных браузеров, похоже, имеют проблемы с 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

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

Здесь codepen

4b9b3361

Ответ 1

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

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

Вот рабочий пример.

Ответ 2

Вот пример быстрого и грязного обходного пути - он быстрее, чем я думал (проверен в документе с 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>

Ответ 3

Вот моя расширенная версия 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, поэтому вы можете вытащить их.

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

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

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

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

Ответ 4

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

Сведения о gory доступны в этой ошибке: https://bugzilla.mozilla.org/show_bug.cgi?id=231162

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

Ответ 5

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

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

Ответ 6

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

Ответ 7

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

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

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

-Brian J. Stinar -

Ответ 8

Это не предпочтительный способ, но если у вас нет другого варианта: вы можете решить эту проблему с помощью родного javascript:

Вот и его суть.

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