def get_context(self, change=None): """Return context for rendering mail""" result = { 'LANGUAGE_CODE': get_language(), 'LANGUAGE_BIDI': get_language_bidi(), 'current_site_url': get_site_url(), 'site_title': settings.SITE_TITLE, 'notification_name': self.verbose, } if not change: return result result['change'] = change # Extract change attributes attribs = ( 'unit', 'translation', 'component', 'project', 'dictionary', 'comment', 'suggestion', 'whiteboard', 'alert', 'user', 'target', 'old', 'details', ) for attrib in attribs: result[attrib] = getattr(change, attrib) if result['translation']: result['translation_url'] = get_site_url( result['translation'].get_absolute_url() ) return result
def get(self, request, *args, **kwargs): object_list = self.get_queryset()[:2000] # Do reasonable ACL check for global acl_obj = self.translation or self.component or self.project if not acl_obj: for change in object_list: if change.component: acl_obj = change.component break if not request.user.has_perm('change.download', acl_obj): raise PermissionDenied() # Always output in english activate('en') response = HttpResponse(content_type='text/csv; charset=utf-8') response['Content-Disposition'] = 'attachment; filename=changes.csv' writer = csv.writer(response) # Add header writer.writerow(('timestamp', 'action', 'user', 'url', 'target')) for change in object_list: writer.writerow(( change.timestamp.isoformat(), change.get_action_display(), change.user.username if change.user else '', get_site_url(change.get_absolute_url()), change.target, )) return response
def download_translations(self, source, language, text, unit, user): """Download list of possible translations from a service.""" # should the machine translation service be used? # (rather than only the term database) enable_mt = False if isinstance(settings.MT_SAP_USE_MT, bool): enable_mt = settings.MT_SAP_USE_MT # build the json body request_data_as_bytes = json.dumps( { 'targetLanguages': [language], 'sourceLanguage': source, 'enableMT': enable_mt, 'enableTranslationQualityEstimation': enable_mt, 'units': [{'value': text}] }, ensure_ascii=False ).encode('utf-8') # create the request translation_url = settings.MT_SAP_BASE_URL + 'translate' request = Request( translation_url if six.PY3 else translation_url.encode("utf-8") ) request.timeout = 0.5 request.add_header('User-Agent', USER_AGENT.encode('utf-8')) request.add_header('Referer', get_site_url().encode('utf-8')) request.add_header('Content-Type', 'application/json; charset=utf-8') request.add_header('Content-Length', len(request_data_as_bytes)) request.add_header('Accept', 'application/json; charset=utf-8') self.authenticate(request) # Read and possibly convert response content = urlopen( request, request_data_as_bytes ).read().decode('utf-8') # Replace literal \t content = content.strip().replace( '\t', '\\t' ).replace( '\r', '\\r' ) response = json.loads(content) translations = [] # prepare the translations for weblate for item in response['units']: for translation in item['translations']: translations.append(( translation['value'], translation.get('qualityIndex', 100), self.name, text )) return translations
def render_template(template, **kwargs): """Helper class to render string template with context.""" translation = kwargs.get('translation') component = kwargs.get('component') project = kwargs.get('project') if getattr(translation, 'id', None): translation.stats.ensure_basic() kwargs['language_code'] = translation.language_code kwargs['language_name'] = translation.language.name kwargs['stats'] = translation.stats.get_data() kwargs['url'] = get_site_url(translation.get_absolute_url()) component = translation.component if getattr(component, 'id', None): kwargs['component_name'] = component.name kwargs['component_slug'] = component.slug kwargs['component_remote_branch'] = \ component.repository.get_remote_branch_name() project = component.project if getattr(project, 'id', None): kwargs['project_name'] = project.name kwargs['project_slug'] = project.slug with override('en'): return Template( template, engine=RestrictedEngine(), ).render( Context(kwargs, autoescape=False), )
def run_domain(checks, request): """Check for domain configuration""" checks.append(( _('Site domain'), check_domain(get_site_domain()), 'production-site', get_site_url(), ))
def get_notification_email(language, email, notification, context=None, info=None): """Render notification email.""" context = context or {} headers = {} LOGGER.info( 'sending notification %s on %s to %s', notification, info, email ) with override('en' if language is None else language): # Template name context['subject_template'] = 'mail/{0}_subject.txt'.format( notification ) context['LANGUAGE_CODE'] = get_language() context['LANGUAGE_BIDI'] = get_language_bidi() # Adjust context context['current_site_url'] = get_site_url() context['site_title'] = settings.SITE_TITLE # Render subject subject = render_to_string( context['subject_template'], context ).strip() # Render body html_body = render_to_string( 'mail/{0}.html'.format(notification), context ) body = html2text(html_body) # Define headers headers['Auto-Submitted'] = 'auto-generated' headers['X-AutoGenerated'] = 'yes' headers['Precedence'] = 'bulk' headers['X-Mailer'] = 'Weblate {0}'.format(VERSION) # List of recipients if email == 'ADMINS': emails = [a[1] for a in settings.ADMINS] else: emails = [email] # Return the mail content return { 'subject': subject, 'body': body, 'to': emails, 'headers': headers, 'html_body': html_body, }
def json_req(self, url, http_post=False, skip_auth=False, raw=False, **kwargs): """Perform JSON request.""" # Encode params if kwargs: params = urlencode(kwargs) else: params = '' # Store for exception handling self.request_url = url self.request_params = params # Append parameters if params and not http_post: url = '?'.join((url, params)) # Create request object with custom headers request = Request(url) request.timeout = 0.5 request.add_header('User-Agent', USER_AGENT) request.add_header('Referer', get_site_url()) # Optional authentication if not skip_auth: self.authenticate(request) # Fire request if http_post: handle = urlopen(request, params.encode('utf-8')) else: handle = urlopen(request) # Read and possibly convert response text = handle.read() # Needed for Microsoft if text[:3] == b'\xef\xbb\xbf': text = text.decode('UTF-8-sig') else: text = text.decode('utf-8') # Replace literal \t text = text.strip().replace( '\t', '\\t' ).replace( '\r', '\\r' ) # Needed for Google while ',,' in text or '[,' in text: text = text.replace(',,', ',null,').replace('[,', '[') if raw: return text # Parse JSON response = json.loads(text) # Return data return response
def get_share_url(self): """Return absolute URL usable for sharing.""" return get_site_url( reverse( 'engage', kwargs={ 'project': self.component.project.slug, 'lang': self.language.code } ) )
def get_export_url(component): """Return Git export URL for component""" return get_site_url( reverse( 'git-export', kwargs={ 'project': component.project.slug, 'component': component.slug, 'path': '', } ) )
def __init__(self, project=None, language=None, url=None, translation=None, fieldnames=None): if translation is not None: self.plural = translation.plural self.project = translation.component.project self.language = translation.language self.url = get_site_url(translation.get_absolute_url()) else: self.project = project self.language = language self.plural = language.plural self.url = url self.fieldnames = fieldnames
def get_widgets_url(self): """Return absolute URL for widgets.""" return get_site_url( '{0}?lang={1}&component={2}'.format( reverse( 'widgets', kwargs={ 'project': self.component.project.slug, } ), self.language.code, self.component.slug, ) )
def is_spam(text, request): """Generic spam checker interface.""" if settings.AKISMET_API_KEY: from akismet import Akismet akismet = Akismet( settings.AKISMET_API_KEY, get_site_url() ) return akismet.comment_check( get_ip_address(request), request.META.get('HTTP_USER_AGENT', ''), comment_content=text, comment_type='comment' ) return False
def commit_and_push(self, component): repository = component.repository with repository.lock: if repository.needs_commit(): files = [t.filename for t in component.translation_set.all()] repository.commit( render_template( self.message, hook_name=self.verbose, project_name=component.project.name, component_name=component.name, url=get_site_url(component.get_absolute_url()) ), files=files ) component.push_if_needed(None)
def report_spam(text, user_ip, user_agent): if not settings.AKISMET_API_KEY: return from akismet import Akismet, ProtocolError akismet = Akismet( settings.AKISMET_API_KEY, get_site_url() ) try: akismet.submit_spam( user_ip, user_agent, comment_content=text, comment_type='comment' ) except ProtocolError as error: report_error(error)
def render(self): translations = [] offset = 30 color = self.COLOR_MAP[self.color] for stats in self.obj.stats.get_language_stats(): language = stats.language percent = stats.translated_percent if self.color == 'auto': if percent >= 90: color = '#4c1' elif percent >= 75: color = '#dfb317' else: color = '#e05d44' translations.append(( # Language name language.name, # Translation percent percent, # Text y offset offset, # Bar y offset offset - 10, # Bar width int(percent * 1.5), # Bar color color, # Row URL get_site_url(reverse( 'project-language', kwargs={'lang': language.code, 'project': self.obj.slug} )), # Bounding box y offset offset - 15, )) offset += 20 self.image = render_to_string( 'multi-language-badge.svg', { 'height': len(translations) * 20 + 20, 'boxheight': len(translations) * 20 + 10, 'translations': translations, } )
def __init__(self, project=None, language=None, url=None, translation=None, fieldnames=None): if translation is not None: self.project = translation.component.project self.language = translation.language self.url = get_site_url(translation.get_absolute_url()) else: self.project = project self.language = language self.url = url self.fieldnames = fieldnames self.storage = self.get_storage() self.storage.setsourcelanguage( self.project.source_language.code ) self.storage.settargetlanguage( self.language.code )
def refresh(self): stats = GlobalStats() data = { "secret": self.secret, "site_url": get_site_url(), "site_title": settings.SITE_TITLE, "users": User.objects.count(), "projects": Project.objects.count(), "components": Component.objects.count(), "languages": stats.languages, "source_strings": stats.source_strings, "strings": stats.all, "words": stats.all_words, } if self.discoverable: data["discoverable"] = 1 data["public_projects"] = json.dumps( [ { "name": project.name, "url": project.get_absolute_url(), "web": project.web, } for project in Project.objects.filter( access_control=Project.ACCESS_PUBLIC ).iterator() ] ) ssh_key = get_key_data() if not ssh_key: generate_ssh_key(None) ssh_key = get_key_data() if ssh_key: data["ssh_key"] = ssh_key["key"] response = request("post", settings.SUPPORT_API_URL, data=data) response.raise_for_status() payload = response.json() self.name = payload["name"] self.expiry = dateutil.parser.parse(payload["expiry"]) self.in_limits = payload["in_limits"] if payload["backup_repository"]: BackupService.objects.get_or_create( repository=payload["backup_repository"], defaults={"enabled": False} )
def get_notification_emails(language, recipients, notification, context=None, info=None): """Render notification email.""" context = context or {} headers = {} LOGGER.info('sending notification %s on %s to %s', notification, info, ', '.join(recipients)) with override('en' if language is None else language): # Template name context['subject_template'] = 'mail/{0}_subject.txt'.format( notification) context['LANGUAGE_CODE'] = get_language() context['LANGUAGE_BIDI'] = get_language_bidi() # Adjust context context['current_site_url'] = get_site_url() context['site_title'] = settings.SITE_TITLE # Render subject subject = render_to_string(context['subject_template'], context).strip() context['subject'] = subject # Render body body = render_to_string('mail/{0}.html'.format(notification), context) # Define headers headers['Auto-Submitted'] = 'auto-generated' headers['X-AutoGenerated'] = 'yes' headers['Precedence'] = 'bulk' headers['X-Mailer'] = 'Weblate {0}'.format(VERSION) # Return the mail content return [{ 'subject': subject, 'body': body, 'address': address, 'headers': headers } for address in recipients]
def get_notification_emails(language, recipients, notification, context=None, info=None): """Render notification email.""" context = context or {} headers = {} LOGGER.info("sending notification %s on %s to %s", notification, info, ", ".join(recipients)) with override("en" if language is None else language): # Template name context["subject_template"] = f"mail/{notification}_subject.txt" context["LANGUAGE_CODE"] = get_language() context["LANGUAGE_BIDI"] = get_language_bidi() # Adjust context context["current_site_url"] = get_site_url() context["site_title"] = settings.SITE_TITLE # Render subject subject = render_to_string(context["subject_template"], context).strip() context["subject"] = subject # Render body body = render_to_string(f"mail/{notification}.html", context) # Define headers headers["Auto-Submitted"] = "auto-generated" headers["X-AutoGenerated"] = "yes" headers["Precedence"] = "bulk" headers[ "X-Mailer"] = "Weblate" if settings.HIDE_VERSION else USER_AGENT # Return the mail content return [{ "subject": subject, "body": body, "address": address, "headers": headers } for address in recipients]
def notify_expired(): for bill in Billing.objects.filter(state=Billing.STATE_ACTIVE): if bill.check_payment_status(): continue users = bill.owners.distinct() for project in bill.projects.all(): users |= User.objects.having_perm('billing.view', project) for user in users: send_notification_email( user.profile.language, user.email, 'billing_expired', context={ 'billing': bill, 'billing_url': get_site_url(reverse('billing')), }, info=bill, )
def get_stats(self): """Return stats dictionary""" return { 'code': self.language.code, 'name': self.language.name, 'total': self.stats.all, 'total_words': self.stats.all_words, 'last_change': self.stats.last_changed, 'last_author': self.get_last_author(), 'translated': self.stats.translated, 'translated_words': self.stats.translated_words, 'translated_percent': self.stats.translated_percent, 'fuzzy': self.stats.fuzzy, 'fuzzy_percent': self.stats.fuzzy_percent, 'failing': self.stats.allchecks, 'failing_percent': self.stats.allchecks_percent, 'url': self.get_share_url(), 'url_translate': get_site_url(self.get_absolute_url()), }
def notify_expired(): possible_billings = Billing.objects.filter( Q(state=Billing.STATE_ACTIVE) | Q(removal__isnull=False) ) for bill in possible_billings: if bill.state != Billing.STATE_TRIAL and bill.check_payment_status(): continue for user in bill.get_notify_users(): send_notification_email( user.profile.language, user.email, 'billing_expired', context={ 'billing': bill, 'billing_url': get_site_url(reverse('billing')), }, info=bill, )
def __call__(self, request): # Fake HttpRequest attribute to inject configured # site name into build_absolute_uri request._current_scheme_host = get_site_url() # Actual proxy handling proxy = None if settings.IP_BEHIND_REVERSE_PROXY: proxy = request.META.get(settings.IP_PROXY_HEADER) if proxy: # X_FORWARDED_FOR returns client1, proxy1, proxy2,... address = proxy.split(", ")[settings.IP_PROXY_OFFSET].strip() try: validate_ipv46_address(address) request.META["REMOTE_ADDR"] = address except ValidationError: report_error(cause="Invalid IP address") return self.get_response(request)
def get_stats(self): """Return stats dictionary.""" return { "code": self.language.code, "name": self.language.name, "total": self.stats.all, "total_words": self.stats.all_words, "last_change": self.stats.last_changed, "last_author": self.get_last_author(), "recent_changes": self.stats.recent_changes, "translated": self.stats.translated, "translated_words": self.stats.translated_words, "translated_percent": self.stats.translated_percent, "fuzzy": self.stats.fuzzy, "fuzzy_percent": self.stats.fuzzy_percent, "failing": self.stats.allchecks, "failing_percent": self.stats.allchecks_percent, "url": self.get_share_url(), "url_translate": get_site_url(self.get_absolute_url()), }
def render_template(template, translation=None, **kwargs): """Helper class to render string template with context.""" context = {} context.update(kwargs) if translation is not None: translation.stats.ensure_basic() context['project_name'] = translation.component.project.name context['project_slug'] = translation.component.project.slug context['component_name'] = translation.component.name context['component_slug'] = translation.component.slug context['language_code'] = translation.language_code context['language_name'] = translation.language.name context['stats'] = translation.stats.get_data() context['url'] = get_site_url(translation.get_absolute_url()) return Template( template, engine=RestrictedEngine(), ).render(Context(context, autoescape=False), )
def perform_removal(): for bill in Billing.objects.filter(removal__lte=timezone.now()): for user in bill.get_notify_users(): send_notification_email( user.profile.language, user.email, 'billing_expired', context={ 'billing': bill, 'billing_url': get_site_url(reverse('billing')), 'final_removal': True, }, info=bill, ) for prj in bill.projects.iterator(): prj.log_warning('removing due to unpaid billing') prj.stats.invalidate() prj.delete() bill.removal = None bill.state = Billing.STATE_TERMINATED bill.save()
def request(self, method, url, skip_auth=False, **kwargs): """Perform JSON request.""" # Create custom headers headers = { "Referer": get_site_url(), "Accept": "application/json; charset=utf-8", } if "headers" in kwargs: headers.update(kwargs.pop("headers")) # Optional authentication if not skip_auth: headers.update(self.get_authentication()) # Fire request response = request(method, url, headers=headers, timeout=5.0, **kwargs) # Directly raise error when response is empty if response.content: response.raise_for_status() return response
def refresh(self): stats = GlobalStats() data = { 'secret': self.secret, 'site_url': get_site_url(), 'users': User.objects.count(), 'projects': Project.objects.count(), 'components': Component.objects.count(), 'languages': stats.languages, } headers = { 'User-Agent': USER_AGENT, } response = requests.request('post', settings.SUPPORT_API_URL, headers=headers, data=data) response.raise_for_status() payload = response.json() self.name = payload['name'] self.expiry = dateutil.parser.parse(payload['expiry'])
def get(self, request, *args, **kwargs): object_list = self.get_queryset()[:2000] # Do reasonable ACL check for global acl_obj = self.translation or self.component or self.project if not acl_obj: for change in object_list: if change.component: acl_obj = change.component break if not request.user.has_perm("change.download", acl_obj): raise PermissionDenied() # Always output in english activate("en") response = HttpResponse(content_type="text/csv; charset=utf-8") response["Content-Disposition"] = "attachment; filename=changes.csv" writer = csv.writer(response) # Add header writer.writerow( ("timestamp", "action", "user", "url", "target", "edit_distance") ) for change in object_list: writer.writerow( ( change.timestamp.isoformat(), change.get_action_display(), change.user.username if change.user else "", get_site_url(change.get_absolute_url()), change.target, change.get_distance(), ) ) return response
def __init__( self, project=None, source_language=None, language=None, url=None, translation=None, fieldnames=None, ): if translation is not None: self.plural = translation.plural self.project = translation.component.project self.source_language = translation.component.source_language self.language = translation.language self.url = get_site_url(translation.get_absolute_url()) else: self.project = project self.language = language self.source_language = source_language self.plural = language.plural self.url = url self.fieldnames = fieldnames
def render_template(template, translation=None, **kwargs): """Helper class to render string template with context.""" context = {} context.update(kwargs) if translation is not None: translation.stats.ensure_basic() context['project_name'] = translation.component.project.name context['project_slug'] = translation.component.project.slug context['component_name'] = translation.component.name context['component_slug'] = translation.component.slug context['language_code'] = translation.language_code context['language_name'] = translation.language.name context['stats'] = translation.stats.get_data() context['url'] = get_site_url(translation.get_absolute_url()) return Template( template, engine=RestrictedEngine(), ).render( Context(context, autoescape=False), )
def get(self, request, *args, **kwargs): object_list = self.get_queryset()[:2000] # Do reasonable ACL check for global acl_obj = self.translation or self.component or self.project if not acl_obj: for change in object_list: if change.component: acl_obj = change.component break if not request.user.has_perm('change.download', acl_obj): raise PermissionDenied() # Always output in english activate('en') response = HttpResponse(content_type='text/csv; charset=utf-8') response['Content-Disposition'] = 'attachment; filename=changes.csv' writer = csv.writer(response) # Add header writer.writerow(('timestamp', 'action', 'user', 'url', 'target')) for change in object_list: writer.writerow( ( change.timestamp.isoformat(), change.get_action_display(), change.user.username if change.user else '', get_site_url(change.get_absolute_url()), change.target, ) ) return response
def download_glossary(request, project, lang): """Export glossary into various formats.""" prj = get_project(request, project) lang = get_object_or_404(Language, code=lang) # Parse parameters export_format = None if "format" in request.GET: export_format = request.GET["format"] if export_format not in EXPORT_TYPES: export_format = "csv" # Grab all terms terms = (Term.objects.for_project(prj).filter( language=lang).prefetch_related("glossary").order()) # Translate toolkit based export exporter = EXPORTERS[export_format]( project=prj, language=lang, source_language=terms[0].glossary.source_language if terms else Language.objects.default_language, url=get_site_url( reverse("show_glossary", kwargs={ "project": prj.slug, "lang": lang.code })), fieldnames=("source", "target"), ) # Add terms for term in terms: exporter.add_glossary_term(term) # Save to response return exporter.get_response("glossary-{project}-{language}.{extension}")
def download_dictionary(request, project, lang): """Export dictionary into various formats.""" prj = get_project(request, project) lang = get_object_or_404(Language, code=lang) # Parse parameters export_format = None if 'format' in request.GET: export_format = request.GET['format'] if export_format not in ('csv', 'po', 'tbx', 'xliff'): export_format = 'csv' # Grab all words words = Dictionary.objects.filter( project=prj, language=lang ).order_by(Lower('source')) # Translate toolkit based export exporter = get_exporter(export_format)( prj, lang, get_site_url(reverse( 'show_dictionary', kwargs={'project': prj.slug, 'lang': lang.code} )), fieldnames=('source', 'target'), ) # Add words for word in words.iterator(): exporter.add_dictionary(word) # Save to response return exporter.get_response( 'glossary-{project}-{language}.{extension}' )
def get_widgets_url(self): """Return absolute URL for widgets.""" return get_site_url(reverse('widgets', kwargs={'project': self.slug}))
def get_widgets_url(self): """Return absolute URL for widgets.""" return get_site_url(reverse("widgets", kwargs={"project": self.slug}))
def performance(request, admin_site): """Show performance tuning tips.""" if request.method == 'POST': return handle_dismiss(request) checks = [] # Check for debug mode checks.append(( _('Debug mode'), not settings.DEBUG, 'production-debug', settings.DEBUG, )) # Check for domain configuration checks.append(( _('Site domain'), check_domain(get_site_domain()), 'production-site', get_site_url(), )) # Check database being used checks.append(( _('Database backend'), "sqlite" not in settings.DATABASES['default']['ENGINE'], 'production-database', settings.DATABASES['default']['ENGINE'], )) # Check configured admins checks.append(( _('Site administrator'), len(settings.ADMINS) > 0 or '*****@*****.**' in [x[1] for x in settings.ADMINS], 'production-admins', ', '.join([x[1] for x in settings.ADMINS]), )) # Check offloading indexing checks.append(( # Translators: Indexing is postponed to cron job _('Indexing offloading'), settings.OFFLOAD_INDEXING, 'production-indexing', settings.OFFLOAD_INDEXING)) if settings.OFFLOAD_INDEXING: if IndexUpdate.objects.count() < 20: index_updates = True elif IndexUpdate.objects.count() < 200: index_updates = None else: index_updates = False checks.append(( # Translators: Indexing is postponed to cron job _('Indexing offloading processing'), index_updates, 'production-indexing', IndexUpdate.objects.count(), )) # Check for sane caching caches = settings.CACHES['default']['BACKEND'].split('.')[-1] if caches in GOOD_CACHE: # We consider these good caches = True elif caches in ['DummyCache']: # This one is definitely bad caches = False else: # These might not be that bad caches = None checks.append(( _('Django caching'), caches, 'production-cache', settings.CACHES['default']['BACKEND'], )) # Avatar caching checks.append(( _('Avatar caching'), 'avatar' in settings.CACHES, 'production-cache-avatar', settings.CACHES['avatar']['BACKEND'] if 'avatar' in settings.CACHES else '', )) # Check email setup default_mails = ('root@localhost', 'webmaster@localhost', '*****@*****.**' '*****@*****.**') checks.append(( _('Email addresses'), (settings.SERVER_EMAIL not in default_mails and settings.DEFAULT_FROM_EMAIL not in default_mails), 'production-email', ', '.join((settings.SERVER_EMAIL, settings.DEFAULT_FROM_EMAIL)), )) # libravatar library checks.append(( _('Federated avatar support'), HAS_LIBRAVATAR, 'production-avatar', HAS_LIBRAVATAR, )) # pyuca library checks.append(( _('pyuca library'), HAS_PYUCA, 'production-pyuca', HAS_PYUCA, )) # Cookie signing key checks.append(( _('Secret key'), settings.SECRET_KEY != settings_example.SECRET_KEY, 'production-secret', '', )) # Allowed hosts checks.append(( _('Allowed hosts'), len(settings.ALLOWED_HOSTS) > 0, 'production-hosts', ', '.join(settings.ALLOWED_HOSTS), )) loader = get_first_loader() # Cached template loader checks.append(( _('Cached template loader'), 'cached.Loader' in loader, 'production-templates', loader, )) # Check for serving static files checks.append(( _('Admin static files'), os.path.exists( os.path.join(settings.STATIC_ROOT, 'admin', 'js', 'core.js')), 'production-admin-files', settings.STATIC_ROOT, )) context = admin_site.each_context(request) context['checks'] = checks context['errors'] = ConfigurationError.objects.filter(ignored=False) return render( request, "admin/performance.html", context, )
def get_widgets_url(self): """Return absolute URL for widgets.""" return get_site_url( reverse('widgets', kwargs={'project': self.slug}) )
def update_units(self, author_name, author_id): """Update backend file and unit.""" updated = False for unit in self.unit_set.filter(pending=True).select_for_update(): # Skip changes by other authors unit_change = unit.change_set.content().order_by('-timestamp')[0] if unit_change.author_id != author_id: continue pounit, add = self.store.find_unit(unit.context, unit.get_source_plurals()[0]) unit.pending = False # Bail out if we have not found anything if pounit is None or pounit.is_obsolete(): self.log_error('message %s disappeared!', unit) unit.save(update_fields=['pending'], same_content=True) continue # Check for changes if ((not add or unit.target == '') and unit.target == pounit.get_target() and unit.approved == pounit.is_approved(unit.approved) and unit.fuzzy == pounit.is_fuzzy()): unit.save(update_fields=['pending'], same_content=True) continue updated = True # Optionally add unit to translation file. # This has be done prior setting tatget as some formats # generate content based on target language. if add: self.store.add_unit(pounit.unit) # Store translations if unit.is_plural(): pounit.set_target(unit.get_target_plurals()) else: pounit.set_target(unit.target) # Update fuzzy/approved flag pounit.mark_fuzzy(unit.state == STATE_FUZZY) pounit.mark_approved(unit.state == STATE_APPROVED) # Update comments as they might have been changed (eg, fuzzy flag # removed) state = unit.get_unit_state(pounit, False) flags = pounit.get_flags() if state != unit.state or flags != unit.flags: unit.state = state unit.flags = flags unit.save(update_fields=['state', 'flags', 'pending'], same_content=True) # Did we do any updates? if not updated: return # Update po file header now = timezone.now() if not timezone.is_aware(now): now = timezone.make_aware(now, timezone.utc) # Prepare headers to update headers = { 'add': True, 'last_translator': author_name, 'plural_forms': self.plural.plural_form, 'language': self.language_code, 'PO_Revision_Date': now.strftime('%Y-%m-%d %H:%M%z'), } # Optionally store language team with link to website if self.component.project.set_translation_team: headers['language_team'] = '{0} <{1}>'.format( self.language.name, get_site_url(self.get_absolute_url())) # Optionally store email for reporting bugs in source report_source_bugs = self.component.report_source_bugs if report_source_bugs: headers['report_msgid_bugs_to'] = report_source_bugs # Update genric headers self.store.update_header(**headers) # save translation changes self.store.save()
def update_units(self, units, store, author_name, author_id): """Update backend file and unit.""" updated = False for unit in units: # We reuse the queryset, so pending units might reappear here if not unit.pending: continue # Skip changes by other authors change_author = unit.get_last_content_change()[0] if change_author.id != author_id: continue # Remove pending flag unit.pending = False if unit.details.get("add_unit"): pounit = store.new_unit( unit.context, unit.get_source_plurals(), unit.get_target_plurals() ) updated = True del unit.details["add_unit"] else: try: pounit, add = store.find_unit(unit.context, unit.source) except UnitNotFound: # Bail out if we have not found anything report_error(cause="String disappeared") self.log_error("disappeared string: %s", unit) continue updated = True # Optionally add unit to translation file. # This has be done prior setting tatget as some formats # generate content based on target language. if add: store.add_unit(pounit.unit) # Store translations if unit.is_plural: pounit.set_target(unit.get_target_plurals()) else: pounit.set_target(unit.target) # Update fuzzy/approved flag pounit.mark_fuzzy(unit.state == STATE_FUZZY) pounit.mark_approved(unit.state == STATE_APPROVED) # Update comments as they might have been changed by state changes state = unit.get_unit_state(pounit, "") flags = pounit.flags update_fields = ["pending", "details"] only_save = True if state != unit.state or flags != unit.flags: unit.state = state update_fields.append("state") unit.flags = flags update_fields.append("flags") only_save = False unit.save( update_fields=update_fields, same_content=True, only_save=only_save ) # Did we do any updates? if not updated: return # Update po file header now = timezone.now() if not timezone.is_aware(now): now = timezone.make_aware(now, timezone.utc) # Prepare headers to update headers = { "add": True, "last_translator": author_name, "plural_forms": self.plural.plural_form, "language": self.language_code, "PO_Revision_Date": now.strftime("%Y-%m-%d %H:%M%z"), } # Optionally store language team with link to website if self.component.project.set_language_team: headers["language_team"] = "{} <{}>".format( self.language.name, get_site_url(self.get_absolute_url()) ) # Optionally store email for reporting bugs in source report_source_bugs = self.component.report_source_bugs if report_source_bugs: headers["report_msgid_bugs_to"] = report_source_bugs # Update genric headers store.update_header(**headers) # save translation changes store.save()
def render(self, response): translations = [] offset = 20 color = self.COLOR_MAP[self.color] language_width = 190 for stats in self.obj.stats.get_language_stats(): language = stats.language percent = stats.translated_percent if self.color == "auto": if percent >= 85: color = "#2eccaa" elif percent >= 50: color = "#38f" else: color = "#f6664c" language_name = force_str(language) language_width = max( language_width, (render_size("DejaVu Sans", Pango.Weight.NORMAL, 11, 0, language_name)[0].width + 5), ) translations.append(( # Language name language_name, # Translation percent int(percent), # Text y offset offset, # Bar y offset offset - 6, # Bar width int(percent * 1.5), # Bar color color, # Row URL get_site_url( reverse( "project-language", kwargs={ "lang": language.code, "project": self.obj.slug }, )), # Top offset for horizontal 10 + int((100 - percent) * 1.5), )) offset += 15 response.write( render_to_string( self.template_name, { "height": len(translations) * 15 + 15, "width": language_width + 210, "language_offset": language_width, "bar_offset": language_width + 10, "text_offset": language_width + 170, "translations": translations, "site_url": get_site_url(), "horizontal_height": language_width + 130, }, ))
def get_attribute(self, instance): value = super().get_attribute(instance) if "http:/" not in value and "https:/" not in value: return get_site_url(value) return value
def get_attribute(self, instance): value = super(AbsoluteURLField, self).get_attribute(instance) if 'http:/' not in value and 'https:/' not in value: return get_site_url(value) return value
def build_absolute_uri(self, path=None): if self.request: self.request.__dict__['_current_scheme_host'] = get_site_url() return super(WeblateStrategy, self).build_absolute_uri(path)
def get_share_url(self): """Return absolute URL usable for sharing.""" return get_site_url( reverse('engage', kwargs={'project': self.slug}) )
def get_share_url(self): """Return absolute URL usable for sharing.""" return get_site_url(reverse('engage', kwargs={'project': self.slug}))
def widgets(request, project): obj = get_project(request, project) # Parse possible language selection form = EngageForm(obj, request.GET) lang = None component = None if form.is_valid(): if form.cleaned_data['lang']: lang = Language.objects.get(code=form.cleaned_data['lang']).code if form.cleaned_data['component']: component = Component.objects.get( slug=form.cleaned_data['component'], project=obj).slug kwargs = {'project': obj.slug} if lang is not None: kwargs['lang'] = lang engage_url = get_site_url(reverse('engage', kwargs=kwargs)) engage_url_track = '{0}?utm_source=widget'.format(engage_url) engage_link = mark_safe('<a href="{0}" id="engage-link">{0}</a>'.format( escape(engage_url))) widget_base_url = get_site_url( reverse('widgets', kwargs={'project': obj.slug})) widget_list = [] for widget_name in sorted(WIDGETS, key=widgets_sorter): widget_class = WIDGETS[widget_name] if not widget_class.show: continue color_list = [] for color in widget_class.colors: kwargs = { 'project': obj.slug, 'widget': widget_name, 'color': color, 'extension': widget_class.extension, } if lang is not None: kwargs['lang'] = lang if component is not None: kwargs['component'] = component color_url = reverse('widget-image', kwargs=kwargs) color_list.append({ 'name': color, 'url': get_site_url(color_url), }) widget_list.append({ 'name': widget_name, 'colors': color_list, }) return render( request, 'widgets.html', { 'engage_url': engage_url, 'engage_link': engage_link, 'engage_url_track': engage_url_track, 'widget_list': widget_list, 'widget_base_url': widget_base_url, 'object': obj, 'project': obj, 'image_src': widget_list[0]['colors'][0]['url'], 'form': form, })
def weblate_context(request): """Context processor to inject various useful variables into context.""" if is_safe_url(request.GET.get('next', ''), allowed_hosts=None): login_redirect_url = request.GET['next'] else: login_redirect_url = request.get_full_path() # Load user translations if user is authenticated subscribed_projects = None if request.user.is_authenticated: subscribed_projects = request.user.profile.subscriptions.all() if settings.OFFER_HOSTING: description = _( 'Hosted Weblate, the place to translate your software project.' ) else: description = _( 'This site runs Weblate for translating various software projects.' ) weblate_url = URL_BASE % weblate.VERSION context = { 'cache_param': '?v={}'.format(weblate.GIT_VERSION), 'version': weblate.VERSION, 'description': description, 'weblate_link': mark_safe( '<a href="{}">weblate.org</a>'.format(escape(weblate_url)) ), 'weblate_name_link': mark_safe( '<a href="{}">Weblate</a>'.format(escape(weblate_url)) ), 'weblate_version_link': mark_safe( '<a href="{}">Weblate {}</a>'.format( escape(weblate_url), weblate.VERSION ) ), 'donate_url': URL_DONATE % weblate.VERSION, 'site_url': get_site_url(), 'site_domain': get_site_domain(), 'current_date': datetime.utcnow().strftime('%Y-%m-%d'), 'current_year': datetime.utcnow().strftime('%Y'), 'current_month': datetime.utcnow().strftime('%m'), 'login_redirect_url': login_redirect_url, 'has_ocr': weblate.screenshots.views.HAS_OCR, 'has_antispam': bool(settings.AKISMET_API_KEY), 'subscribed_projects': subscribed_projects, 'allow_index': False, 'configuration_errors': ConfigurationError.objects.filter( ignored=False ), } add_error_logging_context(context) add_settings_context(context) add_optional_context(context) return context
def get_notification_email(language, email, notification, translation_obj=None, context=None, headers=None, user=None, info=None): """Render notification email.""" cur_language = django_translation.get_language() context = context or {} headers = headers or {} references = None if 'unit' in context: unit = context['unit'] references = '{0}/{1}/{2}/{3}'.format( unit.translation.component.project.slug, unit.translation.component.slug, unit.translation.language.code, unit.id ) if references is not None: references = '<{0}@{1}>'.format(references, get_site_domain()) headers['In-Reply-To'] = references headers['References'] = references try: if info is None: info = force_text(translation_obj) LOGGER.info( 'sending notification %s on %s to %s', notification, info, email ) # Load user language if language is not None: django_translation.activate(language) # Template name context['subject_template'] = 'mail/{0}_subject.txt'.format( notification ) context['LANGUAGE_CODE'] = django_translation.get_language() context['LANGUAGE_BIDI'] = django_translation.get_language_bidi() # Adjust context context['current_site_url'] = get_site_url() if translation_obj is not None: context['translation'] = translation_obj context['translation_url'] = get_site_url( translation_obj.get_absolute_url() ) context['site_title'] = settings.SITE_TITLE # Render subject subject = render_to_string( context['subject_template'], context ).strip() # Render body body = render_to_string( 'mail/{0}.txt'.format(notification), context ) html_body = render_to_string( 'mail/{0}.html'.format(notification), context ) # Define headers headers['Auto-Submitted'] = 'auto-generated' headers['X-AutoGenerated'] = 'yes' headers['Precedence'] = 'bulk' headers['X-Mailer'] = 'Weblate {0}'.format(VERSION) # Reply to header if user is not None: headers['Reply-To'] = user.email # List of recipients if email == 'ADMINS': emails = [a[1] for a in settings.ADMINS] else: emails = [email] # Create message email = EmailMultiAlternatives( settings.EMAIL_SUBJECT_PREFIX + subject, body, to=emails, headers=headers, ) email.attach_alternative( html_body, 'text/html' ) # Return the mail return email finally: django_translation.activate(cur_language)
def widgets(request, project): obj = get_project(request, project) # Parse possible language selection form = EngageForm(obj, request.GET) lang = None component = None if form.is_valid(): if form.cleaned_data['lang']: lang = Language.objects.get(code=form.cleaned_data['lang']).code if form.cleaned_data['component']: component = Component.objects.get( slug=form.cleaned_data['component'], project=obj ).slug kwargs = {'project': obj.slug} if lang is not None: kwargs['lang'] = lang engage_url = get_site_url(reverse('engage', kwargs=kwargs)) engage_url_track = '{0}?utm_source=widget'.format(engage_url) engage_link = mark_safe( '<a href="{0}" id="engage-link">{0}</a>'.format(escape(engage_url)) ) widget_base_url = get_site_url( reverse('widgets', kwargs={'project': obj.slug}) ) widget_list = [] for widget_name in sorted(WIDGETS, key=widgets_sorter): widget_class = WIDGETS[widget_name] if not widget_class.show: continue color_list = [] for color in widget_class.colors: kwargs = { 'project': obj.slug, 'widget': widget_name, 'color': color, 'extension': widget_class.extension, } if lang is not None: kwargs['lang'] = lang if component is not None: kwargs['component'] = component color_url = reverse('widget-image', kwargs=kwargs) color_list.append({ 'name': color, 'url': get_site_url(color_url), }) widget_list.append({ 'name': widget_name, 'colors': color_list, }) return render( request, 'widgets.html', { 'engage_url': engage_url, 'engage_link': engage_link, 'engage_url_track': engage_url_track, 'widget_list': widget_list, 'widget_base_url': widget_base_url, 'object': obj, 'project': obj, 'image_src': widget_list[0]['colors'][0]['url'], 'form': form, } )
def weblate_context(request): """Context processor to inject various useful variables into context.""" if url_has_allowed_host_and_scheme(request.GET.get("next", ""), allowed_hosts=None): login_redirect_url = request.GET["next"] else: login_redirect_url = request.get_full_path() # Load user translations if user is authenticated watched_projects = None if hasattr(request, "user") and request.user.is_authenticated: watched_projects = request.user.watched_projects if settings.OFFER_HOSTING: description = _("Hosted Weblate, the place to localize your software project.") else: description = _( "This site runs Weblate for localizing various software projects." ) context = { "cache_param": f"?v={weblate.GIT_VERSION}" if not settings.COMPRESS_ENABLED else "", "version": weblate.VERSION, "bread_image": get_bread_image(request.path), "description": description, "weblate_link": mark_safe( '<a href="{}">weblate.org</a>'.format(escape(WEBLATE_URL)) ), "weblate_name_link": mark_safe( '<a href="{}">Weblate</a>'.format(escape(WEBLATE_URL)) ), "weblate_version_link": mark_safe( '<a href="{}">Weblate {}</a>'.format( escape(WEBLATE_URL), "" if settings.HIDE_VERSION else weblate.VERSION ) ), "donate_url": DONATE_URL, "site_url": get_site_url(), "site_domain": get_site_domain(), "current_date": datetime.utcnow().strftime("%Y-%m-%d"), "current_year": datetime.utcnow().strftime("%Y"), "current_month": datetime.utcnow().strftime("%m"), "login_redirect_url": login_redirect_url, "has_ocr": weblate.screenshots.views.HAS_OCR, "has_antispam": bool(settings.AKISMET_API_KEY), "has_sentry": bool(settings.SENTRY_DSN), "watched_projects": watched_projects, "allow_index": False, "configuration_errors": ConfigurationError.objects.filter( ignored=False ).order_by("-timestamp"), "preconnect_list": get_preconnect_list(), "custom_css_hash": CustomCSSView.get_hash(request), } add_error_logging_context(context) add_settings_context(context) add_optional_context(context) return context
def weblate_context(request): """Context processor to inject various useful variables into context.""" if is_safe_url(request.GET.get('next', ''), allowed_hosts=None): login_redirect_url = request.GET['next'] else: login_redirect_url = request.get_full_path() # Load user translations if user is authenticated subscribed_projects = None if request.user.is_authenticated: subscribed_projects = request.user.profile.subscriptions.all() if settings.OFFER_HOSTING: description = _( 'Hosted Weblate, the place to translate your software project.' ) else: description = _( 'This site runs Weblate for translating various software projects.' ) if (hasattr(settings, 'ROLLBAR') and 'client_token' in settings.ROLLBAR and 'environment' in settings.ROLLBAR): rollbar_token = settings.ROLLBAR['client_token'] rollbar_environment = settings.ROLLBAR['environment'] else: rollbar_token = None rollbar_environment = None weblate_url = URL_BASE % weblate.VERSION return { 'cache_param': '?v={}'.format(weblate.GIT_VERSION), 'version': weblate.VERSION, 'description': description, 'weblate_link': mark_safe( '<a href="{}">weblate.org</a>'.format(escape(weblate_url)) ), 'weblate_name_link': mark_safe( '<a href="{}">Weblate</a>'.format(escape(weblate_url)) ), 'weblate_version_link': mark_safe( '<a href="{}">Weblate {}</a>'.format( escape(weblate_url), weblate.VERSION ) ), 'donate_url': URL_DONATE % weblate.VERSION, 'site_title': settings.SITE_TITLE, 'site_url': get_site_url(), 'offer_hosting': settings.OFFER_HOSTING, 'demo_server': settings.DEMO_SERVER, 'enable_avatars': settings.ENABLE_AVATARS, 'enable_sharing': settings.ENABLE_SHARING, 'piwik_site_id': settings.PIWIK_SITE_ID, 'piwik_url': settings.PIWIK_URL, 'google_analytics_id': settings.GOOGLE_ANALYTICS_ID, 'current_date': datetime.utcnow().strftime('%Y-%m-%d'), 'current_year': datetime.utcnow().strftime('%Y'), 'current_month': datetime.utcnow().strftime('%m'), 'login_redirect_url': login_redirect_url, 'hooks_enabled': settings.ENABLE_HOOKS, 'has_ocr': weblate.screenshots.views.HAS_OCR, 'registration_open': settings.REGISTRATION_OPEN, 'subscribed_projects': subscribed_projects, 'rollbar_token': rollbar_token, 'rollbar_environment': rollbar_environment, 'allow_index': False, 'legal': 'weblate.legal' in settings.INSTALLED_APPS, 'status_url': settings.STATUS_URL, 'configuration_errors': ConfigurationError.objects.filter( ignored=False ), }
def get_origin(): return get_site_url(reverse("create-billing"))
def weblate_context(request): """Context processor to inject various useful variables into context.""" if is_safe_url(request.GET.get('next', ''), allowed_hosts=None): login_redirect_url = request.GET['next'] else: login_redirect_url = request.get_full_path() # Load user translations if user is authenticated watched_projects = None if hasattr(request, 'user') and request.user.is_authenticated: watched_projects = request.user.allowed_projects.filter( profile=request.user.profile) if settings.OFFER_HOSTING: description = _( 'Hosted Weblate, the place to localize your software project.') else: description = _( 'This site runs Weblate for localizing various software projects.') weblate_url = URL_BASE % weblate.VERSION context = { 'cache_param': '?v={}'.format(weblate.GIT_VERSION), 'version': weblate.VERSION, 'bread_image': get_bread_image(request.path), 'description': description, 'weblate_link': mark_safe('<a href="{}">weblate.org</a>'.format(escape(weblate_url))), 'weblate_name_link': mark_safe('<a href="{}">Weblate</a>'.format(escape(weblate_url))), 'weblate_version_link': mark_safe('<a href="{}">Weblate {}</a>'.format(escape(weblate_url), weblate.VERSION)), 'donate_url': URL_DONATE % weblate.VERSION, 'site_url': get_site_url(), 'site_domain': get_site_domain(), 'current_date': datetime.utcnow().strftime('%Y-%m-%d'), 'current_year': datetime.utcnow().strftime('%Y'), 'current_month': datetime.utcnow().strftime('%m'), 'login_redirect_url': login_redirect_url, 'has_ocr': weblate.screenshots.views.HAS_OCR, 'has_antispam': bool(settings.AKISMET_API_KEY), 'watched_projects': watched_projects, 'allow_index': False, 'configuration_errors': ConfigurationError.objects.filter( ignored=False).order_by('-timestamp'), } add_error_logging_context(context) add_settings_context(context) add_optional_context(context) return context