def datetime_to_countdown(dt: typing.Union[str, datetime.datetime], show_direction=True): """ Convert a datetime.timedelta object into Days, Hours, Minutes, Seconds. """ if isinstance(dt, str): dt = to_aware_datetime(dt) delta = dt - timezone.datetime.now(tz=timezone.get_current_timezone()) a_day = 86400 an_hour = 3600 a_minute = 60 timetot = '' total_secs = secs = delta.total_seconds() if secs > 0: direction = _('later') elif secs < 0: direction = _('ago') total_secs = -total_secs secs = -secs else: return _('now') if secs > a_day: # 60sec * 60min * 24hrs days = int(secs // a_day) # timetot += "{} {}".format(int(days), _('days')) timetot += _n('%(num)s day', '%(num)s days', days) % {'num': days} secs = secs - days * a_day if secs > an_hour: hrs = int(secs // an_hour) # timetot += " {} {}".format(int(hrs), _('hours')) timetot += ' ' timetot += _n('%(num)s hour', '%(num)s hours', hrs) % {'num': hrs} secs = secs - hrs * an_hour if secs > a_minute and total_secs < a_day: mins = int(secs // a_minute) timetot += ' ' timetot += _n('%(num)s minute', '%(num)s minutes', mins) % { 'num': mins } secs = secs - mins * a_minute if secs > 0 and total_secs < an_hour: secs = int(secs) timetot += ' ' timetot += _n('%(num)s second', '%(num)s seconds', secs) % { 'num': secs } if not timetot and secs == 0: timetot = gettext('just now') else: if show_direction: timetot += ' %s' % direction return timetot
def process(self): self._errors = defaultdict(list) raw_args_len = len(self.raw_args) inline_args_len = self._meta.num_required_args if raw_args_len < inline_args_len: self.add_errors( ValidationError(_n( u'Takes at least %(inline_args_len)d non-keyword argument ' u'(%(raw_args_len)d given).', u'Takes at least %(inline_args_len)d non-keyword ' u'arguments (%(raw_args_len)d given).', inline_args_len), params={ 'raw_args_len': raw_args_len, 'inline_args_len': inline_args_len})) return elif raw_args_len > inline_args_len: self.add_errors( ValidationError(_n( u'Takes only %(inline_args_len)d non-keyword argument ' u'(%(raw_args_len)d given).', u'Takes only %(inline_args_len)d non-keyword arguments' u' (%(raw_args_len)d given).', inline_args_len), params={ 'raw_args_len': raw_args_len, 'inline_args_len': inline_args_len})) return args = OrderedDict(self._meta.args) raw_kwargs = self.raw_kwargs.copy() for i, arg_name in enumerate(self._meta.ordering): arg = args.pop(arg_name) try: self.data[arg_name] = arg.process(self.raw_args[i]) except ValidationError as e: self.add_errors(e, arg_name) for arg_name, arg in args.items(): try: val = raw_kwargs.pop(arg_name, arg.default) self.data[arg_name] = arg.process(val) except ValidationError as e: self.add_errors(e, arg_name) if bool(raw_kwargs): for arg_name in raw_kwargs.keys(): self.add_errors( ValidationError(_( u'Got an unexpected keyword argument `%(arg_name)s`'), params={'arg_name': arg_name})) self._clean_fields() self._clean_inline()
def publish_webapps(self, request, queryset): rows_updated = queryset.update(is_published=True, pub_time=now(), publisher=request.user) self.message_user(request, _n('One webapp was successfully marked as published', '%(count)d webapps were successfully marked as published', rows_updated) % {'count': rows_updated})
def voters_filtered_suffix(value): if not value: value = 0 msg = _n('(1 voter selected)', '(%(value)d voters selected)', value) % { 'value': value } return msg if value else _('(all voters selected)')
def buy(request, node_hex, item_id, template="node/buy.html"): """ Buy an item. """ node = Node.by_hex(node_hex) char = gtc(request) item = get_object_or_404(Item, id=item_id) result_str = _n( "Congratulations! You bought %(item)s for %(price)d %(currency_singular)s.", "Congratulations! You bought %(item)s for %(price)d %(currency_plural)s.", item.price) result_str = result_str % {"item": item.name, "price": item.price, "currency_singular": CURRENCY_SINGULAR, "currency_plural": CURRENCY_PLURAL} event = NodeEvent.objects.create( where=node, who=char, day=GameDay.get_day(), who_disguised=char.is_disguised, type=EVENT_BUY ) char.revert_disguise(request) return render(request, template, {"result_str": result_str, "item": item, "node": node})
def clean(self): """Checks if user isn't still on his 'add topic cooldown'.""" cooldown_remaining = Topic.get_user_cooldown(self.user) if not self.instance or not getattr(self.instance, 'pk', None): # Adding a new topic: check cooldown if cooldown_remaining > 0: raise ValidationError( _n( 'You have to wait %(seconds)d more second before you can place another topic', 'You have to wait %(seconds)d more seconds before you can place another topic', cooldown_remaining) % {'seconds': cooldown_remaining}) # Validate post-section of the form when editing the topic. We can only # do this when editing because PostForm needs a topic object to # function and there is none during the topic add process. if self.instance: post_instance = self.instance.head self.post_form = PostForm( user=self.user, ip=self.ip, instance=post_instance, topic=self.instance, data={'body': self.cleaned_data.get('body', '')}) post_form_result = self.post_form.is_valid() if not post_form_result: self.errors.update(self.post_form.errors) return super(TopicForm, self).clean()
def voters_filtered_suffix(value): if not value: value = 0 msg = _n( '(1 voter selected)', '(%(value)d voters selected)', value ) % {'value': value} return msg if value else _('(all voters selected)')
def get_mod_data(request): data = {} num_open_reports = Report.objects.filter(report_closed=False).count() data['open_reports'] = num_open_reports data['text_reports'] = _n("1 open report", "%(num)d open reports", num_open_reports) % { 'num': num_open_reports } return HttpResponse(json.dumps(data), content_type="application/json")
def get_help_text(self): """ Helper method defining text of ValidationError within validate() based on plurality of self.min_chars. """ return _n( 'Your password must contain at least %(min_chars)d lowercase letter.', 'Your password must contain at least %(min_chars)d lowercase letters.', self.min_chars) % { 'min_chars': self.min_chars }
def get_directory_summary(directory, dir_stats): """Returns a list of sentences to be displayed for each directory.""" summary = [ _n("This folder has %(num)d word, %(percentage)d%% of which is " "translated", "This folder has %(num)d words, %(percentage)d%% of which are " "translated", dir_stats['total']['words'], {'num': dir_stats['total']['words'], 'percentage': dir_stats['translated']['percentage']}), _n('<a class="directory-incomplete" href="%(url)s">%(num)d word ' 'needs translation</a>', '<a class="directory-incomplete" href="%(url)s">%(num)d words ' 'need translation</a>', dir_stats['untranslated']['words'], {'num': dir_stats['untranslated']['words'], 'url': dispatch.translate(directory, state='incomplete')}), ] return summary
def title(self): if self.is_free: return strings.PLAN_PRICE_TITLE_FREE elif self.duration_unit == constants.DURATION_UNIT_CHOICES.MONTHS: singular = strings.PLAN_PRICE_TITLE_MONTH plural = strings.PLAN_PRICE_TITLE_MONTH_PLURAL else: singular = strings.PLAN_PRICE_TITLE_YEAR plural = strings.PLAN_PRICE_TITLE_YEAR_PLURAL return '%i %s' % ( self.duration_magnitude, _n(singular, plural, self.duration_magnitude))
def make_published(self, request, queryset): rows_updated = queryset.update(status=Post.STATUS_PUBLIC) # Set published_date on entries that doesn't have one # workaround for http://code.djangoproject.com/ticket/12142 if queryset.filter(published_date__isnull=True).count() > 0: queryset.filter(published_date__isnull=True).update( published_date=datetime.datetime.now() ) message = _n('%(num)d post was published.', '%(num)d posts were published.', rows_updated) % {'num': rows_updated,} self.message_user(request, message)
def get_directory_summary(directory, dir_stats): """Returns a list of sentences to be displayed for each directory.""" summary = [ _n( "This folder has %(num)d word, %(percentage)d%% of which is " "translated", "This folder has %(num)d words, %(percentage)d%% of which are " "translated", dir_stats['total']['words'], { 'num': dir_stats['total']['words'], 'percentage': dir_stats['translated']['percentage'] }), _n( '<a class="directory-incomplete" href="%(url)s">%(num)d word ' 'needs translation</a>', '<a class="directory-incomplete" href="%(url)s">%(num)d words ' 'need translation</a>', dir_stats['untranslated']['words'], { 'num': dir_stats['untranslated']['words'], 'url': dispatch.translate(directory, state='incomplete') }), ] return summary
def humanize_seconds(secs: int): """ seconds turn into hummable datetime string """ a_day = 86400 an_hour = 3600 a_minute = 60 timetot = '' total_secs = secs if secs > a_day: # 60sec * 60min * 24hrs days = int(secs // a_day) # timetot += "{} {}".format(int(days), _('days')) timetot += _n('%(num)s day', '%(num)s days', days) % {'num': days} secs = secs - days * a_day if secs > an_hour: hrs = int(secs // an_hour) # timetot += " {} {}".format(int(hrs), _('hours')) timetot += ' ' timetot += _n('%(num)s hour', '%(num)s hours', hrs) % {'num': hrs} secs = secs - hrs * an_hour if secs > a_minute and total_secs < a_day: mins = int(secs // a_minute) timetot += ' ' timetot += _n('%(num)s minute', '%(num)s minutes', mins) % { 'num': mins } secs = secs - mins * a_minute if secs > 0 and total_secs < an_hour: secs = int(secs) timetot += ' ' timetot += _n('%(num)s second', '%(num)s seconds', secs) % { 'num': secs } return timetot
def set_ban(self): """ Logic to set a ban on failed registration attempts. If a ban is required, the time (in weeks) is exponentially in function of faulty attempts. Returns False if no bans were set. """ num_attempts = RegistrationAttempt.objects.filter( ip_address=self.ip_address, success=False).count() if num_attempts >= 2: from brouwers.banning.models import Ban kwargs = {} # expiry date if num_attempts >= MAX_REGISTRATION_ATTEMPTS: import math i = num_attempts - MAX_REGISTRATION_ATTEMPTS num_weeks = round(math.exp(i)) if num_weeks <= 52: kwargs['expiry_date'] = timezone.now() + timedelta( weeks=num_weeks) # else kwarg not set -> permaban else: kwargs['expiry_date'] = timezone.now() + timedelta( hours=STANDARD_BAN_TIME_HOURS) kwargs['reason'] = _n( 'The system flagged you as a bot or your registration attempt was not valid.', 'You tried registering %(times)s times without succes, the system flagged you as a ' 'bot.', num_attempts) % { 'times': num_attempts } kwargs['reason_internal'] = _( 'Probably spambot, %(num_attempts)s against maximum attempts of %(max)s' ) % { 'num_attempts': num_attempts, 'max': MAX_REGISTRATION_ATTEMPTS } kwargs['automatic'] = True ban = Ban.objects.create(ip=self.ip_address, **kwargs) # set the ban to the registration attempt self.ban = ban self.save() return ban return False
def set_ban(self): """ Logic to set a ban on failed registration attempts. If a ban is required, the time (in weeks) is exponentially in function of faulty attempts. Returns False if no bans were set. """ num_attempts = RegistrationAttempt.objects.filter( ip_address=self.ip_address, success=False ).count() if num_attempts >= 2: from banning.models import Ban kwargs = {} # expiry date if num_attempts >= MAX_REGISTRATION_ATTEMPTS: import math i = num_attempts - MAX_REGISTRATION_ATTEMPTS num_weeks = round(math.exp(i)) if num_weeks <= 52: kwargs['expiry_date'] = datetime.now() + timedelta(weeks=num_weeks) # else kwarg not set -> permaban else: kwargs['expiry_date'] = datetime.now() + timedelta(hours=STANDARD_BAN_TIME_HOURS) kwargs['reason'] = _n('The system flagged you as a bot or your registration attempt was not valid.', 'You tried registering %(times)s times without succes, the system flagged you as a bot.', num_attempts) % { 'times': num_attempts } kwargs['reason_internal'] = _('Probably spambot, %(num_attempts)s against maximum attempts of %(max)s') % { 'num_attempts': num_attempts, 'max': MAX_REGISTRATION_ATTEMPTS } kwargs['automatic'] = True ban = Ban.objects.create( ip = self.ip_address, **kwargs ) # set the ban to the registration attempt self.ban = ban self.save() return ban return False
def get_text(self): a = self.action targets = a.targets.all() ctxt = { 'actor': str(a.actor), 'verb': a.verb, 'targets': str_enum(targets), 'related': str_enum(a.related.all()) } if a.actor: if ctxt['related']: return _('%(actor)s %(verb)s %(targets)s ' 'in relation to %(related)s') % ctxt else: return _('%(actor)s %(verb)s %(targets)s') % ctxt else: if ctxt['related']: return _n( '%(target)s was %(verb)s in relation to %(related)s', '%(target)s were %(verb)s in relation to %(related)s', len(targets)) % ctxt else: return _n('%(target)s was %(verb)s', '%(target)s were %(verb)s', len(targets)) % ctxt
def clean(self): """Checks if Topic is open and user's post cooldown. """ if self.topic.is_locked and not \ pybb_can_administer_forum(self.user, self.topic.forum): # Disallow non-moderators raise ValidationError( _('The topic you are trying to post in is closed')) if not self.instance or not getattr(self.instance, 'pk', None): # Adding new post: check cooldown cooldown_remaining = Post.get_user_cooldown(self.user) if cooldown_remaining > 0: raise ValidationError( _n( 'You have to wait %(seconds)d more second before you can place another post', 'You have to wait %(seconds)d more seconds before you can place another post', cooldown_remaining) % {'seconds': cooldown_remaining}) return super(PostForm, self).clean()
def managed_blog_count(): """Displays text of how many blogs are being managed.""" blog_count = Blog.objects.all().count() return _n("Managing %(count)s WordPress blog", "Managing %(count)s WordPress blogs", blog_count) % { "count": '<span class="count">%s</span>' % apnumber(blog_count) }
class DecimalArgument(IntegerArgument): default_error_messages = { 'invalid': _('Enter a number.'), 'max_digits': _n('Ensure that there are no more than %(max)s digit in total.', 'Ensure that there are no more than %(max)s digits in total.', 'max'), 'max_decimal_places': _n('Ensure that there are no more than %(max)s decimal place.', 'Ensure that there are no more than %(max)s decimal places.', 'max'), 'max_whole_digits': _n( 'Ensure that there are no more than %(max)s digit before the ' 'decimal point.', 'Ensure that there are no more than %(max)s digits before the ' 'decimal point.', 'max') } def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs): self.max_digits, self.decimal_places = max_digits, decimal_places super(DecimalArgument, self).__init__(max_value, min_value, *args, **kwargs) def to_python(self, value): if value in self.empty_values: return None value = smart_text(value).strip() try: value = Decimal(value) except DecimalException: raise ValidationError(self.error_messages['invalid'], code='invalid') return value def validate(self, value): super(DecimalArgument, self).validate(value) if value in self.empty_values: return if value != value or value == Decimal("Inf") \ or value == Decimal("-Inf"): raise ValidationError(self.error_messages['invalid'], code='invalid') sign, digittuple, exponent = value.as_tuple() decimals = abs(exponent) digits = len(digittuple) if decimals > digits: digits = decimals whole_digits = digits - decimals if self.max_digits is not None and digits > self.max_digits: raise ValidationError(self.error_messages['max_digits'], code='max_digits', params={'max': self.max_digits}) if self.decimal_places is not None and decimals > self.decimal_places: raise ValidationError(self.error_messages['max_decimal_places'], code='max_decimal_places', params={'max': self.decimal_places}) if (self.max_digits is not None and self.decimal_places is not None and whole_digits > (self.max_digits - self.decimal_places)): raise ValidationError( self.error_messages['max_whole_digits'], code='max_whole_digits', params={'max': (self.max_digits - self.decimal_places)}) return value
def unpublish_slides(self, request, queryset): rows_updated = queryset.update(is_published=False, publisher=request.user) self.message_user(request, _n('One slide was successfully marked as published', '%(count)d slides were successfully marked as published', rows_updated) % {'count': rows_updated})
def make_withdrawn(self, request, queryset): rows_updated = queryset.update(status=Post.STATUS_DRAFT) message = _n('%(num)d post was withdrawn.', '%(num)d posts were withdrawn.', rows_updated) % {'num': rows_updated,} self.message_user(request, message)
def handle(self, **options): with override(settings.LANGUAGE_CODE): if options['hourly']: last_sent = datetime.utcnow() - timedelta(hours=1) frequency = 'hourly' elif options['daily']: last_sent = datetime.utcnow() - timedelta(days=1) frequency = 'daily' alerts = Alert.objects.filter( frequency=frequency, last_sent__lt=last_sent ) """ at the moment this means that if a user has multiple alerts set up they will get all of them in the same email, even if they have set up one alert to be daily and one to be hourly """ for alert in alerts: events = alert.user.notifications.unread() \ .order_by('action_object_content_type', 'action_object_object_id') details = "" current_object = '' if events.count() > 0: no_change_count = 0 change_count = 0 for event in events: if event.action_object != current_object: if current_object != '': details += "\n" details += _('Changes to {0}\n').format(event.action_object) domain = Site.objects.get_current().domain path = reverse( 'person-view', kwargs={'person_id': event.action_object.id} ) protocol = 'http' if hasattr(settings, 'ACCOUNT_DEFAULT_HTTP_PROTOCOL') and \ settings.ACCOUNT_DEFAULT_HTTP_PROTOCOL == 'https': protocol = 'https' details += "{0}://{1}{2}\n".format( protocol, domain, path ) current_object = event.action_object if event.data: if event.data['changes'] is not None: timestamp = parser.parse(event.data['changes']['timestamp']) event.data['changes']['timestamp'] = timestamp diff = render_to_string('alerts/pretty_diff.txt', context=event.data) # remove extra blank lines diff = "\n".join([ll.rstrip() for ll in diff.splitlines() if ll.strip()]) details += "\n{0}\n".format(diff) change_count += 1 else: no_change_count += 1 else: no_change_count += 1 if no_change_count > 0: if change_count > 0: desc = _n( "And %(no_change_count)d change we don't have details of", "And %(no_change_count)d changes we don't have details of", no_change_count ) % {'no_change_count': no_change_count} else: desc = _n( "There has been %(no_change_count)d change we don't have details of", "There have been %(no_change_count)d changes we don't have details of", no_change_count ) % {'no_change_count': no_change_count} details += "\n{0}\n".format(desc) recipients = [alert.user.email] has_sent = send_mail( _("Recent activity on {0}").format( Site.objects.get_current().name ), details, settings.DEFAULT_FROM_EMAIL, recipients, fail_silently=False, ) if has_sent: alert.last_sent = datetime.utcnow() alert.save() events.mark_all_as_read()
def __unicode__(self): return u"%d %s (at %s)" % (self.length, _n("%s", "%ss", self.length) % self.unit, self.get_due_at_display().lower())
from django.utils.translation import ugettext_lazy as _l, \ ungettext_lazy as _n test_string = _l('This is a lazily translated string') n = 1 test_nstring = _n('This is a translated string using singular', 'This is a translated string using plural', n)
translation_module_2.ngettext_lazy('tm2_ntest_lazy', 'tm2_ntests_lazy', 42) translation_module_2.ungettext('tm2_untest', 'tm2_untests', 42) translation_module_2.ungettext_lazy('tm2_untest_lazy', 'tm2_untests_lazy', 42) translation_module_2.npgettext('context', 'tm2_nptest', 'tm2_nptests', 42) translation_module_2.npgettext_lazy('context', 'tm2_nptest_lazy', 'tm2_nptests_lazy', 42) _('alias_test') _l('alias_test_lazy') _0x90('alias_test_noop') _u('alias_utest') _ul('alias_utest_lazy') _u0x90('alias_utest_noop') _p('context', 'alias_ptest') _pl('context', 'alias_ptest_lazy') _n('alias_ntest', 'alias_ntests', 42) _nl('alias_ntest_lazy', 'alias_ntests_lazy', 42) _un('alias_untest', 'alias_untests', 42) _unl('alias_untest_lazy', 'alias_untests_lazy', 42) _np('context', 'alias_nptest', 'alias_nptests', 42) _npl('context', 'alias_nptest_lazy', 'alias_nptests_lazy', 42) def gettext(message): pass gettext('not a translation') def some_function():
def get_mod_data(request): data = {} num_open_reports = Report.objects.filter(report_closed=False).count() data['open_reports'] = num_open_reports data['text_reports'] = _n("1 open report", "%(num)d open reports", num_open_reports) % {'num': num_open_reports} return HttpResponse(json.dumps(data), content_type="application/json")