Skip to content

Commit 48d9039

Browse files
authored
Add Pontoon links to QA views, improve accesskeys view (#884)
* Add edit link to variables view * Add edit link to Empty strings * Improve accesskeys view
1 parent 219f82a commit 48d9039

File tree

11 files changed

+281
-119
lines changed

11 files changed

+281
-119
lines changed

app/classes/Transvision/ShowResults.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,15 +240,21 @@ public static function formatEntity($entity, $highlight = false)
240240
/**
241241
* Return link to edit a message on external tool used by requested locale
242242
*
243+
* @param string $tool Tool name
243244
* @param string $repo Repository
244245
* @param string $key Key of the current string
245246
* @param string $text Text of the current strings
246247
* @param string $locale Current locale
247248
*
248249
* @return string HTML link to edit the string inside the tool used by this locale
249250
*/
250-
public static function getEditLink($repo, $key, $text, $locale)
251+
public static function getEditLink($tool, $repo, $key, $text, $locale)
251252
{
253+
// Return if it's not a supported tool
254+
if (! in_array($tool, ['pontoon'])) {
255+
return '';
256+
}
257+
252258
$component = explode('/', $key)[0];
253259
$fileAndRawString = explode(':', $key);
254260

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

416422
$edit_link = $toolUsedByTargetLocale != ''
417-
? self::getEditLink($current_repo, $key, $target_string, $locale2)
423+
? self::getEditLink($toolUsedByTargetLocale, $current_repo, $key, $target_string, $locale2)
418424
: '';
419425

420426
if ($transliterate) {

app/classes/Transvision/Utils.php

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -82,52 +82,6 @@ public static function checkboxState($str, $extra = '')
8282
return $str ? ' checked="checked"' : '';
8383
}
8484

85-
/**
86-
* Print a simple table, used in the accesskeys view, needs rework
87-
*
88-
* @param array $arr First column of data
89-
* @param array $arr2 Optional. A second column of data
90-
* @param array $titles Column titles, by default 4 columns
91-
* @param string $cssclass optional css class to apply to the table
92-
*
93-
* @return void
94-
*/
95-
public static function printSimpleTable(
96-
$arr,
97-
$arr2 = false,
98-
$titles = ['Column1', 'Column2', 'Column3', 'Column4'],
99-
$cssclass = ''
100-
) {
101-
if ($cssclass != '') {
102-
echo "<table class='{$cssclass}'>";
103-
} else {
104-
echo '<table>';
105-
}
106-
echo "<thead>\n <tr class='column_headers'>\n" .
107-
" <th>{$titles[0]}</th><th>{$titles[1]}</th>\n";
108-
109-
if ($arr2) {
110-
echo " <th>{$titles[2]}</th><th>{$titles[3]}</th>\n";
111-
}
112-
113-
echo " </tr>\n</thead>\n<tbody>\n";
114-
115-
foreach ($arr as $key => $val) {
116-
echo '<tr>';
117-
if ($arr2) {
118-
echo "<td><span class='celltitle'>{$titles[0]}</span><div class='string'>" . ShowResults::formatEntity($val) . '</div></td>';
119-
echo "<td><span class='celltitle'>{$titles[1]}</span><div class='string'>" . $arr2[$val] . '</div></td>';
120-
echo "<td><span class='celltitle'>{$titles[2]}</span><div class='string'>" . str_replace(' ', '<span class="highlight-red"> </span>', $arr2[$key]) . '</div></td>';
121-
echo "<td><span class='celltitle'>{$titles[3]}</span><div class='string'>" . ShowResults::formatEntity($key) . '</div></td>';
122-
} else {
123-
echo "<td>{$key}</td>";
124-
echo "<td>{$val}</td>";
125-
}
126-
echo '</tr>';
127-
}
128-
echo "</tbody>\n</table>\n";
129-
}
130-
13185
/**
13286
* Split a sentence in words from longest to shortest, ignoring
13387
* words shorter than 2 characters.

app/controllers/accesskeys.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
namespace Transvision;
3+
4+
// Get requested repo and locale
5+
require_once INC . 'l10n-init.php';
6+
7+
include MODELS . 'accesskeys.php';
8+
include VIEWS . 'accesskeys.php';

app/inc/dispatcher.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@
3535
$js_files[] = '/assets/jQuery-Autocomplete/dist/jquery.autocomplete.min.js';
3636
break;
3737
case 'accesskeys':
38-
$view = 'accesskeys';
38+
$controller = 'accesskeys';
3939
$page_title = 'Access Keys';
4040
$page_descr = 'Check your access keys.';
41+
$js_files[] = '/js/component_filter.js';
4142
$js_files[] = '/js/sorttable.js';
4243
break;
4344
case Strings::StartsWith($url['path'], 'api'):

app/models/accesskeys.php

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
namespace Transvision;
3+
4+
$error_messages = [];
5+
$reference_locale = Project::getReferenceLocale($repo);
6+
$supported_locales = Project::getRepositoryLocales($repo, [$reference_locale]);
7+
// If the requested locale is not available, fall back to the first
8+
if (! in_array($locale, $supported_locales)) {
9+
$locale = array_shift($supported_locales);
10+
}
11+
// Build the target locale switcher
12+
$target_locales_list = Utils::getHtmlSelectOptions($supported_locales, $locale);
13+
14+
/*
15+
Only use desktop repositories. If the requested repository is not
16+
available, fall back to the first key.
17+
*/
18+
$channels = array_intersect_key(
19+
Project::getSupportedRepositories(),
20+
array_flip($desktop_repos)
21+
);
22+
if (! isset($channels[$repo])) {
23+
$repo = current(array_keys($channels));
24+
$error_messages[] = "The selected repository is not supported. Falling back to <em>{$repo}</em>.";
25+
}
26+
$channel_selector = Utils::getHtmlSelectOptions($channels, $repo, true);
27+
28+
// Get strings
29+
$source = Utils::getRepoStrings($reference_locale, $repo);
30+
$target = Utils::getRepoStrings($locale, $repo);
31+
32+
// Get strings with 'accesskey' in the string ID
33+
$ak_string_ids = array_filter(
34+
array_keys($target),
35+
function ($entity) {
36+
return strpos($entity, '.accesskey') !== false;
37+
}
38+
);
39+
40+
// Possible labels associated to an access key
41+
$ak_labels = ['.label', '.title', '.message', ''];
42+
43+
// Known false positives
44+
$ignored_ids = [
45+
'suite/chrome/mailnews/messenger.dtd:searchButton.title',
46+
];
47+
48+
$ak_results = [];
49+
foreach ($ak_string_ids as $ak_string_id) {
50+
foreach ($ak_labels as $ak_label) {
51+
/*
52+
Replace 'accesskey' with one of the known IDs used for labels.
53+
E.g.:
54+
* foo.accesskey -> foo.label
55+
* foo.accesskey -> foo.title
56+
* foo.accesskey -> foo.message
57+
* foo.accesskey -> foo (common in devtools)
58+
*/
59+
$entity = str_replace('.accesskey', $ak_label, $ak_string_id);
60+
$current_ak = $target[$ak_string_id];
61+
62+
/*
63+
Ignore:
64+
* Strings not available or empty in target locale.
65+
* Empty access keys in source locale.
66+
*/
67+
if (isset($target[$entity]) && ! empty($target[$entity]) && ! empty($source[$ak_string_id]) ) {
68+
// Ignore known false positives
69+
if (in_array($entity, $ignored_ids)) {
70+
continue;
71+
}
72+
/*
73+
Store the string if the access key is empty or using a
74+
character not available in the label.
75+
*/
76+
if (($current_ak == '') || (mb_stripos($target[$entity], $current_ak) === false)) {
77+
$ak_results[$ak_string_id] = $entity;
78+
}
79+
}
80+
}
81+
}
82+
83+
// Add component filter
84+
if (in_array($repo, $desktop_repos)) {
85+
// Build logic to filter components
86+
$components = Project::getComponents(array_flip($ak_results));
87+
$filter_block = '';
88+
foreach ($components as $value) {
89+
$filter_block .= " <a href='#{$value}' id='{$value}' class='filter'>{$value}</a>";
90+
}
91+
}
92+
93+
// RTL support
94+
$direction = RTLSupport::getDirection($locale);

app/views/accesskeys.php

Lines changed: 102 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,109 @@
11
<?php
22
namespace Transvision;
33

4-
require_once INC . 'l10n-init.php';
5-
6-
$strings[$repo] = Utils::getRepoStrings($locale, $repo);
7-
$strings_english[$repo] = Utils::getRepoStrings('en-US', $repo);
8-
9-
$channel_selector = Utils::getHtmlSelectOptions(
10-
array_intersect_key(
11-
$repos_nice_names,
12-
array_flip($desktop_repos)
13-
),
14-
$repo,
15-
true
16-
);
17-
18-
// Get the locale list
19-
$loc_list = Project::getRepositoryLocales($repo);
20-
21-
// Build the target locale switcher
22-
$target_locales_list = Utils::getHtmlSelectOptions($loc_list, $locale);
23-
24-
$akeys = array_filter(
25-
array_keys($strings[$repo]),
26-
function ($entity) {
27-
return substr($entity, -9) == 'accesskey';
4+
// Include the common simple search form
5+
include __DIR__ . '/simplesearchform.php';
6+
7+
if (! empty($ak_results)) {
8+
$search_id = 'accesskeys';
9+
$content = '';
10+
if (! empty($error_messages)) {
11+
$content .= '<p class="error">' .
12+
implode('<br/>', $error_messages) .
13+
'</p>';
2814
}
29-
);
30-
31-
$ak_labels = ['.label', '.title', '.title2'];
32-
$ak_results = [];
33-
34-
foreach ($akeys as $akey) {
35-
$entity = substr($akey, 0, -10);
36-
$akey_value = $strings[$repo][$akey];
37-
38-
foreach ($ak_labels as $ak_label) {
39-
if (isset($strings[$repo][$entity . $ak_label])
40-
&& !empty($strings[$repo][$entity . $ak_label])
41-
&& isset($strings_english[$repo][$akey])
42-
&& !empty($strings_english[$repo][$akey])
43-
) {
44-
if ($akey_value == '') {
45-
$ak_results[$akey] = $entity . $ak_label;
46-
} elseif (mb_stripos($strings[$repo][$entity . $ak_label], $akey_value) === false) {
47-
$ak_results[$akey] = $entity . $ak_label;
48-
} else {
49-
break;
50-
}
51-
}
15+
$content .= "<h2><span class=\"results_count_{$search_id}\">"
16+
. Utils::pluralize(count($ak_results), 'potential access key error')
17+
. "</span> found</h2>\n";
18+
19+
if (isset($filter_block)) {
20+
$content .= "<div id='filters'>" .
21+
" <h4>Filter by folder:</h4>\n" .
22+
" <a href='#showall' id='showall' class='filter'>Show all results</a>\n" .
23+
$filter_block .
24+
"</div>\n";
25+
}
26+
27+
$content .= "
28+
<table class='collapsable results_table sortable {$search_id}'>
29+
<thead>
30+
<tr class='column_headers'>
31+
<th>Entity</th>
32+
<th>Label</th>
33+
<th>Access&nbsp;key</th>
34+
<th>Access&nbsp;key entity</th>
35+
</tr>
36+
</thead>
37+
<tbody>\n";
38+
39+
// Get the tool used to edit strings for the target locale
40+
$toolUsedByTargetLocale = Project::getLocaleTool($locale);
41+
42+
foreach ($ak_results as $ak_string => $ak_label) {
43+
// Link to entity
44+
$ak_link = "?sourcelocale={$reference_locale}" .
45+
"&locale={$locale}" .
46+
"&repo={$repo}" .
47+
"&search_type=entities&recherche={$ak_string}" .
48+
'&entire_string=entire_string';
49+
$label_link = "?sourcelocale={$reference_locale}" .
50+
"&locale={$locale}" .
51+
"&repo={$repo}" .
52+
"&search_type=entities&recherche={$ak_label}" .
53+
'&entire_string=entire_string';
54+
55+
$path_ak = VersionControl::hgPath($locale, $repo, $ak_string);
56+
$path_label = VersionControl::hgPath($locale, $repo, $ak_label);
57+
58+
$edit_link_ak = $toolUsedByTargetLocale != ''
59+
? ShowResults::getEditLink($toolUsedByTargetLocale, $repo, $ak_string, $target[$ak_string], $locale)
60+
: '';
61+
$edit_link_label = $toolUsedByTargetLocale != ''
62+
? ShowResults::getEditLink($toolUsedByTargetLocale, $repo, $ak_label, $target[$ak_label], $locale)
63+
: '';
64+
65+
$ak_value = ! empty($target[$ak_string])
66+
? Utils::secureText($target[$ak_string])
67+
: '<em class="error">(empty)</em>';
68+
$label_value = ! empty($target[$ak_label])
69+
? Utils::secureText($target[$ak_label])
70+
: '<em class="error">(empty)</em>';
71+
72+
$component = explode('/', $ak_string)[0];
73+
$content .= "<tr class='{$component} {$search_id}'>
74+
<td>
75+
<span class='celltitle'>Entity</span>
76+
<span class='link_to_entity'>
77+
<a href=\"/{$label_link}\">" . ShowResults::formatEntity($ak_label) . "</a>
78+
</span>
79+
</td>
80+
<td dir='{$direction}'>
81+
<span class='celltitle'>Label</span>
82+
<div class='string'>{$label_value}</div>
83+
<div dir='ltr' class='result_meta_link'>
84+
<a class='source_link' href='{$path_label}'>&lt;source&gt;</a>
85+
{$edit_link_label}
86+
</div>
87+
</td>
88+
<td dir='{$direction}'>
89+
<span class='celltitle'>Access&nbsp;key</span>
90+
<div class='string'>{$ak_value}</div>
91+
<div dir='ltr' class='result_meta_link'>
92+
<a class='source_link' href='{$path_ak}'>&lt;source&gt;</a>
93+
{$edit_link_ak}
94+
</div>
95+
</td>
96+
<td>
97+
<span class='celltitle'>Access&nbsp;key entity</span>
98+
<span class='link_to_entity'>
99+
<a href=\"/{$ak_link}\">" . ShowResults::formatEntity($ak_string) . "</a>
100+
</span>
101+
</td>
102+
</tr>\n";
52103
}
104+
$content .= "</tbody>\n</table>\n";
105+
} else {
106+
$content = '<h2>Congratulations, no errors found.</h2>';
53107
}
54-
// Include the common simple search form
55-
include __DIR__ . '/simplesearchform.php';
56108

57-
echo '<h2>' . count($ak_results) . ' potential accesskey errors</h2>';
58-
Utils::printSimpleTable(
59-
$ak_results,
60-
$strings[$repo],
61-
['Label entity', 'Label value', 'Access&nbsp;key', 'Access key entity'],
62-
'collapsable sortable'
63-
);
109+
print $content;

0 commit comments

Comments
 (0)