Skip to content
This repository has been archived by the owner on Jan 10, 2020. It is now read-only.

Commit

Permalink
Fix error handling of translation in news feed
Browse files Browse the repository at this point in the history
Google Translate has a maximum number of characters it will accept in requests, so make sure we
don't send more than that. If an error does occur in translation, indicate this to the user but
allow translations to continue. Also, fix the translation tooltips so that they match the item that
the user hovered over.
  • Loading branch information
tpanningnextcen committed Jun 7, 2016
1 parent 9c0111b commit 9eb5dd9
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 34 deletions.
36 changes: 21 additions & 15 deletions client/app/sprites.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Icon classes can be used entirely standalone. They are named after their origina
*/
.icon-Error_16x16 {
background-image: url(../assets/images/spritesheet.png);
background-position: -336px -52px;
background-position: -336px -72px;
width: 16px;
height: 16px;
}
Expand All @@ -35,7 +35,7 @@ Icon classes can be used entirely standalone. They are named after their origina
}
.icon-Neon_16x16 {
background-image: url(../assets/images/spritesheet.png);
background-position: -320px -52px;
background-position: -320px -72px;
width: 16px;
height: 16px;
}
Expand All @@ -52,6 +52,12 @@ Icon classes can be used entirely standalone. They are named after their origina
height: 34px;
}
.icon-Translated_20x20 {
background-image: url(../assets/images/spritesheet.png);
background-position: -320px -52px;
width: 20px;
height: 20px;
}
.icon-Translation_Failed_20x20 {
background-image: url(../assets/images/spritesheet.png);
background-position: -320px -32px;
width: 20px;
Expand All @@ -65,79 +71,79 @@ Icon classes can be used entirely standalone. They are named after their origina
}
.icon-BarChart64 {
background-image: url(../assets/images/spritesheet.png);
background-position: -192px 0px;
background-position: -192px -64px;
width: 64px;
height: 64px;
}
.icon-Count64 {
background-image: url(../assets/images/spritesheet.png);
background-position: -192px -64px;
background-position: -192px -128px;
width: 64px;
height: 64px;
}
.icon-CreateFilter64 {
background-image: url(../assets/images/spritesheet.png);
background-position: -192px -128px;
background-position: 0px -192px;
width: 64px;
height: 64px;
}
.icon-Gantt64 {
background-image: url(../assets/images/spritesheet.png);
background-position: 0px -192px;
background-position: -64px -192px;
width: 64px;
height: 64px;
}
.icon-Graph64 {
background-image: url(../assets/images/spritesheet.png);
background-position: -64px -192px;
background-position: -128px -192px;
width: 64px;
height: 64px;
}
.icon-LineChart64 {
background-image: url(../assets/images/spritesheet.png);
background-position: -128px -192px;
background-position: 0px 0px;
width: 64px;
height: 64px;
}
.icon-Map64 {
background-image: url(../assets/images/spritesheet.png);
background-position: 0px 0px;
background-position: -256px 0px;
width: 64px;
height: 64px;
}
.icon-News64 {
background-image: url(../assets/images/spritesheet.png);
background-position: -256px 0px;
background-position: -256px -64px;
width: 64px;
height: 64px;
}
.icon-OPS64 {
background-image: url(../assets/images/spritesheet.png);
background-position: -256px -64px;
background-position: -256px -128px;
width: 64px;
height: 64px;
}
.icon-OpsClock64 {
background-image: url(../assets/images/spritesheet.png);
background-position: -256px -128px;
background-position: -256px -192px;
width: 64px;
height: 64px;
}
.icon-PieChart64 {
background-image: url(../assets/images/spritesheet.png);
background-position: -256px -192px;
background-position: 0px -256px;
width: 64px;
height: 64px;
}
.icon-ScatterPlot64 {
background-image: url(../assets/images/spritesheet.png);
background-position: 0px -256px;
background-position: -64px -256px;
width: 64px;
height: 64px;
}
.icon-Sunburst64 {
background-image: url(../assets/images/spritesheet.png);
background-position: -64px -256px;
background-position: -192px 0px;
width: 64px;
height: 64px;
}
Expand Down
13 changes: 9 additions & 4 deletions client/app/translation.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,15 @@ angular.module("neonDemo.services")
});
deferred.resolve(response);
}, function(response) {
deferred.reject({
message: response.data.error.message,
reason: concatErrorResponses(response.data.error.errors)
});
var rejection = {
message: "",
reasion: ""
};
if(response && response.data && response.data.error) {
rejection.message = response.data.error.message;
rejection.reason = concatErrorResponses(response.data.error.errors);
}
deferred.reject(rejection);
});

return deferred.promise;
Expand Down
Binary file added client/assets/images/Translation_Failed_20x20.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified client/assets/images/spritesheet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 52 additions & 14 deletions client/components/newsFeed/newsFeed.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ angular.module('neonDemo.controllers').controller('newsFeedController', ['$scope
// Prevents translation api calls from getting too long and returning an error
var TRANSLATION_INTERVAL = 10;

var MAXIMUM_TRANSLATION_QUERY_LENGTH = 10000;

// The data in this newsfeed from a news event or an empty array if the data in this newsfeed is from a query.
var newsEventData = [];

Expand Down Expand Up @@ -378,6 +380,36 @@ angular.module('neonDemo.controllers').controller('newsFeedController', ['$scope
sliceStart = sliceStart || 0;
sliceEnd = sliceEnd || sliceStart + TRANSLATION_INTERVAL;

var getLengthOfField = function(index, key) {
if($scope.active.data[index] && _.isString($scope.active.data[index][key])) {
return encodeURIComponent($scope.active.data[index][key]).length;
} else {
return 0;
}
};

var queryLength = 0;
for(var i = sliceStart; i < sliceEnd; ++i) {
queryLength += getLengthOfField(i, "primaryTitle");
queryLength += getLengthOfField(i, "secondaryTitle");
queryLength += getLengthOfField(i, "content");
if(queryLength > MAXIMUM_TRANSLATION_QUERY_LENGTH) {
// If this item causes us to go over the maximum length, then stop before this
// item...
if(i > sliceStart) {
sliceEnd = i;
break;
} else {
// ...unless this was the first item, in which case this item is too long to
// translate on its own, so just mark its translation as failed and skip it.
$scope.active.data[i].isTranslated = false;
$scope.active.data[i].translationFailed = true;
sliceStart = i + 1;
queryLength = 0;
}
}
}

runTranslation("primaryTitle", sliceStart, sliceEnd, function() {
runTranslation("secondaryTitle", sliceStart, sliceEnd, function() {
runTranslation("content", sliceStart, sliceEnd, function() {
Expand All @@ -395,37 +427,43 @@ angular.module('neonDemo.controllers').controller('newsFeedController', ['$scope
* @param {String} newsProperty
* @param {Integer} sliceStart
* @param {Integer} sliceEnd
* @param {Function} successCallback
* @param {Function} finishedCallback
* @method runTranslation
* @private
*/
var runTranslation = function(newsProperty, sliceStart, sliceEnd, successCallback) {
var runTranslation = function(newsProperty, sliceStart, sliceEnd, finishedCallback) {
var dataText = _.pluck($scope.active.data, newsProperty).map(function(data) {
return $.isNumeric(data) ? "" : data;
});

var translationSuccessCallback = function(translations) {
var index = sliceStart;
translations.forEach(function(item) {
while(!$scope.active.data[index][newsProperty] && index < sliceEnd) {
index++;
}
if(index < sliceEnd) {
var newsItem = $scope.active.data[index];
newsItem[newsProperty + "Translated"] = item.translatedText;
newsItem.isTranslated = newsItem.isTranslated || newsItem[newsProperty] !== newsItem[newsProperty + "Translated"];
index++;
}
});
successCallback();
try {
translations.forEach(function(item) {
if(index < sliceEnd) {
if(!($scope.active.data[index] && $scope.active.data[index][newsProperty])) {
index++;
} else {
var newsItem = $scope.active.data[index];
newsItem[newsProperty + "Translated"] = item.translatedText;
newsItem.isTranslated = !newsItem.translationFailed && (newsItem.isTranslated || newsItem[newsProperty] !== newsItem[newsProperty + "Translated"]);
index++;
}
}
});
} catch(err) {
}
finishedCallback();
};

var translationFailureCallback = function() {
for(var i = sliceStart; i < sliceEnd; ++i) {
$scope.active.data[i][newsProperty + "Translated"] = $scope.active.data[i][newsProperty];
$scope.active.data[i].isTranslated = false;
$scope.active.data[i].translationFailed = true;
}
$scope.loadingTranslations = false;
finishedCallback();
};

$scope.functions.runTranslation(dataText.slice(sliceStart, sliceEnd), translationSuccessCallback, translationFailureCallback);
Expand Down
1 change: 1 addition & 0 deletions client/components/newsFeed/newsFeedDisplay.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<div>
<span ng-if="active.feedType == active.TWITTER" class="icon-Twitter_32x32 neon-sprite" title="Tweet"></span>
<span ng-show="active.showTranslations && item.isTranslated" class="icon-Translated_20x20 neon-sprite" title="Showing Translation"></span>
<span ng-show="active.showTranslations && item.translationFailed" class="icon-Translation_Failed_20x20 neon-sprite" title="Translation Failed"></span>
<span ng-class="{true: 'vertical-align', false: ''}[active.feedType == active.TWITTER]">
<span class="primary-title" ng-if="item.primaryTitle != undefined" ng-hide="active.showTranslations" ng-bind="item.primaryTitle"></span>
<span class="primary-title" ng-if="item.primaryTitleTranslated != undefined" ng-show="active.showTranslations" ng-bind="item.primaryTitleTranslated" title="{{item.primaryTitle}}"></span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,7 @@ function($scope, external, connectionService, datasetService, errorNotificationS
}
$scope.errorMessage = errorNotificationService.showErrorMessage($scope.element, response.message, response.reason);
if(translationFailureCallback) {
translationFailureCallback(response.data.data.translations);
translationFailureCallback();
}
}, $scope.languages.chosenFromLanguage);
};
Expand Down

0 comments on commit 9eb5dd9

Please sign in to comment.