Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
35.90% covered (danger)
35.90%
14 / 39
25.00% covered (danger)
25.00%
2 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
TranslationPage
35.90% covered (danger)
35.90%
14 / 39
25.00% covered (danger)
25.00%
2 / 8
42.87
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 getPageContent
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getMessageCollection
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 filterMessageCollection
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 extractMessages
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 generateSourceFromTranslations
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 generateSourceFromMessageCollection
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 generateSource
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\PageTranslation;
5
6use Content;
7use ContentHandler;
8use Language;
9use MediaWiki\Extension\Translate\MessageLoading\Message;
10use MediaWiki\Extension\Translate\MessageLoading\MessageCollection;
11use MediaWiki\Title\Title;
12use Parser;
13use WikiPageMessageGroup;
14
15/**
16 * Generates wikitext source code for translation pages.
17 *
18 * Also handles loading of translations, but that can be skipped and translations given directly.
19 *
20 * @author Niklas Laxström
21 * @license GPL-2.0-or-later
22 * @since 2020.08
23 */
24class TranslationPage {
25    /** @var ParserOutput */
26    private $output;
27    /** @var WikiPageMessageGroup */
28    private $group;
29    /** @var Language */
30    private $targetLanguage;
31    /** @var Language */
32    private $sourceLanguage;
33    /** @var bool */
34    private $showOutdated;
35    /** @var bool */
36    private $wrapUntranslated;
37    /** @var Title */
38    private $sourcePageTitle;
39
40    public function __construct(
41        ParserOutput $output,
42        WikiPageMessageGroup $group,
43        Language $targetLanguage,
44        Language $sourceLanguage,
45        bool $showOutdated,
46        bool $wrapUntranslated,
47        Title $sourcePageTitle
48    ) {
49        $this->output = $output;
50        $this->group = $group;
51        $this->targetLanguage = $targetLanguage;
52        $this->sourceLanguage = $sourceLanguage;
53        $this->showOutdated = $showOutdated;
54        $this->wrapUntranslated = $wrapUntranslated;
55        $this->sourcePageTitle = $sourcePageTitle;
56    }
57
58    /** @since 2021.07 */
59    public function getPageContent( Parser $parser, ?int &$percentageTranslated = null ): Content {
60        $text = $this->generateSource( $parser, $percentageTranslated );
61        $model = $this->sourcePageTitle->getContentModel();
62        return ContentHandler::makeContent( $text, null, $model );
63    }
64
65    public function getMessageCollection(): MessageCollection {
66        return $this->group->initCollection( $this->targetLanguage->getCode() );
67    }
68
69    public function filterMessageCollection( MessageCollection $collection ): void {
70        $collection->loadTranslations();
71        if ( $this->showOutdated ) {
72            $collection->filter( 'hastranslation', false );
73        } else {
74            $collection->filter( 'translated', false );
75        }
76    }
77
78    /** @return Message[] */
79    private function extractMessages( MessageCollection $collection ): array {
80        $messages = [];
81        $prefix = $this->sourcePageTitle->getPrefixedDBkey() . '/';
82        foreach ( $this->output->units() as $unit ) {
83            // Even if a unit id has spaces, the message collection will have the
84            // key as spaces replaced with underscore. See: T326516
85            $normalizedUnitId = str_replace( ' ', '_', $unit->id );
86            $messages[$unit->id] = $collection[$prefix . $normalizedUnitId] ?? null;
87        }
88
89        return $messages;
90    }
91
92    /**
93     * @param Parser $parser
94     * @param Message[] $messages
95     */
96    public function generateSourceFromTranslations( Parser $parser, array $messages ): string {
97        return $this->output->getPageTextForRendering(
98            $this->sourceLanguage,
99            $this->targetLanguage,
100            $this->wrapUntranslated,
101            $messages,
102            $parser
103        );
104    }
105
106    public function generateSourceFromMessageCollection(
107        Parser $parser,
108        MessageCollection $collection
109    ): string {
110        $messages = $this->extractMessages( $collection );
111        return $this->generateSourceFromTranslations( $parser, $messages );
112    }
113
114    /** Generate translation page source using default options. */
115    private function generateSource( Parser $parser, ?int &$percentageTranslated = null ): string {
116        $collection = $this->getMessageCollection();
117        $allKeys = count( $collection );
118        $this->filterMessageCollection( $collection );
119        $keysWithTranslation = count( $collection );
120
121        if ( $allKeys === 0 ) {
122            $percentageTranslated = 0;
123        } else {
124            $percentageTranslated = (int)( ( $keysWithTranslation / $allKeys ) * 100 );
125        }
126
127        $messages = $this->extractMessages( $collection );
128        return $this->generateSourceFromTranslations( $parser, $messages );
129    }
130}