diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -4,3 +4,4 @@ c3fe200198f5aa34cf2e4066df2881a9cefe3704
7fd5c850745e2ea821fb4406af5f4bff9b0a7526 v4.1.1
41c87da28a179953df86061d817bc35533c66dd2 v4.1.2
baaf9f5bcea3bae0ef12ae20c8b270482e62abb6 v4.2.0
+32a70c7e56844a825f61df496ee5eaf8c3c4e189 v4.2.1
diff --git a/Gruntfile.js b/Gruntfile.js
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -19,6 +19,7 @@ module.exports = function(grunt) {
'<%= dirs.js.src %>/mousetrap.js',
'<%= dirs.js.src %>/moment.js',
'<%= dirs.js.src %>/appenlight-client-0.4.1.min.js',
+ '<%= dirs.js.src %>/i18n_utils.js',
// Plugins
'<%= dirs.js.src %>/plugins/jquery.pjax.js',
diff --git a/docs/release-notes/release-notes-4.2.1.rst b/docs/release-notes/release-notes-4.2.1.rst
new file mode 100644
--- /dev/null
+++ b/docs/release-notes/release-notes-4.2.1.rst
@@ -0,0 +1,14 @@
+|RCE| 4.2.1 |RNS|
+-----------------
+
+Release Date
+^^^^^^^^^^^^
+
+- 2016-07-04
+
+Fixes
+^^^^^
+
+- ui: fixed empty labels caused by missing translation of JS components
+- login: fixed bad routing URL in comments when user is not logged in.
+- celery: make sure to run tasks in sync mode if connection to celery is lost.
diff --git a/docs/release-notes/release-notes.rst b/docs/release-notes/release-notes.rst
--- a/docs/release-notes/release-notes.rst
+++ b/docs/release-notes/release-notes.rst
@@ -9,6 +9,7 @@ Release Notes
.. toctree::
:maxdepth: 1
+ release-notes-4.2.1.rst
release-notes-4.2.0.rst
release-notes-4.1.2.rst
release-notes-4.1.1.rst
diff --git a/rhodecode/public/js/rhodecode/i18n/select2/translations.js b/rhodecode/public/js/rhodecode/i18n/select2/translations.js
--- a/rhodecode/public/js/rhodecode/i18n/select2/translations.js
+++ b/rhodecode/public/js/rhodecode/i18n/select2/translations.js
@@ -1,33 +1,42 @@
// translate select2 components
select2Locales = {
formatLoadMore: function(pageNumber) {
- return _TM["Loading more results..."];
+ return _gettext("Loading more results...");
},
formatSearching: function() {
- return _TM["Searching..."];
+ return _gettext("Searching...");
},
formatNoMatches: function() {
- return _TM["No matches found"];
+ return _gettext("No matches found");
},
formatAjaxError: function(jqXHR, textStatus, errorThrown) {
- return _TM["Loading failed"];
+ return _gettext("Loading failed");
},
formatMatches: function(matches) {
if (matches === 1) {
- return _TM["One result is available, press enter to select it."];
+ return _gettext("One result is available, press enter to select it.");
}
- return _TM["{0} results are available, use up and down arrow keys to navigate."].format(matches);
+ return _gettext("{0} results are available, use up and down arrow keys to navigate.").format(matches);
},
formatInputTooShort: function(input, min) {
var n = min - input.length;
- return "Please enter {0} or more character".format(n) + (n === 1 ? "" : "s");
+ if (n === 1) {
+ return _gettext("Please enter {0} or more character").format(n);
+ }
+ return _gettext("Please enter {0} or more characters").format(n);
},
formatInputTooLong: function(input, max) {
var n = input.length - max;
- return "Please delete {0} character".format(n) + (n === 1 ? "" : "s");
+ if (n === 1) {
+ return _gettext("Please delete {0} character").format(n);
+ }
+ return _gettext("Please delete {0} characters").format(n);
},
formatSelectionTooBig: function(limit) {
- return "You can only select {0} item".format(limit) + (limit === 1 ? "" : "s");
+ if (limit === 1) {
+ return _gettext("You can only select {0} item").format(limit);
+ }
+ return _gettext("You can only select {0} items").format(limit);
}
};
diff --git a/rhodecode/public/js/src/i18n_utils.js b/rhodecode/public/js/src/i18n_utils.js
new file mode 100644
--- /dev/null
+++ b/rhodecode/public/js/src/i18n_utils.js
@@ -0,0 +1,36 @@
+// # Copyright (C) 2016-2016 RhodeCode GmbH
+// #
+// # This program is free software: you can redistribute it and/or modify
+// # it under the terms of the GNU Affero General Public License, version 3
+// # (only), as published by the Free Software Foundation.
+// #
+// # This program is distributed in the hope that it will be useful,
+// # but WITHOUT ANY WARRANTY; without even the implied warranty of
+// # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// # GNU General Public License for more details.
+// #
+// # You should have received a copy of the GNU Affero General Public License
+// # along with this program. If not, see .
+// #
+// # This program is dual-licensed. If you wish to learn more about the
+// # RhodeCode Enterprise Edition, including its added features, Support services,
+// # and proprietary license terms, please see https://rhodecode.com/licenses/
+
+i18nLog = Logger.get('i18n');
+
+var _gettext = function (s) {
+ if (_TM.hasOwnProperty(s)) {
+ return _TM[s];
+ }
+ i18nLog.error(
+ 'String `' + s + '` was requested but cannot be ' +
+ 'found in translation table');
+ return s
+};
+
+var _ngettext = function (singular, plural, n) {
+ if (n === 1) {
+ return _gettext(singular)
+ }
+ return _gettext(plural)
+};
diff --git a/rhodecode/public/js/src/plugins/jquery.autocomplete.js b/rhodecode/public/js/src/plugins/jquery.autocomplete.js
--- a/rhodecode/public/js/src/plugins/jquery.autocomplete.js
+++ b/rhodecode/public/js/src/plugins/jquery.autocomplete.js
@@ -84,7 +84,7 @@
return typeof response === 'string' ? $.parseJSON(response) : response;
},
showNoSuggestionNotice: false,
- noSuggestionNotice: _TM['No results'],
+ noSuggestionNotice: _gettext('No results'),
orientation: 'bottom',
forceFixPosition: false,
replaceOnArrowKey: true
diff --git a/rhodecode/public/js/src/plugins/jquery.timeago-extension.js b/rhodecode/public/js/src/plugins/jquery.timeago-extension.js
--- a/rhodecode/public/js/src/plugins/jquery.timeago-extension.js
+++ b/rhodecode/public/js/src/plugins/jquery.timeago-extension.js
@@ -10,21 +10,6 @@ var AgeModule = (function () {
var show_suffix = show_suffix || true;
var short_format = short_format || false;
- // alias for backward compat
- var _ = function(s) {
- if (_TM.hasOwnProperty(s)) {
- return _TM[s];
- }
- return s
- };
-
- var ungettext = function (singular, plural, n) {
- if (n === 1){
- return _(singular)
- }
- return _(plural)
- };
-
var _get_relative_delta = function(now, prevdate) {
var duration = moment.duration(moment(now).diff(prevdate));
@@ -121,12 +106,12 @@ var AgeModule = (function () {
} else {
var fmt_funcs = {
- 'year': function(d) {return ungettext('{0} year', '{0} years', d).format(d)},
- 'month': function(d) {return ungettext('{0} month', '{0} months', d).format(d)},
- 'day': function(d) {return ungettext('{0} day', '{0} days', d).format(d)},
- 'hour': function(d) {return ungettext('{0} hour', '{0} hours', d).format(d)},
- 'minute': function(d) {return ungettext('{0} min', '{0} min', d).format(d)},
- 'second': function(d) {return ungettext('{0} sec', '{0} sec', d).format(d)}
+ 'year': function(d) {return _ngettext('{0} year', '{0} years', d).format(d)},
+ 'month': function(d) {return _ngettext('{0} month', '{0} months', d).format(d)},
+ 'day': function(d) {return _ngettext('{0} day', '{0} days', d).format(d)},
+ 'hour': function(d) {return _ngettext('{0} hour', '{0} hours', d).format(d)},
+ 'minute': function(d) {return _ngettext('{0} min', '{0} min', d).format(d)},
+ 'second': function(d) {return _ngettext('{0} sec', '{0} sec', d).format(d)}
}
}
@@ -146,7 +131,7 @@ var AgeModule = (function () {
var _val = fmt_funcs[part](value);
if (future) {
if (show_suffix) {
- return _('in {0}').format(_val)
+ return _gettext('in {0}').format(_val)
} else {
return _val
}
@@ -154,7 +139,7 @@ var AgeModule = (function () {
}
else {
if (show_suffix) {
- return _('{0} ago').format(_val)
+ return _gettext('{0} ago').format(_val)
} else {
return _val
}
@@ -166,17 +151,17 @@ var AgeModule = (function () {
if (short_format) {
var datetime_tmpl = '{0}, {1}';
if (show_suffix) {
- datetime_tmpl = _('{0}, {1} ago');
+ datetime_tmpl = _gettext('{0}, {1} ago');
if (future) {
- datetime_tmpl = _('in {0}, {1}');
+ datetime_tmpl = _gettext('in {0}, {1}');
}
}
} else {
- var datetime_tmpl = _('{0} and {1}');
+ var datetime_tmpl = _gettext('{0} and {1}');
if (show_suffix) {
- datetime_tmpl = _('{0} and {1} ago');
+ datetime_tmpl = _gettext('{0} and {1} ago');
if (future) {
- datetime_tmpl = _('in {0} and {1}')
+ datetime_tmpl = _gettext('in {0} and {1}')
}
}
}
@@ -186,7 +171,7 @@ var AgeModule = (function () {
i += 1;
}
- return _('just now')
+ return _gettext('just now')
},
createTimeComponent: function(dateTime, text) {
diff --git a/rhodecode/public/js/src/rhodecode.js b/rhodecode/public/js/src/rhodecode.js
--- a/rhodecode/public/js/src/rhodecode.js
+++ b/rhodecode/public/js/src/rhodecode.js
@@ -24,15 +24,6 @@ if (typeof console == "undefined" || typ
console = { log: function() {} }
}
-
-// alias for backward compat
-var _tm = function(s) {
- if (_TM.hasOwnProperty(s)) {
- return _TM[s];
- }
- return s
-};
-
// TODO: move the following function to submodules
/**
@@ -148,7 +139,7 @@ var showRepoStats = function(target, dat
var td2 = document.createElement('td');
var trending_language = document.createElement('div');
- var nr_files = obj.count +" "+ (obj.count === 1 ? _tm('file'): _tm('files'));
+ var nr_files = obj.count +" "+ _ngettext('file', 'files', obj.count);
trending_language.title = key + " " + nr_files;
@@ -168,7 +159,7 @@ var showRepoStats = function(target, dat
lnk = document.createElement('a');
lnk.href = '#';
- lnk.innerHTML = _tm('Show more');
+ lnk.innerHTML = _ngettext('Show more');
lnk.id = 'code_stats_show_more';
td.appendChild(lnk);
diff --git a/rhodecode/public/js/src/rhodecode/codemirror.js b/rhodecode/public/js/src/rhodecode/codemirror.js
--- a/rhodecode/public/js/src/rhodecode/codemirror.js
+++ b/rhodecode/public/js/src/rhodecode/codemirror.js
@@ -366,7 +366,7 @@ var initCommentBoxCodeMirror = function(
var actions = [
{
text: "approve",
- displayText: _TM['Set status to Approved'],
+ displayText: _gettext('Set status to Approved'),
hint: function(CodeMirror, data, completion) {
CodeMirror.replaceRange("", completion.from || data.from,
completion.to || data.to, "complete");
@@ -384,7 +384,7 @@ var initCommentBoxCodeMirror = function(
},
{
text: "reject",
- displayText: _TM['Set status to Rejected'],
+ displayText: _gettext('Set status to Rejected'),
hint: function(CodeMirror, data, completion) {
CodeMirror.replaceRange("", completion.from || data.from,
completion.to || data.to, "complete");
diff --git a/rhodecode/public/js/src/rhodecode/comments.js b/rhodecode/public/js/src/rhodecode/comments.js
--- a/rhodecode/public/js/src/rhodecode/comments.js
+++ b/rhodecode/public/js/src/rhodecode/comments.js
@@ -240,7 +240,7 @@ var deleteComment = function(comment_id)
};
var createInlineAddButton = function(tr){
- var label = _TM['Add another comment'];
+ var label = _gettext('Add another comment');
var html_el = document.createElement('div');
$(html_el).addClass('add-comment');
html_el.innerHTML = '{0}'.format(label);
@@ -458,7 +458,7 @@ var CommentForm = (function() {
};
$(this.submitForm).find(this.statusChange).select2({
- placeholder: _TM['Status Review'],
+ placeholder: _gettext('Status Review'),
formatResult: formatResult,
formatSelection: formatSelection,
containerCssClass: "drop-menu status_box_menu",
@@ -472,7 +472,7 @@ var CommentForm = (function() {
$(self.submitButton).prop('disabled', false);
}
//todo, fix this name
- var placeholderText = _TM['Comment text will be set automatically based on currently selected status ({0}) ...'].format(status);
+ var placeholderText = _gettext('Comment text will be set automatically based on currently selected status ({0}) ...').format(status);
self.cm.setOption('placeholder', placeholderText);
})
};
@@ -586,7 +586,7 @@ var CommentForm = (function() {
}
$(this.submitButton).prop('disabled', submitState);
if (submitEvent) {
- $(this.submitButton).val(_TM['Submitting...']);
+ $(this.submitButton).val(_gettext('Submitting...'));
} else {
$(this.submitButton).val(this.submitButtonText);
}
@@ -636,7 +636,7 @@ var CommentForm = (function() {
self.setActionButtonsDisabled(true);
$(self.previewBoxSelector).addClass('unloaded');
- $(self.previewBoxSelector).html(_TM['Loading ...']);
+ $(self.previewBoxSelector).html(_gettext('Loading ...'));
$(self.editContainer).hide();
$(self.previewContainer).show();
diff --git a/rhodecode/public/js/src/rhodecode/files.js b/rhodecode/public/js/src/rhodecode/files.js
--- a/rhodecode/public/js/src/rhodecode/files.js
+++ b/rhodecode/public/js/src/rhodecode/files.js
@@ -147,9 +147,9 @@ var fileBrowserListeners = function(node
if(results.length > limit){
var truncated_count = results.length - matches_max;
if (truncated_count === 1) {
- match.push('
{0} {1} | |
'.format(truncated_count, _TM['truncated result']));
+ match.push('{0} {1} | |
'.format(truncated_count, _gettext('truncated result')));
} else {
- match.push('{0} {1} | |
'.format(truncated_count, _TM['truncated results']));
+ match.push('{0} {1} | |
'.format(truncated_count, _gettext('truncated results')));
}
}
}
@@ -158,7 +158,7 @@ var fileBrowserListeners = function(node
$('#tbody_filtered').show();
if (match.length === 0){
- match.push('{0} | |
'.format(_TM['No matching files']));
+ match.push('{0} | |
'.format(_gettext('No matching files')));
}
$('#tbody_filtered').html(match.join(""));
}
@@ -293,7 +293,7 @@ var getSelectionLink = function(e) {
anchor = '#L'+ranges[0]+'-'+ranges[1];
var link = document.createElement('a');
link.href = location.href.substring(0,location.href.indexOf('#'))+anchor;
- link.innerHTML = _TM['Selection link'];
+ link.innerHTML = _gettext('Selection link');
hl_div.appendChild(link);
$('#codeblock').append(hl_div);
diff --git a/rhodecode/public/js/src/rhodecode/followers.js b/rhodecode/public/js/src/rhodecode/followers.js
--- a/rhodecode/public/js/src/rhodecode/followers.js
+++ b/rhodecode/public/js/src/rhodecode/followers.js
@@ -23,8 +23,8 @@ var onSuccessFollow = function(target){
if(f.hasClass('follow')){
f.removeClass('follow');
f.addClass('following');
- f.attr('title', _TM['Stop following this repository']);
- $(f).html(_TM['Unfollow']);
+ f.attr('title', _gettext('Stop following this repository'));
+ $(f).html(_gettext('Unfollow'));
if(f_cnt.length){
var cnt = Number(f_cnt.html())+1;
f_cnt.html(cnt);
@@ -33,8 +33,8 @@ var onSuccessFollow = function(target){
else{
f.removeClass('following');
f.addClass('follow');
- f.attr('title', _TM['Start following this repository']);
- $(f).html(_TM['Follow']);
+ f.attr('title', _gettext('Start following this repository'));
+ $(f).html(_gettext('Follow'));
if(f_cnt.length){
var cnt = Number(f_cnt.html())-1;
f_cnt.html(cnt);
diff --git a/rhodecode/public/js/src/rhodecode/tooltips.js b/rhodecode/public/js/src/rhodecode/tooltips.js
--- a/rhodecode/public/js/src/rhodecode/tooltips.js
+++ b/rhodecode/public/js/src/rhodecode/tooltips.js
@@ -116,7 +116,7 @@ var show_changeset_tooltip = function(){
}
if(rid && !$(target).hasClass('tooltip')){
$(target).attr('id', ttid);
- $(target).attr('title', _TM['loading ...']);
+ $(target).attr('title', _gettext('loading ...'));
TTIP.main.set_listeners(target);
TTIP.main.show_tip(e, target);
var url = pyroutes.url('changeset_info', {"repo_name":repo_name, "revision": rid});
diff --git a/rhodecode/templates/admin/auth/auth_settings.html b/rhodecode/templates/admin/auth/auth_settings.html
--- a/rhodecode/templates/admin/auth/auth_settings.html
+++ b/rhodecode/templates/admin/auth/auth_settings.html
@@ -101,7 +101,7 @@
elems.splice(elems.indexOf(plugin_id), 1);
auth_plugins_input.val(elems.join(','));
$(cur_button).removeClass('btn-success');
- cur_button.innerHTML = _TM['disabled'];
+ cur_button.innerHTML = _gettext('disabled');
}
else{
if(elems.indexOf(plugin_id) == -1){
@@ -109,7 +109,7 @@
}
auth_plugins_input.val(elems.join(','));
$(cur_button).addClass('btn-success');
- cur_button.innerHTML = _TM['enabled'];
+ cur_button.innerHTML = _gettext('enabled');
}
});
diff --git a/rhodecode/templates/admin/users/users.html b/rhodecode/templates/admin/users/users.html
--- a/rhodecode/templates/admin/users/users.html
+++ b/rhodecode/templates/admin/users/users.html
@@ -42,8 +42,8 @@
var api = datatable.api();
var total = api.page.info().recordsDisplay;
var active = datatable.fnGetFilteredData();
-
- $('#user_count').text(_TM["{0} active out of {1} users"].format(active, total));
+ var _text = _gettext("{0} active out of {1} users").format(active, total);
+ $('#user_count').text(_text);
};
// custom filter that filters by username OR email
diff --git a/rhodecode/templates/changelog/changelog.html b/rhodecode/templates/changelog/changelog.html
--- a/rhodecode/templates/changelog/changelog.html
+++ b/rhodecode/templates/changelog/changelog.html
@@ -228,9 +228,9 @@
open_new_pull_request.hide();
} else {
if (selected_changes == 1) {
- open_new_pull_request.html(_TM['Open new pull request for selected commit']);
+ open_new_pull_request.html(_gettext('Open new pull request for selected commit'));
} else if (selected_changes == 0) {
- open_new_pull_request.html(_TM['Open new pull request']);
+ open_new_pull_request.html(_gettext('Open new pull request'));
}
open_new_pull_request.show();
}
@@ -244,8 +244,8 @@
'revision': revStart+'...'+revEnd});
var link = (revStart == revEnd)
- ? _TM['Show selected commit __S']
- : _TM['Show selected commits __S ... __E'];
+ ? _gettext('Show selected commit __S')
+ : _gettext('Show selected commits __S ... __E');
link = link.replace('__S', revStart.substr(0,6));
link = link.replace('__E', revEnd.substr(0,6));
diff --git a/rhodecode/templates/changeset/changeset_file_comment.html b/rhodecode/templates/changeset/changeset_file_comment.html
--- a/rhodecode/templates/changeset/changeset_file_comment.html
+++ b/rhodecode/templates/changeset/changeset_file_comment.html
@@ -151,7 +151,7 @@
${h.form('', class_='inline-form comment-form-login', method='get')}