diff --git a/gui/slick/js/core.js b/gui/slick/js/core.js index 29696eccf023f27ce9360fc5f1ea00665e24f1cc..6b6ff0e088fa372bd05e4afa8260ee977f7c0903 100644 --- a/gui/slick/js/core.js +++ b/gui/slick/js/core.js @@ -50,10 +50,11 @@ function notifyModal(message){ $('#site-notification-modal').modal(); } -function addSiteMessage(level, message){ +function addSiteMessage(level, tag, message){ level = level || 'danger'; + tag = tag || ''; message = message || ''; - $.post(srRoot + '/ui/set_site_message', {level: level, message: message}, function (siteMessages) { + $.post(srRoot + '/ui/set_site_message', {level: level, tag: tag, message: message}, function (siteMessages) { var messagesDiv = $('#site-messages'); if (messagesDiv !== undefined) { messagesDiv.empty(); @@ -4047,14 +4048,15 @@ var UTIL = { }; // Handle js-gettext + load javascript functions -var gt = null; +var gt = null, _n = null; $.getJSON(srRoot + '/ui/locale.json', function(data) { if (data !== undefined) { gt = new Gettext(data.messages); // jshint ignore:line } else { gt = new Gettext(); // jshint ignore:line } - _ = function(str) { return gt.gettext(str); }; // Create shortcut + _ = function(str) { return gt.gettext(str); }; // Shortcut for normal gettext + _n = function(str, pluralStr, num) { return gt.ngettext(str, pluralStr, num); }; // Shortcut for plural gettext if (navigator.userAgent.indexOf('PhantomJS') === -1) { $(document).ready(UTIL.init); diff --git a/gui/slick/js/core.min.js b/gui/slick/js/core.min.js index d73dc773a4115f40ceaf6ba4a5f5f1d980327888..a1b62aac5847a7b165f1d1f6c237d64befb4d339 100644 Binary files a/gui/slick/js/core.min.js and b/gui/slick/js/core.min.js differ diff --git a/setup.cfg b/setup.cfg index 45c6a7239c3b18456d3f6eb4e4903e2e25002318..1114881b3785e1306d5c8afcd610ca80a2a67faf 100644 --- a/setup.cfg +++ b/setup.cfg @@ -2,9 +2,12 @@ width = 80 charset = utf-8 output-file = locale/messages.pot -keywords = _ gettext ngettext +# keywords to look for in addition to the defaults. +keywords = _n:1,2 copyright-holder = SickRage msgid-bugs-address = miigotu@gmail.com +# place comment block with TAG (or those preceding keyword lines) in output file. Separate multiple TAGs with commas(,) +add-comments = TRANSLATORS: [compile_catalog] directory = locale diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index dfcc891a5bf2157f33b28a58bcff66180e1938e5..4eb549caf74208f3d91aa594d741426bdb4d1598 100644 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -68,7 +68,7 @@ import requests from tornado.locale import load_gettext_translations -gettext.install('messages', unicode=1, codeset='UTF-8') +gettext.install('messages', unicode=1, codeset='UTF-8', names=["ngettext"]) # Some strings come from metadata or libraries or 3rd party sites, # So we need to pre-define them to get translations for them @@ -870,9 +870,9 @@ def initialize(consoleLogging=True): # pylint: disable=too-many-locals, too-man GUI_LANG = check_setting_str(CFG, 'GUI', 'language') if GUI_LANG: - gettext.translation('messages', LOCALE_DIR, languages=[GUI_LANG], codeset='UTF-8').install(unicode=1) + gettext.translation('messages', LOCALE_DIR, languages=[GUI_LANG], codeset='UTF-8').install(unicode=1, names=["ngettext"]) else: - gettext.install('messages', LOCALE_DIR, unicode=1, codeset='UTF-8') + gettext.install('messages', LOCALE_DIR, unicode=1, codeset='UTF-8', names=["ngettext"]) load_gettext_translations(LOCALE_DIR, 'messages') diff --git a/sickbeard/common.py b/sickbeard/common.py index 6bb556ddf8e5100015be31fb04400cba2c0a9fcc..2381f29bd614b063a6b32c26c6cc195d35b44c8d 100644 --- a/sickbeard/common.py +++ b/sickbeard/common.py @@ -43,7 +43,7 @@ from sickrage.helper.encoding import ek from sickrage.recompiled import tags from sickrage.tagger.episode import EpisodeTags -gettext.install('messages', unicode=1, codeset='UTF-8') +gettext.install('messages', unicode=1, codeset='UTF-8', names=["ngettext"]) # If some provider has an issue with functionality of SR, other than user agents, it's best to come talk to us rather than block. # It is no different than us going to a provider if we have questions or issues. Be a team player here. diff --git a/sickbeard/helpers.py b/sickbeard/helpers.py index 2618b9aa52b1cb442cb779fc8e1c97443c6c51f2..eca4b4ad0b7c29af272bd16bb4329dc31d86b0a7 100644 --- a/sickbeard/helpers.py +++ b/sickbeard/helpers.py @@ -1839,24 +1839,15 @@ def recursive_listdir(path): MESSAGE_COUNTER = 0 -def add_site_message(message, level='danger'): +def add_site_message(message, tag=None, level='danger'): with sickbeard.MESSAGES_LOCK: - to_add = dict(level=level, message=message) + to_add = dict(level=level, tag=tag, message=message) - basic_update_url = sickbeard.versionChecker.UpdateManager.get_update_url().split('?')[0] - for index, existing in six.iteritems(sickbeard.SITE_MESSAGES): - if basic_update_url in existing['message'] and basic_update_url in message: - sickbeard.SITE_MESSAGES[index] = to_add - return - - if message.endswith('Please use \'master\' unless specifically asked') and \ - existing['message'].endswith('Please use \'master\' unless specifically asked'): - sickbeard.SITE_MESSAGES[index] = to_add - return - - if message.startswith('No NZB/Torrent providers found or enabled for') and \ - existing['message'].startswith('No NZB/Torrent providers found or enabled for'): - sickbeard.SITE_MESSAGES[index] = to_add + if tag: # prevent duplicate messages of the same type + # http://www.goodmami.org/2013/01/30/Getting-only-the-first-match-in-a-list-comprehension.html + existing = next((x for x, msg in six.iteritems(sickbeard.SITE_MESSAGES) if msg.get('tag') == tag), None) + if existing: + sickbeard.SITE_MESSAGES[existing] = to_add return global MESSAGE_COUNTER @@ -1864,22 +1855,14 @@ def add_site_message(message, level='danger'): sickbeard.SITE_MESSAGES[MESSAGE_COUNTER] = to_add -def remove_site_message(begins='', ends='', contains='', key=None): +def remove_site_message(key=None, tag=None): with sickbeard.MESSAGES_LOCK: if key is not None and int(key) in sickbeard.SITE_MESSAGES: del sickbeard.SITE_MESSAGES[int(key)] - - for index, existing in six.iteritems(sickbeard.SITE_MESSAGES.copy()): - checks = [] - if begins and isinstance(begins, six.string_types): - checks.append(existing['message'].startswith(begins)) - if ends and isinstance(ends, six.string_types): - checks.append(existing['message'].endsswith(ends)) - if contains and isinstance(ends, six.string_types): - checks.append(contains in existing['message']) - - if all(checks): - del sickbeard.SITE_MESSAGES[index] + elif tag is not None: + found = [idx for idx, msg in six.iteritems(sickbeard.SITE_MESSAGES) if msg.get('tag') == tag] + for key in found: + del sickbeard.SITE_MESSAGES[key] def sortable_name(name): diff --git a/sickbeard/providers/__init__.py b/sickbeard/providers/__init__.py index 9c2820e8e3c4d201ede33427b14459e346f3da35..5ea124139b2054adbbcf27204283ce4d76cd77e3 100644 --- a/sickbeard/providers/__init__.py +++ b/sickbeard/providers/__init__.py @@ -108,9 +108,11 @@ def check_enabled_providers(): break if not (daily_enabled and backlog_enabled): - formatted_msg = "No NZB/Torrent providers found or enabled for {0}.<br/>".format( - (("daily searches and backlog searches", "daily searches")[backlog_enabled], "backlog searches")[daily_enabled]) - formatted_msg += "Please <a href=\"" + sickbeard.WEB_ROOT + "/config/providers/\">check your settings</a>." - sickbeard.helpers.add_site_message(formatted_msg, 'danger') + searches = ((_('daily searches and backlog searches'), _('daily searches'))[backlog_enabled], + _('backlog searches'))[daily_enabled] + formatted_msg = _('No NZB/Torrent providers found or enabled for {searches}.<br/>' + 'Please <a href="{web_root}/config/providers/">check your settings</a>.') + sickbeard.helpers.add_site_message(formatted_msg.format(searches=searches, web_root=sickbeard.WEB_ROOT), + tag='no_providers_enabled', level='danger') else: - sickbeard.helpers.remove_site_message(begins="No NZB/Torrent providers found or enabled for") + sickbeard.helpers.remove_site_message(tag='no_providers_enabled') diff --git a/sickbeard/versionChecker.py b/sickbeard/versionChecker.py index f16791dca2a7ba227a1d1821a094e754e90c9035..c63f64c51f5b89515752ba599743bbb09a0c9581 100644 --- a/sickbeard/versionChecker.py +++ b/sickbeard/versionChecker.py @@ -371,11 +371,6 @@ class GitUpdateManager(UpdateManager): def get_num_commits_behind(self): return self._num_commits_behind - @staticmethod - def _git_error(): - error_message = 'Unable to find your git executable - Shutdown SickRage and EITHER set git_path in your config.ini OR delete your .git folder and run from source to enable updates.' - helpers.add_site_message(error_message, 'danger') - def _find_working_git(self): test_cmd = 'version' @@ -419,9 +414,10 @@ class GitUpdateManager(UpdateManager): logger.log("Not using: " + cur_git, logger.DEBUG) # Still haven't found a working git - error_message = 'Unable to find your git executable - Shutdown SickRage and EITHER set git_path in your config.ini OR delete your .git folder and run from source to enable updates.' - helpers.add_site_message(error_message, 'danger') - + helpers.add_site_message( + _('Unable to find your git executable - Shutdown SickRage and EITHER set git_path in ' + 'your config.ini OR delete your .git folder and run from source to enable updates.'), + tag='unable_to_find_git', level='danger') return None @staticmethod @@ -552,12 +548,14 @@ class GitUpdateManager(UpdateManager): return logger.log("cur_commit = {0}, newest_commit = {1}, num_commits_behind = {2}, num_commits_ahead = {3}".format - (self._cur_commit_hash, self._newest_commit_hash, self._num_commits_behind, self._num_commits_ahead), logger.DEBUG) + (self._cur_commit_hash, self._newest_commit_hash, self._num_commits_behind, self._num_commits_ahead), + logger.DEBUG) def set_newest_text(self): if self._num_commits_ahead: - logger.log("Local branch is ahead of " + self.branch + ". Automatic update not possible.", logger.WARNING) - newest_text = "Local branch is ahead of " + self.branch + ". Automatic update not possible." + newest_tag = 'local_branch_ahead' + newest_text = 'Local branch is ahead of {branch}. Automatic update not possible.'.format(branch=self.branch) + logger.log(newest_text, logger.WARNING) elif self._num_commits_behind > 0: @@ -567,16 +565,18 @@ class GitUpdateManager(UpdateManager): else: url = base_url + '/commits/' - newest_text = 'There is a <a href="' + url + '" onclick="window.open(this.href); return false;">newer version available</a> ' - newest_text += " (you're " + str(self._num_commits_behind) + " commit" - if self._num_commits_behind > 1: - newest_text += 's' - newest_text += ' behind)' + "— <a href=\"" + self.get_update_url() + "\">Update Now</a>" + newest_tag = 'newer_version_available' + commits_behind = ngettext("(you're {num_commits} commit behind)", "(you're {num_commits} commits behind)", + self._num_commits_behind).format(num_commits=self._num_commits_behind) + newest_text = _('There is a <a href="{compare_url}" onclick="window.open(this.href); return false;">' + 'newer version available</a> {commits_behind} — ' + '<a href="{update_url}">Update Now</a>').format( + compare_url=url, commits_behind=commits_behind, update_url=self.get_update_url()) else: return - helpers.add_site_message(newest_text, 'success') + helpers.add_site_message(newest_text, tag=newest_tag, level='success') def need_update(self): @@ -750,15 +750,17 @@ class SourceUpdateManager(UpdateManager): # when _cur_commit_hash doesn't match anything _num_commits_behind == 100 self._num_commits_behind += 1 - logger.log("cur_commit = " + str(self._cur_commit_hash) + ", newest_commit = " + str(self._newest_commit_hash) + - ", num_commits_behind = " + str(self._num_commits_behind), logger.DEBUG) + logger.log("cur_commit = {0}, newest_commit = {1}, num_commits_behind = {2}".format + (self._cur_commit_hash, self._newest_commit_hash, self._num_commits_behind), logger.DEBUG) def set_newest_text(self): if not self._cur_commit_hash: logger.log("Unknown current version number, don't know if we should update or not", logger.DEBUG) - newest_text = "Unknown current version number: If you've never used the SickRage upgrade system before then current version is not set." - newest_text += "— <a href=\"" + self.get_update_url() + "\">Update Now</a>" + newest_tag = 'unknown_current_version' + newest_text = _('Unknown current version number: ' + 'If you\'ve never used the SickRage upgrade system before then current version is not set. ' + '— <a href="{update_url}">Update Now</a>').format(update_url=self.get_update_url()) elif self._num_commits_behind > 0: base_url = 'http://github.com/' + sickbeard.GIT_ORG + '/' + sickbeard.GIT_REPO @@ -767,15 +769,17 @@ class SourceUpdateManager(UpdateManager): else: url = base_url + '/commits/' - newest_text = 'There is a <a href="' + url + '" onclick="window.open(this.href); return false;">newer version available</a>' - newest_text += " (you're " + str(self._num_commits_behind) + " commit" - if self._num_commits_behind > 1: - newest_text += "s" - newest_text += " behind)" + "— <a href=\"" + self.get_update_url() + "\">Update Now</a>" + newest_tag = 'newer_version_available' + commits_behind = ngettext("(you're {num_commits} commit behind)", "(you're {num_commits} commits behind)", + self._num_commits_behind).format(num_commits=self._num_commits_behind) + newest_text = _('There is a <a href="{compare_url}" onclick="window.open(this.href); return false;">' + 'newer version available</a> (you\'re {commits_behind} behind) — ' + '<a href="{update_url}">Update Now</a>').format( + compare_url=url, commits_behind=commits_behind, update_url=self.get_update_url()) else: return - helpers.add_site_message(newest_text, 'success') + helpers.add_site_message(newest_text, tag=newest_tag, level='success') def update(self): # pylint: disable=too-many-statements """ diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index 407c8ed6656b33e2302a7e480899eb8edb764848..78ce939e11ecb998f0109f05c994c1fee6ec0434 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -632,14 +632,15 @@ class UI(WebRoot): return json.dumps(messages) - def set_site_message(self, message, level): + def set_site_message(self, message, tag, level): self.set_header('Cache-Control', 'max-age=0,no-cache,no-store') if message: - helpers.add_site_message(message, level) + helpers.add_site_message(message, tag=tag, level=level) else: if sickbeard.BRANCH and sickbeard.BRANCH != 'master' and not sickbeard.DEVELOPER and self.get_current_user(): - message = _('You\'re using the {branch} branch. Please use \'master\' unless specifically asked').format(branch=sickbeard.BRANCH) - helpers.add_site_message(message, 'danger') + message = _('You\'re using the {branch} branch. ' + 'Please use \'master\' unless specifically asked').format(branch=sickbeard.BRANCH) + helpers.add_site_message(message, tag='not_using_master_branch', level='danger') return sickbeard.SITE_MESSAGES @@ -3949,10 +3950,10 @@ class ConfigGeneral(Config): if gui_language != sickbeard.GUI_LANG: if gui_language: # Selected language - gettext.translation('messages', sickbeard.LOCALE_DIR, languages=[gui_language], codeset='UTF-8').install(unicode=1) + gettext.translation('messages', sickbeard.LOCALE_DIR, languages=[gui_language], codeset='UTF-8').install(unicode=1, names=["ngettext"]) else: # System default language - gettext.install('messages', sickbeard.LOCALE_DIR, unicode=1, codeset='UTF-8') + gettext.install('messages', sickbeard.LOCALE_DIR, unicode=1, codeset='UTF-8', names=["ngettext"]) sickbeard.GUI_LANG = gui_language