public function execute() { $output = $this->getOption('output', 'default'); // Select an output engine switch ($output) { case 'wiki': $out = new WikiStatsOutput(); break; case 'text': $out = new TextStatsOutput(); break; case 'csv': $out = new CsvStatsOutput(); break; default: $out = new TranslateStatsOutput(); } $skipLanguages = array(); if ($this->hasOption('skiplanguages')) { $skipLanguages = array_map('trim', explode(',', $this->getOption('skiplanguages'))); } $reportScore = false; // Check if score should be reported and prepare weights $most = $this->getOption('most'); $weights = array(); if ($most && isset($this->localisedWeights[$most])) { $reportScore = true; foreach ($this->localisedWeights[$most] as $weight) { $weights[] = $weight; } } // check if l10n should be done $l10n = false; if (($output === 'wiki' || $output === 'default') && !$this->hasOption('nol10n')) { $l10n = true; } $wmfscore = $this->hasOption('wmfscore'); // Get groups from input $groups = array(); if ($reportScore) { $reqGroups = array_keys($this->localisedWeights[$most]); } elseif ($wmfscore) { $reqGroups = array_keys($this->localisedWeights['wikimedia']); } else { $reqGroups = array_map('trim', explode(',', $this->getOption('groups'))); } // List of all groups $allGroups = MessageGroups::singleton()->getGroups(); // Get list of valid groups foreach ($reqGroups as $id) { // Page translation group ids use spaces which are not nice on command line $id = str_replace('_', ' ', $id); if (isset($allGroups[$id])) { $groups[$id] = $allGroups[$id]; } else { $this->output("Unknown group: {$id}"); } } if ($wmfscore) { // Override/set parameters $out = new CsvStatsOutput(); $reportScore = true; $weights = array(); foreach ($this->localisedWeights['wikimedia'] as $weight) { $weights[] = $weight; } $wmfscores = array(); } if (!count($groups)) { $this->error('No groups given', true); } // List of all languages. $languages = Language::fetchLanguageNames(false); // Default sorting order by language code, users can sort wiki output. ksort($languages); if ($this->hasOption('legenddetail')) { $out->addFreeText("{{" . $this->getOption('legenddetail') . "}}\n"); } $totalWeight = 0; if ($reportScore) { if ($wmfscore) { foreach ($this->localisedWeights['wikimedia'] as $weight) { $totalWeight += $weight; } } else { foreach ($this->localisedWeights[$most] as $weight) { $totalWeight += $weight; } } } $showContinent = $this->getOption('continent'); if (!$wmfscore) { // Output headers $out->heading(); $out->blockstart(); if ($most) { $out->element($l10n ? "{{int:translate-gs-pos}}" : 'Pos.', true); } $out->element($l10n ? "{{int:translate-gs-code}}" : 'Code', true); $out->element($l10n ? "{{int:translate-page-language}}" : 'Language', true); if ($showContinent) { $out->element($l10n ? "{{int:translate-gs-continent}}" : 'Continent', true); } if ($most && $this->hasOption('speakers')) { $out->element($l10n ? "{{int:translate-gs-speakers}}" : 'Speakers', true); } if ($reportScore) { $out->element(($l10n ? "{{int:translate-gs-score}}" : 'Score') . ' (' . $totalWeight . ')', true); } /** * @var $g MessageGroup */ foreach ($groups as $g) { // Add unprocessed description of group as heading if ($reportScore) { $gid = $g->getId(); $heading = $g->getLabel() . " (" . $this->localisedWeights[$most][$gid] . ")"; } else { $heading = $g->getLabel(); } $out->element($heading, true); if (!$reportScore && $this->hasOption('fuzzy')) { $out->element($l10n ? "{{int:translate-percentage-fuzzy}}" : 'Fuzzy', true); } } $out->blockend(); } $rows = array(); foreach ($languages as $code => $name) { // Skip list if (in_array($code, $skipLanguages)) { continue; } $rows[$code] = array(); } foreach ($groups as $groupName => $g) { $stats = MessageGroupStats::forGroup($groupName); // Perform the statistic calculations on every language foreach ($languages as $code => $name) { // Skip list if (!$most && in_array($code, $skipLanguages)) { continue; } // Do not calculate if we do not need it for anything. if ($wmfscore && isset($this->wikimediaCodeMap[$code]) && $this->wikimediaCodeMap[$code] == '') { continue; } // If --most is set, skip all other if ($most && !isset($this->mostSpokenLanguages[$code])) { continue; } $total = $stats[$code][MessageGroupStats::TOTAL]; $translated = $stats[$code][MessageGroupStats::TRANSLATED]; $fuzzy = $stats[$code][MessageGroupStats::FUZZY]; $rows[$code][] = array(false, $translated, $total); if ($this->hasOption('fuzzy')) { $rows[$code][] = array(true, $fuzzy, $total); } } unset($collection); } // init summary array $summarise = false; if ($this->hasOption('summary')) { $summarise = true; $summary = array(); } foreach ($languages as $code => $name) { // Skip list if (!$most && in_array($code, $skipLanguages)) { continue; } // Skip unneeded if ($wmfscore && isset($this->wikimediaCodeMap[$code]) && $this->wikimediaCodeMap[$code] == '') { continue; } // If --most is set, skip all other if ($most && !isset($this->mostSpokenLanguages[$code])) { continue; } $columns = $rows[$code]; $allZero = true; foreach ($columns as $fields) { if (intval($fields[1]) !== 0) { $allZero = false; } } // Skip dummy languages if requested if ($allZero && $this->hasOption('skipzero')) { continue; } // Output the the row if (!$wmfscore) { $out->blockstart(); } // Fill language position field if ($most) { $out->element($this->mostSpokenLanguages[$code][0]); } // Fill language name field if (!$wmfscore) { // Fill language code field $out->element($code); if ($l10n && function_exists('efI18nTagsInit')) { $out->element("{{#languagename:" . $code . "}}"); } else { $out->element($name); } } // Fill continent field if ($showContinent) { if ($this->mostSpokenLanguages[$code][2] == 'multiple') { $continent = $l10n ? "{{int:translate-gs-multiple}}" : 'Multiple'; } else { $continent = $l10n ? "{{int:timezoneregion-" . $this->mostSpokenLanguages[$code][2] . "}}" : ucfirst($this->mostSpokenLanguages[$code][2]); } $out->element($continent); } // Fill speakers field if ($most && $this->hasOption('speakers')) { $out->element(number_format($this->mostSpokenLanguages[$code][1])); } // Fill the score field if ($reportScore) { // Keep count $i = 0; // Start with 0 points $score = 0; foreach ($columns as $fields) { list(, $upper, $total) = $fields; // Weigh the score and add it to the current score $score += $weights[$i] * $upper / $total; $i++; } // Report a round numbers $score = number_format($score, 0); if ($summarise) { $continent = $this->mostSpokenLanguages[$code][2]; if (isset($summary[$continent])) { $newcount = $summary[$continent][0] + 1; $newscore = $summary[$continent][1] + (int) $score; } else { $newcount = 1; $newscore = $score; } $summary[$continent] = array($newcount, $newscore); } if ($wmfscore) { // Multiple variants can be used for the same wiki. // Store the scores in an array and output them later // when they can be averaged. if (isset($this->wikimediaCodeMap[$code])) { $wmfcode = $this->wikimediaCodeMap[$code]; } else { $codeparts = explode('-', $code); $wmfcode = $codeparts[0]; } if (isset($wmfscores[$wmfcode])) { $count = $wmfscores[$wmfcode]['count'] + 1; $tmpWmfScore = (int) $wmfscores[$wmfcode]['score']; $tmpWmfCount = (int) $wmfscores[$wmfcode]['count']; $score = ($tmpWmfCount * $tmpWmfScore + (int) $score) / $count; $wmfscores[$wmfcode] = array('score' => $score, 'count' => $count); } else { $wmfscores[$wmfcode] = array('score' => $score, 'count' => 1); } } else { $out->element($score); } } // Fill fields for groups if (!$wmfscore) { foreach ($columns as $fields) { list($invert, $upper, $total) = $fields; $c = $out->formatPercent($upper, $total, $invert); $out->element($c); } $out->blockend(); } } $out->footer(); if ($reportScore && $this->hasOption('summary')) { if ($reportScore && $this->hasOption('legendsummary')) { $out->addFreeText("{{" . $this->getOption('legendsummary') . "}}\n"); } $out->summaryheading(); $out->blockstart(); $out->element($l10n ? "{{int:translate-gs-continent}}" : 'Continent', true); $out->element($l10n ? "{{int:translate-gs-count}}" : 'Count', true); $out->element($l10n ? "{{int:translate-gs-avgscore}}" : 'Avg. score', true); $out->blockend(); ksort($summary); $totals = array(0, 0); foreach ($summary as $key => $values) { $out->blockstart(); if ($key == 'multiple') { $out->element($l10n ? "{{int:translate-gs-multiple}}" : 'Multiple'); } else { $out->element($l10n ? "{{int:timezoneregion-" . $key . "}}" : ucfirst($key)); } $out->element($values[0]); $out->element(number_format($values[1] / $values[0])); $out->blockend(); $totals[0] += $values[0]; $totals[1] += $values[1]; } $out->blockstart(); $out->element($l10n ? "{{int:translate-gs-total}}" : 'Total'); $out->element($totals[0]); $out->element(number_format($totals[1] / $totals[0])); $out->blockend(); $out->footer(); } // Custom output if ($wmfscore) { ksort($wmfscores); foreach ($wmfscores as $code => $stats) { echo $code . ';' . number_format($stats['score']) . ";\n"; } } }
break; case 'text': $output = new TextStatsOutput(); break; case 'csv': $output = new CsvStatsOutput(); break; default: showUsage(); } # Languages $wgLanguages = new Languages(); # Header $output->heading(); $output->blockstart(); $output->element('Language', true); $output->element('Code', true); $output->element('Fallback', true); $output->element('Translated', true); $output->element('%', true); $output->element('Obsolete', true); $output->element('%', true); $output->element('Problematic', true); $output->element('%', true); $output->blockend(); $wgGeneralMessages = $wgLanguages->getGeneralMessages(); $wgRequiredMessagesNumber = count($wgGeneralMessages['required']); foreach ($wgLanguages->getLanguages() as $code) { # Don't check English, RTL English or dummy language codes if ($code == 'en' || $code == 'enRTL' || is_array($wgDummyLanguageCodes) && isset($wgDummyLanguageCodes[$code])) { continue;