34 public function __construct(
35 private readonly Language $contentLanguage,
36 private readonly LanguageNameUtils $languageNameUtils,
37 private readonly IConnectionProvider $dbProvider,
38 private readonly SearchEngineFactory $searchEngineFactory,
40 parent::__construct(
'Translations' );
43 protected function getGroupName():
string {
49 return $this->msg(
'translations' );
54 return $this->prefixSearchString( $search, $limit, $offset, $this->searchEngineFactory );
64 $this->outputHeader();
66 $out = $this->getOutput();
67 $out->addModuleStyles(
'ext.translate.specialpages.styles' );
71 if ( $this->including() ) {
72 $title = Title::newFromText( $par );
74 $out->addWikiMsg(
'translate-translations-including-no-param' );
76 $this->showTranslations( $title );
85 $request = $this->getRequest();
86 $message = $request->getText(
'message', $par );
87 $namespace = $request->getInt(
'namespace', NS_MAIN );
89 $title = Title::newFromText( $message, $namespace );
92 'Help:Extension:Translate/Statistics_and_reporting#Translations_in_all_languages'
96 $title = Title::makeTitle( NS_MEDIAWIKI,
'' );
97 $this->namespaceMessageForm( $title );
99 $this->namespaceMessageForm( $title );
100 $out->addHTML(
'<br />' );
101 $this->showTranslations( $title );
108 private function namespaceMessageForm( Title $title ): void {
114 'label-message' =>
'translate-translations-messagename',
116 'default' => $title->getText(),
120 'name' =>
'namespace',
122 'label-message' =>
'translate-translations-project',
123 'options' => $this->getSortedNamespaces(),
124 'default' => $title->getNamespace(),
128 HTMLForm::factory(
'ooui', $formDescriptor, $this->getContext() )
130 ->setTitle( $this->getPageTitle() )
131 ->setSubmitTextMsg(
'allpagessubmit' )
132 ->setWrapperLegendMsg(
'translate-translations-fieldset-title' )
134 ->displayForm(
false );
142 private function getSortedNamespaces(): array {
144 foreach ( $this->getConfig()->
get(
'TranslateMessageNamespaces' ) as $ns ) {
145 $nslist[$this->contentLanguage->getFormattedNsText( $ns )] = $ns;
155 private function showTranslations( Title $title ): void {
156 $handle = new MessageHandle( $title );
157 $namespace = $title->getNamespace();
159 if ( !$handle->isValid() ) {
160 $this->getOutput()->addWikiMsg(
'translate-translations-no-message', $title->getPrefixedText() );
165 $revisions = Utilities::getTranslationRevisions( $handle );
168 $this->getOutput()->addWikiMsg(
169 'translate-translations-no-message',
170 $title->getPrefixedText()
175 $this->getOutput()->addWikiMsg(
176 'translate-translations-count',
177 Message::numParam( count( $revisions ) )
185 Html::element(
'th', [], $this->msg(
'allmessagesname' )->text() ) .
186 Html::element(
'th', [], $this->msg(
'allmessagescurrent' )->text() ) .
187 Html::element(
'th', [], $this->msg(
'translate-translations-last-edit-header' )->text() )
191 $historyText =
"\u{00A0}<sup>" .
192 $this->msg(
'translate-translations-history-short' )->escaped() .
194 $separator = $this->msg(
'word-separator' )->plain();
196 foreach ( $revisions as $key => $revision ) {
197 $tTitle = Title::makeTitle( $namespace, $key );
198 $tHandle =
new MessageHandle( $tTitle );
200 $code = $tHandle->getCode();
202 $text = Utilities::getLanguageName( $code, $this->getLanguage()->getCode() );
204 $text .= $this->msg(
'parentheses' )->params( $code )->plain();
206 'edit' => Html::element(
208 [
'href' => Utilities::getEditorUrl( $tHandle ) ],
211 'history' => $this->getLinkRenderer()->makeLink(
213 new HtmlArmor( $historyText ),
215 'title' => $this->msg(
'history-title', $tTitle->getPrefixedDBkey() )->text()
217 [
'action' =>
'history' ]
221 $mainContent = $revision->getContent( SlotRecord::MAIN );
223 $pageText = Utilities::getTextFromTextContent( $mainContent );
224 }
catch ( UnexpectedValueException ) {
229 if ( MessageHandle::hasFuzzyString( $pageText ) || $tHandle->isFuzzy() ) {
230 $class =
'mw-sp-translate-fuzzy';
233 $languageAttributes = [];
234 if ( $this->languageNameUtils->isKnownLanguageTag( $code ) ) {
235 $language = $tHandle->getEffectiveLanguage();
236 $languageAttributes = [
237 'lang' => $language->getHtmlCode(),
238 'dir' => $language->getDir(),
242 $formattedContent = Utilities::convertWhiteSpaceToHTML( $pageText );
245 $revTimestamp = $revision->getTimestamp();
246 $unixTimestamp = wfTimestamp( TS_UNIX, $revTimestamp );
247 $humanTimestamp = $this->getLanguage()->getHumanTimestamp(
new MWTimestamp( $revTimestamp ) );
249 $user = $revision->getUser( RevisionRecord::FOR_PUBLIC );
250 if ( $user !==
null ) {
251 $userLinkHtml = $this->getLinkRenderer()->makeUserLink( $user, $this->getContext() );
253 $userLinkHtml = Html::element(
255 [
'class' =>
'history-deleted' ],
256 $this->msg(
'rev-deleted-user' )->text()
260 $lastEditHtml = $this->msg(
'translate-translations-last-edit' )
261 ->params( $humanTimestamp )
262 ->rawParams( $userLinkHtml )
265 $rows[] = Html::rawElement(
267 [
'class' => $class ],
268 Html::rawElement(
'td', [], $tools[
'history'] . $tools[
'edit'] ) .
269 Html::rawElement(
'td', $languageAttributes, $formattedContent ) .
270 Html::rawElement(
'td', [
'data-sort-value' => $unixTimestamp ], $lastEditHtml )
274 $out = Html::rawElement(
276 [
'class' =>
'mw-sp-translate-table sortable wikitable' ],
277 "\n" . implode(
"\n", $rows ) .
"\n"
279 $this->getOutput()->addHTML( $out );