Skip to content

Commit

Permalink
Add Pontoon links to QA views, improve accesskeys view (#884)
Browse files Browse the repository at this point in the history
* Add edit link to variables view
* Add edit link to Empty strings
* Improve accesskeys view
  • Loading branch information
flodolo authored Sep 18, 2017
1 parent 219f82a commit 48d9039
Show file tree
Hide file tree
Showing 11 changed files with 281 additions and 119 deletions.
10 changes: 8 additions & 2 deletions app/classes/Transvision/ShowResults.php
Original file line number Diff line number Diff line change
Expand Up @@ -240,15 +240,21 @@ public static function formatEntity($entity, $highlight = false)
/**
* Return link to edit a message on external tool used by requested locale
*
* @param string $tool Tool name
* @param string $repo Repository
* @param string $key Key of the current string
* @param string $text Text of the current strings
* @param string $locale Current locale
*
* @return string HTML link to edit the string inside the tool used by this locale
*/
public static function getEditLink($repo, $key, $text, $locale)
public static function getEditLink($tool, $repo, $key, $text, $locale)
{
// Return if it's not a supported tool
if (! in_array($tool, ['pontoon'])) {
return '';
}

$component = explode('/', $key)[0];
$fileAndRawString = explode(':', $key);

Expand Down Expand Up @@ -414,7 +420,7 @@ public static function resultsTable($search_object, $search_results, $page)
$transliterate = $locale2 == 'sr' && ! $extra_locale && $target_string && $target_string != '@@missing@@';

$edit_link = $toolUsedByTargetLocale != ''
? self::getEditLink($current_repo, $key, $target_string, $locale2)
? self::getEditLink($toolUsedByTargetLocale, $current_repo, $key, $target_string, $locale2)
: '';

if ($transliterate) {
Expand Down
46 changes: 0 additions & 46 deletions app/classes/Transvision/Utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,52 +82,6 @@ public static function checkboxState($str, $extra = '')
return $str ? ' checked="checked"' : '';
}

/**
* Print a simple table, used in the accesskeys view, needs rework
*
* @param array $arr First column of data
* @param array $arr2 Optional. A second column of data
* @param array $titles Column titles, by default 4 columns
* @param string $cssclass optional css class to apply to the table
*
* @return void
*/
public static function printSimpleTable(
$arr,
$arr2 = false,
$titles = ['Column1', 'Column2', 'Column3', 'Column4'],
$cssclass = ''
) {
if ($cssclass != '') {
echo "<table class='{$cssclass}'>";
} else {
echo '<table>';
}
echo "<thead>\n <tr class='column_headers'>\n" .
" <th>{$titles[0]}</th><th>{$titles[1]}</th>\n";

if ($arr2) {
echo " <th>{$titles[2]}</th><th>{$titles[3]}</th>\n";
}

echo " </tr>\n</thead>\n<tbody>\n";

foreach ($arr as $key => $val) {
echo '<tr>';
if ($arr2) {
echo "<td><span class='celltitle'>{$titles[0]}</span><div class='string'>" . ShowResults::formatEntity($val) . '</div></td>';
echo "<td><span class='celltitle'>{$titles[1]}</span><div class='string'>" . $arr2[$val] . '</div></td>';
echo "<td><span class='celltitle'>{$titles[2]}</span><div class='string'>" . str_replace(' ', '<span class="highlight-red"> </span>', $arr2[$key]) . '</div></td>';
echo "<td><span class='celltitle'>{$titles[3]}</span><div class='string'>" . ShowResults::formatEntity($key) . '</div></td>';
} else {
echo "<td>{$key}</td>";
echo "<td>{$val}</td>";
}
echo '</tr>';
}
echo "</tbody>\n</table>\n";
}

/**
* Split a sentence in words from longest to shortest, ignoring
* words shorter than 2 characters.
Expand Down
8 changes: 8 additions & 0 deletions app/controllers/accesskeys.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php
namespace Transvision;

// Get requested repo and locale
require_once INC . 'l10n-init.php';

include MODELS . 'accesskeys.php';
include VIEWS . 'accesskeys.php';
3 changes: 2 additions & 1 deletion app/inc/dispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@
$js_files[] = '/assets/jQuery-Autocomplete/dist/jquery.autocomplete.min.js';
break;
case 'accesskeys':
$view = 'accesskeys';
$controller = 'accesskeys';
$page_title = 'Access Keys';
$page_descr = 'Check your access keys.';
$js_files[] = '/js/component_filter.js';
$js_files[] = '/js/sorttable.js';
break;
case Strings::StartsWith($url['path'], 'api'):
Expand Down
94 changes: 94 additions & 0 deletions app/models/accesskeys.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php
namespace Transvision;

$error_messages = [];
$reference_locale = Project::getReferenceLocale($repo);
$supported_locales = Project::getRepositoryLocales($repo, [$reference_locale]);
// If the requested locale is not available, fall back to the first
if (! in_array($locale, $supported_locales)) {
$locale = array_shift($supported_locales);
}
// Build the target locale switcher
$target_locales_list = Utils::getHtmlSelectOptions($supported_locales, $locale);

/*
Only use desktop repositories. If the requested repository is not
available, fall back to the first key.
*/
$channels = array_intersect_key(
Project::getSupportedRepositories(),
array_flip($desktop_repos)
);
if (! isset($channels[$repo])) {
$repo = current(array_keys($channels));
$error_messages[] = "The selected repository is not supported. Falling back to <em>{$repo}</em>.";
}
$channel_selector = Utils::getHtmlSelectOptions($channels, $repo, true);

// Get strings
$source = Utils::getRepoStrings($reference_locale, $repo);
$target = Utils::getRepoStrings($locale, $repo);

// Get strings with 'accesskey' in the string ID
$ak_string_ids = array_filter(
array_keys($target),
function ($entity) {
return strpos($entity, '.accesskey') !== false;
}
);

// Possible labels associated to an access key
$ak_labels = ['.label', '.title', '.message', ''];

// Known false positives
$ignored_ids = [
'suite/chrome/mailnews/messenger.dtd:searchButton.title',
];

$ak_results = [];
foreach ($ak_string_ids as $ak_string_id) {
foreach ($ak_labels as $ak_label) {
/*
Replace 'accesskey' with one of the known IDs used for labels.
E.g.:
* foo.accesskey -> foo.label
* foo.accesskey -> foo.title
* foo.accesskey -> foo.message
* foo.accesskey -> foo (common in devtools)
*/
$entity = str_replace('.accesskey', $ak_label, $ak_string_id);
$current_ak = $target[$ak_string_id];

/*
Ignore:
* Strings not available or empty in target locale.
* Empty access keys in source locale.
*/
if (isset($target[$entity]) && ! empty($target[$entity]) && ! empty($source[$ak_string_id]) ) {
// Ignore known false positives
if (in_array($entity, $ignored_ids)) {
continue;
}
/*
Store the string if the access key is empty or using a
character not available in the label.
*/
if (($current_ak == '') || (mb_stripos($target[$entity], $current_ak) === false)) {
$ak_results[$ak_string_id] = $entity;
}
}
}
}

// Add component filter
if (in_array($repo, $desktop_repos)) {
// Build logic to filter components
$components = Project::getComponents(array_flip($ak_results));
$filter_block = '';
foreach ($components as $value) {
$filter_block .= " <a href='#{$value}' id='{$value}' class='filter'>{$value}</a>";
}
}

// RTL support
$direction = RTLSupport::getDirection($locale);
158 changes: 102 additions & 56 deletions app/views/accesskeys.php
Original file line number Diff line number Diff line change
@@ -1,63 +1,109 @@
<?php
namespace Transvision;

require_once INC . 'l10n-init.php';

$strings[$repo] = Utils::getRepoStrings($locale, $repo);
$strings_english[$repo] = Utils::getRepoStrings('en-US', $repo);

$channel_selector = Utils::getHtmlSelectOptions(
array_intersect_key(
$repos_nice_names,
array_flip($desktop_repos)
),
$repo,
true
);

// Get the locale list
$loc_list = Project::getRepositoryLocales($repo);

// Build the target locale switcher
$target_locales_list = Utils::getHtmlSelectOptions($loc_list, $locale);

$akeys = array_filter(
array_keys($strings[$repo]),
function ($entity) {
return substr($entity, -9) == 'accesskey';
// Include the common simple search form
include __DIR__ . '/simplesearchform.php';

if (! empty($ak_results)) {
$search_id = 'accesskeys';
$content = '';
if (! empty($error_messages)) {
$content .= '<p class="error">' .
implode('<br/>', $error_messages) .
'</p>';
}
);

$ak_labels = ['.label', '.title', '.title2'];
$ak_results = [];

foreach ($akeys as $akey) {
$entity = substr($akey, 0, -10);
$akey_value = $strings[$repo][$akey];

foreach ($ak_labels as $ak_label) {
if (isset($strings[$repo][$entity . $ak_label])
&& !empty($strings[$repo][$entity . $ak_label])
&& isset($strings_english[$repo][$akey])
&& !empty($strings_english[$repo][$akey])
) {
if ($akey_value == '') {
$ak_results[$akey] = $entity . $ak_label;
} elseif (mb_stripos($strings[$repo][$entity . $ak_label], $akey_value) === false) {
$ak_results[$akey] = $entity . $ak_label;
} else {
break;
}
}
$content .= "<h2><span class=\"results_count_{$search_id}\">"
. Utils::pluralize(count($ak_results), 'potential access key error')
. "</span> found</h2>\n";

if (isset($filter_block)) {
$content .= "<div id='filters'>" .
" <h4>Filter by folder:</h4>\n" .
" <a href='#showall' id='showall' class='filter'>Show all results</a>\n" .
$filter_block .
"</div>\n";
}

$content .= "
<table class='collapsable results_table sortable {$search_id}'>
<thead>
<tr class='column_headers'>
<th>Entity</th>
<th>Label</th>
<th>Access&nbsp;key</th>
<th>Access&nbsp;key entity</th>
</tr>
</thead>
<tbody>\n";

// Get the tool used to edit strings for the target locale
$toolUsedByTargetLocale = Project::getLocaleTool($locale);

foreach ($ak_results as $ak_string => $ak_label) {
// Link to entity
$ak_link = "?sourcelocale={$reference_locale}" .
"&locale={$locale}" .
"&repo={$repo}" .
"&search_type=entities&recherche={$ak_string}" .
'&entire_string=entire_string';
$label_link = "?sourcelocale={$reference_locale}" .
"&locale={$locale}" .
"&repo={$repo}" .
"&search_type=entities&recherche={$ak_label}" .
'&entire_string=entire_string';

$path_ak = VersionControl::hgPath($locale, $repo, $ak_string);
$path_label = VersionControl::hgPath($locale, $repo, $ak_label);

$edit_link_ak = $toolUsedByTargetLocale != ''
? ShowResults::getEditLink($toolUsedByTargetLocale, $repo, $ak_string, $target[$ak_string], $locale)
: '';
$edit_link_label = $toolUsedByTargetLocale != ''
? ShowResults::getEditLink($toolUsedByTargetLocale, $repo, $ak_label, $target[$ak_label], $locale)
: '';

$ak_value = ! empty($target[$ak_string])
? Utils::secureText($target[$ak_string])
: '<em class="error">(empty)</em>';
$label_value = ! empty($target[$ak_label])
? Utils::secureText($target[$ak_label])
: '<em class="error">(empty)</em>';

$component = explode('/', $ak_string)[0];
$content .= "<tr class='{$component} {$search_id}'>
<td>
<span class='celltitle'>Entity</span>
<span class='link_to_entity'>
<a href=\"/{$label_link}\">" . ShowResults::formatEntity($ak_label) . "</a>
</span>
</td>
<td dir='{$direction}'>
<span class='celltitle'>Label</span>
<div class='string'>{$label_value}</div>
<div dir='ltr' class='result_meta_link'>
<a class='source_link' href='{$path_label}'>&lt;source&gt;</a>
{$edit_link_label}
</div>
</td>
<td dir='{$direction}'>
<span class='celltitle'>Access&nbsp;key</span>
<div class='string'>{$ak_value}</div>
<div dir='ltr' class='result_meta_link'>
<a class='source_link' href='{$path_ak}'>&lt;source&gt;</a>
{$edit_link_ak}
</div>
</td>
<td>
<span class='celltitle'>Access&nbsp;key entity</span>
<span class='link_to_entity'>
<a href=\"/{$ak_link}\">" . ShowResults::formatEntity($ak_string) . "</a>
</span>
</td>
</tr>\n";
}
$content .= "</tbody>\n</table>\n";
} else {
$content = '<h2>Congratulations, no errors found.</h2>';
}
// Include the common simple search form
include __DIR__ . '/simplesearchform.php';

echo '<h2>' . count($ak_results) . ' potential accesskey errors</h2>';
Utils::printSimpleTable(
$ak_results,
$strings[$repo],
['Label entity', 'Label value', 'Access&nbsp;key', 'Access key entity'],
'collapsable sortable'
);
print $content;
Loading

0 comments on commit 48d9039

Please sign in to comment.