CSS:文本转换不适用于土耳其语字符

Posted

技术标签:

【中文标题】CSS:文本转换不适用于土耳其语字符【英文标题】:CSS: text-transform not working properly for Turkish characters 【发布时间】:2011-04-16 04:49:27 【问题描述】:

主要浏览器的实现似乎对带有土耳其字符的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

【问题讨论】:

你能展示一个工作的,呃,不工作的例子吗? 好的,看看malax.de/turkish-css-text-transform.html 链接失效了,仅供参考。 【参考方案1】:

您可以添加lang 属性并将其值设置为tr 来解决此问题:

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

Here is working example.

【讨论】:

我遇到了麻烦。它可以完美地在桌面上与 Chrome 和 Safari 一起使用。然而 ios 浏览器似乎忽略了这个标签。它在移动 Chrome 和移动 Safari 上失败,有什么想法吗? ok,显然iOS 7有问题~,iOS 8可以用~ 是的,我刚刚在 iOS 8 上的 Chrome 和 Safari 上进行了测试,看起来还不错。 感谢@Barlas 的编辑。我最近发现 lang 属性适用于任何元素,但我没有想到要编辑答案。 @Hkan np mate,我以前多次被这个错误挑战过,这里的 js 解决方案:***.com/a/33856951/1428241【参考方案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>

【讨论】:

我喜欢您将整个内容大写而不是像我建议的那样替换特定字符并依赖 CSS 的实现。不过,我对您的递归替换和 .innerHTML 有疑问,主要是因为我不太了解此属性。如果我有嵌套元素 contents ,并且我调用了你的 replaceRecursive(),id 会大写吗?感谢您帮助我了解您的实施。 您可能想为lang="tr" 添加测试,绝对不应该使用for...in 来遍历NodeList 对象:developer.mozilla.org/En/DOM/NodeList。否则,+1 好点Yi,这也不适用于混合元素/文本子节点(例如当您有一个包装输入框及其描述的标签时)。我已经解决了所有这些问题,并且有一个我在生产中使用的解决方案,我将作为单独的回复分享。【参考方案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)修复了这个问题,并且应该在没有任何 hack 的情况下处理这个问题(正如 CSS3 规范所要求的那样)。

该错误中提供了血腥细节:https://bugzilla.mozilla.org/show_bug.cgi?id=231162

他们还解决了我认为 font-variant 的问题(对于那些不知道 font-variant 做什么的人,请参阅 https://developer.mozilla.org/en/CSS/font-variant ,尚未更新该更改,但该文档与浏览器无关并且是一个 wiki ,所以...)

【讨论】:

【参考方案5】:

这个问题的根本原因一定是所有这些浏览器中使用的 unicode 库对这些土耳其字符的处理不正确。所以我怀疑是否有一个前端解决方案。

必须有人将此问题报告给这些 un​​icode 库的开发人员,并且会在几周/几个月内修复。

【讨论】:

他们并没有错误地处理它们,他们根本无法知道它是土耳其语。 周/月?尝试几年/几十年。我发现了 Firefox 和 Safari 的开放错误:bugzilla.mozilla.org/show_bug.cgi?id=231162bugs.webkit.org/show_bug.cgi?id=21312 @tdammers 这是 HTML 中的 lang 属性和 HTTP 中的 Content-Language 标头的用途。【参考方案6】:

如果您不能依赖文本转换和浏览器,您将不得不自己在服务器上以大写形式呈现您的文本(希望您在用户键入时不要将文本大写)。 您应该在那里对国际化有更好的支持。

【讨论】:

【参考方案7】:

此解决方法需要一些 javascript。如果您不想这样做,但有一些服务器端可以预处理文本,那么这个想法也可以在那里工作(我认为)。

首先,检测您是否使用土耳其语运行。如果你是,然后扫描你要大写的任何内容,看看它是否包含问题字符。如果是这样,请将所有这些字符替换为它们的大写版本。然后应用大写的 CSS。由于问题字符已经是大写的,这应该是一个完全可以解决的问题(ghetto)。对于 Javascript,我设想必须在受影响的元素上处理一些 .innerHTML。

如果您需要任何实现细节,请告诉我,我很清楚如何使用 Javascript 字符串操作方法在 Javascript 中执行此操作。这个总体思路应该可以帮助您完成大部分工作(希望能给我带来丰厚的回报!)

-布莱恩·J·斯蒂纳尔-

【讨论】:

以上是关于CSS:文本转换不适用于土耳其语字符的主要内容,如果未能解决你的问题,请参考以下文章

将特殊的土耳其字符转换为国际拉丁字符

JavaScript 中的土耳其语大小写转换

mongodb排序规则不适用于facet阶段的insinde聚合

javascript 土耳其char转换

iOS Parse OrderByAscending 结果错误的土耳其字符

在 Java 中从 Excel 中读取土耳其字符