| [ Index ] |
PHP Cross Reference of GlotPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Handles translation warnings 4 */ 5 6 class GP_Translation_Warnings { 7 var $callbacks = array(); 8 9 function add( $id, $callback ) { 10 $this->callbacks[$id] = $callback; 11 } 12 13 function remove( $id ) { 14 unset( $this->callbacks[$id] ); 15 } 16 17 function has( $id ) { 18 return isset( $this->callbacks[$id] ); 19 } 20 21 function check( $singular, $plural, $translations, $locale ) { 22 $problems = array(); 23 foreach( $translations as $translation_index => $translation ) { 24 if ( !$translation ) continue; 25 $skip = array( 'singular' => false, 'plural' => false ); 26 if ( !is_null( $plural ) ) { 27 $numbers_for_index = $locale->numbers_for_index( $translation_index ); 28 if ( $numbers_for_index == array(1) ) { 29 $skip['plural'] = true; 30 } 31 if ( !in_array( 1, $numbers_for_index ) ) { 32 $skip['singular'] = true; 33 } 34 if ( $locale->nplurals == 1 ) { 35 $skip['singular'] = true; 36 } 37 } 38 foreach( $this->callbacks as $callback_id => $callback ) { 39 if ( !$skip['singular']) { 40 $singular_test = call_user_func( $callback, $singular, $translation, $locale ); 41 if ( true !== $singular_test ) { 42 $problems[$translation_index][$callback_id] = $singular_test; 43 } 44 } 45 if ( !is_null( $plural ) && !$skip['plural'] ) { 46 $plural_test = call_user_func( $callback, $plural, $translation, $locale ); 47 if ( true !== $plural_test ) { 48 $problems[$translation_index][$callback_id] = $plural_test; 49 } 50 } 51 } 52 } 53 return empty($problems)? null : $problems; 54 } 55 } 56 57 class GP_Builtin_Translation_Warnings { 58 59 var $length_lower_bound = 0.2; 60 var $length_upper_bound = 5.0; 61 var $length_exclude_languages = array('ja', 'zh', 'zh-hk', 'zh-cn', 'zh-sg', 'zh-tw'); 62 63 function warning_length( $original, $translation, $locale ) { 64 if ( in_array( $locale->slug, $this->length_exclude_languages ) ) { 65 return true; 66 } 67 if ( gp_startswith( $original, 'number_format_' ) ) { 68 return true; 69 } 70 $len_src = gp_strlen( $original ); 71 $len_trans = gp_strlen( $translation ); 72 if ( !( $this->length_lower_bound*$len_src < $len_trans && $len_trans < $this->length_upper_bound*$len_src ) && 73 ( !gp_in( '_abbreviation', $original ) && !gp_in( '_initial', $original ) ) ) { 74 return __('Lengths of source and translation differ too much.'); 75 } 76 return true; 77 } 78 79 function warning_tags( $original, $translation, $locale ) { 80 $tag_pattern = "(<[^>]*>)"; 81 $tag_re = "/$tag_pattern/Us"; 82 $original_parts = preg_split($tag_re, $original, -1, PREG_SPLIT_DELIM_CAPTURE); 83 $translation_parts = preg_split($tag_re, $translation, -1, PREG_SPLIT_DELIM_CAPTURE); 84 if ( count( $original_parts) > count( $translation_parts ) ) { 85 return __('Missing tags from translation.'); 86 } 87 if ( count( $original_parts) < count( $translation_parts ) ) { 88 return __('Too many tags in translation.'); 89 } 90 foreach( gp_array_zip( $original_parts, $translation_parts ) as $tags ) { 91 list( $original_tag, $translation_tag ) = $tags; 92 $expected_error_msg = "Expected $original_tag, got $translation_tag."; 93 $original_is_tag = preg_match( "/^$tag_pattern$/", $original_tag ); 94 $translation_is_tag = preg_match( "/^$tag_pattern$/", $translation_tag ); 95 // translations should never need a quote in their title attribute 96 if ( $original_is_tag && $translation_is_tag && $original_tag != $translation_tag ) { 97 // we allow translations to have a different title tag 98 $title_re_single = '\s*title=\'[^\']+\'\s*'; 99 $title_re = '%'.$title_re_single.'|'.str_replace( "'", '"', $title_re_single ).'%'; 100 $original_tag = preg_replace( $title_re, '', $original_tag ); 101 $translation_tag = preg_replace( $title_re, '', $translation_tag ); 102 if ( $original_tag != $translation_tag ) { 103 return $expected_error_msg; 104 } 105 } 106 } 107 return true; 108 } 109 110 function warning_placeholders( $original, $translation, $locale ) { 111 $placeholders_re = apply_filters( 'warning_placeholders_re', '%[a-z]*|%[A-Z]+|%\d+\$(?:s|d)' ); 112 113 $original_counts = $this->_placeholders_counts( $original, $placeholders_re ); 114 $translation_counts = $this->_placeholders_counts( $translation, $placeholders_re ); 115 $all_placeholders = array_unique( array_merge( array_keys( $original_counts ), array_keys( $translation_counts ) ) ); 116 foreach( $all_placeholders as $placeholder ) { 117 $original_count = gp_array_get( $original_counts, $placeholder, 0 ); 118 $translation_count = gp_array_get( $translation_counts, $placeholder, 0 ); 119 if ( $original_count > $translation_count ) { 120 return sprintf(__('Missing %s placeholder in translation.'), $placeholder); 121 } 122 if ( $original_count < $translation_count ) { 123 return sprintf(__('Extra %s placeholder in translation.'), $placeholder); 124 } 125 } 126 return true; 127 } 128 129 function _placeholders_counts( $string, $re ) { 130 $counts = array(); 131 preg_match_all( "/$re/", $string, $matches ); 132 foreach( $matches[0] as $match ) { 133 $counts[$match] = gp_array_get( $counts, $match, 0) + 1; 134 } 135 return $counts; 136 } 137 138 function warning_both_begin_end_on_newlines( $original, $translation, $locale ) { 139 if ( gp_endswith( $original, "\n" ) xor gp_endswith( $translation, "\n" ) ) { 140 return __('Original and translation should both end on newline.'); 141 } 142 if ( gp_startswith( $original, "\n" ) xor gp_startswith( $translation, "\n" ) ) { 143 return __('Original and translation should both begin on newline.'); 144 } 145 return true; 146 } 147 148 /** 149 * Adds all methods starting with warning_ to $translation_warnings 150 */ 151 function add_all( &$translation_warnings ) { 152 $warnigs = array_filter( get_class_methods( get_class( $this ) ), create_function( '$f', 'return gp_startswith($f, "warning_");' ) ); 153 foreach( $warnigs as $warning ) { 154 $translation_warnings->add( str_replace( 'warning_', '', $warning ), array( &$this, $warning ) ); 155 } 156 } 157 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu May 24 03:59:35 2012 | Hosted by follow the white rabbit. |