【问题标题】:Greek and text-transform:uppercase希腊语和文本转换:大写
【发布时间】:2012-03-15 02:18:04
【问题描述】:

我编写了一个 Web 应用程序,其中包含多种语言的翻译(其中一种是希腊语。)

当在标题上显示某个翻译时,设计规则是文本应该是大写的,这在世界上任何其他语言中都可以,但是当涉及到希腊语时,浏览器不知道要写什么处理重音符号(请参阅this),以便它们显示错误的大写字符串。

从我上面链接的那个补丁中,我已经将它转换为 Javascript,针对它运行了一些用例,并且它可以工作。现在我要做的就是:

如果不对每个需要大写的元素(有很多)添加uppercase 类,我可以使用计算的样式属性查询DOM 吗? IE。给我所有计算出text-transform: uppercase的元素

【问题讨论】:

    标签: javascript css internationalization


    【解决方案1】:

    这个问题的解决方法如上例3here

    This is an example 应该可以在任何浏览器上运行(仅在 firefox 25 上测试过)

    HTML:

    <body>
      <p id="withlang" lang="el">κεφαλαία με μετατροπή σύμφωνα με την γλώσσα</p>
      <p id="withoutlang">κεφαλαία με μετατροπή σύμφωνα με αντιστοιχίσεις unicode</p>
      <p id="withlangsmall" lang="el">μικρά κεφαλαία με μετατροπή σύμφωνα με την γλώσσα</p>
      <p id="withoutlangsmall">μικρά κεφαλαία με μετατροπή σύμφωνα με αντιστοιχίσεις unicode</p>
    </body>
    

    CSS:

    #withlang, #withoutlang{
      text-transform: uppercase;
    }
    
    #withlangsmall, #withoutlangsmall{
      font-variant: small-caps;
    }
    

    您还可以在更高级别使用 lang 属性,例如在 body 标记处。

    HTML:

    <body lang="el">
      <p id="withlang">κεφαλαία με μετατροπή σύμφωνα με την γλώσσα</p>
      <p id="withlangsmall">μικρά κεφαλαία με μετατροπή σύμφωνα με την γλώσσα</p>
    </body>
    

    CSS:

    #withlang{
      text-transform: uppercase;
    }
    
    #withlangsmall{
      font-variant: small-caps;
    }
    

    【讨论】:

    • 在 IE 和 Chrome 中不工作,对于 Chrome,如果你将 lang="el" 添加到 html 标签,它会工作
    【解决方案2】:

    我强烈建议不要为此使用 jQuery。而是这样做:

    var e = document.getElementsByTagName('*'), l = e.length, i;
    if( typeof getComputedStyle == "undefined")
        getComputedStyle = function(e) {return e.currentStyle;};
    for( i=0; i<l; i++) {
        if( getComputedStyle(e[i]).textTransform == "uppercase") {
            // do stuff with e[i] here.
        }
    }
    

    使用 10,000 个元素进行测试,其中 2,500 个具有“大写”文本转换。

    jQuery 处理时间为 595 毫秒
    JS 处理时间为 60ms

    所以 JavaScript 在这方面比 jQuery 快大约 10 倍。

    编辑:另一个测试,这次有 100,000 个元素:

    jQuery failed.TypeError: 对象不支持属性或方法'each'
    JS 处理时间为 577ms

    【讨论】:

      【解决方案3】:

      我正在使用这个 PHP 函数:

      function toUpper($str){
              $search = array('Ά', 'Έ', 'Ί', 'Ή', 'Ύ', 'Ό', 'Ώ');
              $replace = array('Α', 'Ε', 'Ι', 'Η', 'Υ', 'Ο', 'Ω');
              $str = mb_strtoupper($str,  "UTF-8");
              return str_replace($search, $replace, $str);
          }
      

      【讨论】:

      • 您的方法的问题在于它不是那么简单。一些转换依赖于前一个、前 2 个或前 3 个字母。
      • 老实说,我不明白你的意思。我发布的函数将所有没有重音标记的字母大写,其余的使用 str_replace。现在,作为希腊人相信我,这是一种服务器端方法,我发布它是因为您说您使用的是 PHP。现在,我已经在几个网站上使用过它,没有任何问题。以前的信件与它无关。而且由于它是我的母语,我会知道它是否会翻译错误! :p
      • 我从这里得到了我的解决方案的内部工作原理:bug307039.bugzilla.mozilla.org/attachment.cgi?id=588764 我没有使用 PHP(我在服务器端使用 Ruby),这是一个表示规则,所以它适合 Javascript .这个补丁有错吗?我应该用更简单的东西代替我拥有的东西吗?
      • 我对Ruby一无所知,但如果我遇到任何有用的东西,我会发布它!
      • 您没有在评论中回答问题 ;-) 我链接的那个补丁有误吗?
      【解决方案4】:

      好的,仅供参考,这是我目前的解决方案:

      GREEK_CHARS = {
        LOWER_ALPHA                : 0x03B1
        LOWER_ALPHA_ACC            : 0x03AC
        LOWER_EPSILON              : 0x03B5
        LOWER_EPSILON_ACC          : 0x03AD
        LOWER_ETA                  : 0x03B7
        LOWER_ETA_ACC              : 0x03AE
        LOWER_IOTA                 : 0x03B9
        LOWER_IOTA_ACC             : 0x03AF
        LOWER_IOTA_ACC_DIAERESIS   : 0x0390
        LOWER_OMICRON              : 0x03BF
        LOWER_OMICRON_ACC          : 0x03CC
        LOWER_UPSILON              : 0x03C5
        LOWER_UPSILON_ACC          : 0x03CD
        LOWER_UPSILON_ACC_DIAERESIS: 0x03B0
        LOWER_OMEGA_ACC            : 0x03CE
        UPPER_ALPHA                : 0x0391
        UPPER_EPSILON              : 0x0395
        UPPER_ETA                  : 0x0397
        UPPER_IOTA                 : 0x0399
        UPPER_IOTA_DIAERESIS       : 0x03AA
        UPPER_OMICRON              : 0x039F
        UPPER_UPSILON              : 0x03A5
        UPPER_UPSILON_DIAERESIS    : 0x03AB
        UPPER_OMEGA                : 0x03A9
        UPPER_ALPHA_ACC            : 0x0386
        UPPER_EPSILON_ACC          : 0x0388
        UPPER_ETA_ACC              : 0x0389
        UPPER_IOTA_ACC             : 0x038A
        UPPER_OMICRON_ACC          : 0x038C
        UPPER_UPSILON_ACC          : 0x038E
        UPPER_OMEGA_ACC            : 0x038F
        COMBINING_ACUTE_ACCENT           : 0x0301
        COMBINING_DIAERESIS              : 0x0308
        COMBINING_ACUTE_TONE_MARK        : 0x0341
        COMBINING_GREEK_DIALYTIKA_TONOS  : 0x0344
      }
      
      String::toUpperCaseWithoutGreek = String::toUpperCase
      String::toUpperCase = ->
        newStringCharCodes  = []
        insideTag           = false
        for char, idx in this
          insideTag = true if char == '<'
          insideTag = false if char == '>'
          charCode      = char.charCodeAt(0)
      
          if insideTag
            newStringCharCodes.push charCode
            continue
      
          prev          = if idx > 0 then newStringCharCodes[idx-1] else GREEK_CHARS.UPPER_ALPHA
          prevPrev      = if idx > 1 then newStringCharCodes[idx-2] else GREEK_CHARS.UPPER_ALPHA
          prevPrevPrev  = if idx > 2 then newStringCharCodes[idx-3] else GREEK_CHARS.UPPER_ALPHA
      
          switch charCode
            when GREEK_CHARS.LOWER_ALPHA_ACC, GREEK_CHARS.UPPER_ALPHA_ACC
              newStringCharCodes.push GREEK_CHARS.UPPER_ALPHA
            when GREEK_CHARS.LOWER_EPSILON_ACC, GREEK_CHARS.UPPER_EPSILON_ACC
              newStringCharCodes.push GREEK_CHARS.UPPER_EPSILON
            when GREEK_CHARS.LOWER_ETA_ACC, GREEK_CHARS.UPPER_ETA_ACC
              newStringCharCodes.push GREEK_CHARS.UPPER_ETA
            when GREEK_CHARS.LOWER_IOTA_ACC, GREEK_CHARS.UPPER_IOTA_ACC
              newStringCharCodes.push GREEK_CHARS.UPPER_IOTA
            when GREEK_CHARS.LOWER_IOTA_ACC_DIAERESIS
              newStringCharCodes.push GREEK_CHARS.UPPER_IOTA_DIAERESIS
            when GREEK_CHARS.LOWER_OMICRON_ACC, GREEK_CHARS.UPPER_OMICRON_ACC
              newStringCharCodes.push GREEK_CHARS.UPPER_OMICRON
            when GREEK_CHARS.LOWER_UPSILON_ACC, GREEK_CHARS.UPPER_UPSILON_ACC
              newStringCharCodes.push GREEK_CHARS.UPPER_UPSILON
            when GREEK_CHARS.LOWER_UPSILON_ACC_DIAERESIS
              newStringCharCodes.push GREEK_CHARS.UPPER_UPSILON_DIAERESIS
            when GREEK_CHARS.LOWER_OMEGA_ACC, GREEK_CHARS.UPPER_OMEGA_ACC
              newStringCharCodes.push GREEK_CHARS.UPPER_OMEGA
      
            when GREEK_CHARS.LOWER_IOTA
              switch prev
                when GREEK_CHARS.LOWER_ALPHA_ACC, GREEK_CHARS.LOWER_EPSILON_ACC, GREEK_CHARS.LOWER_OMICRON_ACC
                  newStringCharCodes.push GREEK_CHARS.UPPER_IOTA_DIAERESIS
                when GREEK_CHARS.LOWER_UPSILON_ACC
                  if prevPrev == GREEK_CHARS.LOWER_OMICRON
                    newStringCharCodes.push GREEK_CHARS.UPPER_IOTA
                  else
                    newStringCharCodes.push GREEK_CHARS.UPPER_IOTA_DIAERESIS
                when GREEK_CHARS.COMBINING_ACUTE_ACCENT, GREEK_CHARS.COMBINING_ACUTE_TONE_MARK
                  switch prevPrev
                    when GREEK_CHARS.LOWER_ALPHA, GREEK_CHARS.LOWER_EPSILON, GREEK_CHARS.LOWER_OMICRON
                      newStringCharCodes.push GREEK_CHARS.UPPER_IOTA_DIAERESIS
                    when GREEK_CHARS.LOWER_UPSILON
                      if prevPrevPrev == GREEK_CHARS.LOWER_OMICRON
                        newStringCharCodes.push GREEK_CHARS.UPPER_IOTA
                      else
                        newStringCharCodes.push GREEK_CHARS.UPPER_IOTA_DIAERESIS
                    else
                      newStringCharCodes.push GREEK_CHARS.UPPER_IOTA
                else
                  newStringCharCodes.push GREEK_CHARS.UPPER_IOTA
      
            when GREEK_CHARS.LOWER_UPSILON
              switch prev
                when GREEK_CHARS.LOWER_ALPHA_ACC, GREEK_CHARS.LOWER_EPSILON_ACC, GREEK_CHARS.LOWER_ETA_ACC, GREEK_CHARS.LOWER_OMICRON_ACC
                  newStringCharCodes.push GREEK_CHARS.UPPER_UPSILON_DIAERESIS
                when GREEK_CHARS.COMBINING_ACUTE_ACCENT, GREEK_CHARS.COMBINING_ACUTE_TONE_MARK
                  switch prevPrev
                    when GREEK_CHARS.LOWER_ALPHA, GREEK_CHARS.LOWER_EPSILON, GREEK_CHARS.LOWER_ETA, GREEK_CHARS.LOWER_OMICRON
                      newStringCharCodes.push GREEK_CHARS.UPPER_UPSILON_DIAERESIS
                    else
                      newStringCharCodes.push GREEK_CHARS.UPPER_UPSILON
                else
                  newStringCharCodes.push GREEK_CHARS.UPPER_UPSILON
      
            when GREEK_CHARS.COMBINING_GREEK_DIALYTIKA_TONOS
              newStringCharCodes.push GREEK_CHARS.COMBINING_DIAERESIS
            when GREEK_CHARS.COMBINING_ACUTE_ACCENT, GREEK_CHARS.COMBINING_ACUTE_TONE_MARK
              if prev < GREEK_CHARS.LOWER_OMEGA_ACC && prev > GREEK_CHARS.UPPER_ALPHA_ACC
                newStringCharCodes.push null
            else
              newStringCharCodes.push(String.fromCharCode(charCode).toUpperCaseWithoutGreek().charCodeAt(0))
      
        String.fromCharCode.apply(null, newStringCharCodes)
      

      这是根据上述错误中提供的补丁改编的咖啡脚本。

      这是渲染视图后我所做的:

      # Fix greek uppercase.
      [].concat($('*').get()).filter((elm) ->
        window.getComputedStyle(elm).getPropertyValue('text-transform') == "uppercase";
      ).forEach((elm) ->
        if elm.value
          elm.value = elm.value.toUpperCase()
        else
          $elm = $(elm)
          $elm.html($elm.html().toUpperCase())
      )
      

      不管怎么想,这都不是很好,但它确实有效。

      有两件事我不应该在这里做,并且可能会改变:劫持toUpperCase() 并有不解析标签的特定规则。仍然愿意接受更好的建议!

      【讨论】:

        【解决方案5】:

        我喜欢 Otovo 的回答,因为它最优雅、最快捷。我当然不建议扫描text-transform 的所有元素。对于移动设备上的大页面,速度效率低下是显着的。

        因此,我建议简单地记下 CSS 文件中带有 text-transform 的所有选择器。对于大多数情况,这应该是可能的。然后,直接在这些选择器上使用 jQuery。

        因此,为了扩展 Otovo 的答案,请在 body 中的某处为每种语言添加一个独特的类,如 i18n-el(这是 Drupal 的默认设置,但任何类似的东西都可以)。然后运行:

        $('.i18n-el').find('.all-relevant-selectors').attr('lang', 'el');
        

        显然,请将 .all-relevant-selectors 替换为您从 CSS 文件中记下的选择器,并用逗号分隔。

        另外,值得一提的是,这仅适用于 text-transform: uppercase 而不适用于 Chrome 39 的 font-variant: small-caps

        另外,有一个名为jquery-remove-upcase-accents 的jQuery 插件,虽然我根本没有评估它。

        【讨论】:

          【解决方案6】:

          这对希腊字符没有帮助,但我很好奇找到具有给定 css 属性的所有元素。 我设置了这个:http://jsfiddle.net/pQfUv/1/

          你会感兴趣的一点是:

          $('*').each(function() {
                      if ($(this).css('text-transform') == 'uppercase') {
                          //Do Stuff to the element
                      }
                  });
          

          不过,遍历所有元素可能是一件相当昂贵的事情。 希望对您有所帮助。

          干杯, 异

          【讨论】:

            【解决方案7】:

            我可以向您保证,不仅希腊语受到影响。您肯定在使用德语 Sharp S 和土耳其语 letters i 时遇到问题。

            我不太确定使用这些转换的目的是什么,但请记住,许多语言是用没有大小写字符概念的脚本编写的。如果您使用它来强调,我建议完全删除所有转换并简单地用适当的大小写编写部分文本。这样,翻译人员可能会决定如何强调单词或句子。

            顺便说一句。在翻译中允许 span 元素具有特定的类也可能是一个好主意 - 这样有人可能会使用 ie color 来不同地标记文本(尽管它不会真正帮助色盲的人。)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2021-07-20
              • 2017-09-24
              • 2019-04-24
              • 1970-01-01
              • 2014-04-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多