16use Wikimedia\Bcp47Code\Bcp47Code;
17use Wikimedia\Bcp47Code\Bcp47CodeValue;
19use Wikimedia\Parsoid\Config\PageConfig;
20use Wikimedia\Parsoid\Config\SiteConfig;
21use Wikimedia\Parsoid\Core\PageBundle;
22use Wikimedia\Parsoid\DOM\Element;
23use Wikimedia\Parsoid\Parsoid;
24use Wikimedia\Parsoid\Utils\DOMCompat;
25use Wikimedia\Parsoid\Utils\DOMUtils;
33 private ?PageConfig $pageConfig =
null;
35 private Title $pageTitle;
36 private Parsoid $parsoid;
37 private SiteConfig $siteConfig;
43 private ?Bcp47Code $pageLanguageOverride =
null;
44 private bool $isFallbackLanguageConverterEnabled =
true;
50 SiteConfig $siteConfig,
55 $this->pageConfigFactory = $pageConfigFactory;
56 $this->pageIdentity = $pageIdentity;
57 $this->parsoid = $parsoid;
58 $this->siteConfig = $siteConfig;
60 $this->languageConverterFactory = $languageConverterFactory;
61 $this->languageFactory = $languageFactory;
72 $this->pageConfig = $pageConfig;
82 $this->pageLanguageOverride = $language;
97 PageBundle $pageBundle,
98 Bcp47Code $targetVariant,
99 ?Bcp47Code $sourceVariant =
null
101 [ $pageLanguage, $sourceVariant ] =
102 $this->getBaseAndSourceLanguage( $pageBundle, $sourceVariant );
104 if ( !$this->siteConfig->langConverterEnabledBcp47( $pageLanguage ) ) {
109 $pageConfig = $this->getPageConfig( $pageLanguage, $sourceVariant );
111 if ( $this->parsoid->implementsLanguageConversionBcp47( $pageConfig, $targetVariant ) ) {
112 return $this->parsoid->pb2pb(
113 $pageConfig,
'variant', $pageBundle,
116 'source' => $sourceVariant,
117 'target' => $targetVariant,
122 if ( !$this->isFallbackLanguageConverterEnabled ) {
130 $baseLanguage = $this->languageFactory->getParentLanguage( $targetVariant );
131 $languageConverter = $this->languageConverterFactory->getLanguageConverter( $baseLanguage );
132 $targetVariantCode = $this->languageFactory->getLanguage( $targetVariant )->getCode();
133 if ( $languageConverter->hasVariant( $targetVariantCode ) ) {
137 $convertedHtml = $languageConverter->convertTo( $pageBundle->html, $targetVariantCode );
138 $pageVariant = $targetVariant;
141 $convertedHtml = $pageBundle->html;
142 $pageVariant = $pageConfig->getPageLanguageBcp47();
146 $msg =
"<!-- Variant conversion performed using the core LanguageConverter -->";
147 $convertedHtml = $msg . $convertedHtml;
152 'content-language' => $pageVariant->toBcp47Code(),
153 'vary' => [
'Accept',
'Accept-Language' ]
155 $doc = DOMUtils::parseHTML(
'' );
156 $doc->appendChild( $doc->createElement(
'head' ) );
157 DOMUtils::addHttpEquivHeaders( $doc, $headers );
158 $docElt = $doc->documentElement;
159 '@phan-var Element $docElt';
160 $docHtml = DOMCompat::getOuterHTML( $docElt );
161 $convertedHtml = preg_replace(
"#</body>#", $docHtml,
"$convertedHtml</body>" );
162 return new PageBundle(
163 $convertedHtml, [], [], $pageBundle->version, $headers
179 Bcp47Code $targetVariant,
180 ?Bcp47Code $sourceVariant =
null
183 $modifiedPageBundle = $this->convertPageBundleVariant( $pageBundle, $targetVariant, $sourceVariant );
192 $this->isFallbackLanguageConverterEnabled = false;
195 private function getPageConfig( Bcp47Code $pageLanguage, ?Bcp47Code $sourceVariant ): PageConfig {
196 if ( $this->pageConfig ) {
197 return $this->pageConfig;
201 $this->pageConfig = $this->pageConfigFactory->create(
209 if ( $sourceVariant ) {
210 $this->pageConfig->setVariantBcp47( $sourceVariant );
212 }
catch ( RevisionAccessException $exception ) {
215 throw new LocalizedHttpException(
new MessageValue(
"rest-specified-revision-unavailable" ), 404 );
218 return $this->pageConfig;
247 private function getPageLanguage( PageBundle $pageBundle, ?Bcp47Code $default =
null ): Bcp47Code {
249 if ( $this->pageLanguageOverride ) {
250 return $this->pageLanguageOverride;
254 $pageBundleLanguage = $pageBundle->headers[
'content-language' ] ??
null;
255 if ( $pageBundleLanguage ) {
258 return new Bcp47CodeValue( $pageBundleLanguage );
269 if ( $this->pageConfig ) {
270 return $this->pageConfig->getPageLanguageBcp47();
275 return $this->pageTitle->getPageLanguage();
293 private function getBaseAndSourceLanguage( PageBundle $pageBundle, ?Bcp47Code $sourceLanguage ): array {
296 $baseLanguage = $this->getPageLanguage( $pageBundle, $sourceLanguage );
299 $parentLang = $this->languageFactory->getParentLanguage( $baseLanguage );
305 if ( $parentLang && strcasecmp( $parentLang->toBcp47Code(), $baseLanguage->toBcp47Code() ) !== 0 ) {
306 if ( !$sourceLanguage ) {
307 $sourceLanguage = $baseLanguage;
309 $baseLanguage = $parentLang;
312 if ( $sourceLanguage !==
null ) {
313 $parentConverter = $this->languageConverterFactory->getLanguageConverter( $parentLang );
316 strcasecmp( $parentLang->toBcp47Code(), $sourceLanguage->toBcp47Code() ) !== 0 &&
317 $parentConverter->hasVariant(
318 LanguageCode::bcp47ToInternal( $sourceLanguage->toBcp47Code() )
321 if ( !$sourceIsVariant ) {
322 $sourceLanguage =
null;
326 return [ $baseLanguage, $sourceLanguage ];
if(!defined('MW_SETUP_CALLBACK'))
Helper class used by MediaWiki to create Parsoid PageConfig objects.
Provides methods for conversion between PageBundle and ParserOutput TODO: Convert to a trait once we ...
static parserOutputFromPageBundle(PageBundle $pageBundle, ?ParserOutput $originalParserOutput=null)
Creates a ParserOutput object containing the relevant data from the given PageBundle object.
Interface for objects (potentially) representing an editable wiki page.