Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
plural-comparison.php
Go to the documentation of this file.
1<?php
12use CLDRPluralRuleParser\Evaluator;
13use MediaWiki\Languages\LanguageNameUtils;
14use MediaWiki\MediaWikiServices;
15
16// Standard boilerplate to define $IP
17if ( getenv( 'MW_INSTALL_PATH' ) !== false ) {
18 $IP = getenv( 'MW_INSTALL_PATH' );
19} else {
20 $IP = __DIR__ . '/../../..';
21}
22require_once "$IP/maintenance/Maintenance.php";
23
25class PluralCompare extends Maintenance {
26 public function __construct() {
27 parent::__construct();
28 $this->addDescription( 'Script for comparing different plural implementations.' );
29 }
30
31 public function execute() {
32 $mwLanguages = $this->loadMediaWiki();
33 $gtLanguages = $this->loadGettext();
34 $clLanguages = $this->loadCLDR();
35
36 $all = MediaWikiServices::getInstance()
37 ->getLanguageNameUtils()
38 ->getLanguageNames( null, LanguageNameUtils::ALL );
39 $allkeys = array_keys( $all + $mwLanguages + $gtLanguages + $clLanguages );
40 sort( $allkeys );
41
42 $this->output( sprintf( "%12s %3s %3s %4s\n", 'Code', 'MW', 'Get', 'CLDR' ) );
43 foreach ( $allkeys as $code ) {
44 $mw = isset( $mwLanguages[$code] ) ? '+' : '';
45 $gt = isset( $gtLanguages[$code] ) ? '+' : '';
46 $cl = isset( $clLanguages[$code] ) ? '+' : '';
47
48 if ( $mw === '' ) {
49 $fallbacks = Language::getFallbacksFor( $code );
50 foreach ( $fallbacks as $fcode ) {
51 if ( $fcode !== 'en' && isset( $mwLanguages[$fcode] ) ) {
52 $mw = '.';
53 }
54 }
55 }
56
57 $error = '';
58 if ( substr_count( sprintf( '%s%s%s', $mw, $gt, $cl ), '+' ) > 1 ) {
59 $error = $this->tryMatch( $code, $mw, $gtLanguages, $clLanguages );
60 }
61
62 $this->output( sprintf( "%12s %-3s %-3s %-4s %s\n", $code, $mw, $gt, $cl, $error ) );
63 }
64 }
65
66 protected function tryMatch( $code, $mws, $gtLanguages, $clLanguages ) {
67 if ( $mws !== '' ) {
68 $mwExp = true;
69 $lang = Language::factory( $code );
70 } else {
71 $mwExp = false;
72 }
73
74 if ( isset( $gtLanguages[$code] ) ) {
75 $gtExp = 'return (int) ' . str_replace( 'n', '$i', $gtLanguages[$code] ) . ';';
76 } else {
77 $gtExp = false;
78 }
79
80 $cldrExp = $clLanguages[$code] ?? false;
81
82 for ( $i = 0; $i <= 250; $i++ ) {
83 $mw = $gt = $cl = '?';
84
85 if ( $mwExp ) {
86 // @phan-suppress-next-line PhanPossiblyUndeclaredVariable
87 $exp = $lang->getCompiledPluralRules();
88 $mw = Evaluator::evaluateCompiled( $i, $exp );
89 }
90
91 if ( $gtExp ) {
92 $gt = eval( $gtExp );
93 }
94
95 if ( $cldrExp ) {
96 $cl = Evaluator::evaluate( $i, $cldrExp );
97 }
98
99 if ( self::comp( $mw, $gt ) && self::comp( $gt, $cl ) && self::comp( $cl, $mw ) ) {
100 continue;
101 }
102
103 return "$i: $mw $gt $cl";
104 }
105
106 return '';
107 }
108
109 public static function comp( $a, $b ) {
110 return $a === '?' || $b === '?' || $a === $b;
111 }
112
113 protected function loadPluralFile( $fileName ) {
114 $doc = new DOMDocument;
115 $doc->load( $fileName );
116 $rulesets = $doc->getElementsByTagName( 'pluralRules' );
117 $plurals = [];
118 foreach ( $rulesets as $ruleset ) {
119 $codes = $ruleset->getAttribute( 'locales' );
120 $rules = [];
121 $ruleElements = $ruleset->getElementsByTagName( 'pluralRule' );
122 foreach ( $ruleElements as $elt ) {
123 $rules[] = $elt->nodeValue;
124 }
125 foreach ( explode( ' ', $codes ) as $code ) {
126 $plurals[$code] = $rules;
127 }
128 }
129
130 return $plurals;
131 }
132
133 public function loadCLDR() {
134 global $IP;
135
136 return $this->loadPluralFile( "$IP/languages/data/plurals.xml" );
137 }
138
139 public function loadMediaWiki() {
140 global $IP;
141
142 $rules = $this->loadPluralFile( "$IP/languages/data/plurals.xml" );
143 $rulesMW = $this->loadPluralFile( "$IP/languages/data/plurals-mediawiki.xml" );
144
145 return array_merge( $rules, $rulesMW );
146 }
147
148 public function loadGettext() {
149 $gtData = file_get_contents( __DIR__ . '/../data/plural-gettext.txt' );
150 $gtLanguages = [];
151 foreach ( preg_split( '/\n|\r/', $gtData, -1, PREG_SPLIT_NO_EMPTY ) as $line ) {
152 list( $code, $rule ) = explode( "\t", $line );
153 $rule = preg_replace( '/^.*?plural=/', '', $rule );
154 $gtLanguages[$code] = $rule;
155 }
156
157 return $gtLanguages;
158 }
159}
160
161$maintClass = PluralCompare::class;
162require_once RUN_MAINTENANCE_IF_MAIN;
Script for comparing different plural implementations.