2012-02-24 80 views
12

我已经写了包含几种语言的翻译Web应用程序希腊和文本转换:(他们是希腊的一个)大写

当显示的标题一定的翻译,设计规则是,文本应该是大写的,在世界上任何其他语言都是好的,但是对于希腊语,浏览器不知道如何处理这些重音(见this),因此它们显示错误的大写字符串。

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

如果不需要为需要大写的每个元素添加uppercase类,那么我可以使用计算样式属性来查询DOM吗? IE浏览器。给我所有的有一个计算text-transform: uppercase

回答

10

。而是这样做:

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. 
    } 
} 

测试了10000个元素,其中2500个“大写”文本转换。

jQuery processed in 595ms
JS processed in 60ms

因此,JavaScript比jQuery快大约10倍。

编辑:另一个测试,这次10万组的元素:

jQuery failed.TypeError: Object doesn't support property or method 'each'
JS processed in 577ms

+0

不错!将更新:-) – changelog 2012-02-24 17:38:57

+0

我应该在哪里放置这段代码? – zekia 2016-05-09 14:22:50

3

OK的元素,仅供参考,这里是我的解决方案迄今:

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()并且有特定的规则来解析标签。仍然打开更好的建议!

1

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

会感兴趣,你将是位:

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

通过所有的元素循环可能是相当昂贵的事情,虽然。 希望它有帮助。

干杯, ISO我强烈建议不使用jQuery这个

1

我可以向你保证,不仅希腊会受到影响。德国Sharp S和土耳其letters i肯定有问题。

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

顺便说一句。允许跨度在翻译中的元素与特定的类也可能是一个好主意 - (虽然它不会真正帮助色盲的人)的方式有人可能会使用即颜色不同的标记文本

3

我使用此PHP函数:

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

你的方法存在的问题是它并不那么简单。先前的2个或前3个字母有一些变化。 – changelog 2012-04-17 12:52:55

+0

我不明白你的意思是说实话。我发布的函数将所有没有压力标记的字母大写,并且其余部分使用str_replace。现在,作为一个希腊人相信我,这是一个服务器端的方法,我发布它,因为你说你正在使用PHP。现在,我已经在几个网站中使用过它,没有任何问题。以前的信件与它无关。既然是我的母语,我会知道它是否会错误地翻译错误! :p P.S. <3葡萄牙! :) – 2012-04-17 13:03:50

+0

我从这里得到了我的解决方案的内部工作原理:https://bug307039.bugzilla.mozilla.org/attachment.cgi?id=588764 我没有使用PHP(我在服务器端使用Ruby ),这是一个演示规则,所以它适合Javascript。这个补丁是否错误?我应该用简单的东西来取代我所拥有的东西吗? – changelog 2012-04-17 13:13:30

11

在这个问题的解决方案实施例3 here

This is an example如上所述,应该在任何浏览器中工作(只测试在火狐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; 
} 
+1

非常有帮助的回答,upvoted! – Elio 2014-04-16 11:10:04

+3

在IE和Chrome中不起作用,对于Chrome,如果您将lang =“el”添加到html标记,它将起作用 – 2014-05-21 14:57:00

1

我喜欢Otovo的回答是最优雅,快速。我当然不会推荐扫描所有元素为text-transform。对于移动设备上的大页面,速度效率不高是显着的。

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

因此,要扩展Otovo的答案,请在body(这是Drupal的默认设置,但任何类似的工作)的地方添加每种语言的i18n-el等独特类。然后运行:

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

Obviouslt与您从CSS文件中记下的选择,用逗号分隔取代.all-relevant-selectors

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

另外,还有一个jQuery插件这个事情叫做jquery-remove-upcase-accents,虽然我还没有评估它。