Index: branches/jsgrammar/tests/qunit/QUnitTestResources.php |
— | — | @@ -25,8 +25,8 @@ |
26 | 26 | 'tests/qunit/suites/resources/mediawiki/mediawiki.user.test.js', |
27 | 27 | 'tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js', |
28 | 28 | 'tests/qunit/suites/resources/mediawiki.special/mediawiki.special.recentchanges.test.js', |
29 | | - "tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js", |
30 | | - "tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js", |
| 29 | + 'tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js', |
| 30 | + 'tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js', |
31 | 31 | ), |
32 | 32 | 'dependencies' => array( |
33 | 33 | 'jquery.autoEllipsis', |
— | — | @@ -43,7 +43,7 @@ |
44 | 44 | 'jquery.tablesorter', |
45 | 45 | 'jquery.textSelection', |
46 | 46 | 'mediawiki', |
47 | | - 'language', |
| 47 | + 'mediawiki.language.data', |
48 | 48 | 'mediawiki.Title', |
49 | 49 | 'mediawiki.user', |
50 | 50 | 'mediawiki.util', |
Index: branches/jsgrammar/includes/resourceloader/ResourceLoaderLanguageModule.php |
— | — | @@ -1,78 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * This program is free software; you can redistribute it and/or modify |
5 | | - * it under the terms of the GNU General Public License as published by |
6 | | - * the Free Software Foundation; either version 2 of the License, or |
7 | | - * (at your option) any later version. |
8 | | - * |
9 | | - * This program is distributed in the hope that it will be useful, |
10 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | - * GNU General Public License for more details. |
13 | | - * |
14 | | - * You should have received a copy of the GNU General Public License along |
15 | | - * with this program; if not, write to the Free Software Foundation, Inc., |
16 | | - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
17 | | - * http://www.gnu.org/copyleft/gpl.html |
18 | | - * |
19 | | - * @file |
20 | | - * @author Santhosh Thottingal |
21 | | - * @author Timo Tijhof |
22 | | - */ |
23 | | - |
24 | | -/** |
25 | | - * ResourceLoader module for generating language specific scripts/css. |
26 | | - */ |
27 | | -class ResourceLoaderLanguageModule extends ResourceLoaderModule { |
28 | | - |
29 | | - /** |
30 | | - * Get the grammer forms for the site content language. |
31 | | - * |
32 | | - * @return Array |
33 | | - */ |
34 | | - protected function getSiteLangGrammarForms() { |
35 | | - global $wgContLang; |
36 | | - return $wgContLang->getGrammarForms(); |
37 | | - } |
38 | | - /** |
39 | | - * @param $context ResourceLoaderContext |
40 | | - * @return string Javascript code |
41 | | - */ |
42 | | - public function getScript( ResourceLoaderContext $context ) { |
43 | | - global $wgContLang; |
44 | | - $code = Xml::encodeJsVar( $wgContLang->getCode() ); |
45 | | - $forms = Xml::encodeJsVar( $this->getSiteLangGrammarForms() ); |
46 | | - |
47 | | - $js = |
48 | | -<<<JAVASCRIPT |
49 | | -var langCode = $code, |
50 | | -langData = mw.language.data; |
51 | | -if ( langData[langCode] === undefined ) { |
52 | | - langData[langCode] = new mw.Map(); |
53 | | -} |
54 | | -langData[langCode].set( "grammarForms", $forms ); |
55 | | -JAVASCRIPT; |
56 | | - |
57 | | - return $js; |
58 | | - } |
59 | | - /** |
60 | | - * @param $context ResourceLoaderContext |
61 | | - * @return array|int|Mixed |
62 | | - */ |
63 | | - public function getModifiedTime( ResourceLoaderContext $context ) { |
64 | | - global $wgCacheEpoch; |
65 | | - /* |
66 | | - global $wgContLang, $wgCacheEpoch; |
67 | | - return max( $wgCacheEpoch, $wgContLang->getLastModified() ); |
68 | | - */ |
69 | | - |
70 | | - return $wgCacheEpoch; |
71 | | - } |
72 | | - /** |
73 | | - * @return array |
74 | | - */ |
75 | | - public function getDependencies() { |
76 | | - return array( 'mediawiki.language' ); |
77 | | - } |
78 | | -} |
79 | | - |
Index: branches/jsgrammar/includes/resourceloader/ResourceLoaderLanguageDataModule.php |
— | — | @@ -0,0 +1,86 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * This program is free software; you can redistribute it and/or modify |
| 5 | + * it under the terms of the GNU General Public License as published by |
| 6 | + * the Free Software Foundation; either version 2 of the License, or |
| 7 | + * (at your option) any later version. |
| 8 | + * |
| 9 | + * This program is distributed in the hope that it will be useful, |
| 10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | + * GNU General Public License for more details. |
| 13 | + * |
| 14 | + * You should have received a copy of the GNU General Public License along |
| 15 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 16 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 17 | + * http://www.gnu.org/copyleft/gpl.html |
| 18 | + * |
| 19 | + * @file |
| 20 | + * @author Santhosh Thottingal |
| 21 | + * @author Timo Tijhof |
| 22 | + */ |
| 23 | + |
| 24 | +/** |
| 25 | + * ResourceLoader module for populating language specific data. |
| 26 | + */ |
| 27 | +class ResourceLoaderLanguageDataModule extends ResourceLoaderModule { |
| 28 | + |
| 29 | + /** |
| 30 | + * Get the grammer forms for the site content language. |
| 31 | + * |
| 32 | + * @return array |
| 33 | + */ |
| 34 | + protected function getSiteLangGrammarForms() { |
| 35 | + global $wgContLang; |
| 36 | + return $wgContLang->getGrammarForms(); |
| 37 | + } |
| 38 | + |
| 39 | + /** |
| 40 | + * @param $context ResourceLoaderContext |
| 41 | + * @return string Javascript code |
| 42 | + */ |
| 43 | + public function getScript( ResourceLoaderContext $context ) { |
| 44 | + global $wgContLang; |
| 45 | + |
| 46 | + return Xml::encodeJsCall( 'mw.language.setData', array( |
| 47 | + $wgContLang->getCode(), |
| 48 | + $this->getSiteLangGrammarForms() |
| 49 | + ) ); |
| 50 | + } |
| 51 | + |
| 52 | + /** |
| 53 | + * @param $context ResourceLoaderContext |
| 54 | + * @return array|int|Mixed |
| 55 | + */ |
| 56 | + public function getModifiedTime( ResourceLoaderContext $context ) { |
| 57 | + global $wgCacheEpoch; |
| 58 | + |
| 59 | + /** |
| 60 | + * @todo FIXME: This needs to change whenever the array created by |
| 61 | + * $wgContLang->getGrammarForms() changes. Which gets its data from |
| 62 | + * $wgGrammarForms, which (for standard installations) comes from LocalSettings |
| 63 | + * and $wgCacheEpoch would cover that. However there's two three problems: |
| 64 | + * |
| 65 | + * 1) $wgCacheEpoch is not meant for this use. |
| 66 | + * 2) If $wgInvalidateCacheOnLocalSettingsChange is set to false, |
| 67 | + * $wgCacheEpoch will not be raised if LocalSettings is modified (see #1). |
| 68 | + * 3) $wgGrammarForms can be set from anywhere. For example on WMF it is set |
| 69 | + * by the WikimediaMessages extension. Other farms might set it form |
| 70 | + * their 'CommonSettings.php'-like file or something (see #1). |
| 71 | + * |
| 72 | + * Possible solutions: |
| 73 | + * - Store grammarforms in the language object cache instead of directly |
| 74 | + * from the global everytime. Then use $wgContLang->getLastModified(). |
| 75 | + * - Somehow monitor the value of $wgGrammarForms. |
| 76 | + */ |
| 77 | + |
| 78 | + return $wgCacheEpoch; |
| 79 | + } |
| 80 | + |
| 81 | + /** |
| 82 | + * @return array |
| 83 | + */ |
| 84 | + public function getDependencies() { |
| 85 | + return array( 'mediawiki.language' ); |
| 86 | + } |
| 87 | +} |
Property changes on: branches/jsgrammar/includes/resourceloader/ResourceLoaderLanguageDataModule.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 88 | + native |
Index: branches/jsgrammar/includes/AutoLoader.php |
— | — | @@ -732,7 +732,7 @@ |
733 | 733 | 'ResourceLoaderUserModule' => 'includes/resourceloader/ResourceLoaderUserModule.php', |
734 | 734 | 'ResourceLoaderUserOptionsModule' => 'includes/resourceloader/ResourceLoaderUserOptionsModule.php', |
735 | 735 | 'ResourceLoaderUserTokensModule' => 'includes/resourceloader/ResourceLoaderUserTokensModule.php', |
736 | | - 'ResourceLoaderLanguageModule' => 'includes/resourceloader/ResourceLoaderLanguageModule.php', |
| 736 | + 'ResourceLoaderLanguageDataModule' => 'includes/resourceloader/ResourceLoaderLanguageDataModule.php', |
737 | 737 | 'ResourceLoaderWikiModule' => 'includes/resourceloader/ResourceLoaderWikiModule.php', |
738 | 738 | |
739 | 739 | # includes/revisiondelete |
Index: branches/jsgrammar/resources/Resources.php |
— | — | @@ -12,8 +12,8 @@ |
13 | 13 | 'user.options' => array( 'class' => 'ResourceLoaderUserOptionsModule' ), |
14 | 14 | 'user.cssprefs' => array( 'class' => 'ResourceLoaderUserCSSPrefsModule' ), |
15 | 15 | 'user.tokens' => array( 'class' => 'ResourceLoaderUserTokensModule' ), |
16 | | - 'language' => array( 'class' => 'ResourceLoaderLanguageModule' ), |
17 | 16 | 'filepage' => array( 'class' => 'ResourceLoaderFilePageModule' ), |
| 17 | + 'mediawiki.language.data' => array( 'class' => 'ResourceLoaderLanguageDataModule' ), |
18 | 18 | |
19 | 19 | /* Skins */ |
20 | 20 | |
Index: branches/jsgrammar/resources/mediawiki.language/mediawiki.language.js |
— | — | @@ -5,48 +5,78 @@ |
6 | 6 | * Language.php in MediaWiki. This object contains methods for loading and |
7 | 7 | * transforming message text. |
8 | 8 | */ |
9 | | -( function( $, mw ) { |
| 9 | +( function ( $, mw ) { |
10 | 10 | |
11 | | -mw.language = { |
| 11 | +var language = { |
12 | 12 | /** |
13 | | - * @var data {Object} Language related data |
14 | | - * Keyed by language, contains instances of mw.Map |
15 | | - * @example Set data |
16 | | - * <code> |
17 | | - * var langCode = 'nl'; |
18 | | - * var langData = mw.language.data; |
19 | | - * if ( langData[langCode] === undefined ) { |
20 | | - * langData[langCode] = new mw.Map(); |
21 | | - * } |
22 | | - * langData[langCode].set( .. ); // Will override, extend or create the data |
23 | | - * </code> |
24 | | - * @example Get data |
25 | | - * <code> |
26 | | - * var grammarForms = mw.language.data[langCode].get( 'grammarForms' ); |
27 | | - * </code> |
28 | | - */ |
| 13 | + * @var data {Object} Language related data (keyed by language, |
| 14 | + * contains instances of mw.Map). |
| 15 | + * @example Set data |
| 16 | + * <code> |
| 17 | + * // Override, extend or create the language data object of 'nl' |
| 18 | + * mw.language.setData( 'nl', 'myKey', 'My value' ); |
| 19 | + * </code> |
| 20 | + * @example Get GrammarForms data for language 'nl': |
| 21 | + * <code> |
| 22 | + * var grammarForms = mw.language.getData( 'nl', 'grammarForms' ); |
| 23 | + * </code> |
| 24 | + */ |
29 | 25 | data: {}, |
| 26 | + |
30 | 27 | /** |
| 28 | + * Convenience method for retreiving language data by language code and data key, |
| 29 | + * covering for the potential inexistance of a data object for this langiage. |
| 30 | + * @param langCode {String} |
| 31 | + * @param dataKey {String} |
| 32 | + * @return {mixed} Value stored in the mw.Map (or undefined if there is no map for |
| 33 | + the specified langCode). |
| 34 | + */ |
| 35 | + getData: function ( langCode, dataKey ) { |
| 36 | + var langData = language.data; |
| 37 | + if ( langData[langCode] instanceof mw.Map ) { |
| 38 | + return langData[langCode].get( dataKey ); |
| 39 | + } |
| 40 | + return undefined; |
| 41 | + }, |
| 42 | + |
| 43 | + /** |
| 44 | + * Convenience method for setting language data by language code and data key. |
| 45 | + * Creates a data object if there isn't one for the specified language already. |
| 46 | + * @param langCode {String} |
| 47 | + * @param dataKey {String} |
| 48 | + * @param value {mixed} |
| 49 | + */ |
| 50 | + setData: function ( langCode, dataKey, value ) { |
| 51 | + var langData = language.data; |
| 52 | + if ( !( langData[langCode] instanceof mw.Map ) ) { |
| 53 | + langData[langCode] = new mw.Map(); |
| 54 | + } |
| 55 | + langData[langCode].set( dataKey, value ); |
| 56 | + }, |
| 57 | + |
| 58 | + /** |
31 | 59 | * Process the PLURAL template substitution |
32 | 60 | * |
33 | | - * @param {object} template Template object |
| 61 | + * @param template {Object} Template object |
34 | 62 | * @format template |
35 | | - * { |
36 | | - * 'title': [title of template], |
37 | | - * 'parameters': [template parameters] |
38 | | - * } |
| 63 | + * { |
| 64 | + * title: [title of template], |
| 65 | + * parameters: [template parameters] |
| 66 | + * } |
39 | 67 | * @example {{Template:title|params}} |
40 | 68 | */ |
41 | | - procPLURAL: function( template ) { |
42 | | - if ( template.title && template.parameters && mw.language.convertPlural ) { |
| 69 | + procPLURAL: function ( template ) { |
| 70 | + var count; |
| 71 | + |
| 72 | + if ( template.title && template.parameters ) { |
43 | 73 | // Check if we have forms to replace |
44 | 74 | if ( template.parameters.length === 0 ) { |
45 | 75 | return ''; |
46 | 76 | } |
47 | 77 | // Restore the count into a Number ( if it got converted earlier ) |
48 | | - var count = mw.language.convertNumber( template.title, true ); |
| 78 | + count = language.convertNumber( template.title, true ); |
49 | 79 | // Do convertPlural call |
50 | | - return mw.language.convertPlural( parseInt( count, 10 ), template.parameters ); |
| 80 | + return language.convertPlural( parseInt( count, 10 ), template.parameters ); |
51 | 81 | } |
52 | 82 | // Could not process plural return first form or nothing |
53 | 83 | if ( template.parameters[0] ) { |
— | — | @@ -54,25 +84,27 @@ |
55 | 85 | } |
56 | 86 | return ''; |
57 | 87 | }, |
| 88 | + |
58 | 89 | /** |
59 | 90 | * Plural form transformations, needed for some languages. |
60 | 91 | * |
61 | | - * @param count integer Non-localized quantifier |
62 | | - * @param forms array List of plural forms |
63 | | - * @return string Correct form for quantifier in this language |
| 92 | + * @param count {Number} Non-localized quantifier |
| 93 | + * @param forms {Array} List of plural forms |
| 94 | + * @return {String} Correct form for quantifier in this language |
64 | 95 | */ |
65 | | - convertPlural: function( count, forms ){ |
66 | | - if ( !forms || forms.length === 0 ) { |
| 96 | + convertPlural: function ( count, forms ){ |
| 97 | + if ( !$.isArray( forms ) || forms.length === 0 ) { |
67 | 98 | return ''; |
68 | 99 | } |
69 | | - return ( parseInt( count, 10 ) == 1 ) ? forms[0] : forms[1]; |
| 100 | + return ( parseInt( count, 10 ) === 1 ) ? forms[0] : forms[1]; |
70 | 101 | }, |
| 102 | + |
71 | 103 | /** |
72 | 104 | * Pads an array to a specific length by copying the last one element. |
73 | 105 | * |
74 | | - * @param forms array Number of forms given to convertPlural |
75 | | - * @param count integer Number of forms required |
76 | | - * @return array Padded array of forms |
| 106 | + * @param forms {Array} List of forms given to convertPlural |
| 107 | + * @param count {Number} Number of forms required |
| 108 | + * @return {Array} Padded array of forms |
77 | 109 | */ |
78 | 110 | preConvertPlural: function( forms, count ) { |
79 | 111 | while ( forms.length < count ) { |
— | — | @@ -80,32 +112,35 @@ |
81 | 113 | } |
82 | 114 | return forms; |
83 | 115 | }, |
| 116 | + |
84 | 117 | /** |
85 | 118 | * Converts a number using digitTransformTable. |
86 | 119 | * |
87 | | - * @param {num} number Value to be converted |
88 | | - * @param {boolean} integer Convert the return value to an integer |
| 120 | + * @param num {Number} Value to be converted |
| 121 | + * @param integer {Boolean} Convert the return value to an integer |
89 | 122 | */ |
90 | 123 | convertNumber: function( num, integer ) { |
91 | | - if ( !mw.language.digitTransformTable ) { |
| 124 | + var transformTable, tmp, i, numberString, convertedNumber; |
| 125 | + |
| 126 | + if ( !language.digitTransformTable ) { |
92 | 127 | return num; |
93 | 128 | } |
94 | 129 | // Set the target Transform table: |
95 | | - var transformTable = mw.language.digitTransformTable; |
| 130 | + transformTable = language.digitTransformTable; |
96 | 131 | // Check if the "restore" to Latin number flag is set: |
97 | 132 | if ( integer ) { |
98 | | - if ( parseInt( num, 10 ) == num ) { |
| 133 | + if ( parseInt( num, 10 ) === num ) { |
99 | 134 | return num; |
100 | 135 | } |
101 | | - var tmp = []; |
102 | | - for ( var i in transformTable ) { |
| 136 | + tmp = []; |
| 137 | + for ( i in transformTable ) { |
103 | 138 | tmp[ transformTable[ i ] ] = i; |
104 | 139 | } |
105 | 140 | transformTable = tmp; |
106 | 141 | } |
107 | | - var numberString = '' + num; |
108 | | - var convertedNumber = ''; |
109 | | - for ( var i = 0; i < numberString.length; i++ ) { |
| 142 | + numberString = String( num ); |
| 143 | + convertedNumber = ''; |
| 144 | + for ( i = 0; i < numberString.length; i++ ) { |
110 | 145 | if ( transformTable[ numberString[i] ] ) { |
111 | 146 | convertedNumber += transformTable[numberString[i]]; |
112 | 147 | } else { |
— | — | @@ -114,6 +149,7 @@ |
115 | 150 | } |
116 | 151 | return integer ? parseInt( convertedNumber, 10 ) : convertedNumber; |
117 | 152 | }, |
| 153 | + |
118 | 154 | /** |
119 | 155 | * Provides an alternative text depending on specified gender. |
120 | 156 | * Usage {{gender:[gender|user object]|masculine|feminine|neutral}}. |
— | — | @@ -121,16 +157,17 @@ |
122 | 158 | * |
123 | 159 | * These details may be overriden per language. |
124 | 160 | * |
125 | | - * @param gender string male, female, or anything else for neutral. |
126 | | - * @param forms array List of gender forms |
| 161 | + * @param gender {String} Male, female, or anything else for neutral. |
| 162 | + * @param forms {Array} List of gender forms |
127 | 163 | * |
128 | | - * @return string |
| 164 | + * @return {String} |
129 | 165 | */ |
130 | | - gender: function( gender, forms ) { |
131 | | - if ( !forms || forms.length === 0 ) { |
| 166 | + |
| 167 | + gender: function ( gender, forms ) { |
| 168 | + if ( !$.isArray( forms ) || forms.length === 0 ) { |
132 | 169 | return ''; |
133 | 170 | } |
134 | | - forms = mw.language.preConvertPlural( forms, 2 ); |
| 171 | + forms = language.preConvertPlural( forms, 2 ); |
135 | 172 | if ( gender === 'male' ) { |
136 | 173 | return forms[0]; |
137 | 174 | } |
— | — | @@ -139,24 +176,31 @@ |
140 | 177 | } |
141 | 178 | return ( forms.length === 3 ) ? forms[2] : forms[0]; |
142 | 179 | }, |
| 180 | + |
143 | 181 | /** |
144 | 182 | * Grammatical transformations, needed for inflected languages. |
145 | 183 | * Invoked by putting {{grammar:form|word}} in a message. |
146 | | - * The rules can be defined in wgGrammarForms global or grammar |
| 184 | + * The rules can be defined in $wgGrammarForms global or grammar |
147 | 185 | * forms can be computed dynamically by overriding this method per language |
148 | 186 | * |
149 | | - * @param word string |
150 | | - * @param form string |
151 | | - * @return string |
| 187 | + * @param word {String} |
| 188 | + * @param form {String} |
| 189 | + * @return {String} |
152 | 190 | */ |
153 | | - convertGrammar: function( word, form ) { |
154 | | - var grammarForms = mw.language.data[mw.config.get( 'wgContentLanguage' )].get( 'grammarForms' ); |
| 191 | + convertGrammar: function ( word, form ) { |
| 192 | + var grammarForms = language.getData( mw.config.get( 'wgContentLanguage' ), 'grammarForms' ); |
155 | 193 | if ( grammarForms && grammarForms[form] ) { |
156 | 194 | return grammarForms[form][word] || word; |
157 | 195 | } |
158 | 196 | return word; |
159 | 197 | }, |
160 | | - // Digit Transform Table, populated by language classes where applicable |
| 198 | + |
| 199 | + /** |
| 200 | + * @var {Object} Digit Transform Table, populated by language classes where applicable. |
| 201 | + */ |
161 | 202 | digitTransformTable: null |
162 | 203 | }; |
163 | | -} )( jQuery, mediaWiki ); |
| 204 | + |
| 205 | +mw.language = language; |
| 206 | + |
| 207 | +}( jQuery, mediaWiki ) ); |