Skip to content
Permalink
Browse files

Create QA view for Empty strings (fixes #813) (#814)

  • Loading branch information
flodolo authored and TheoChevalier committed Sep 27, 2016
1 parent 1075320 commit 17373b2a2e366a693ef15831c8d93be6f904b675
@@ -49,6 +49,12 @@ public static function reportErrorLink($locale, $entity, $source_string, $target
{
$bug_summary = rawurlencode("[{$locale}] Translation update proposed for {$entity}");
$transvision_url = "https://transvision.mozfr.org/{$entity_link}";
$source_string = $source_string != ''
? $source_string
: '(empty string)';
$target_string = $target_string != ''
? $target_string
: '(empty string)';
$bug_message = rawurlencode(
html_entity_decode(
"The string:\n{$source_string}\n\n"
@@ -115,11 +115,11 @@ public static function multipleStringReplace($replacements, $string)
public static function highlightSpecial($string, $exclude_whitespaces = true)
{
$replacements = [
' ' => '<span class="highlight-space" title="White space"> </span>',
' ' => '<span class="highlight-gray" title="Non breakable space"> </span>',
' ' => '<span class="highlight-red" title="Narrow no-break space"> </span>',
'…' => '<span class="highlight-gray" title="Real ellipsis">…</span>',
'&hellip;' => '<span class="highlight-red" title="HTML ellipsis">…</span>',
' ' => '<span class="highlight-special highlight-space" title="White space"> </span>',
' ' => '<span class="highlight-special highlight-gray" title="Non breakable space"> </span>',
' ' => '<span class="highlight-special highlight-red" title="Narrow no-break space"> </span>',
'…' => '<span class="highlight-special highlight-gray" title="Real ellipsis">…</span>',
'&hellip;' => '<span class="highlight-special highlight-red" title="HTML ellipsis">…</span>',
];

if ($exclude_whitespaces) {
@@ -0,0 +1,8 @@
<?php
namespace Transvision;

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

include MODELS . 'empty_strings.php';
include VIEWS . 'empty_strings.php';
@@ -71,6 +71,14 @@
$css_files[] = 'tmx.css';
$js_files[] = '/js/select_all.js';
break;
case 'empty-strings':
$experimental = true;
$controller = 'empty_strings';
$page_title = 'Empty Strings';
$page_descr = '';
$js_files[] = '/js/component_filter.js';
$js_files[] = '/js/sorttable.js';
break;
case 'news':
$controller = 'changelog';
$page_title = 'Transvision News and Release Notes';
@@ -2,22 +2,23 @@

$urls = [
'/' => 'root',
'news' => 'changelog',
'rss' => 'rss',
'stats' => 'stats',
'3locales' => '3locales',
'accesskeys' => 'keys',
'api' => 'api',
'channelcomparison' => 'channelcomp',
'consistency' => 'consistency',
'accesskeys' => 'keys',
'credits' => 'credits',
'downloads' => 'downloads',
'empty-strings' => 'empty_strings',
'news' => 'changelog',
'productization' => 'productization',
'rss' => 'rss',
'showrepos' => 'showrepos',
'stats' => 'stats',
'string' => 'onestring',
'unchanged' => 'unchangedstrings',
'unlocalized' => 'unlocalized',
'unlocalized-all' => 'unlocalized_all',
'unlocalized-json' => 'unlocalized_json',
'unlocalized' => 'unlocalized',
'variables' => 'checkvariables',
'3locales' => '3locales',
'string' => 'onestring',
'productization' => 'productization',
'api' => 'api',
];
@@ -0,0 +1,65 @@
<?php
namespace Transvision;

// Build arrays for the search form, ignore mozilla.org and iOS
$channel_selector = Utils::getHtmlSelectOptions(
array_intersect_key(
$repos_nice_names,
array_flip($desktop_repos)
),
$repo,
true
);

$target_locales_list = Utils::getHtmlSelectOptions(
Project::getRepositoryLocales($repo),
$locale
);

$reference_locale = Project::getReferenceLocale($repo);

$reference_strings = Utils::getRepoStrings($reference_locale, $repo);
$locale_strings = Utils::getRepoStrings($locale, $repo);

/*
Identify empty strings in reference locale, store the translation
only if locale has a non empty string for that ID. Then repeat the
process for the locale.
*/
$empty_strings = [];

$empty_reference = array_filter($reference_strings, function ($string) {
return strlen($string) == 0;
});
foreach ($empty_reference as $string_id => $value) {
if (isset($locale_strings[$string_id]) && $locale_strings[$string_id] != '') {
$empty_strings[$string_id] = [
'reference' => $value,
'translation' => $locale_strings[$string_id],
];
}
}

$empty_locale = array_filter($locale_strings, function ($string) {
return strlen($string) == 0;
});
foreach ($empty_locale as $string_id => $value) {
if (isset($reference_strings[$string_id]) && $reference_strings[$string_id] != '') {
$empty_strings[$string_id] = [
'reference' => $reference_strings[$string_id],
'translation' => $value,
];
}
}

unset($reference_strings);
unset($locale_strings);

if (count($empty_strings) > 0) {
ksort($empty_strings);
$components = Project::getComponents($empty_strings);
$filter_block = '';
foreach ($components as $value) {
$filter_block .= " <a href='#{$value}' id='{$value}' class='filter'>{$value}</a>";
}
}
@@ -0,0 +1,131 @@
<?php
namespace Transvision;

?>
<p class="intro">This view displays strings that are empty in the reference language
but have a translation in the requested language, and viceversa.
It can be used to identify strings that should have been localized and
are empty by mistake, and strings that should actually remain empty.
</p>
<form name="searchform" id="simplesearchform" method="get" action="">
<fieldset id="main_search">

<?php if (isset($target_locales_list)) : ?>
<fieldset>
<label>Locale</label>
<div class="select-style">
<select name="locale" title="Locale" id="simplesearch_locale">
<?=$target_locales_list?>
</select>
</div>
</fieldset>
<?php endif; ?>

<?php if (isset($channel_selector)) : ?>
<fieldset>
<label>Repository</label>
<div class="select-style">
<select name="repo" title="Repository" id="simplesearch_repository">
<?=$channel_selector?>
</select>
</div>
</fieldset>
<?php endif; ?>

<input type="submit" value="Go" alt="Go" />
</fieldset>
</form>
<?php if (isset($filter_block)) {
?>
<div id="filters">
<h4>Filter by folder:</h4>
<a href="#showall" id="showall" class="filter">Show all results</a>
<?=$filter_block; ?>
</div>
<?php

}

if (count($empty_strings) == 0) {
echo "<div class=\"message\"><p>No strings found.</p></div>";
} else {
$text_direction = RTLSupport::getDirection($locale);
$table = "<table class='collapsable results_table sortable'>
<thead>
<tr class='column_headers'>
<th>Entity</th>
<th>{$reference_locale}</th>
<th>{$locale}</th>
</tr>
</thead>
<tbody>\n";

foreach ($empty_strings as $key => $strings) {
$entity = ShowResults::formatEntity($key);
$component = explode('/', $key)[0];
$reference_string = htmlspecialchars($strings['reference']);
$locale_string = Strings::highlightSpecial(htmlspecialchars($strings['translation']), false);

$entity_link = "?sourcelocale={$reference_locale}"
. "&locale={$locale}"
. "&repo={$repo}"
. "&search_type=entities&recherche={$key}"
. "&perfect_match=perfect_match";

$bugzilla_link = [Bugzilla::reportErrorLink(
$locale, $key, $reference_string, $locale_string, $repo, $entity_link
)];

$reference_path = VersionControl::hgPath($reference_locale, $repo, $key);
$locale_path = VersionControl::hgPath($locale, $repo, $key);

if (! $reference_string) {
$reference_string = '<em class="error">(empty)</em>';
}
if ($locale_string == '@@missing@@') {
$locale_string = '<em class="error">Missing string</em>';
} elseif ($locale_string == '') {
$locale_string = '<em class="error">(empty)</em>';
}

// Replace / and : in the key name and use it as an anchor name
$anchor_name = str_replace(['/', ':'], '_', $key);

$table .= "
<tr class='{$component}'>
<td>
<span class='celltitle'>Entity</span>
<a class='resultpermalink tag' id='{$anchor_name}' href='#{$anchor_name}' title='Permalink to this string'>link</a>
<a class='l10n tag' href='/string/?entity={$key}&amp;repo={$repo}' title='List all translations for this entity'>l10n</a>
<a class='link_to_entity' href=\"/{$entity_link}\">{$entity}</a>
</td>
<td dir='ltr' lang='{$reference_locale}'>
<span class='celltitle'>{$reference_locale}</span>
<div class='string'>
{$reference_string}
</div>
<div dir='ltr' class='result_meta_link'>
<a class='source_link' href='{$reference_path}'>
&lt;source&gt;
</a>
</div>
</td>
<td dir='{$text_direction}' lang='{$locale}'>
<span class='celltitle'>{$locale}</span>
<div class='string'>{$locale_string}</div>
<div dir='ltr' class='result_meta_link'>
<a class='source_link' href='{$locale_path}'>
&lt;source&gt;
</a>
&nbsp;
<a class='bug_link' target='_blank' href='{$bugzilla_link[0]}'>
&lt;report a bug&gt;
</a>
</div>
</td>
</tr>";
}
$table .= " </tbody>\n</table>\n";

echo $table;
}
@@ -45,6 +45,7 @@
<ul>
{$li_link('keys', 'Check your access keys', 'Access Keys')}
{$li_link('checkvariables', 'Check what variable differences there are from English', 'Check Variables')}
{$li_link('empty_strings', 'Display empty strings in English or locale', 'Empty Strings')}
{$li_link('unchangedstrings', 'Display all strings identical to English', 'Unchanged Strings')}
{$li_link('unlocalized_all', 'Display common words remaining in English', 'Unlocalized Words')}
</ul>
@@ -7,6 +7,7 @@
['consistency/?locale=fr&repo=central', 200, 'English String', 'Available Translations'],
['consistency/?locale=en-US&repo=central', 200, 'No inconsistent translations found.', 'Analyze translation consistency across repositories.'],
['credits/', 200, 'Transvision 1.0 was created', 'Transvision is a community project under the MozFR umbrella'],
['empty-strings/', 200, 'Empty Strings', 'Repository'],
['downloads/', 200, 'Select which strings', 'Generate the TMX'],
['news/', 200, 'Version 4.0', 'End user visible changes'],
['productization/', 200, 'Show productization', 'firefox'],
@@ -96,13 +96,13 @@ public function multipleStringReplaceDP()
return [
[
[
' ' => '<span class="highlight-gray" title="Non breakable space"> </span>', // Nbsp highlight
' ' => '<span class="highlight-red" title="Thin space"> </span>', // Thin space highlight
'…' => '<span class="highlight-gray">…</span>', // Right ellipsis highlight
'&hellip;' => '<span class="highlight-gray">…</span>', // Right ellipsis highlight
' ' => '<span class="highlight-special highlight-gray" title="Non breakable space"> </span>', // Nbsp highlight
' ' => '<span class="highlight-special highlight-red" title="Thin space"> </span>', // Thin space highlight
'…' => '<span class="highlight-special highlight-gray">…</span>', // Right ellipsis highlight
'&hellip;' => '<span class="highlight-special highlight-gray">…</span>', // Right ellipsis highlight
],
'&hellip;  …',
'<span class="highlight-gray">…</span><span class="highlight-gray" title="Non breakable space"> </span><span class="highlight-red" title="Thin space"> </span><span class="highlight-gray">…</span>',
'<span class="highlight-special highlight-gray">…</span><span class="highlight-special highlight-gray" title="Non breakable space"> </span><span class="highlight-special highlight-red" title="Thin space"> </span><span class="highlight-special highlight-gray">…</span>',
],
];
}
@@ -123,10 +123,10 @@ public function testHighlightSpecial()
$obj = new _Strings();
$this
->string($obj->highlightSpecial('Foo is bar ; Bar is Foo…'))
->isEqualTo('Foo is bar<span class="highlight-gray" title="Non breakable space"> </span>;<span class="highlight-gray" title="Non breakable space"> </span>Bar is Foo<span class="highlight-gray" title="Real ellipsis">…</span>');
->isEqualTo('Foo is bar<span class="highlight-special highlight-gray" title="Non breakable space"> </span>;<span class="highlight-special highlight-gray" title="Non breakable space"> </span>Bar is Foo<span class="highlight-special highlight-gray" title="Real ellipsis">…</span>');
$this
->string($obj->highlightSpecial('Foo is bar ; Bar is Foo…', false))
->isEqualTo('Foo<span class="highlight-space" title="White space"> </span>is<span class="highlight-space" title="White space"> </span>bar<span class="highlight-gray" title="Non breakable space"> </span>;<span class="highlight-gray" title="Non breakable space"> </span>Bar<span class="highlight-space" title="White space"> </span>is<span class="highlight-space" title="White space"> </span>Foo<span class="highlight-gray" title="Real ellipsis">…</span>');
->isEqualTo('Foo<span class="highlight-special highlight-space" title="White space"> </span>is<span class="highlight-special highlight-space" title="White space"> </span>bar<span class="highlight-special highlight-gray" title="Non breakable space"> </span>;<span class="highlight-special highlight-gray" title="Non breakable space"> </span>Bar<span class="highlight-special highlight-space" title="White space"> </span>is<span class="highlight-special highlight-space" title="White space"> </span>Foo<span class="highlight-special highlight-gray" title="Real ellipsis">…</span>');
}

public function markStringDP()
@@ -947,6 +947,18 @@ input[type="checkbox"]:disabled + label {
margin-top: -10px;
}

/* Empty strings view */
#empty_strings .intro,
#empty_strings .message {
margin: 0 auto;
text-align: center;
width: 75%;
}

#empty_strings .highlight-special {
min-width: 0.5em;
}

/* Glossary view */
#glossary_matches {
width: 80%;

0 comments on commit 17373b2

Please sign in to comment.
You can’t perform that action at this time.