2012-02-24 31 views
12

Tôi đã viết một ứng dụng web có chứa dịch trong một số ngôn ngữHy Lạp và text-transform: (. Một trong số họ là tiếng Hy Lạp) chữ hoa

Khi hiển thị một bản dịch nhất định trên tiêu đề, nguyên tắc thiết kế là các văn bản được cho là dựa trên, mà trong bất kỳ ngôn ngữ nào khác trên thế giới là tốt, nhưng khi nói đến tiếng Hy Lạp, các trình duyệt không biết phải làm gì với các dấu (xem this) để chúng hiển thị chuỗi trên không đúng.

Từ bản vá đó tôi đã liên kết ở trên, tôi đã chuyển nó thành Javascript, chạy một số trường hợp sử dụng chống lại nó và hoạt động. Bây giờ tất cả những gì tôi phải làm là:

Nếu không thêm một lớp uppercase vào mọi phần tử cần được viết hoa (có một số ít), tôi có thể truy vấn DOM bằng thuộc tính được tính toán không? I E. cho tôi tất cả những yếu tố đó có một tính text-transform: uppercase

Trả lời

10

tôi mạnh mẽ đề nghị không sử dụng jQuery cho việc này. Thay vào đó, hãy thực hiện điều này:

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

Đã thử nghiệm với 10.000 phần tử, trong đó 2.500 có văn bản "chữ hoa" chuyển đổi.

jQuery processed in 595ms
JS processed in 60ms

Vì vậy, JavaScript nhanh hơn khoảng 10 lần so với jQuery.

EDIT: thử nghiệm khác, lần này với 100.000 yếu tố:

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

+0

Thật tuyệt vời! Sẽ cập nhật :-) – changelog

+0

nơi tôi nên đặt mã này? – zekia

3

OK, chỉ để tham khảo, đây là giải pháp của tôi cho đến nay:

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) 

Đây là một sự thích nghi script cà phê từ các bản vá được cung cấp trong các lỗi trên.

Dưới đây là những gì tôi làm sau một cái nhìn được hiển thị:

# 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()) 
) 

Đây không phải là rất tốt đẹp, bởi bất kỳ căng của trí tưởng tượng, nhưng nó hoạt động.

Hai điều tôi không nên làm ở đây và có thể thay đổi: hijack toUpperCase() và có các quy tắc cụ thể không phân tích cú pháp thẻ. Vẫn mở để gợi ý tốt hơn!

1

Điều này sẽ không giúp ích gì với các ký tự Hy Lạp, nhưng tôi tò mò về việc tìm tất cả các phần tử có thuộc tính css đã cho. tôi thiết lập: http://jsfiddle.net/pQfUv/1/

Các bit sẽ quan tâm đến bạn sẽ là:

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

Looping qua tất cả các yếu tố có lẽ là một điều khá tốn kém để làm, mặc dù. Hy vọng điều đó sẽ hữu ích.

Chúc mừng, iso

1

tôi có thể đảm bảo với bạn rằng, không chỉ Hy Lạp bị ảnh hưởng. Bạn chắc chắn đang gặp sự cố với tiếng Đức Sharp S và Thổ Nhĩ Kỳ letters i.

Tôi không thực sự chắc chắn mục đích của việc sử dụng các phép biến đổi này là gì, nhưng xin lưu ý rằng nhiều ngôn ngữ được viết bằng các tập lệnh không có khái niệm chữ hoa và chữ thường. Nếu bạn sử dụng điều này để nhấn mạnh, tôi đề nghị loại bỏ tất cả các biến đổi hoàn toàn và chỉ cần viết một phần của văn bản với trường hợp thích hợp. Bằng cách đó, người dịch có thể quyết định cách họ nhấn mạnh từ hoặc câu.

BTW. Việc cho phép các phần tử span trong bản dịch với một lớp cụ thể cũng có thể là một ý tưởng hay - theo cách đó, ai đó có thể sử dụng màu sắc để đánh dấu văn bản khác nhau (mặc dù nó sẽ không thực sự giúp người mù màu.)

3

Tôi sử dụng chức năng PHP này:

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

Vấn đề với cách tiếp cận của bạn là nó không đơn giản. Một số phép biến đổi tách trên hai chữ cái trước đó trước đó hoặc 3 chữ cái trước đó. – changelog

+0

Tôi không hiểu ý bạn là trung thực.Hàm tôi đã viết hoa tất cả các chữ cái không có dấu nhấn và bạn sử dụng str_replace cho phần còn lại. Bây giờ, như một người Hy Lạp tin tưởng tôi, đó là một cách tiếp cận phía máy chủ và tôi đăng nó kể từ khi bạn nói rằng bạn đang sử dụng PHP. Bây giờ, tôi đã sử dụng nó trong một số trang web mà không có bất kỳ vấn đề bao giờ hết. Các chữ cái trước không liên quan gì đến nó. Và vì đó là ngôn ngữ mẹ đẻ của tôi, tôi sẽ biết nếu nó sẽ dịch một cái gì đó sai trái! : p P.S. <3 Bồ Đào Nha! :) –

+0

Tôi nhận được các hoạt động bên trong của giải pháp của tôi từ đây: https://bug307039.bugzilla.mozilla.org/attachment.cgi?id=588764 Tôi không sử dụng PHP (Tôi sử dụng Ruby ở phía máy chủ) và đây là quy tắc trình bày, vì vậy nó phù hợp với Javascript. Bản vá này có sai không? Tôi có nên thay thế những gì tôi có bằng một cái gì đó đơn giản hơn? – changelog

11

Các giải pháp trong vấn đề này được mô tả ở trên ví dụ 3 here

This is an example nên hoạt động trên mọi trình duyệt (chỉ được thử nghiệm tại 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; 
} 

Bạn cũng có thể sử dụng thuộc tính lang ở mức độ cao hơn, ví dụ ở thẻ cơ thể.

HTML:

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

CSS:

#withlang{ 
    text-transform: uppercase; 
} 

#withlangsmall{ 
    font-variant: small-caps; 
} 
+1

Câu trả lời rất hữu ích, được bình chọn! – Elio

+3

Không hoạt động trong IE và Chrome, đối với Chrome, nó sẽ hoạt động nếu bạn thêm lang = "el" vào thẻ html –

1

Tôi thích câu trả lời của Otovo là thanh lịch và nhanh chóng nhất. Tôi chắc chắn sẽ không khuyên bạn quét tất cả các phần tử cho text-transform. Đối với các trang lớn trên thiết bị di động, tốc độ không hiệu quả là đáng chú ý.

Vì vậy, tôi khuyên bạn nên chỉ cần ghi lại tất cả các bộ chọn với text-transform từ các tệp CSS. Điều này có thể xảy ra đối với hầu hết các trường hợp. Sau đó, sử dụng jQuery trực tiếp trên các bộ chọn đó.

Vì vậy, để mở rộng câu trả lời của Otovo, hãy thêm một lớp duy nhất như i18n-el cho mỗi ngôn ngữ ở một nơi nào đó như trong body (đây là mặc định cho Drupal nhưng mọi thứ tương tự sẽ hoạt động). Sau đó chạy:

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

Xóa thay thế .all-relevant-selectors bằng bộ chọn mà bạn đã ghi lại từ tệp CSS, được phân tách bằng dấu phẩy.

Ngoài ra, nó là đáng nói rằng công trình này chỉ dành cho text-transform: uppercase và không font-variant: small-caps dành cho Chrome 39.

Ngoài ra, có một plugin jQuery cho vấn đề này được gọi là jquery-remove-upcase-accents, mặc dù tôi đã không được đánh giá điều đó chút nào.

Các vấn đề liên quan