summaryrefslogtreecommitdiff
blob: 499364449709175243dc43c0a7b24f220e6300a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<?php
/**
 * @file
 * @license GPL-2.0-or-later
 */

namespace MediaWiki\Extension\Translate\Utilities;

/**
 * Implements partial support for SmartFormat plural syntax parsing.
 * @see https://github.com/axuno/SmartFormat/wiki/Pluralization
 * @since 2019.11
 */
class SmartFormatPlural {
	/**
	 * Example input:
	 *   {0} {0:message|messages} older than {1} {1:week|weeks} {0:has|have} been deleted.
	 * Example output:
	 *   [
	 *   	'0' => [
	 *   		[
	 *   			'forms' => [ 'message', 'messages' ],
	 *   			'original' => '{0:message|messages}',
	 *   		],
	 *   		[
	 *   			'forms' => [ 'has', 'have' ],
	 *   			'original' => '{0:has|have}',
	 *   		],
	 *   	],
	 *   	'1' => [
	 *   		[
	 *   			'forms' => [ 'week', 'weeks' ],
	 *   			'original' => '{1:week|weeks}',
	 *   		],
	 *   	],
	 *   ]
	 *
	 * @param string $text
	 * @return array
	 */
	public static function getPluralInstances( string $text ): array {
		// ldns = Large Deeply-Nested Structure
		$ldns = [];

		// Named variables seem to be supported by the spec, but we limit ourselves
		// only to numbers. Example syntax {0:message|messages}
		$regex = '/\{(\d+):([^}]+)\}/Us';
		$matches = [];
		preg_match_all( $regex, $text, $matches, PREG_SET_ORDER );

		foreach ( $matches as $instance ) {
			$original = $instance[ 0 ];
			$variable = $instance[ 1 ];
			$forms = explode( '|', $instance[ 2 ] );
			$ldns[ $variable ] = $ldns[ $variable ] ?? [];
			$ldns[ $variable ][] = [
				'forms' => $forms,
				'original' => $original,
			];
		}

		return $ldns;
	}
}

class_alias( SmartFormatPlural::class, '\MediaWiki\Extensions\Translate\SmartFormatPlural' );