count($fa),
'bCount' => count($fb),
'diff' => count($fa) - count($fb),
); unused var */
$missing = array();
$notrans = array();
$ka = array_keys($fa);
$kb = array_keys($fb);
$missing = array_diff($ka, $kb);
$extra = array_diff($kb, $ka);
// search for untranslated strings
foreach ($fa as $k => $v) {
if (array_key_exists($k, $fb)) {
if ($v == $fb[$k] || '' == $fb[$k]) {
$notrans[] = $k;
}
}
}
return array(
'a_name' => $a,
'b_name' => $b,
'a' => count($fa),
'b' => count($fb),
'missing' => $missing,
'notrans' => $notrans,
'extra' => $extra,
'dup_str' => $duplicates,
);
}
/**
* Diff pot and po files, to get:
* - source (pot) strings count
* - missing strings in target
* - untranslated strings in target
* - empty array for extra and duplicate strings for backward compatibility
*
* @param string $locale locale name ('sl')
* @param string $resource file name ('about/license')
* @param array $source_l array with source file strings (to avoid duplicated parsing)
* @param string $path directly passed path for nonlocal files
*
* @return array
*/
function _po_diff($locale, $resource, $source_l = NULL, $path = NULL)
{
if (is_null($path)) {
if (NULL == $source_l) {
$source_l = read_translation_file('en', $resource);
}
$target_l = read_translation_file($locale, $resource);
} else {
if (NULL == $source_l) {
$source_path_filename = sprintf('%s/%s.pot', $path, $resource);
$source_l = phpmo_parse_po_file($source_path_filename);
}
if ('en' == $locale) {
$target_l = $source_l;
} else {
$locale = locale_hyphen_underscore($locale, true);
$target_path_filename = sprintf('%s/%s.po', $path, $locale);
$target_l = phpmo_parse_po_file($target_path_filename);
}
}
$pot_strings = array();
$untrans = array();
$fuzzy_or_missing = array();
$num_of_original_strings = 0;
if (FALSE != $source_l) {
foreach ($source_l as $escaped_string => $subarray) {
if (!empty($subarray["msgid"])) { // filter out header
$msgctxt = array();
foreach ($subarray["msgstr"] as $key => $unused) {
if (isset($subarray["msgctxt"][$key])) {
$msgctxt[$key] = $subarray["msgctxt"][$key];
} else {
$msgctxt[$key] = TRUE;
}
$num_of_original_strings++;
}
$pot_strings[$escaped_string] = $msgctxt;
}
}
}
$fuzzy_or_missing = $pot_strings;
$untrans = $pot_strings;
if (FALSE != $target_l) {
foreach ($target_l as $escaped_string => $subarray) {
if (!empty($subarray["msgid"])) { // filter out header
foreach ($subarray["msgstr"] as $key => $msgstr) {
// remove present string
unset($fuzzy_or_missing[$escaped_string][$key]);
if (!empty($msgstr)) {
// remove translated string
if(is_array($msgstr)) { // are there any plural strings present?
$erase_plural_key = TRUE;
foreach ($msgstr as $nplural) {
if (empty($nplural)) {
$erase_plural_key = FALSE;
}
}
// if all plural keys are translated, remove msgstr for that msgid
if ($erase_plural_key) {
unset($untrans[$escaped_string][$key]);
}
} else {
unset($untrans[$escaped_string][$key]);
}
}
}
}
}
}
$arrays = array($fuzzy_or_missing, $untrans);
foreach ($arrays as &$current_array) {
$strings = array();
$cnt = 0;
foreach ($current_array as $escaped_string => $msgctxt) {
if(!empty($msgctxt)) {
$keys = array_keys($msgctxt);
if(is_numeric($keys[0])) {
$index = $cnt;
} else {
$index = $keys[0];
}
$strings[$index] = $escaped_string;
$cnt++;
}
}
$current_array = $strings;
}
unset($current_array);
list($fuzzy_or_missing, $untrans) = $arrays;
$untrans = array_diff($untrans, $fuzzy_or_missing);
return array(
'a' => $num_of_original_strings, // # of original strings
// 'b' => count($po_strings), // # of target strings
'source_strings' => $source_l, // array of original strings
'fuzzy_or_missing' => $fuzzy_or_missing, // array of fuzzy or missing strings
'notrans' => $untrans, // array of untranslated strings
'extra' => array(),
'dup_str' => array(),
);
}
/**
* Diff English and translated ts files, to get:
* - source (ts) strings count
* - missing strings in target
* - untranslated strings in target
* - empty array for extra and duplicate strings for backward compatibility
*
* @param string $locale locale name ('sl')
* @param string $resource file name ('mageiaSync')
* @param array $source_l array with source file strings (to avoid duplicated parsing)
* @param string $path directly passed path for nonlocal files
*
* @return array
*/
function _ts_diff($locale, $resource, $source_l = NULL, $path = NULL)
{
$source_path_filename = sprintf('%s%s_%s.ts', $path, $resource, $locale); // mageiaSync_sl.ts
$source_strings = array();
$untranslated_strings = array();
$obsoleted_strings = array();
// read .ts file
$file_handle = @fopen($source_path_filename, 'r');
if ($file_handle === false) {
// Could not open file resource
return false;
}
// iterate over lines
while(($line = fgets($file_handle, 65536)) !== false) {
// count ??? lines
if (false !== strpos($line, '')) {
preg_match_all("/()([a-z_A-Z@-]+)(<\/source>)/", $line, $source_string);
$source_strings[] = $source_string[2];
}
// count lines
if (false !== strpos($line, ' lines
if (false !== strpos($line, ' count($source_strings), // # of original strings
// 'b' => , // # of target strings
'source_strings' => $source_strings, // array of original strings
'fuzzy_or_missing' => array(), // array of fuzzy or missing strings
'notrans' => $untranslated_strings, // array of untranslated strings
'extra' => $obsoleted_strings,
'dup_str' => array(),
);
}
/*function _lang_diff_stats($a, $b)
{
$diff = _lang_diff($a, $b);
$diff['missing'] = count($diff['missing']);
$diff['notrans'] = count($diff['notrans']);
$diff['extra'] = count($diff['extra']);
$diff['ok'] = (($diff['b'] - $diff['a']) == 0) ? true : false;
$diff['correct'] = $diff['b'] - $diff['notrans'] - $diff['missing'];
return $diff;
} /**/
if ( ! function_exists('glob_recursive'))
{
// Does not support flag GLOB_BRACE
function glob_recursive($pattern, $flags = 0)
{
$files = glob($pattern, $flags);
// removing dirs from $files as they are not files ;)
$files_wo_dirs = array();
foreach ($files as $single_file) {
$single_file_as_string = str_split($single_file);
$last_sign = array_pop($single_file_as_string);
if($last_sign != '/') {
$files_wo_dirs[] = $single_file;
};
}
$files = $files_wo_dirs;
foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir)
{
$files = array_merge($files, glob_recursive($dir.'/'.basename($pattern), $flags));
}
return $files;
}
}
/**
* Create 'sl/about/license.sl.lang'
* from 'en/about/license.en.lang'
* or ../_nav/langs/sl.lang
* from ../_nav/langs/en.lang
*
* @param string $s file name with path
* @param string $l locale name
*
* @return string
*/
function _lang_file_switch($s, $l)
{
$s = str_replace('en.lang', $l . '.lang', $s);
return str_replace('en/', $l . '/', $s);
}
/**
* Create 'sl/about/license.po'
* from 'en/about/license.pot'
* or ../_nav/langs/sl.po
* from ../_nav/langs/en.pot
*
* @param string $s file name with path
* @param string $l locale name
*
* @return string
*/
function _po_file_switch($s, $l)
{
if($l != 'en') {
$s = str_replace('.pot', '.po', $s);
}
$s = str_replace('/en.', '/' . $l . '.', $s);
return str_replace('en/', $l . '/', $s);
}
/**
* Create 'about/license'
* from 'en/about/license.pot' or 'en/about/license.en.lang'
*
* @param string $source_file file name with path
* @param string $extension file extension to remove
*
* @return string
*/
function _extract_resource($source_file, $extension = '.pot')
{
$resource = str_replace($extension, '', $source_file);
return str_replace('en/', '', $resource);
}
function get_lang_references($pattern = '*')
{
return glob_recursive('en/' . $pattern, GLOB_MARK);
}
function get_other_langs()
{
$ls = glob('*');
$re = array();
foreach ($ls as $l) {
if (!is_dir($l)) continue;
if ($l == 'en') continue;
$re[] = $l;
}
array_unshift($re, 'en');
return $re;
}
function aproximate_number_of_untranslated_constitution_lines($app_root, $lang, $unique_lines_in_eng_constitution = array())
{
$constitution_readable = FALSE;
$dest_constitution = sprintf('%s/%s/%s/%s_%s.md', $app_root, $lang, 'about/constitution', 'mageia.org_statutes', $lang);
$number_of_unique_lines_in_eng_constitution = count($unique_lines_in_eng_constitution);
$aproximate_number_of_untranslated_lines = 0;
if(is_readable($dest_constitution)) {
$unique_lines_in_constitution = array_unique(file($dest_constitution));
$number_of_unique_lines_in_constitution = count($unique_lines_in_constitution);
$constitution_readable = TRUE;
if ($lang == 'en') {
$aproximate_number_of_untranslated_lines = $number_of_unique_lines_in_constitution;
$untranslated_lines_in_constitution = array();
} else {
$untranslated_lines_in_constitution = array_intersect($unique_lines_in_eng_constitution, $unique_lines_in_constitution);
$number_of_nonunique_lines_lang_constitution = count($untranslated_lines_in_constitution);
$ratio = $number_of_nonunique_lines_lang_constitution / $number_of_unique_lines_in_eng_constitution;
$limit_ratio = 0.15; // limit ratio of "allowed" untranslated lines
if ($ratio > $limit_ratio) {
// add aproximate number of untranslated constitution lines
$aproximate_number_of_untranslated_lines = $number_of_nonunique_lines_lang_constitution - round($limit_ratio * $number_of_unique_lines_in_eng_constitution);
}
}
} else {
$unique_lines_in_constitution = $unique_lines_in_eng_constitution;
$aproximate_number_of_untranslated_lines = $number_of_unique_lines_in_eng_constitution;
$untranslated_lines_in_constitution = $unique_lines_in_eng_constitution;
}
return array(
'unique_lines_in_constitution' => $unique_lines_in_constitution,
'constitution_readable' => $constitution_readable,
'untranslated_lines_in_constitution' => $untranslated_lines_in_constitution,
'aproximate_number_of_untranslated_lines' => $aproximate_number_of_untranslated_lines,
);
}
function build_language_and_resource_summary($report, $all_languages_only_one_resource = FALSE, $one_resource = NULL, $one_language_all_resources = FALSE, $one_language = NULL)
{
$total_num_of_strings = 0; // total of all source strings
$language_summary = array();
$resource_summary = array();
foreach ($report as $resource_data) {
if ($resource_data['language'] == 'en') {
$total_num_of_strings += $resource_data['num_of_all_strings'];
}
// don't add if there is a need to store languages only for one resource
if(!$all_languages_only_one_resource || $resource_data['resource_filename'] == $one_resource) {
$key_exists = recursive_array_search($resource_data['language'], $language_summary); // is language already in the $language_summary array?
if($resource_data['resource_filename'] == $one_resource) {
$temp_var[0]['language'] = $resource_data['language'];
$temp_var[0]['num_of_all_strings'] = $resource_data['num_of_all_strings'];
$temp_var[0]['num_of_fuzzy_or_missing_strings'] = $resource_data['num_of_fuzzy_or_missing_strings'];
$temp_var[0]['num_of_untranslated_strings'] = $resource_data['num_of_untranslated_strings'];
$temp_var[0]['references'] = $resource_data['references'];
$language_summary[] = $temp_var[0];
unset($temp_var[0]); // clear var
} else {
if ($key_exists !== FALSE) {
$language_summary[$key_exists]['num_of_all_strings'] += $resource_data['num_of_all_strings'];
$language_summary[$key_exists]['num_of_fuzzy_or_missing_strings'] += $resource_data['num_of_fuzzy_or_missing_strings'];
$language_summary[$key_exists]['num_of_untranslated_strings'] += $resource_data['num_of_untranslated_strings'];
} else {
if($key_exists === FALSE) {
$key_exists = count($language_summary);
}
$language_summary[$key_exists]['language'] = $resource_data['language'];
$language_summary[$key_exists]['num_of_all_strings'] = $resource_data['num_of_all_strings'];
$language_summary[$key_exists]['num_of_fuzzy_or_missing_strings'] = $resource_data['num_of_fuzzy_or_missing_strings'];
$language_summary[$key_exists]['num_of_untranslated_strings'] = $resource_data['num_of_untranslated_strings'];
$language_summary[$key_exists]['references'] = $resource_data['references'];
}
}
}
// don't add if there is a need to store resources only for one language
if(!$one_language_all_resources || ($resource_data['language'] == $one_language || $resource_data['language'] == 'en')) {
$key_exists = recursive_array_search($resource_data['resource_filename'], $resource_summary); // is resource already in the $resource_summary array?
if($resource_data['language'] == 'en') {
$temp_var[0]['resource_filename'] = $resource_data['resource_filename'];
$temp_var[0]['num_of_all_strings'] = $resource_data['num_of_all_strings'];
$temp_var[0]['num_of_fuzzy_or_missing_strings'] = $resource_data['num_of_fuzzy_or_missing_strings'];
$temp_var[0]['num_of_untranslated_strings'] = $resource_data['num_of_untranslated_strings'];
$temp_var[0]['references'] = $resource_data['references'];
$resource_summary[] = $temp_var[0];
unset($temp_var[0]); // clear var
} else {
if($one_language_all_resources) {
if($key_exists === FALSE) {
$key_exists = count($resource_summary);
}
$resource_summary[$key_exists]['num_of_fuzzy_or_missing_strings'] = $resource_data['num_of_fuzzy_or_missing_strings'];
$resource_summary[$key_exists]['num_of_untranslated_strings'] = $resource_data['num_of_untranslated_strings'];
$resource_summary[$key_exists]['references'] = $resource_data['references'];
} else if ($key_exists !== FALSE) {
$resource_summary[$key_exists]['num_of_all_strings'] += $resource_data['num_of_all_strings'];
$resource_summary[$key_exists]['num_of_fuzzy_or_missing_strings'] += $resource_data['num_of_fuzzy_or_missing_strings'];
$resource_summary[$key_exists]['num_of_untranslated_strings'] += $resource_data['num_of_untranslated_strings'];
}
}
}
}
foreach ($language_summary as &$single_language_summary) {
$single_language_summary['num_of_translated_strings'] =
$single_language_summary['num_of_all_strings'] -
$single_language_summary['num_of_fuzzy_or_missing_strings'] -
$single_language_summary['num_of_untranslated_strings'];
}
unset($single_language_summary); // foreach by reference
foreach ($resource_summary as &$single_resource_summary) {
$single_resource_summary['num_of_translated_strings'] =
$single_resource_summary['num_of_all_strings'] -
$single_resource_summary['num_of_fuzzy_or_missing_strings'] -
$single_resource_summary['num_of_untranslated_strings'];
}
unset($single_resource_summary); // foreach by reference
return array(
'total_num_of_strings' => $total_num_of_strings, // total of all source strings
'language_summary' => $language_summary,
'resource_summary' => $resource_summary,
);
}
/**
* from http://www.php.net/manual/en/function.array-search.php#91365
*
* copyright (c) the PHP Documentation
* covered by the Creative Commons Attribution 3.0 License (http://creativecommons.org/licenses/by/3.0/legalcode)
*/
function recursive_array_search($needle, $haystack)
{
foreach ($haystack as $key => $value) {
$current_key = $key;
if ($needle === $value OR (is_array($value) && recursive_array_search($needle, $value) !== FALSE)) {
return $current_key;
}
}
return FALSE;
}