16 private $placeholderFactory;
19 $this->placeholderFactory = $placeholderFactory;
22 public function containsMarkup(
string $text ):
bool {
24 $text = $this->armourNowiki( $nowiki, $text );
25 return preg_match(
'~</?translate[ >]~', $text ) !== 0;
34 $text = $this->armourNowiki( $nowiki, $text );
35 $text = preg_replace(
'~<translate( nowrap)?>\n?~s',
'', $text );
36 $text = preg_replace(
'~\n?</translate>~s',
'', $text );
38 $ic = preg_quote( TranslationUnit::UNIT_MARKER_INVALID_CHARS,
'~' );
39 $text = preg_replace(
"~(^=.*=) <!--T:[^$ic]+-->$~um",
'\1', $text );
40 $text = preg_replace(
"~<!--T:[^$ic]+-->[\n ]?~um",
'', $text );
43 $text = $unit->getTextForTrans();
45 $text = $this->unarmourNowiki( $nowiki, $text );
52 $text = $this->armourNowiki( $nowiki, $text );
55 $tagPlaceHolders = [];
58 $re =
'~(<translate(?: nowrap)?>)(.*?)</translate>~s';
60 $ok = preg_match( $re, $text, $matches, PREG_OFFSET_CAPTURE );
62 if ( $ok === 0 || $ok ===
false ) {
66 $contentWithTags = $matches[0][0];
67 $contentWithoutTags = $matches[2][0];
69 $offsetStart = $matches[0][1];
70 $offsetEnd = $offsetStart + strlen( $contentWithTags );
73 $ph = $this->placeholderFactory->make();
74 $text = substr( $text, 0, $offsetStart ) . $ph . substr( $text, $offsetEnd );
76 if ( preg_match(
'~<translate( nowrap)?>~', $contentWithoutTags ) !== 0 ) {
79 [
'pt-parse-nested', $contentWithoutTags ]
83 $openTag = $matches[1][0];
84 $canWrap = $openTag !==
'<translate nowrap>';
87 $contentWithoutTags = $this->unarmourNowiki( $nowiki, $contentWithoutTags );
88 $parse = $this->parseSection( $contentWithoutTags, $canWrap );
91 $sections += $parse[
'sections'];
92 $tagPlaceHolders[$ph] =
new Section( $openTag, $parse[
'template'],
'</translate>' );
95 $prettyTemplate = $text;
96 foreach ( $tagPlaceHolders as $ph => $value ) {
97 $prettyTemplate = str_replace( $ph,
'[...]', $prettyTemplate );
100 if ( preg_match(
'~<translate( nowrap)?>~', $text ) !== 0 ) {
101 throw new ParsingFailure(
102 'Unmatched opening tag',
103 [
'pt-parse-open', $prettyTemplate ]
105 } elseif ( strpos( $text,
'</translate>' ) !==
false ) {
106 throw new ParsingFailure(
107 "Unmatched closing tag",
108 [
'pt-parse-close', $prettyTemplate ]
112 $text = $this->unarmourNowiki( $nowiki, $text );
114 return new ParserOutput( $text, $tagPlaceHolders, $sections );
124 $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE;
125 $parts = preg_split(
'~(^\s*|\s*\n\n\s*|\s*$)~', $text, -1, $flags );
127 $inline = preg_match(
'~\n~', $text ) === 0;
132 foreach ( $parts as $_ ) {
133 if ( trim( $_ ) ===
'' ) {
136 $ph = $this->placeholderFactory->make();
137 $tpsection = $this->parseUnit( $_ );
138 $tpsection->setIsInline( $inline );
139 $tpsection->setCanWrap( $canWrap );
140 $sections[$ph] = $tpsection;
146 'template' => $template,
147 'sections' => $sections,
158 $re =
'~<!--T:(.*?)-->~';
160 $count = preg_match_all( $re, $content, $matches, PREG_SET_ORDER );
164 'Multiple translation unit markers',
165 [
'pt-shake-multiple', $content ]
170 $id = TranslationUnit::NEW_UNIT_ID;
171 if ( $count === 1 ) {
172 foreach ( $matches as $match ) {
177 $rer1 =
'~^<!--T:(.*?)-->( |\n)~';
178 $rer2 =
'~\s*<!--T:(.*?)-->$~m';
179 $content = preg_replace( $rer1,
'', $content );
180 $content = preg_replace( $rer2,
'', $content );
182 if ( preg_match( $re, $content ) === 1 ) {
184 'Translation unit marker is in unsupported position',
185 [
'pt-shake-position', $content ]
187 } elseif ( trim( $content ) ===
'' ) {
188 throw new ParsingFailure(
189 'Translation unit has no content besides marker',
190 [
'pt-shake-empty', $id ]
196 return new TranslationUnit( $content, $id );
200 public function armourNowiki( array &$holders,
string $text ): string {
201 $re =
'~(<nowiki>)(.*?)(</nowiki>)~s';
203 while ( preg_match( $re, $text, $matches ) ) {
204 $ph = $this->placeholderFactory->make();
205 $text = str_replace( $matches[0], $ph, $text );
206 $holders[$ph] = $matches[0];
213 public function unarmourNowiki( array $holders,
string $text ): string {
214 return strtr( $text, $holders );
return[ 'Translate:ConfigHelper'=> static function():ConfigHelper { return new ConfigHelper();}, 'Translate:CsvTranslationImporter'=> static function(MediaWikiServices $services):CsvTranslationImporter { return new CsvTranslationImporter( $services->getWikiPageFactory());}, 'Translate:EntitySearch'=> static function(MediaWikiServices $services):EntitySearch { return new EntitySearch($services->getMainWANObjectCache(), $services->getCollationFactory() ->makeCollation( 'uca-default-u-kn'), MessageGroups::singleton(), $services->getNamespaceInfo(), $services->get( 'Translate:MessageIndex'), $services->getTitleParser(), $services->getTitleFormatter());}, 'Translate:ExternalMessageSourceStateImporter'=> static function(MediaWikiServices $services):ExternalMessageSourceStateImporter { return new ExternalMessageSourceStateImporter($services->getMainConfig(), $services->get( 'Translate:GroupSynchronizationCache'), $services->getJobQueueGroup(), LoggerFactory::getInstance( 'Translate.GroupSynchronization'), MessageIndex::singleton());}, 'Translate:GroupSynchronizationCache'=> static function(MediaWikiServices $services):GroupSynchronizationCache { return new GroupSynchronizationCache( $services->get( 'Translate:PersistentCache'));}, 'Translate:MessageBundleStore'=> static function(MediaWikiServices $services):MessageBundleStore { return new MessageBundleStore(new RevTagStore(), $services->getJobQueueGroup(), $services->getLanguageNameUtils(), $services->get( 'Translate:MessageIndex'));}, 'Translate:MessageGroupReview'=> static function(MediaWikiServices $services):MessageGroupReview { return new MessageGroupReview($services->getDBLoadBalancer(), $services->getHookContainer());}, 'Translate:MessageIndex'=> static function(MediaWikiServices $services):MessageIndex { $params=$services->getMainConfig() ->get( 'TranslateMessageIndex');if(is_string( $params)) { $params=(array) $params;} $class=array_shift( $params);return new $class( $params);}, 'Translate:ParsingPlaceholderFactory'=> static function():ParsingPlaceholderFactory { return new ParsingPlaceholderFactory();}, 'Translate:PersistentCache'=> static function(MediaWikiServices $services):PersistentCache { return new PersistentDatabaseCache($services->getDBLoadBalancer(), $services->getJsonCodec());}, 'Translate:ProgressStatsTableFactory'=> static function(MediaWikiServices $services):ProgressStatsTableFactory { return new ProgressStatsTableFactory($services->getLinkRenderer(), $services->get( 'Translate:ConfigHelper'));}, 'Translate:SubpageListBuilder'=> static function(MediaWikiServices $services):SubpageListBuilder { return new SubpageListBuilder($services->get( 'Translate:TranslatableBundleFactory'), $services->getLinkBatchFactory());}, 'Translate:TranslatableBundleFactory'=> static function(MediaWikiServices $services):TranslatableBundleFactory { return new TranslatableBundleFactory($services->get( 'Translate:TranslatablePageStore'), $services->get( 'Translate:MessageBundleStore'));}, 'Translate:TranslatableBundleMover'=> static function(MediaWikiServices $services):TranslatableBundleMover { return new TranslatableBundleMover($services->getMovePageFactory(), $services->getJobQueueGroup(), $services->getLinkBatchFactory(), $services->get( 'Translate:TranslatableBundleFactory'), $services->get( 'Translate:SubpageListBuilder'), $services->getMainConfig() ->get( 'TranslatePageMoveLimit'));}, 'Translate:TranslatablePageParser'=> static function(MediaWikiServices $services):TranslatablePageParser { return new TranslatablePageParser($services->get( 'Translate:ParsingPlaceholderFactory'));}, 'Translate:TranslatablePageStore'=> static function(MediaWikiServices $services):TranslatablePageStore { return new TranslatablePageStore($services->get( 'Translate:MessageIndex'), $services->getJobQueueGroup(), new RevTagStore(), $services->getDBLoadBalancer());}, 'Translate:TranslationStashReader'=> static function(MediaWikiServices $services):TranslationStashReader { $db=$services->getDBLoadBalancer() ->getConnectionRef(DB_REPLICA);return new TranslationStashStorage( $db);}, 'Translate:TranslationStatsDataProvider'=> static function(MediaWikiServices $services):TranslationStatsDataProvider { return new TranslationStatsDataProvider(new ServiceOptions(TranslationStatsDataProvider::CONSTRUCTOR_OPTIONS, $services->getMainConfig()), $services->getObjectFactory());}, 'Translate:TranslationUnitStoreFactory'=> static function(MediaWikiServices $services):TranslationUnitStoreFactory { return new TranslationUnitStoreFactory( $services->getDBLoadBalancer());}, 'Translate:TranslatorActivity'=> static function(MediaWikiServices $services):TranslatorActivity { $query=new TranslatorActivityQuery($services->getMainConfig(), $services->getDBLoadBalancer());return new TranslatorActivity($services->getMainObjectStash(), $query, $services->getJobQueueGroup());}, 'Translate:TtmServerFactory'=> static function(MediaWikiServices $services):TtmServerFactory { $config=$services->getMainConfig();$default=$config->get( 'TranslateTranslationDefaultService');if( $default===false) { $default=null;} return new TtmServerFactory( $config->get( 'TranslateTranslationServices'), $default);}]
@phpcs-require-sorted-array