Index: trunk/extensions/Translate/Translate.php |
— | — | @@ -11,7 +11,7 @@ |
12 | 12 | * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later |
13 | 13 | */ |
14 | 14 | |
15 | | -define( 'TRANSLATE_VERSION', '9 (2008-07-29:1)' ); |
| 15 | +define( 'TRANSLATE_VERSION', '9 (2008-07-29:2)' ); |
16 | 16 | |
17 | 17 | $wgExtensionCredits['specialpage'][] = array( |
18 | 18 | 'name' => 'Translate', |
— | — | @@ -50,8 +50,10 @@ |
51 | 51 | } |
52 | 52 | |
53 | 53 | $wgHooks['ArticleSave'][] = 'TranslateTag::save'; |
| 54 | +$wgHooks['ArticleSaveComplete'][] = 'TranslateTag::purgeAfterSave'; |
54 | 55 | $wgHooks['ParserAfterStrip'][] = 'TranslateTag::tag'; |
55 | 56 | $wgHooks['OutputPageBeforeHTML'][] = 'TranslateTag::addcss'; |
| 57 | +$wgHooks['PageRenderingHash'][] = 'TranslateTag::renderinghash'; |
56 | 58 | |
57 | 59 | $wgJobClasses['FuzzyJob'] = 'FuzzyJob'; |
58 | 60 | $wgAvailableRights[] = 'translate'; |
Index: trunk/extensions/Translate/README |
— | — | @@ -33,6 +33,7 @@ |
34 | 34 | </code> |
35 | 35 | |
36 | 36 | == Changes in version 10 == |
| 37 | +* 2008-07-29:2 support for variables and purging and fallbacks in page translation |
37 | 38 | * 2008-07-29:1 bug fixes and enhanced magic word support for AdvancedTranslate |
38 | 39 | * 2008-07-26:2 proper parents for branched messages |
39 | 40 | * 2008-07-26:1 |
Index: trunk/extensions/Translate/tag/Tag.php |
— | — | @@ -17,7 +17,27 @@ |
18 | 18 | return $obj; |
19 | 19 | } |
20 | 20 | |
| 21 | + public static function renderinghash( &$string ) { |
| 22 | + global $wgRequest, $wgLang; |
| 23 | + $code = $wgRequest->getText( 'pagelang', '' ); |
| 24 | + if ( $code === '' ) $string .= $code; |
| 25 | + return true; |
| 26 | + } |
21 | 27 | |
| 28 | + public static function purgeAfterSave ( |
| 29 | + $article, $user, $text, $summary, $isminor, $_, $_, $flags, $revision |
| 30 | + ) { |
| 31 | + $title = $article->getTitle(); |
| 32 | + $namespace = $title->getNamespace(); |
| 33 | + $key = $title->getDBkey(); |
| 34 | + $group = TranslateUtils::messageKeyToGroup( $namespace, $key ); |
| 35 | + if ( $group instanceof WikiPageMessageGroup ) { |
| 36 | + $group->title->touchLinks(); |
| 37 | + } |
| 38 | + return true; |
| 39 | + } |
| 40 | + |
| 41 | + |
22 | 42 | // Remember to to use TranslateUtils::injectCSS() |
23 | 43 | public static function getHeader( Title $title ) { |
24 | 44 | global $wgLang; |
— | — | @@ -36,10 +56,11 @@ |
37 | 57 | $legendFuzzy = wfMsgNoTrans( 'translate-tag-legend-fuzzy' ); |
38 | 58 | |
39 | 59 | $legend = "[[Category:$cat]]"; |
| 60 | + $legend .= "<div style=\"font-size: x-small\">"; |
40 | 61 | $legend .= "<span class='plainlinks'>[$link $linkDesc]</span> | "; |
41 | 62 | $legend .= "$legendText <span class=\"mw-translate-other\">$legendOther</span>"; |
42 | 63 | $legend .= " <span class=\"mw-translate-fuzzy\">$legendFuzzy</span>"; |
43 | | - $legend .= '<br />This page is translatable using the experimental wiki page translation feature.'; |
| 64 | + $legend .= '<br />This page is translatable using the experimental wiki page translation feature.</div>'; |
44 | 65 | $legend .= "\n----\n"; |
45 | 66 | return $legend; |
46 | 67 | } |
— | — | @@ -59,8 +80,8 @@ |
60 | 81 | |
61 | 82 | |
62 | 83 | $obj = self::getInstance(); |
| 84 | + $obj->title = $parser->getTitle(); |
63 | 85 | |
64 | | - |
65 | 86 | $cb = array( $obj, 'parseMetadata' ); |
66 | 87 | preg_replace_callback( self::METADATA, $cb, $text ); |
67 | 88 | |
— | — | @@ -73,11 +94,19 @@ |
74 | 95 | return true; |
75 | 96 | } |
76 | 97 | |
| 98 | + /** |
| 99 | + * Replaces sections with translations if available, and substitutes variables |
| 100 | + */ |
77 | 101 | public function replaceTags( $data ) { |
78 | | - global $wgLang, $wgTitle; |
| 102 | + global $wgContLang; |
79 | 103 | |
80 | 104 | $input = $data[2]; |
81 | 105 | |
| 106 | + // separate interface language from page language, but default to interface |
| 107 | + global $wgRequest, $wgLang; |
| 108 | + $code = $wgRequest->getText( 'pagelang', '' ); |
| 109 | + if ( $code === '' ) $code = $wgLang->getCode(); |
| 110 | + |
82 | 111 | $regex = $this->getSectionRegex(); |
83 | 112 | $matches = array(); |
84 | 113 | preg_match_all( $regex, $input, $matches, PREG_SET_ORDER ); |
— | — | @@ -85,20 +114,25 @@ |
86 | 115 | $key = $match['id']; |
87 | 116 | $section = $match['section']; |
88 | 117 | |
| 118 | + $translation = null; |
| 119 | + if ( $code !== $wgContLang ) |
| 120 | + $translation = $this->getContents( $this->title, $key, $code ); |
89 | 121 | |
| 122 | + if ( $translation !== null ) { |
| 123 | + $vars = $this->extractVariablesFromSection( $section ); |
| 124 | + foreach( $vars as $v ) { |
| 125 | + list( $search, $replace ) = $v; |
| 126 | + $translation = str_replace( $search, $replace, $translation ); |
| 127 | + } |
90 | 128 | |
91 | | - $key = $this->getTranslationPage( $wgTitle, $key, $wgLang->getCode() ); |
92 | | - $transTitle = Title::newFromText( $key ); |
93 | | - $rev = Revision::loadFromTitle( wfGetDb(), $transTitle ); |
94 | | - if ( $rev ) { |
95 | | - $translation = $rev->getText(); |
96 | | - if ( strpos( $translation, TRANSLATE_FUZZY ) !== false ) { |
97 | | - $translation = str_replace( TRANSLATE_FUZZY, '', $translation ); |
98 | | - $translation = '<div class="mw-translate-fuzzy">' . "\n" . $translation . "\n". '</div>'; |
99 | | - } |
100 | | - $input = str_replace( $section, $translation, $input); |
| 129 | + // Inject the translation in the source by replacing the definition with it |
| 130 | + $input = str_replace( $section, $translation, $input ); |
101 | 131 | } else { |
102 | | - $replace = '<div class="mw-translate-other">' . "\n" . $section . "\n". '</div>'; |
| 132 | + // Do in-place replace of variables, copy to keep $section intact for |
| 133 | + // the replace later |
| 134 | + $replace = $section; |
| 135 | + $this->extractVariablesFromSection( $replace, true ); |
| 136 | + $replace = '<div class="mw-translate-other">' . "\n" . $replace . "\n". '</div>'; |
103 | 137 | $input = str_replace( $section, $replace, $input ); |
104 | 138 | $input = str_replace( $match['holder'], '', $input ); |
105 | 139 | } |
— | — | @@ -111,7 +145,63 @@ |
112 | 146 | return trim($input); |
113 | 147 | |
114 | 148 | } |
| 149 | + |
| 150 | + public function extractVariablesFromSection( &$text, $subst = false ) { |
| 151 | + $regex = '~<tvar(?:\|(?P<id>[^>]+))>(?P<value>.*?)</>~u'; |
| 152 | + $matches = array(); |
| 153 | + // Quick return |
| 154 | + if ( !preg_match_all( $regex, $text, $matches, PREG_SET_ORDER ) ) return array(); |
115 | 155 | |
| 156 | + // Extracting |
| 157 | + $vars = array(); |
| 158 | + foreach ( $matches as $match ) { |
| 159 | + $id = $match['id']; // Default to provided id |
| 160 | + // But if it isn't provided, autonumber them from one onwards |
| 161 | + if ( $id === '' ) $id = count($vars) ? max(array_keys($vars)) + 1 : 1; |
| 162 | + // Index by id, for above to work. |
| 163 | + // Store array or replace, replacement for easy replace afterwards |
| 164 | + $vars[$id] = array( '$' . $id, $match['value'] ); |
| 165 | + // If requested, subst them immediately |
| 166 | + if ( $subst ) $text = str_replace( $match[0], $match['value'], $text ); |
| 167 | + } |
| 168 | + |
| 169 | + return $vars; |
| 170 | + } |
| 171 | + |
| 172 | + /** |
| 173 | + * Fetches translation for a section trying the full fallback chain. Returns |
| 174 | + * null if translation is not found before $wgContLang is hit. This may lead |
| 175 | + * to problems if content language is in a middle of fallback chain. |
| 176 | + */ |
| 177 | + public function getContents( Title $title, $key, $code ) { |
| 178 | + global $wgContLang; |
| 179 | + |
| 180 | + // If we don't get exact hit, we want to know about it |
| 181 | + $targetCode = $code; |
| 182 | + do { |
| 183 | + $sectionPageName = $this->getTranslationPage( $title, $key, $code ); |
| 184 | + $sectionTitle = Title::newFromText( $sectionPageName ); |
| 185 | + $revision = Revision::loadFromTitle( wfGetDb(), $sectionTitle ); |
| 186 | + if ( $revision ) { |
| 187 | + $translation = $revision->getText(); |
| 188 | + if ( strpos( $translation, TRANSLATE_FUZZY ) !== false ) { |
| 189 | + $translation = str_replace( TRANSLATE_FUZZY, '', $translation ); |
| 190 | + $translation = '<div class="mw-translate-fuzzy">' . "\n" . $translation . "\n". '</div>'; |
| 191 | + } |
| 192 | + if ( $code !== $targetCode ) { |
| 193 | + $translation = '<div class="mw-translate-other">' . "\n" . $translation . "\n". '</div>'; |
| 194 | + } |
| 195 | + |
| 196 | + return $translation; |
| 197 | + } |
| 198 | + |
| 199 | + $code = Language::getFallbackFor( $code ); |
| 200 | + |
| 201 | + } while( $code && $code !== $wgContLang ); |
| 202 | + |
| 203 | + return null; |
| 204 | + } |
| 205 | + |
116 | 206 | const PATTERN_SECTION = '~(<!--T:[^-]+-->)(.*?)<!--T;-->~us'; |
117 | 207 | const PATTERN_PLACEHOLDER = '~<!--T:[^-/]+/?-->~us'; |
118 | 208 | |