summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'MLEB/Translate/scripts/export-rename-language.php')
-rw-r--r--MLEB/Translate/scripts/export-rename-language.php148
1 files changed, 148 insertions, 0 deletions
diff --git a/MLEB/Translate/scripts/export-rename-language.php b/MLEB/Translate/scripts/export-rename-language.php
new file mode 100644
index 00000000..bdfc6172
--- /dev/null
+++ b/MLEB/Translate/scripts/export-rename-language.php
@@ -0,0 +1,148 @@
+<?php
+/**
+ * Script to automate renaming of language codes in supported repos.
+ *
+ * @license GPL-2.0-or-later
+ * @file
+ */
+
+// Standard boilerplate to define $IP
+if ( getenv( 'MW_INSTALL_PATH' ) !== false ) {
+ $IP = getenv( 'MW_INSTALL_PATH' );
+} else {
+ $dir = __DIR__;
+ $IP = "$dir/../../..";
+}
+require_once "$IP/maintenance/Maintenance.php";
+
+class ExportRenameLanguage extends Maintenance {
+ private const MARKER = '%CODE%';
+
+ public function __construct() {
+ parent::__construct();
+ $this->addDescription( 'Renames language codes in repos.' );
+ $this->addOption(
+ 'group',
+ 'Comma separated list of group IDs (can use * as wildcard)',
+ true, /*required*/
+ true /*has arg*/
+ );
+ $this->addOption(
+ 'source-language',
+ 'Language code',
+ true, /*required*/
+ true /*has arg*/
+ );
+
+ $this->addOption(
+ 'target-language',
+ 'Language code',
+ true, /*required*/
+ true /*has arg*/
+ );
+ $this->addOption(
+ 'target',
+ 'Target directory for exported files',
+ true, /*required*/
+ true /*has arg*/
+ );
+ $this->requireExtension( 'Translate' );
+ }
+
+ public function execute() {
+ $target = rtrim( $this->getOption( 'target' ), '/' );
+ $sourceLanguage = $this->getOption( 'source-language' );
+ $targetLanguage = $this->getOption( 'target-language' );
+
+ if ( !is_writable( $target ) ) {
+ $this->fatalError( "Target directory is not writable ($target)." );
+ }
+
+ $groupIds = explode( ',', trim( $this->getOption( 'group' ) ) );
+ $groupIds = MessageGroups::expandWildcards( $groupIds );
+ $groups = MessageGroups::getGroupsById( $groupIds );
+ $groups = $this->filterGroups( $groups );
+
+ if ( $groups === [] ) {
+ $this->fatalError( 'EE1: No valid message groups identified.' );
+ }
+
+ foreach ( $groups as $group ) {
+ // Source path can be wrong if source language is the source language of the
+ // message group. This is because getTargetFilename doesn't check definitionFile
+ // property first.
+ $sourcePath = $group->getTargetFilename( $sourceLanguage );
+ $targetPath = $group->getTargetFilename( $targetLanguage );
+
+ if ( !file_exists( "$target/$sourcePath" ) ) {
+ continue;
+ }
+
+ $this->output( "Renaming $sourcePath to $targetPath\n" );
+ $this->renameFile( "$target/$sourcePath", "$target/$targetPath" );
+
+ $pathPattern = "$target/" . $group->getTargetFilename( self::MARKER );
+ $pathToRemove = '';
+ $needsCleanup = $this->needsCleanup( $pathPattern, $sourceLanguage, $pathToRemove );
+ if ( $needsCleanup === 'yes' ) {
+ $this->output( "Removing empty directory $pathToRemove\n" );
+ rmdir( $pathToRemove );
+ } elseif ( $needsCleanup === 'maybe' ) {
+ $this->output( "Not removing (yet?) non-empty directory $pathToRemove\n" );
+ }
+ }
+
+ $this->output( "Done\n" );
+ }
+
+ /**
+ * @param MessageGroup[] $groups
+ * @return FileBasedMessageGroup[]
+ */
+ private function filterGroups( array $groups ) {
+ foreach ( $groups as $groupId => $group ) {
+ if ( !$group instanceof FileBasedMessageGroup ) {
+ $this->output( "Skipping non-file based message group $groupId.\n" );
+ unset( $groups[$groupId] );
+ }
+ }
+ return $groups;
+ }
+
+ private function renameFile( $source, $target ) {
+ // In case %CODE% is in the path
+ if ( !is_dir( dirname( $target ) ) ) {
+ mkdir( dirname( $target ), 0777, true );
+ }
+
+ rename( $source, $target );
+ }
+
+ private function isDirectoryEmpty( $dir ) {
+ return array_diff( scandir( $dir ), [ '..', '.' ] ) === [];
+ }
+
+ private function needsCleanup( $pathPattern, $sourceLanguage, &$pathToRemove ) {
+ do {
+ $currentComponent = basename( $pathPattern );
+ if ( strpos( $currentComponent, self::MARKER ) === false ) {
+ $pathPattern = dirname( $pathPattern );
+ continue;
+ }
+
+ $pathToRemove = str_replace( self::MARKER, $sourceLanguage, $pathPattern );
+ if ( !is_dir( $pathToRemove ) ) {
+ // %CODE% is in the filename
+ return 'no';
+ }
+
+ return $this->isDirectoryEmpty( $pathToRemove ) ? 'yes' : 'maybe';
+ } while ( $currentComponent !== '' );
+
+ // This should never be reached.
+ return 'no';
+ }
+}
+
+$maintClass = ExportRenameLanguage::class;
+require_once RUN_MAINTENANCE_IF_MAIN;