/**
* Grammatical transformations, needed for inflected languages.
- * Invoked by putting `{{grammar:form|word}}` in a message.
+ * Invoked by putting `{{grammar:case|word}}` in a message.
*
* The rules can be defined in $wgGrammarForms global or computed
* dynamically by overriding this method per language.
* @return {string}
*/
convertGrammar: function ( word, form ) {
- var grammarForms = mw.language.getData( mw.config.get( 'wgUserLanguage' ), 'grammarForms' );
- if ( grammarForms && grammarForms[ form ] ) {
- return grammarForms[ form ][ word ] || word;
+ var userLanguage, forms, transformations,
+ patterns, i, rule, sourcePattern, regexp, replacement;
+
+ userLanguage = mw.config.get( 'wgUserLanguage' );
+
+ forms = mw.language.getData( userLanguage, 'grammarForms' );
+ if ( forms && forms[ form ] ) {
+ return forms[ form ][ word ];
+ }
+
+ transformations = mediaWiki.language.getData( userLanguage, 'grammarTransformations' );
+
+ if ( !( transformations && transformations[ form ] ) ) {
+ return word;
+ }
+
+ patterns = transformations[ form ];
+
+ // Some names of grammar rules are aliases for other rules.
+ // In such cases the value is a string rather than object,
+ // so load the actual rules.
+ if ( typeof patterns === 'string' ) {
+ patterns = transformations[ patterns ];
+ }
+
+ for ( i = 0; i < patterns.length; i++ ) {
+ rule = patterns[ i ];
+ sourcePattern = rule[ 0 ];
+
+ if ( sourcePattern === '@metadata' ) {
+ continue;
+ }
+
+ regexp = new RegExp( sourcePattern );
+ replacement = rule[ 1 ];
+
+ if ( word.match( regexp ) ) {
+ return word.replace( regexp, replacement );
+ }
}
+
return word;
},
setSpecialCharacters: function ( data ) {
this.specialCharacters = data;
+ },
+
+ /**
+ * Formats language tags according the BCP47 standard.
+ * See wfBCP47 for the PHP implementation.
+ *
+ * @param {string} languageTag Well-formed language tag
+ * @return {string}
+ */
+ bcp47: function ( languageTag ) {
+ var formatted,
+ isFirstSegment = true,
+ isPrivate = false,
+ segments = languageTag.split( '-' );
+
+ formatted = segments.map( function ( segment ) {
+ var newSegment;
+
+ // when previous segment is x, it is a private segment and should be lc
+ if ( isPrivate ) {
+ newSegment = segment.toLowerCase();
+ // ISO 3166 country code
+ } else if ( segment.length === 2 && !isFirstSegment ) {
+ newSegment = segment.toUpperCase();
+ // ISO 15924 script code
+ } else if ( segment.length === 4 && !isFirstSegment ) {
+ newSegment = segment.charAt( 0 ).toUpperCase() + segment.substring( 1 ).toLowerCase();
+ // Use lowercase for other cases
+ } else {
+ newSegment = segment.toLowerCase();
+ }
+
+ isPrivate = segment.toLowerCase() === 'x';
+ isFirstSegment = false;
+
+ return newSegment;
+ } );
+
+ return formatted.join( '-' );
}
} );