diff --git a/includes/CommentParser.php b/includes/CommentParser.php index b7be3f8ff..a618ddd82 100644 --- a/includes/CommentParser.php +++ b/includes/CommentParser.php @@ -37,9 +37,12 @@ class CommentParser { /** @var Config */ private $config; + /** @var Language */ + private $language; + private $dateFormat; private $digits; - /** @var string[] */ + /** @var string[][] */ private $contLangMessages; private $localTimezone; private $timezones; @@ -53,6 +56,7 @@ class CommentParser { public function __construct( DOMElement $rootNode, Language $language, Config $config, array $data = [] ) { $this->rootNode = $rootNode; $this->config = $config; + $this->language = $language; if ( !$data ) { // TODO: Instead of passing data used for mocking, mock the methods that fetch the data. @@ -133,13 +137,16 @@ class CommentParser { } /** - * @param string[] $messageKeys Message keys + * Get text of localisation messages in content language. + * + * @param string $contLangVariant Content language variant + * @param string[] $messages Message keys * @return string[] Message values */ - private function getMessages( array $messageKeys ) : array { - return array_map( function ( string $key ) { - return $this->contLangMessages[$key]; - }, $messageKeys ); + private function getMessages( string $contLangVariant, array $messages ) : array { + return array_map( function ( string $key ) use ( $contLangVariant ) { + return $this->contLangMessages[$contLangVariant][$key]; + }, $messages ); } /** @@ -150,6 +157,7 @@ class CommentParser { * and only dates when MediaWiki existed, let's say 2000 onwards (Thai dates before 1941 are * complicated). * + * @param string $contLangVariant Content language variant * @param string $format Date format * @param string $digitsRegexp Regular expression matching a single localised digit, e.g. '[0-9]' * @param array $tzAbbrs Associative array mapping localised timezone abbreviations to @@ -157,7 +165,7 @@ class CommentParser { * @return string Regular expression */ private function getTimestampRegexp( - string $format, string $digitsRegexp, array $tzAbbrs + string $contLangVariant, string $format, string $digitsRegexp, array $tzAbbrs ) : string { $formatLength = strlen( $format ); $s = ''; @@ -178,7 +186,7 @@ class CommentParser { break; case 'xg': $s .= self::regexpAlternateGroup( - $this->getMessages( Language::MONTH_GENITIVE_MESSAGES ) + $this->getMessages( $contLangVariant, Language::MONTH_GENITIVE_MESSAGES ) ); break; case 'd': @@ -186,7 +194,7 @@ class CommentParser { break; case 'D': $s .= self::regexpAlternateGroup( - $this->getMessages( Language::WEEKDAY_ABBREVIATED_MESSAGES ) + $this->getMessages( $contLangVariant, Language::WEEKDAY_ABBREVIATED_MESSAGES ) ); break; case 'j': @@ -194,17 +202,17 @@ class CommentParser { break; case 'l': $s .= self::regexpAlternateGroup( - $this->getMessages( Language::WEEKDAY_MESSAGES ) + $this->getMessages( $contLangVariant, Language::WEEKDAY_MESSAGES ) ); break; case 'F': $s .= self::regexpAlternateGroup( - $this->getMessages( Language::MONTH_MESSAGES ) + $this->getMessages( $contLangVariant, Language::MONTH_MESSAGES ) ); break; case 'M': $s .= self::regexpAlternateGroup( - $this->getMessages( Language::MONTH_ABBREVIATED_MESSAGES ) + $this->getMessages( $contLangVariant, Language::MONTH_ABBREVIATED_MESSAGES ) ); break; case 'n': @@ -269,6 +277,7 @@ class CommentParser { * Get a function that parses timestamps generated using the given date format, based on the result * of matching the regexp returned by getTimestampRegexp() * + * @param string $contLangVariant Content language variant * @param string $format Date format, as used by MediaWiki * @param string[]|null $digits Localised digits from 0 to 9, e.g. `[ '0', '1', ..., '9' ]` * @param string $localTimezone Local timezone IANA name, e.g. `America/New_York` @@ -277,7 +286,7 @@ class CommentParser { * @return callable Parser function */ private function getTimestampParser( - string $format, ?array $digits, string $localTimezone, array $tzAbbrs + string $contLangVariant, string $format, ?array $digits, string $localTimezone, array $tzAbbrs ) : callable { $untransformDigits = function ( string $text ) use ( $digits ) { if ( !$digits ) { @@ -342,7 +351,7 @@ class CommentParser { } return function ( array $match ) use ( - $matchingGroups, $untransformDigits, $localTimezone, $tzAbbrs + $matchingGroups, $untransformDigits, $localTimezone, $tzAbbrs, $contLangVariant ) { if ( is_array( $match[0] ) ) { // Strip PREG_OFFSET_CAPTURE data @@ -360,7 +369,10 @@ class CommentParser { $text = $match[$i + 1]; switch ( $code ) { case 'xg': - $monthIdx = array_search( $text, $this->getMessages( Language::MONTH_GENITIVE_MESSAGES ) ); + $monthIdx = array_search( + $text, + $this->getMessages( $contLangVariant, Language::MONTH_GENITIVE_MESSAGES ) + ); break; case 'd': case 'j': @@ -371,10 +383,16 @@ class CommentParser { // Day of the week - unused break; case 'F': - $monthIdx = array_search( $text, $this->getMessages( Language::MONTH_MESSAGES ) ); + $monthIdx = array_search( + $text, + $this->getMessages( $contLangVariant, Language::MONTH_MESSAGES ) + ); break; case 'M': - $monthIdx = array_search( $text, $this->getMessages( Language::MONTH_ABBREVIATED_MESSAGES ) ); + $monthIdx = array_search( + $text, + $this->getMessages( $contLangVariant, Language::MONTH_ABBREVIATED_MESSAGES ) + ); break; case 'n': $monthIdx = intval( $untransformDigits( $text ) ) - 1; @@ -444,35 +462,41 @@ class CommentParser { } /** - * Get a regular expression that matches timestamps in the local date format. + * Get a regexp that matches timestamps in the local date format, for each language variant. * * This calls getTimestampRegexp() with predefined data for the current wiki. * - * @return string Regular expression + * @return string[] Regular expressions */ - public function getLocalTimestampRegexp() : string { - return $this->getTimestampRegexp( - $this->dateFormat, - $this->digits ? '[' . implode( '', $this->digits ) . ']' : '\\d', - $this->timezones - ); + public function getLocalTimestampRegexps() : array { + return array_map( function ( $contLangVariant ) { + return $this->getTimestampRegexp( + $contLangVariant, + $this->dateFormat[$contLangVariant], + '[' . implode( '', $this->digits[$contLangVariant] ) . ']', + $this->timezones[$contLangVariant] + ); + }, $this->language->getVariants() ); } /** - * Get a function that parses timestamps in the local date format, based on the result - * of matching the regexp returned by getLocalTimestampRegexp(). + * Get a function that parses timestamps in the local date format, for each language variant, + * based on the result of matching the regexp returned by getLocalTimestampRegexp(). * * This calls getTimestampParser() with predefined data for the current wiki. * - * @return callable Parser function + * @return callable[] Parser functions */ - private function getLocalTimestampParser() : callable { - return $this->getTimestampParser( - $this->dateFormat, - $this->digits, - $this->localTimezone, - $this->timezones - ); + private function getLocalTimestampParsers() : array { + return array_map( function ( $contLangVariant ) { + return $this->getTimestampParser( + $contLangVariant, + $this->dateFormat[$contLangVariant], + $this->digits[$contLangVariant], + $this->localTimezone, + $this->timezones[$contLangVariant] + ); + }, $this->language->getVariants() ); } /** @@ -601,10 +625,14 @@ class CommentParser { * Find a timestamps in a given text node * * @param DOMText $node Text node - * @param string $timestampRegex Timestamp regex - * @return array|null Match data + * @param string[] $timestampRegexps Timestamp regexps + * @return array|null Array with the following keys: + * - int 'offset' Length of extra text preceding the node that was used for matching + * - int 'parserIndex' Which of the regexps matched + * - array 'matchData' Regexp match data, which specifies the location of the match, + * and which can be parsed using getLocalTimestampParsers() */ - public function findTimestamp( DOMText $node, string $timestampRegex ) : ?array { + public function findTimestamp( DOMText $node, array $timestampRegexps ) : ?array { $nodeText = ''; $offset = 0; @@ -638,11 +666,16 @@ class CommentParser { } } - $matchData = null; - // Allows us to mimic match.index in #getComments - if ( preg_match( $timestampRegex, $nodeText, $matchData, PREG_OFFSET_CAPTURE ) ) { - $matchData['offset'] = $offset; - return $matchData; + foreach ( $timestampRegexps as $i => $timestampRegexp ) { + $matchData = null; + // Allows us to mimic match.index in #getComments + if ( preg_match( $timestampRegexp, $nodeText, $matchData, PREG_OFFSET_CAPTURE ) ) { + return [ + 'matchData' => $matchData, + 'offset' => $offset, + 'parserIndex' => $i, + ]; + } } return null; } @@ -715,10 +748,10 @@ class CommentParser { } private function buildThreadItems() : void { - $timestampRegex = $this->getLocalTimestampRegexp(); + $timestampRegexps = $this->getLocalTimestampRegexps(); $commentItems = []; $threadItems = []; - $dfParser = $this->getLocalTimestampParser(); + $dfParsers = $this->getLocalTimestampParsers(); // Placeholder heading in case there are comments in the 0th section $range = new ImmutableRange( $this->rootNode, 0, $this->rootNode, 0 ); @@ -739,7 +772,7 @@ class CommentParser { $curComment = new HeadingItem( $range ); $curComment->setRootNode( $this->rootNode ); $threadItems[] = $curComment; - } elseif ( $node instanceof DOMText && ( $match = $this->findTimestamp( $node, $timestampRegex ) ) ) { + } elseif ( $node instanceof DOMText && ( $match = $this->findTimestamp( $node, $timestampRegexps ) ) ) { $warnings = []; $foundSignature = $this->findSignature( $node, $lastSigNode ); $author = $foundSignature[1]; @@ -753,7 +786,7 @@ class CommentParser { } $lastSigNodeOffset = $lastSigNode === $node ? - $match[0][1] + strlen( $match[0][0] ) - $match['offset'] : + $match['matchData'][0][1] + strlen( $match['matchData'][0][0] ) - $match['offset'] : CommentUtils::childIndexOf( $lastSigNode ) + 1; $sigRange = new ImmutableRange( $firstSigNode->parentNode, @@ -800,7 +833,7 @@ class CommentParser { // Should this use the indent level of $startNode or $node? $level = min( $startLevel, $endLevel ); - $dateTime = $dfParser( $match ); + $dateTime = $dfParsers[ $match['parserIndex'] ]( $match['matchData'] ); if ( isset( $dateTime->discussionToolsWarning ) ) { $warnings[] = $dateTime->discussionToolsWarning; } diff --git a/includes/Data.php b/includes/Data.php index 21d763f54..46b6103c9 100644 --- a/includes/Data.php +++ b/includes/Data.php @@ -12,6 +12,7 @@ namespace MediaWiki\Extension\DiscussionTools; use Config; use DateTimeZone; use ExtensionRegistry; +use ILanguageConverter; use Language; use MediaWiki\MediaWikiServices; use ResourceLoaderContext; @@ -39,13 +40,30 @@ class Data { $lang = MediaWikiServices::getInstance()->getLanguageFactory()->getLanguage( $lang ); } + $langConv = $lang->getConverter(); + $data = []; - $data['dateFormat'] = $lang->getDateFormatString( 'both', $lang->dateFormat( false ) ); + $data['dateFormat'] = []; + $dateFormat = $lang->getDateFormatString( 'both', $lang->dateFormat( false ) ); + foreach ( $lang->getVariants() as $variant ) { + $convDateFormat = self::convertDateFormat( $dateFormat, $langConv, $variant ); + $data['dateFormat'][$variant] = $convDateFormat; + } - $data['digits'] = $config->get( 'TranslateNumerals' ) ? - preg_split( '//u', $lang->formatNumNoSeparators( '0123456789' ), -1, PREG_SPLIT_NO_EMPTY ) : - null; + $data['digits'] = []; + foreach ( $lang->getVariants() as $variant ) { + $data['digits'][$variant] = []; + foreach ( str_split( '0123456789' ) as $digit ) { + if ( $config->get( 'TranslateNumerals' ) ) { + $localDigit = $lang->formatNumNoSeparators( $digit ); + } else { + $localDigit = $digit; + } + $convLocalDigit = $langConv->translate( $localDigit, $variant ); + $data['digits'][$variant][] = $convLocalDigit; + } + } // ApiQuerySiteinfo $data['localTimezone'] = $config->get( 'Localtimezone' ); @@ -67,23 +85,30 @@ class Data { return false; } ) ); - $data['timezones'] = array_combine( - array_map( function ( string $tzMsg ) use ( $lang ) { - // MWTimestamp::getTimezoneMessage() - // Parser::pstPass2() - // Messages used here: 'timezone-utc' and so on - $key = 'timezone-' . strtolower( trim( $tzMsg ) ); - $msg = wfMessage( $key )->inLanguage( $lang ); - // TODO: This probably causes a similar issue to https://phabricator.wikimedia.org/T221294, - // but we *must* check the message existence in the database, because the messages are not - // actually defined by MediaWiki core for any timezone other than UTC... - if ( $msg->exists() ) { - return $msg->text(); - } - return strtoupper( $tzMsg ); - }, $timezoneAbbrs ), - array_map( 'strtoupper', $timezoneAbbrs ) - ); + + $data['timezones'] = []; + foreach ( $lang->getVariants() as $variant ) { + $data['timezones'][$variant] = array_combine( + array_map( function ( string $tzMsg ) use ( $lang, $langConv, $variant ) { + // MWTimestamp::getTimezoneMessage() + // Parser::pstPass2() + // Messages used here: 'timezone-utc' and so on + $key = 'timezone-' . strtolower( trim( $tzMsg ) ); + $msg = wfMessage( $key )->inLanguage( $lang ); + // TODO: This probably causes a similar issue to https://phabricator.wikimedia.org/T221294, + // but we *must* check the message existence in the database, because the messages are not + // actually defined by MediaWiki core for any timezone other than UTC... + if ( $msg->exists() ) { + $text = $msg->text(); + } else { + $text = strtoupper( $tzMsg ); + } + $convText = $langConv->translate( $text, $variant ); + return $convText; + }, $timezoneAbbrs ), + array_map( 'strtoupper', $timezoneAbbrs ) + ); + } // Messages in content language $messagesKeys = array_merge( @@ -93,12 +118,16 @@ class Data { Language::MONTH_GENITIVE_MESSAGES, Language::MONTH_ABBREVIATED_MESSAGES ); - $data['contLangMessages'] = array_combine( - $messagesKeys, - array_map( function ( $key ) use ( $lang ) { - return wfMessage( $key )->inLanguage( $lang )->text(); - }, $messagesKeys ) - ); + $data['contLangMessages'] = []; + foreach ( $lang->getVariants() as $variant ) { + $data['contLangMessages'][$variant] = array_combine( + $messagesKeys, + array_map( function ( $key ) use ( $lang, $langConv, $variant ) { + $text = wfMessage( $key )->inLanguage( $lang )->text(); + return $langConv->translate( $text, $variant ); + }, $messagesKeys ) + ); + } // How far backwards we look for a signature associated with a timestamp before giving up. // Note that this is not a hard limit on the length of signatures we detect. @@ -107,6 +136,89 @@ class Data { return $data; } + /** + * Convert a date format string to a different language variant, leaving all special characters + * unchanged and applying language conversion to the plain text fragments. + * + * @param string $format + * @param ILanguageConverter $langConv + * @param string $variant + * @return string + */ + private static function convertDateFormat( + string $format, + ILanguageConverter $langConv, + string $variant + ) : string { + $formatLength = strlen( $format ); + $s = ''; + // The supported codes must match CommentParser::getTimestampRegexp() + for ( $p = 0; $p < $formatLength; $p++ ) { + $num = false; + $code = $format[ $p ]; + if ( $code === 'x' && $p < $formatLength - 1 ) { + $code .= $format[++$p]; + } + if ( $code === 'xk' && $p < $formatLength - 1 ) { + $code .= $format[++$p]; + } + + // LAZY SHORTCUTS that might cause bugs: + // * We assume that result of $langConv->translate() doesn't produce any special codes/characters + // * We assume that calling $langConv->translate() separately for each character is correct + switch ( $code ) { + case 'xx' : + case 'xg': + case 'd': + case 'D': + case 'j': + case 'l': + case 'F': + case 'M': + case 'n': + case 'Y': + case 'xkY': + case 'G': + case 'H': + case 'i': + // Special code - pass through unchanged + $s .= $code; + break; + case '\\': + // Plain text (backslash escaping) - convert to language variant + if ( $p < $formatLength - 1 ) { + $s .= '\\' . $langConv->translate( $format[++$p], $variant ); + } else { + $s .= $code; + } + break; + case '"': + // Plain text (quoted literal) - convert to language variant + if ( $p < $formatLength - 1 ) { + $endQuote = strpos( $format, '"', $p + 1 ); + if ( $endQuote === false ) { + // No terminating quote, assume literal " + $s .= $code; + } else { + $s .= '"' . + $langConv->translate( substr( $format, $p + 1, $endQuote - $p - 1 ), $variant ) . + '"'; + $p = $endQuote; + } + } else { + // Quote at end of string, assume literal " + $s .= $code; + } + break; + default: + // Plain text - convert to language variant + $s .= $langConv->translate( $format[$p], $variant ); + } + } + + return $s; + } + /** * Return messages in content language, for use in a ResourceLoader module. * diff --git a/modules/Parser.js b/modules/Parser.js index 99af45036..4a107c5b4 100644 --- a/modules/Parser.js +++ b/modules/Parser.js @@ -35,12 +35,13 @@ OO.initClass( Parser ); * Get text of localisation messages in content language. * * @private - * @param {string[]} messages - * @return {string[]} + * @param {string} contLangVariant Content language variant + * @param {string[]} messages Message keys + * @return {string[]} Message values */ -function getMessages( messages ) { +function getMessages( contLangVariant, messages ) { return messages.map( function ( code ) { - return data.contLangMessages[ code ]; + return data.contLangMessages[ contLangVariant ][ code ]; } ); } @@ -53,13 +54,14 @@ function getMessages( messages ) { * complicated). * * @private + * @param {string} contLangVariant Content language variant * @param {string} format Date format, as used by MediaWiki * @param {string} digitsRegexp Regular expression matching a single localised digit, e.g. `[0-9]` * @param {Object} tzAbbrs Map of localised timezone abbreviations to IANA abbreviations * for the local timezone, e.g. `{EDT: "EDT", EST: "EST"}` * @return {string} Regular expression */ -Parser.prototype.getTimestampRegexp = function ( format, digitsRegexp, tzAbbrs ) { +Parser.prototype.getTimestampRegexp = function ( contLangVariant, format, digitsRegexp, tzAbbrs ) { var s, p, num, code, endQuote, tzRegexp, regexp; function regexpGroup( r ) { @@ -87,7 +89,7 @@ Parser.prototype.getTimestampRegexp = function ( format, digitsRegexp, tzAbbrs ) s += 'x'; break; case 'xg': - s += regexpAlternateGroup( getMessages( [ + s += regexpAlternateGroup( getMessages( contLangVariant, [ 'january-gen', 'february-gen', 'march-gen', 'april-gen', 'may-gen', 'june-gen', 'july-gen', 'august-gen', 'september-gen', 'october-gen', 'november-gen', 'december-gen' @@ -97,7 +99,7 @@ Parser.prototype.getTimestampRegexp = function ( format, digitsRegexp, tzAbbrs ) num = '2'; break; case 'D': - s += regexpAlternateGroup( getMessages( [ + s += regexpAlternateGroup( getMessages( contLangVariant, [ 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat' ] ) ); break; @@ -105,20 +107,20 @@ Parser.prototype.getTimestampRegexp = function ( format, digitsRegexp, tzAbbrs ) num = '1,2'; break; case 'l': - s += regexpAlternateGroup( getMessages( [ + s += regexpAlternateGroup( getMessages( contLangVariant, [ 'sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday' ] ) ); break; case 'F': - s += regexpAlternateGroup( getMessages( [ + s += regexpAlternateGroup( getMessages( contLangVariant, [ 'january', 'february', 'march', 'april', 'may_long', 'june', 'july', 'august', 'september', 'october', 'november', 'december' ] ) ); break; case 'M': - s += regexpAlternateGroup( getMessages( [ + s += regexpAlternateGroup( getMessages( contLangVariant, [ 'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec' ] ) ); @@ -186,6 +188,7 @@ Parser.prototype.getTimestampRegexp = function ( format, digitsRegexp, tzAbbrs ) * of matching the regexp returned by #getTimestampRegexp. * * @private + * @param {string} contLangVariant Content language variant * @param {string} format Date format, as used by MediaWiki * @param {string[]|null} digits Localised digits from 0 to 9, e.g. `[ '0', '1', ..., '9' ]` * @param {string} localTimezone Local timezone IANA name, e.g. `America/New_York` @@ -193,7 +196,7 @@ Parser.prototype.getTimestampRegexp = function ( format, digitsRegexp, tzAbbrs ) * for the local timezone, e.g. `{EDT: "EDT", EST: "EST"}` * @return {TimestampParser} Timestamp parser function */ -Parser.prototype.getTimestampParser = function ( format, digits, localTimezone, tzAbbrs ) { +Parser.prototype.getTimestampParser = function ( contLangVariant, format, digits, localTimezone, tzAbbrs ) { var p, code, endQuote, matchingGroups = []; for ( p = 0; p < format.length; p++ ) { code = format[ p ]; @@ -280,7 +283,7 @@ Parser.prototype.getTimestampParser = function ( format, digits, localTimezone, switch ( code2 ) { case 'xg': - monthIdx = getMessages( [ + monthIdx = getMessages( contLangVariant, [ 'january-gen', 'february-gen', 'march-gen', 'april-gen', 'may-gen', 'june-gen', 'july-gen', 'august-gen', 'september-gen', 'october-gen', 'november-gen', 'december-gen' @@ -295,14 +298,14 @@ Parser.prototype.getTimestampParser = function ( format, digits, localTimezone, // Day of the week - unused break; case 'F': - monthIdx = getMessages( [ + monthIdx = getMessages( contLangVariant, [ 'january', 'february', 'march', 'april', 'may_long', 'june', 'july', 'august', 'september', 'october', 'november', 'december' ] ).indexOf( text ); break; case 'M': - monthIdx = getMessages( [ + monthIdx = getMessages( contLangVariant, [ 'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec' ] ).indexOf( text ); @@ -362,37 +365,45 @@ Parser.prototype.getTimestampParser = function ( format, digits, localTimezone, }; /** - * Get a regexp that matches timestamps in the local date format. + * Get a regexp that matches timestamps in the local date format, for each language variant. * * This calls #getTimestampRegexp with predefined data for the current wiki. * * @private - * @return {string} Regular expression + * @return {string[]} Regular expressions */ -Parser.prototype.getLocalTimestampRegexp = function () { - return this.getTimestampRegexp( - data.dateFormat, - data.digits ? '[' + data.digits.join( '' ) + ']' : '\\d', - data.timezones - ); +Parser.prototype.getLocalTimestampRegexps = function () { + var parser = this; + return Object.keys( data.dateFormat ).map( function ( contLangVariant ) { + return parser.getTimestampRegexp( + contLangVariant, + data.dateFormat[ contLangVariant ], + '[' + data.digits[ contLangVariant ].join( '' ) + ']', + data.timezones[ contLangVariant ] + ); + } ); }; /** - * Get a function that parses timestamps in the local date format, based on the result - * of matching the regexp returned by #getLocalTimestampRegexp. + * Get a function that parses timestamps in the local date format, for each language variant, + * based on the result of matching the regexps returned by #getLocalTimestampRegexps. * * This calls #getTimestampParser with predefined data for the current wiki. * * @private - * @return {TimestampParser} Timestamp parser function + * @return {TimestampParser[]} Timestamp parser functions */ -Parser.prototype.getLocalTimestampParser = function () { - return this.getTimestampParser( - data.dateFormat, - data.digits, - data.localTimezone, - data.timezones - ); +Parser.prototype.getLocalTimestampParsers = function () { + var parser = this; + return Object.keys( data.dateFormat ).map( function ( contLangVariant ) { + return parser.getTimestampParser( + contLangVariant, + data.dateFormat[ contLangVariant ], + data.digits[ contLangVariant ], + data.localTimezone, + data.timezones[ contLangVariant ] + ); + } ); }; /** @@ -411,16 +422,19 @@ function acceptOnlyNodesAllowingComments( node ) { } /** - * Find a timestamps in a given text node + * Find a timestamp in a given text node * * @private * @param {Text} node Text node - * @param {string} timestampRegex Timestamp regex - * @return {Array} Regexp match data, which specifies the location of the match, - * and which can be parsed using #getLocalTimestampParser + * @param {string[]} timestampRegexps Timestamp regexps + * @return {Object|null} Object with the following keys: + * - {number} offset Length of extra text preceding the node that was used for matching + * - {number} parserIndex Which of the regexps matched + * - {Array} matchData Regexp match data, which specifies the location of the match, + * and which can be parsed using #getLocalTimestampParsers */ -Parser.prototype.findTimestamp = function ( node, timestampRegex ) { - var matchData, +Parser.prototype.findTimestamp = function ( node, timestampRegexps ) { + var matchData, i, nodeText = '', offset = 0; while ( node ) { @@ -453,14 +467,19 @@ Parser.prototype.findTimestamp = function ( node, timestampRegex ) { } } - // Technically, there could be multiple matches in a single text node. However, the ultimate - // point of this is to find the signatures which precede the timestamps, and any later - // timestamps in the text node can't be directly preceded by a signature (as we require them to - // have links), so we only concern ourselves with the first match. - matchData = nodeText.match( timestampRegex ); - if ( matchData ) { - matchData.offset = offset; - return matchData; + for ( i = 0; i < timestampRegexps.length; i++ ) { + // Technically, there could be multiple matches in a single text node. However, the ultimate + // point of this is to find the signatures which precede the timestamps, and any later + // timestamps in the text node can't be directly preceded by a signature (as we require them to + // have links), so we only concern ourselves with the first match. + matchData = nodeText.match( timestampRegexps[ i ] ); + if ( matchData ) { + return { + matchData: matchData, + offset: offset, + parserIndex: i + }; + } } return null; }; @@ -714,8 +733,8 @@ Parser.prototype.findCommentById = function ( id ) { Parser.prototype.buildThreadItems = function () { var - dfParser = this.getLocalTimestampParser(), - timestampRegex = this.getLocalTimestampRegexp(), + dfParsers = this.getLocalTimestampParsers(), + timestampRegexps = this.getLocalTimestampRegexps(), commentItems = [], threadItems = [], treeWalker, @@ -754,7 +773,7 @@ Parser.prototype.buildThreadItems = function () { curComment = new HeadingItem( range ); curComment.rootNode = this.rootNode; threadItems.push( curComment ); - } else if ( node.nodeType === Node.TEXT_NODE && ( match = this.findTimestamp( node, timestampRegex ) ) ) { + } else if ( node.nodeType === Node.TEXT_NODE && ( match = this.findTimestamp( node, timestampRegexps ) ) ) { warnings = []; foundSignature = this.findSignature( node, lastSigNode ); author = foundSignature[ 1 ]; @@ -768,7 +787,7 @@ Parser.prototype.buildThreadItems = function () { } lastSigNodeOffset = lastSigNode === node ? - match.index + match[ 0 ].length - match.offset : + match.matchData.index + match.matchData[ 0 ].length - match.offset : utils.childIndexOf( lastSigNode ) + 1; sigRange = { startContainer: firstSigNode.parentNode, @@ -813,7 +832,7 @@ Parser.prototype.buildThreadItems = function () { // Should this use the indent level of `startNode` or `node`? level = Math.min( startLevel, endLevel ); - dateTime = dfParser( match ); + dateTime = dfParsers[ match.parserIndex ]( match.matchData ); if ( dateTime.discussionToolsWarning ) { warnings.push( dateTime.discussionToolsWarning ); } diff --git a/tests/data/arwiki-data.json b/tests/data/arwiki-data.json index e3e1baa33..f1e637cb0 100644 --- a/tests/data/arwiki-data.json +++ b/tests/data/arwiki-data.json @@ -1,74 +1,82 @@ { - "dateFormat": "H:i، j xg Y", - "digits": [ - "0", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9" - ], + "dateFormat": { + "ar": "H:i، j xg Y" + }, + "digits": { + "ar": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9" + ] + }, "localTimezone": "UTC", "specialContributionsName": "مساهمات", "timezones": { - "ت ع م": "UTC" + "ar": { + "ت ع م": "UTC" + } }, "contLangMessages": { - "timezone-utc": "ت ع م", - "sunday": "الأحد", - "monday": "الاثنين", - "tuesday": "الثلاثاء", - "wednesday": "الأربعاء", - "thursday": "الخميس", - "friday": "الجمعة", - "saturday": "السبت", - "sun": "أحد", - "mon": "اثنين", - "tue": "ثلاثاء", - "wed": "أربعاء", - "thu": "خميس", - "fri": "جمعة", - "sat": "سبت", - "january": "يناير", - "february": "فبراير", - "march": "مارس", - "april": "أبريل", - "may_long": "مايو", - "june": "يونيو", - "july": "يوليو", - "august": "أغسطس", - "september": "سبتمبر", - "october": "أكتوبر", - "november": "نوفمبر", - "december": "ديسمبر", - "january-gen": "يناير", - "february-gen": "فبراير", - "march-gen": "مارس", - "april-gen": "أبريل", - "may-gen": "مايو", - "june-gen": "يونيو", - "july-gen": "يوليو", - "august-gen": "أغسطس", - "september-gen": "سبتمبر", - "october-gen": "أكتوبر", - "november-gen": "نوفمبر", - "december-gen": "ديسمبر", - "jan": "يناير", - "feb": "فبراير", - "mar": "مارس", - "apr": "أبريل", - "may": "مايو", - "jun": "يونيو", - "jul": "يوليو", - "aug": "أغسطس", - "sep": "سبتمبر", - "oct": "أكتوبر", - "nov": "نوفمبر", - "dec": "ديسمبر" + "ar": { + "timezone-utc": "ت ع م", + "sunday": "الأحد", + "monday": "الاثنين", + "tuesday": "الثلاثاء", + "wednesday": "الأربعاء", + "thursday": "الخميس", + "friday": "الجمعة", + "saturday": "السبت", + "sun": "أحد", + "mon": "اثنين", + "tue": "ثلاثاء", + "wed": "أربعاء", + "thu": "خميس", + "fri": "جمعة", + "sat": "سبت", + "january": "يناير", + "february": "فبراير", + "march": "مارس", + "april": "أبريل", + "may_long": "مايو", + "june": "يونيو", + "july": "يوليو", + "august": "أغسطس", + "september": "سبتمبر", + "october": "أكتوبر", + "november": "نوفمبر", + "december": "ديسمبر", + "january-gen": "يناير", + "february-gen": "فبراير", + "march-gen": "مارس", + "april-gen": "أبريل", + "may-gen": "مايو", + "june-gen": "يونيو", + "july-gen": "يوليو", + "august-gen": "أغسطس", + "september-gen": "سبتمبر", + "october-gen": "أكتوبر", + "november-gen": "نوفمبر", + "december-gen": "ديسمبر", + "jan": "يناير", + "feb": "فبراير", + "mar": "مارس", + "apr": "أبريل", + "may": "مايو", + "jun": "يونيو", + "jul": "يوليو", + "aug": "أغسطس", + "sep": "سبتمبر", + "oct": "أكتوبر", + "nov": "نوفمبر", + "dec": "ديسمبر" + } }, "signatureScanLimit": 100 } diff --git a/tests/data/ckbwiki-data.json b/tests/data/ckbwiki-data.json index b805052d3..70222eb91 100644 --- a/tests/data/ckbwiki-data.json +++ b/tests/data/ckbwiki-data.json @@ -1,73 +1,81 @@ { - "dateFormat": "‏H:i، jی xg Y", - "digits": [ - "٠", - "١", - "٢", - "٣", - "٤", - "٥", - "٦", - "٧", - "٨", - "٩" - ], + "dateFormat": { + "ckb": "‏H:i، jی xg Y" + }, + "digits": { + "ckb": [ + "٠", + "١", + "٢", + "٣", + "٤", + "٥", + "٦", + "٧", + "٨", + "٩" + ] + }, "localTimezone": "UTC", "specialContributionsName": "بەشدارییەکان", "timezones": { - "UTC": "UTC" + "ckb": { + "UTC": "UTC" + } }, "contLangMessages": { - "sunday": "یەکشەممە", - "monday": "دووشەممە", - "tuesday": "سێشەممە", - "wednesday": "چوارشەممە", - "thursday": "پێنجشەممە", - "friday": "ھەینی", - "saturday": "شەممە", - "sun": "یەکشەممە", - "mon": "دووشەممە", - "tue": "سێشەممە", - "wed": "چوارشەممە", - "thu": "پێنجشەممە", - "fri": "ھەینی", - "sat": "شەممە", - "january": "کانوونی دووەم", - "february": "شوبات", - "march": "ئازار", - "april": "نیسان", - "may_long": "ئایار", - "june": "حوزەیران", - "july": "تەممووز", - "august": "ئاب", - "september": "ئەیلوول", - "october": "تشرینی یەکەم", - "november": "تشرینی دووەم", - "december": "کانوونی یەکەم", - "january-gen": "کانوونی دووەمی", - "february-gen": "شوباتی", - "march-gen": "ئازاری", - "april-gen": "نیسانی", - "may-gen": "ئایاری", - "june-gen": "حوزەیرانی", - "july-gen": "تەممووزی", - "august-gen": "ئابی", - "september-gen": "ئەیلوولی", - "october-gen": "تشرینی یەکەمی", - "november-gen": "تشرینی دووەمی", - "december-gen": "کانوونی یەکەمی", - "jan": "کانوونی دووەم", - "feb": "شوبات", - "mar": "ئازار", - "apr": "نیسان", - "may": "ئایار", - "jun": "حوزەیران", - "jul": "تەممووز", - "aug": "ئاب", - "sep": "ئەیلوول", - "oct": "تشرینی یەکەم", - "nov": "تشرینی دووەم", - "dec": "کانوونی یەکەم" + "ckb": { + "sunday": "یەکشەممە", + "monday": "دووشەممە", + "tuesday": "سێشەممە", + "wednesday": "چوارشەممە", + "thursday": "پێنجشەممە", + "friday": "ھەینی", + "saturday": "شەممە", + "sun": "یەکشەممە", + "mon": "دووشەممە", + "tue": "سێشەممە", + "wed": "چوارشەممە", + "thu": "پێنجشەممە", + "fri": "ھەینی", + "sat": "شەممە", + "january": "کانوونی دووەم", + "february": "شوبات", + "march": "ئازار", + "april": "نیسان", + "may_long": "ئایار", + "june": "حوزەیران", + "july": "تەممووز", + "august": "ئاب", + "september": "ئەیلوول", + "october": "تشرینی یەکەم", + "november": "تشرینی دووەم", + "december": "کانوونی یەکەم", + "january-gen": "کانوونی دووەمی", + "february-gen": "شوباتی", + "march-gen": "ئازاری", + "april-gen": "نیسانی", + "may-gen": "ئایاری", + "june-gen": "حوزەیرانی", + "july-gen": "تەممووزی", + "august-gen": "ئابی", + "september-gen": "ئەیلوولی", + "october-gen": "تشرینی یەکەمی", + "november-gen": "تشرینی دووەمی", + "december-gen": "کانوونی یەکەمی", + "jan": "کانوونی دووەم", + "feb": "شوبات", + "mar": "ئازار", + "apr": "نیسان", + "may": "ئایار", + "jun": "حوزەیران", + "jul": "تەممووز", + "aug": "ئاب", + "sep": "ئەیلوول", + "oct": "تشرینی یەکەم", + "nov": "تشرینی دووەم", + "dec": "کانوونی یەکەم" + } }, "signatureScanLimit": 100 } diff --git a/tests/data/enwiki-data.json b/tests/data/enwiki-data.json index 87087b542..cd62643be 100644 --- a/tests/data/enwiki-data.json +++ b/tests/data/enwiki-data.json @@ -1,73 +1,81 @@ { - "dateFormat": "H:i, j F Y", - "digits": [ - "0", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9" - ], + "dateFormat": { + "en": "H:i, j F Y" + }, + "digits": { + "en": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9" + ] + }, "localTimezone": "UTC", "specialContributionsName": "Contributions", "timezones": { - "UTC": "UTC" + "en": { + "UTC": "UTC" + } }, "contLangMessages": { - "sunday": "Sunday", - "monday": "Monday", - "tuesday": "Tuesday", - "wednesday": "Wednesday", - "thursday": "Thursday", - "friday": "Friday", - "saturday": "Saturday", - "sun": "Sun", - "mon": "Mon", - "tue": "Tue", - "wed": "Wed", - "thu": "Thu", - "fri": "Fri", - "sat": "Sat", - "january": "January", - "february": "February", - "march": "March", - "april": "April", - "may_long": "May", - "june": "June", - "july": "July", - "august": "August", - "september": "September", - "october": "October", - "november": "November", - "december": "December", - "january-gen": "January", - "february-gen": "February", - "march-gen": "March", - "april-gen": "April", - "may-gen": "May", - "june-gen": "June", - "july-gen": "July", - "august-gen": "August", - "september-gen": "September", - "october-gen": "October", - "november-gen": "November", - "december-gen": "December", - "jan": "Jan", - "feb": "Feb", - "mar": "Mar", - "apr": "Apr", - "may": "May", - "jun": "Jun", - "jul": "Jul", - "aug": "Aug", - "sep": "Sep", - "oct": "Oct", - "nov": "Nov", - "dec": "Dec" + "en": { + "sunday": "Sunday", + "monday": "Monday", + "tuesday": "Tuesday", + "wednesday": "Wednesday", + "thursday": "Thursday", + "friday": "Friday", + "saturday": "Saturday", + "sun": "Sun", + "mon": "Mon", + "tue": "Tue", + "wed": "Wed", + "thu": "Thu", + "fri": "Fri", + "sat": "Sat", + "january": "January", + "february": "February", + "march": "March", + "april": "April", + "may_long": "May", + "june": "June", + "july": "July", + "august": "August", + "september": "September", + "october": "October", + "november": "November", + "december": "December", + "january-gen": "January", + "february-gen": "February", + "march-gen": "March", + "april-gen": "April", + "may-gen": "May", + "june-gen": "June", + "july-gen": "July", + "august-gen": "August", + "september-gen": "September", + "october-gen": "October", + "november-gen": "November", + "december-gen": "December", + "jan": "Jan", + "feb": "Feb", + "mar": "Mar", + "apr": "Apr", + "may": "May", + "jun": "Jun", + "jul": "Jul", + "aug": "Aug", + "sep": "Sep", + "oct": "Oct", + "nov": "Nov", + "dec": "Dec" + } }, "signatureScanLimit": 100 } diff --git a/tests/data/frwiki-data.json b/tests/data/frwiki-data.json index 56783d472..748504760 100644 --- a/tests/data/frwiki-data.json +++ b/tests/data/frwiki-data.json @@ -1,78 +1,86 @@ { - "dateFormat": "j F Y à H:i", - "digits": [ - "0", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9" - ], + "dateFormat": { + "fr": "j F Y à H:i" + }, + "digits": { + "fr": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9" + ] + }, "localTimezone": "Europe/Paris", "specialContributionsName": "Contributions", "timezones": { - "CEST": "CEST", - "CET": "CET", - "PMT": "PMT", - "WEMT": "WEMT", - "WEST": "WEST", - "WET": "WET" + "fr": { + "CEST": "CEST", + "CET": "CET", + "PMT": "PMT", + "WEMT": "WEMT", + "WEST": "WEST", + "WET": "WET" + } }, "contLangMessages": { - "sunday": "dimanche", - "monday": "lundi", - "tuesday": "mardi", - "wednesday": "mercredi", - "thursday": "jeudi", - "friday": "vendredi", - "saturday": "samedi", - "sun": "dim.", - "mon": "lun.", - "tue": "mar.", - "wed": "mer.", - "thu": "jeu.", - "fri": "ven.", - "sat": "sam.", - "january": "janvier", - "february": "février", - "march": "mars", - "april": "avril", - "may_long": "mai", - "june": "juin", - "july": "juillet", - "august": "août", - "september": "septembre", - "october": "octobre", - "november": "novembre", - "december": "décembre", - "january-gen": "janvier", - "february-gen": "février", - "march-gen": "mars", - "april-gen": "avril", - "may-gen": "mai", - "june-gen": "juin", - "july-gen": "juillet", - "august-gen": "août", - "september-gen": "septembre", - "october-gen": "octobre", - "november-gen": "novembre", - "december-gen": "décembre", - "jan": "janv.", - "feb": "fév.", - "mar": "mars", - "apr": "avr.", - "may": "mai", - "jun": "juin", - "jul": "juill.", - "aug": "août", - "sep": "sept.", - "oct": "oct.", - "nov": "nov.", - "dec": "déc." + "fr": { + "sunday": "dimanche", + "monday": "lundi", + "tuesday": "mardi", + "wednesday": "mercredi", + "thursday": "jeudi", + "friday": "vendredi", + "saturday": "samedi", + "sun": "dim.", + "mon": "lun.", + "tue": "mar.", + "wed": "mer.", + "thu": "jeu.", + "fri": "ven.", + "sat": "sam.", + "january": "janvier", + "february": "février", + "march": "mars", + "april": "avril", + "may_long": "mai", + "june": "juin", + "july": "juillet", + "august": "août", + "september": "septembre", + "october": "octobre", + "november": "novembre", + "december": "décembre", + "january-gen": "janvier", + "february-gen": "février", + "march-gen": "mars", + "april-gen": "avril", + "may-gen": "mai", + "june-gen": "juin", + "july-gen": "juillet", + "august-gen": "août", + "september-gen": "septembre", + "october-gen": "octobre", + "november-gen": "novembre", + "december-gen": "décembre", + "jan": "janv.", + "feb": "fév.", + "mar": "mars", + "apr": "avr.", + "may": "mai", + "jun": "juin", + "jul": "juill.", + "aug": "août", + "sep": "sept.", + "oct": "oct.", + "nov": "nov.", + "dec": "déc." + } }, "signatureScanLimit": 100 } diff --git a/tests/data/huwiki-data.json b/tests/data/huwiki-data.json index 7cb88fa5c..4a9b72679 100644 --- a/tests/data/huwiki-data.json +++ b/tests/data/huwiki-data.json @@ -1,75 +1,83 @@ { - "dateFormat": "Y. F j., H:i", - "digits": [ - "0", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9" - ], + "dateFormat": { + "hu": "Y. F j., H:i" + }, + "digits": { + "hu": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9" + ] + }, "localTimezone": "Europe/Berlin", "specialContributionsName": "Szerkesztő_közreműködései", "timezones": { - "CEMT": "CEMT", - "CEST": "CEST", - "CET": "CET" + "hu": { + "CEMT": "CEMT", + "CEST": "CEST", + "CET": "CET" + } }, "contLangMessages": { - "sunday": "vasárnap", - "monday": "hétfő", - "tuesday": "kedd", - "wednesday": "szerda", - "thursday": "csütörtök", - "friday": "péntek", - "saturday": "szombat", - "sun": "vas", - "mon": "hét", - "tue": "kedd", - "wed": "sze", - "thu": "csü", - "fri": "pén", - "sat": "szo", - "january": "január", - "february": "február", - "march": "március", - "april": "április", - "may_long": "május", - "june": "június", - "july": "július", - "august": "augusztus", - "september": "szeptember", - "october": "október", - "november": "november", - "december": "december", - "january-gen": "január", - "february-gen": "február", - "march-gen": "március", - "april-gen": "április", - "may-gen": "május", - "june-gen": "június", - "july-gen": "július", - "august-gen": "augusztus", - "september-gen": "szeptember", - "october-gen": "október", - "november-gen": "november", - "december-gen": "december", - "jan": "jan", - "feb": "febr", - "mar": "márc", - "apr": "ápr", - "may": "máj", - "jun": "jún", - "jul": "júl", - "aug": "aug", - "sep": "szept", - "oct": "okt", - "nov": "nov", - "dec": "dec" + "hu": { + "sunday": "vasárnap", + "monday": "hétfő", + "tuesday": "kedd", + "wednesday": "szerda", + "thursday": "csütörtök", + "friday": "péntek", + "saturday": "szombat", + "sun": "vas", + "mon": "hét", + "tue": "kedd", + "wed": "sze", + "thu": "csü", + "fri": "pén", + "sat": "szo", + "january": "január", + "february": "február", + "march": "március", + "april": "április", + "may_long": "május", + "june": "június", + "july": "július", + "august": "augusztus", + "september": "szeptember", + "october": "október", + "november": "november", + "december": "december", + "january-gen": "január", + "february-gen": "február", + "march-gen": "március", + "april-gen": "április", + "may-gen": "május", + "june-gen": "június", + "july-gen": "július", + "august-gen": "augusztus", + "september-gen": "szeptember", + "october-gen": "október", + "november-gen": "november", + "december-gen": "december", + "jan": "jan", + "feb": "febr", + "mar": "márc", + "apr": "ápr", + "may": "máj", + "jun": "jún", + "jul": "júl", + "aug": "aug", + "sep": "szept", + "oct": "okt", + "nov": "nov", + "dec": "dec" + } }, "signatureScanLimit": 100 } diff --git a/tests/data/nlwiki-data.json b/tests/data/nlwiki-data.json index 3dfcf5e2d..cae26d806 100644 --- a/tests/data/nlwiki-data.json +++ b/tests/data/nlwiki-data.json @@ -1,75 +1,83 @@ { - "dateFormat": "j M Y H:i", - "digits": [ - "0", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9" - ], + "dateFormat": { + "nl": "j M Y H:i" + }, + "digits": { + "nl": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9" + ] + }, "localTimezone": "Europe/Berlin", "specialContributionsName": "Bijdragen", "timezones": { - "CEMT": "CEMT", - "CEST": "CEST", - "CET": "CET" + "nl": { + "CEMT": "CEMT", + "CEST": "CEST", + "CET": "CET" + } }, "contLangMessages": { - "sunday": "zondag", - "monday": "maandag", - "tuesday": "dinsdag", - "wednesday": "woensdag", - "thursday": "donderdag", - "friday": "vrijdag", - "saturday": "zaterdag", - "sun": "zo", - "mon": "ma", - "tue": "di", - "wed": "wo", - "thu": "do", - "fri": "vr", - "sat": "za", - "january": "januari", - "february": "februari", - "march": "maart", - "april": "april", - "may_long": "mei", - "june": "juni", - "july": "juli", - "august": "augustus", - "september": "september", - "october": "oktober", - "november": "november", - "december": "december", - "january-gen": "januari", - "february-gen": "februari", - "march-gen": "maart", - "april-gen": "april", - "may-gen": "mei", - "june-gen": "juni", - "july-gen": "juli", - "august-gen": "augustus", - "september-gen": "september", - "october-gen": "oktober", - "november-gen": "november", - "december-gen": "december", - "jan": "jan", - "feb": "feb", - "mar": "mrt", - "apr": "apr", - "may": "mei", - "jun": "jun", - "jul": "jul", - "aug": "aug", - "sep": "sep", - "oct": "okt", - "nov": "nov", - "dec": "dec" + "nl": { + "sunday": "zondag", + "monday": "maandag", + "tuesday": "dinsdag", + "wednesday": "woensdag", + "thursday": "donderdag", + "friday": "vrijdag", + "saturday": "zaterdag", + "sun": "zo", + "mon": "ma", + "tue": "di", + "wed": "wo", + "thu": "do", + "fri": "vr", + "sat": "za", + "january": "januari", + "february": "februari", + "march": "maart", + "april": "april", + "may_long": "mei", + "june": "juni", + "july": "juli", + "august": "augustus", + "september": "september", + "october": "oktober", + "november": "november", + "december": "december", + "january-gen": "januari", + "february-gen": "februari", + "march-gen": "maart", + "april-gen": "april", + "may-gen": "mei", + "june-gen": "juni", + "july-gen": "juli", + "august-gen": "augustus", + "september-gen": "september", + "october-gen": "oktober", + "november-gen": "november", + "december-gen": "december", + "jan": "jan", + "feb": "feb", + "mar": "mrt", + "apr": "apr", + "may": "mei", + "jun": "jun", + "jul": "jul", + "aug": "aug", + "sep": "sep", + "oct": "okt", + "nov": "nov", + "dec": "dec" + } }, "signatureScanLimit": 100 } diff --git a/tests/data/plwiki-data.json b/tests/data/plwiki-data.json index 51f1040cf..fea177b4c 100644 --- a/tests/data/plwiki-data.json +++ b/tests/data/plwiki-data.json @@ -1,77 +1,85 @@ { - "dateFormat": "H:i, j M Y", - "digits": [ - "0", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9" - ], + "dateFormat": { + "pl": "H:i, j M Y" + }, + "digits": { + "pl": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9" + ] + }, "localTimezone": "Europe/Warsaw", "specialContributionsName": "Wkład", "timezones": { - "CEST": "CEST", - "CET": "CET", - "EEST": "EEST", - "EET": "EET", - "WMT": "WMT" + "pl": { + "CEST": "CEST", + "CET": "CET", + "EEST": "EEST", + "EET": "EET", + "WMT": "WMT" + } }, "contLangMessages": { - "sunday": "niedziela", - "monday": "poniedziałek", - "tuesday": "wtorek", - "wednesday": "środa", - "thursday": "czwartek", - "friday": "piątek", - "saturday": "sobota", - "sun": "N", - "mon": "Pn", - "tue": "Wt", - "wed": "Śr", - "thu": "Cz", - "fri": "Pt", - "sat": "So", - "january": "styczeń", - "february": "luty", - "march": "marzec", - "april": "kwiecień", - "may_long": "maj", - "june": "czerwiec", - "july": "lipiec", - "august": "sierpień", - "september": "wrzesień", - "october": "październik", - "november": "listopad", - "december": "grudzień", - "january-gen": "stycznia", - "february-gen": "lutego", - "march-gen": "marca", - "april-gen": "kwietnia", - "may-gen": "maja", - "june-gen": "czerwca", - "july-gen": "lipca", - "august-gen": "sierpnia", - "september-gen": "września", - "october-gen": "października", - "november-gen": "listopada", - "december-gen": "grudnia", - "jan": "sty", - "feb": "lut", - "mar": "mar", - "apr": "kwi", - "may": "maj", - "jun": "cze", - "jul": "lip", - "aug": "sie", - "sep": "wrz", - "oct": "paź", - "nov": "lis", - "dec": "gru" + "pl": { + "sunday": "niedziela", + "monday": "poniedziałek", + "tuesday": "wtorek", + "wednesday": "środa", + "thursday": "czwartek", + "friday": "piątek", + "saturday": "sobota", + "sun": "N", + "mon": "Pn", + "tue": "Wt", + "wed": "Śr", + "thu": "Cz", + "fri": "Pt", + "sat": "So", + "january": "styczeń", + "february": "luty", + "march": "marzec", + "april": "kwiecień", + "may_long": "maj", + "june": "czerwiec", + "july": "lipiec", + "august": "sierpień", + "september": "wrzesień", + "october": "październik", + "november": "listopad", + "december": "grudzień", + "january-gen": "stycznia", + "february-gen": "lutego", + "march-gen": "marca", + "april-gen": "kwietnia", + "may-gen": "maja", + "june-gen": "czerwca", + "july-gen": "lipca", + "august-gen": "sierpnia", + "september-gen": "września", + "october-gen": "października", + "november-gen": "listopada", + "december-gen": "grudnia", + "jan": "sty", + "feb": "lut", + "mar": "mar", + "apr": "kwi", + "may": "maj", + "jun": "cze", + "jul": "lip", + "aug": "sie", + "sep": "wrz", + "oct": "paź", + "nov": "lis", + "dec": "gru" + } }, "signatureScanLimit": 100 } diff --git a/tests/phpunit/CommentParserTest.php b/tests/phpunit/CommentParserTest.php index ab6f7491b..a3101a99f 100644 --- a/tests/phpunit/CommentParserTest.php +++ b/tests/phpunit/CommentParserTest.php @@ -117,7 +117,7 @@ class CommentParserTest extends CommentTestCase { $expected = str_replace( ':', '\:', $expected ); $expected = '/' . $expected . '/u'; - $result = $parser->getTimestampRegexp( $format, '\\d', [ 'UTC' => 'UTC' ] ); + $result = $parser->getTimestampRegexp( 'en', $format, '\\d', [ 'UTC' => 'UTC' ] ); self::assertSame( $expected, $result, $message ); } @@ -138,7 +138,7 @@ class CommentParserTest extends CommentTestCase { $expected = new DateTimeImmutable( $expected ); - $tsParser = $parser->getTimestampParser( $format, null, 'UTC', [ 'UTC' => 'UTC' ] ); + $tsParser = $parser->getTimestampParser( 'en', $format, null, 'UTC', [ 'UTC' => 'UTC' ] ); self::assertEquals( $expected, $tsParser( $data ), $message ); } @@ -158,8 +158,8 @@ class CommentParserTest extends CommentTestCase { CommentParser::newFromGlobalState( new DOMELement( 'div' ) ) ); - $regexp = $parser->getTimestampRegexp( $format, '\\d', $timezoneAbbrs ); - $tsParser = $parser->getTimestampParser( $format, null, $timezone, $timezoneAbbrs ); + $regexp = $parser->getTimestampRegexp( 'en', $format, '\\d', $timezoneAbbrs ); + $tsParser = $parser->getTimestampParser( 'en', $format, null, $timezone, $timezoneAbbrs ); $expected = new DateTimeImmutable( $expected ); $expectedUtc = new DateTimeImmutable( $expectedUtc ); diff --git a/tests/qunit/parser.test.js b/tests/qunit/parser.test.js index 25bef208b..19f8aa0ec 100644 --- a/tests/qunit/parser.test.js +++ b/tests/qunit/parser.test.js @@ -13,7 +13,7 @@ QUnit.test( '#getTimestampRegexp', function ( assert ) { cases.forEach( function ( caseItem ) { assert.strictEqual( - parser.getTimestampRegexp( caseItem.format, '\\d', { UTC: 'UTC' } ), + parser.getTimestampRegexp( 'en', caseItem.format, '\\d', { UTC: 'UTC' } ), caseItem.expected, caseItem.message ); @@ -27,7 +27,7 @@ QUnit.test( '#getTimestampParser', function ( assert ) { testUtils.overrideParserData( require( '../data-en.json' ) ); cases.forEach( function ( caseItem ) { - var tsParser = parser.getTimestampParser( caseItem.format, null, 'UTC', { UTC: 'UTC' } ), + var tsParser = parser.getTimestampParser( 'en', caseItem.format, null, 'UTC', { UTC: 'UTC' } ), expectedDate = moment( caseItem.expected ); assert.ok( @@ -44,8 +44,8 @@ QUnit.test( '#getTimestampParser (at DST change)', function ( assert ) { testUtils.overrideParserData( require( '../data-en.json' ) ); cases.forEach( function ( caseItem ) { - var regexp = parser.getTimestampRegexp( caseItem.format, '\\d', caseItem.timezoneAbbrs ), - tsParser = parser.getTimestampParser( caseItem.format, null, caseItem.timezone, caseItem.timezoneAbbrs ), + var regexp = parser.getTimestampRegexp( 'en', caseItem.format, '\\d', caseItem.timezoneAbbrs ), + tsParser = parser.getTimestampParser( 'en', caseItem.format, null, caseItem.timezone, caseItem.timezoneAbbrs ), date = tsParser( caseItem.sample.match( regexp ) ); assert.ok(