web-dev-qa-db-ja.com

CSS:トルコ語の文字に対してテキスト変換が正しく機能しない

主要なブラウザの実装では、トルコ語の文字を含む_text-transform: uppercase_に問題があるようです。私の知る限り(トルコ語ではありません。)4つの異なるi文字があります:_ı i I İ_ここで、最後の2つは前の2つの大文字の表記です。

ただし、_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 です

51
Malax

これを解決するには、lang属性を追加し、その値をtrに設定します。

<html lang="tr">または<div lang="tr">

これが実際の例です。

76
Hkan

これはすばやく簡単な回避策の例です-思ったよりも高速です(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>
15
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);
_

ここでは、ready()関数に対してのみjQueryを使用していることに注意してください。 jQuery互換ラッパーは、関数の名前空間を作成する便利な方法としても使用できます。それ以外は、2つの関数はjQueryにまったく依存していないため、それらを引き出すことができます。

アレックスの元のバージョンと比較して、これはいくつかの問題を解決します:

  • トルコ語と他のラテン語のコンテンツが混在していると、トルコ語以外の言語で不適切な変換が行われるため、再帰するlang属性を追跡します。これに従って、htmlではなく、ベースのbody要素を渡します。トルコ語ではないタグに_lang="en"_を付けて、不適切な大文字の使用を防ぐことができます。

  • 変換は_TEXT_NODES_にのみ適用されます。これは、以前のinnerHTMLメソッドが、テキストと要素が混在するラベル(その中にテキストとチェックボックスが含まれているラベルなど)では機能しなかったためです。

サーバー側のソリューションと比較していくつかの顕著な欠点がありますが、いくつかの主要な利点もあります。その主な利点は、サーバー側がどのコンテンツにどのスタイルが適用されているかを意識する必要がないカバレッジが保証されていることです。コンテンツのいずれかがインデックスに登録され、Googleの概要に表示されている場合(たとえば)、配信時に小文字のままにしておく方がはるかに優れています。

7
gtd

Firefox Nightlyの次のバージョン(Firefox 14になるはずです)では、この問題が修正されており、ハッキングすることなく(CSS3仕様で要求されているように)ケースを処理できます。

バグの詳細はそのバグで利用可能です: https://bugzilla.mozilla.org/show_bug.cgi?id=231162

彼らは私が思うfont-variantの問題も修正しました(font-variantの機能がわからない場合は、 https://developer.mozilla.org/en/CSS/font-variant を参照してください。最新の変更ですが、ドキュメントはブラウザに依存せず、Wikiなので、...)

4
teoli

この回避策には、Javascriptが必要です。あなたがそれをしたくないが、テキストを前処理できる何かサーバー側があるなら、この考えはそこでもうまくいくでしょう(私は思う)。

まず、トルコ語で実行しているかどうかを検出します。ある場合は、大文字にするものをスキャンして、問題のある文字が含まれているかどうかを確認します。含まれている場合は、それらのすべての文字を大文字バージョンに置き換えます。次に、大文字のCSSを適用します。問題のある文字は既に大文字であるため、これは完全に適切な(ゲットー)回避策です。 JavaScriptの場合、影響を受ける要素の.innerHTMLを処理する必要があることを想定しています。

実装の詳細が必要な場合は、JavaScriptの文字列操作メソッドを使用してJavascriptでこれを行う方法を教えてください。この一般的なアイデアは、ほとんどの方法であなたを得るはずです(そしてうまくいけば私に賞金をもらえます!)

-ブライアンJ.スティナー-

0
Brian Stinar

テキスト変換とブラウザに依存できない場合は、サーバーでテキストを大文字でレンダリングする必要があります(ユーザーが入力するときにテキストを大文字にしないでください)。そこでの国際化に対するより良いサポートが必要です。

0
Jakub Konecki

この問題の根本的な原因は、これらすべてのブラウザで使用されるUnicodeライブラリによるこれらのトルコ語の文字の不適切な処理にあるはずです。ですから、そのためのフロントエンド側の修正があるとは思えません。

誰かがこの問題をこれらのユニコードライブラリの開発者に報告する必要があり、数週間/月で修正されます。

0
BarsMonster