Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F1427208
MediaWikiPluralValidator.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
MediaWikiPluralValidator.php
View Options
<?php
declare
(
strict_types
=
1
);
namespace
MediaWiki\Extension\Translate\Validation\Validators
;
use
MediaWiki\Extension\Translate\MessageLoading\Message
;
use
MediaWiki\Extension\Translate\Validation\MessageValidator
;
use
MediaWiki\Extension\Translate\Validation\ValidationIssue
;
use
MediaWiki\Extension\Translate\Validation\ValidationIssues
;
use
MediaWiki\Languages\LanguageFactory
;
use
MediaWiki\Parser\Parser
;
use
MediaWiki\User\UserFactory
;
use
ParserFactory
;
use
ParserOptions
;
use
PPFrame
;
/**
* Handles plural validation for MediaWiki inline plural syntax.
* @author Abijeet Patro
* @license GPL-2.0-or-later
* @since 2019.06
*/
class
MediaWikiPluralValidator
implements
MessageValidator
{
/** @var LanguageFactory */
private
$languageFactory
;
/** @var ParserFactory */
private
$parserFactory
;
/** @var UserFactory */
private
$userFactory
;
public
function
__construct
(
LanguageFactory
$languageFactory
,
ParserFactory
$parserFactory
,
UserFactory
$userFactory
)
{
$this
->
languageFactory
=
$languageFactory
;
$this
->
parserFactory
=
$parserFactory
;
$this
->
userFactory
=
$userFactory
;
}
public
function
getIssues
(
Message
$message
,
string
$targetLanguage
):
ValidationIssues
{
$issues
=
new
ValidationIssues
();
$this
->
pluralCheck
(
$message
,
$issues
);
$this
->
pluralFormsCheck
(
$message
,
$targetLanguage
,
$issues
);
return
$issues
;
}
private
function
pluralCheck
(
Message
$message
,
ValidationIssues
$issues
):
void
{
$definition
=
$message
->
definition
();
$translation
=
$message
->
translation
();
if
(
stripos
(
$definition
,
'{{plural:'
)
!==
false
&&
stripos
(
$translation
,
'{{plural:'
)
===
false
)
{
$issue
=
new
ValidationIssue
(
'plural'
,
'missing'
,
'translate-checks-plural'
);
$issues
->
add
(
$issue
);
}
}
protected
function
pluralFormsCheck
(
Message
$message
,
string
$code
,
ValidationIssues
$issues
):
void
{
$translation
=
$message
->
translation
();
// Are there any plural forms for this language in this message?
if
(
stripos
(
$translation
,
'{{plural:'
)
===
false
)
{
return
;
}
$plurals
=
$this
->
getPluralForms
(
$translation
);
$allowed
=
$this
->
getPluralFormCount
(
$code
);
foreach
(
$plurals
as
$forms
)
{
$forms
=
self
::
removeExplicitPluralForms
(
$forms
);
$provided
=
count
(
$forms
);
if
(
$provided
>
$allowed
)
{
$issue
=
new
ValidationIssue
(
'plural'
,
'forms'
,
'translate-checks-plural-forms'
,
[
[
'COUNT'
,
$provided
],
[
'COUNT'
,
$allowed
],
]
);
$issues
->
add
(
$issue
);
}
// Are the last two forms identical?
if
(
$provided
>
1
&&
$forms
[
$provided
-
1
]
===
$forms
[
$provided
-
2
]
)
{
$issue
=
new
ValidationIssue
(
'plural'
,
'dupe'
,
'translate-checks-plural-dupe'
);
$issues
->
add
(
$issue
);
}
}
}
/** Returns the number of plural forms %MediaWiki supports for a language. */
public
function
getPluralFormCount
(
string
$code
):
int
{
$forms
=
$this
->
languageFactory
->
getLanguage
(
$code
)->
getPluralRules
();
// +1 for the 'other' form
return
count
(
$forms
)
+
1
;
}
/**
* Ugly home made probably awfully slow looping parser that parses {{PLURAL}} instances from
* a message and returns array of invocations having array of forms.
*
* @return array[]
*/
public
function
getPluralForms
(
string
$translation
):
array
{
// Stores the forms from plural invocations
$plurals
=
[];
$cb
=
static
function
(
$parser
,
$frame
,
$args
)
use
(
&
$plurals
)
{
$forms
=
[];
foreach
(
$args
as
$index
=>
$form
)
{
// The first arg is the number, we skip it
if
(
$index
!==
0
)
{
// Collect the raw text
$forms
[]
=
$frame
->
expand
(
$form
,
PPFrame
::
RECOVER_ORIG
);
// Expand the text to process embedded plurals
$frame
->
expand
(
$form
);
}
}
$plurals
[]
=
$forms
;
return
''
;
};
// Setup parser
$parser
=
$this
->
parserFactory
->
create
();
$parser
->
setFunctionHook
(
'plural'
,
$cb
,
Parser
::
SFH_NO_HASH
|
Parser
::
SFH_OBJECT_ARGS
);
// Setup things needed for preprocess
$title
=
null
;
$options
=
ParserOptions
::
newFromUserAndLang
(
$this
->
userFactory
->
newAnonymous
(),
$this
->
languageFactory
->
getLanguage
(
'en'
)
);
$parser
->
preprocess
(
$translation
,
$title
,
$options
);
return
$plurals
;
}
/** Remove forms that start with an explicit number. */
public
static
function
removeExplicitPluralForms
(
array
$forms
):
array
{
// Handle explicit 0= and 1= forms
foreach
(
$forms
as
$index
=>
$form
)
{
if
(
preg_match
(
'/^[0-9]+=/'
,
$form
)
)
{
unset
(
$forms
[
$index
]
);
}
}
return
array_values
(
$forms
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, May 16, 14:21 (1 d, 10 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
49/04/e234eab723f51eb25316cdbe6d55
Default Alt Text
MediaWikiPluralValidator.php (4 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment