changeset 8364:68d4aae74194 i18n

Merge default pre 0.6
author Mads Kiilerich <mads@kiilerich.com>
date Mon, 27 Apr 2020 13:25:28 +0200
parents 826810fb830e (current diff) 90dd59c2a76a (diff)
children d5e77cc4a4f2
files docs/setup.rst kallithea/i18n/be/LC_MESSAGES/kallithea.po kallithea/i18n/bg/LC_MESSAGES/kallithea.po kallithea/i18n/cs/LC_MESSAGES/kallithea.po kallithea/i18n/da/LC_MESSAGES/kallithea.po kallithea/i18n/de/LC_MESSAGES/kallithea.po kallithea/i18n/el/LC_MESSAGES/kallithea.po kallithea/i18n/es/LC_MESSAGES/kallithea.po kallithea/i18n/fr/LC_MESSAGES/kallithea.po kallithea/i18n/hu/LC_MESSAGES/kallithea.po kallithea/i18n/ja/LC_MESSAGES/kallithea.po kallithea/i18n/kallithea.pot kallithea/i18n/lb/LC_MESSAGES/kallithea.po kallithea/i18n/nb_NO/LC_MESSAGES/kallithea.po kallithea/i18n/nl_BE/LC_MESSAGES/kallithea.po kallithea/i18n/pl/LC_MESSAGES/kallithea.po kallithea/i18n/pt_BR/LC_MESSAGES/kallithea.po kallithea/i18n/ru/LC_MESSAGES/kallithea.po kallithea/i18n/sk/LC_MESSAGES/kallithea.po kallithea/i18n/tr/LC_MESSAGES/kallithea.po kallithea/i18n/uk/LC_MESSAGES/kallithea.po kallithea/i18n/zh_CN/LC_MESSAGES/kallithea.po kallithea/i18n/zh_TW/LC_MESSAGES/kallithea.po
diffstat 259 files changed, 11225 insertions(+), 10572 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.eslintrc.js	Mon Apr 27 13:25:28 2020 +0200
@@ -0,0 +1,21 @@
+module.exports = {
+    "env": {
+        "browser": true,
+        "es6": true,
+        "jquery": true
+    },
+    "extends": "eslint:recommended",
+    "globals": {
+        "Atomics": "readonly",
+        "SharedArrayBuffer": "readonly"
+    },
+    "parserOptions": {
+        "ecmaVersion": 2018,
+        "sourceType": "module"
+    },
+    "plugins": [
+        "html"
+    ],
+    "rules": {
+    }
+};
--- a/dev_requirements.txt	Mon Apr 13 21:40:33 2020 +0200
+++ b/dev_requirements.txt	Mon Apr 27 13:25:28 2020 +0200
@@ -1,8 +1,9 @@
-pytest >= 4.6.6, < 4.7
+pytest >= 4.6.6, < 5.4
 pytest-sugar >= 0.9.2, < 0.10
 pytest-benchmark >= 3.2.2, < 3.3
 pytest-localserver >= 0.5.0, < 0.6
-mock >= 3.0.0, < 3.1
-Sphinx >= 1.8.0, < 1.9
+mock >= 3.0.0, < 4.1
+Sphinx >= 1.8.0, < 2.4
 WebTest >= 2.0.6, < 2.1
 isort == 4.3.21
+pyflakes == 2.1.1
--- a/development.ini	Mon Apr 13 21:40:33 2020 +0200
+++ b/development.ini	Mon Apr 27 13:25:28 2020 +0200
@@ -1,10 +1,10 @@
-################################################################################
-################################################################################
-# Kallithea - config file generated with kallithea-config                      #
-#                                                                              #
-# The %(here)s variable will be replaced with the parent directory of this file#
-################################################################################
-################################################################################
+###################################################################################
+###################################################################################
+## Kallithea config file generated with kallithea-config                         ##
+##                                                                               ##
+## The %(here)s variable will be replaced with the parent directory of this file ##
+###################################################################################
+###################################################################################
 
 [DEFAULT]
 
@@ -54,11 +54,11 @@
 ## For "SSL", use smtp_use_ssl = true and smtp_port = 465.
 ## For "STARTTLS", use smtp_use_tls = true and smtp_port = 587.
 smtp_server =
-#smtp_username =
-#smtp_password =
+smtp_username =
+smtp_password =
 smtp_port =
-#smtp_use_ssl = false
-#smtp_use_tls = false
+smtp_use_ssl = false
+smtp_use_tls = false
 
 ## Entry point for 'gearbox serve'
 [server:main]
@@ -126,7 +126,7 @@
 ## used, which is correct in many cases but for example not when using uwsgi.
 ## If you change this setting, you should reinstall the Git hooks via
 ## Admin > Settings > Remap and Rescan.
-# git_hook_interpreter = /srv/kallithea/venv/bin/python3
+#git_hook_interpreter = /srv/kallithea/venv/bin/python3
 
 ## path to git executable
 git_path = git
@@ -198,7 +198,7 @@
 ## issue_pat, issue_server_link and issue_sub can have suffixes to specify
 ## multiple patterns, to other issues server, wiki or others
 ## below an example how to create a wiki pattern
-# wiki-some-id -> https://wiki.example.com/some-id
+## wiki-some-id -> https://wiki.example.com/some-id
 
 #issue_pat_wiki = wiki-(\S+)
 #issue_server_link_wiki = https://wiki.example.com/\1
@@ -216,12 +216,12 @@
 allow_custom_hooks_settings = True
 
 ## extra extensions for indexing, space separated and without the leading '.'.
-# index.extensions =
+#index.extensions =
 #    gemfile
 #    lock
 
 ## extra filenames for indexing, space separated
-# index.filenames =
+#index.filenames =
 #    .dockerignore
 #    .editorconfig
 #    INSTALL
@@ -250,25 +250,23 @@
 ###        CELERY CONFIG        ####
 ####################################
 
+## Note: Celery doesn't support Windows.
 use_celery = false
 
-## Example: connect to the virtual host 'rabbitmqhost' on localhost as rabbitmq:
-broker.url = amqp://rabbitmq:qewqew@localhost:5672/rabbitmqhost
+## Celery config settings from https://docs.celeryproject.org/en/4.4.0/userguide/configuration.html prefixed with 'celery.'.
 
-celery.imports = kallithea.lib.celerylib.tasks
-celery.accept.content = pickle
-celery.result.backend = amqp
-celery.result.dburi = amqp://
-celery.result.serialier = json
+## Example: use the message queue on the local virtual host 'kallitheavhost' as the RabbitMQ user 'kallithea':
+celery.broker_url = amqp://kallithea:thepassword@localhost:5672/kallitheavhost
 
-#celery.send.task.error.emails = true
+celery.result.backend = db+sqlite:///celery-results.db
+
 #celery.amqp.task.result.expires = 18000
 
-celeryd.concurrency = 2
-celeryd.max.tasks.per.child = 1
+celery.worker_concurrency = 2
+celery.worker_max_tasks_per_child = 1
 
 ## If true, tasks will never be sent to the queue, but executed locally instead.
-celery.always.eager = false
+celery.task_always_eager = false
 
 ####################################
 ###         BEAKER CACHE        ####
@@ -277,19 +275,15 @@
 beaker.cache.data_dir = %(here)s/data/cache/data
 beaker.cache.lock_dir = %(here)s/data/cache/lock
 
-beaker.cache.regions = short_term,long_term,sql_cache_short
-
-beaker.cache.short_term.type = memory
-beaker.cache.short_term.expire = 60
-beaker.cache.short_term.key_length = 256
+beaker.cache.regions = long_term,long_term_file
 
 beaker.cache.long_term.type = memory
 beaker.cache.long_term.expire = 36000
 beaker.cache.long_term.key_length = 256
 
-beaker.cache.sql_cache_short.type = memory
-beaker.cache.sql_cache_short.expire = 10
-beaker.cache.sql_cache_short.key_length = 256
+beaker.cache.long_term_file.type = file
+beaker.cache.long_term_file.expire = 604800
+beaker.cache.long_term_file.key_length = 256
 
 ####################################
 ###       BEAKER SESSION        ####
@@ -324,24 +318,33 @@
 #session.sa.url = postgresql://postgres:qwe@localhost/kallithea
 #session.table_name = db_session
 
-############################
-## ERROR HANDLING SYSTEMS ##
-############################
+####################################
+###       ERROR HANDLING        ####
+####################################
+
+## Show a nice error page for application HTTP errors and exceptions (default true)
+#errorpage.enabled = true
 
-# Propagate email settings to ErrorReporter of TurboGears2
-# You do not normally need to change these lines
-get trace_errors.error_email = email_to
+## Enable Backlash client-side interactive debugger (default false)
+## WARNING: *THIS MUST BE false IN PRODUCTION ENVIRONMENTS!!!*
+## This debug mode will allow all visitors to execute malicious code.
+#debug = false
+debug = true
+
+## Enable Backlash server-side error reporting (unless debug mode handles it client-side) (default true)
+#trace_errors.enable = true
+## Errors will be reported by mail if trace_errors.error_email is set.
+
+## Propagate email settings to ErrorReporter of TurboGears2
+## You do not normally need to change these lines
 get trace_errors.smtp_server = smtp_server
 get trace_errors.smtp_port = smtp_port
 get trace_errors.from_address = error_email_from
+get trace_errors.error_email = email_to
+get trace_errors.smtp_username = smtp_username
+get trace_errors.smtp_password = smtp_password
+get trace_errors.smtp_use_tls = smtp_use_tls
 
-################################################################################
-## WARNING: *DEBUG MODE MUST BE OFF IN A PRODUCTION ENVIRONMENT*              ##
-## Debug mode will enable the interactive debugging tool, allowing ANYONE to  ##
-## execute malicious code after an exception is raised.                       ##
-################################################################################
-#debug = false
-debug = true
 
 ##################################
 ###       LOGVIEW CONFIG       ###
@@ -355,10 +358,10 @@
 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG    ###
 #########################################################
 
-# SQLITE [default]
+## SQLITE [default]
 sqlalchemy.url = sqlite:///%(here)s/kallithea.db?timeout=60
 
-# see sqlalchemy docs for others
+## see sqlalchemy docs for other backends
 
 sqlalchemy.pool_recycle = 3600
 
@@ -389,9 +392,8 @@
 [logger_root]
 level = NOTSET
 #handlers = console
+## For coloring based on log level:
 handlers = console_color
-# For coloring based on log level:
-# handlers = console_color
 
 [logger_routes]
 #level = WARN
@@ -434,10 +436,10 @@
 level = WARN
 handlers =
 qualname = sqlalchemy.engine
-# For coloring based on log level and pretty printing of SQL:
-# level = INFO
-# handlers = console_color_sql
-# propagate = 0
+## For coloring based on log level and pretty printing of SQL:
+#level = INFO
+#handlers = console_color_sql
+#propagate = 0
 
 [logger_whoosh_indexer]
 #level = WARN
@@ -465,13 +467,13 @@
 formatter = generic
 
 [handler_console_color]
-# ANSI color coding based on log level
+## ANSI color coding based on log level
 class = StreamHandler
 args = (sys.stderr,)
 formatter = color_formatter
 
 [handler_console_color_sql]
-# ANSI color coding and pretty printing of SQL statements
+## ANSI color coding and pretty printing of SQL statements
 class = StreamHandler
 args = (sys.stderr,)
 formatter = color_formatter_sql
@@ -502,16 +504,16 @@
 ## SSH LOGGING ##
 #################
 
-# The default loggers use 'handler_console' that uses StreamHandler with
-# destination 'sys.stderr'. In the context of the SSH server process, these log
-# messages would be sent to the client, which is normally not what you want.
-# By default, when running ssh-serve, just use NullHandler and disable logging
-# completely. For other logging options, see:
-# https://docs.python.org/2/library/logging.handlers.html
+## The default loggers use 'handler_console' that uses StreamHandler with
+## destination 'sys.stderr'. In the context of the SSH server process, these log
+## messages would be sent to the client, which is normally not what you want.
+## By default, when running ssh-serve, just use NullHandler and disable logging
+## completely. For other logging options, see:
+## https://docs.python.org/2/library/logging.handlers.html
 
 [ssh_serve:logger_root]
 level = CRITICAL
 handlers = null
 
-# Note: If logging is configured with other handlers, they might need similar
-# muting for ssh-serve too.
+## Note: If logging is configured with other handlers, they might need similar
+## muting for ssh-serve too.
--- a/docs/api/models.rst	Mon Apr 13 21:40:33 2020 +0200
+++ b/docs/api/models.rst	Mon Apr 27 13:25:28 2020 +0200
@@ -13,9 +13,6 @@
 .. automodule:: kallithea.model.permission
    :members:
 
-.. automodule:: kallithea.model.repo_permission
-   :members:
-
 .. automodule:: kallithea.model.repo
    :members:
 
--- a/docs/conf.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/docs/conf.py	Mon Apr 27 13:25:28 2020 +0200
@@ -46,8 +46,8 @@
 master_doc = 'index'
 
 # General information about the project.
-project = u'Kallithea'
-copyright = u'2010-2020 by various authors, licensed as GPLv3.'
+project = 'Kallithea'
+copyright = '2010-2020 by various authors, licensed as GPLv3.'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
@@ -187,8 +187,8 @@
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, documentclass [howto/manual]).
 latex_documents = [
-  ('index', 'Kallithea.tex', u'Kallithea Documentation',
-   u'Kallithea Developers', 'manual'),
+  ('index', 'Kallithea.tex', 'Kallithea Documentation',
+   'Kallithea Developers', 'manual'),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
@@ -220,8 +220,8 @@
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
 man_pages = [
-    ('index', 'kallithea', u'Kallithea Documentation',
-     [u'Kallithea Developers'], 1)
+    ('index', 'kallithea', 'Kallithea Documentation',
+     ['Kallithea Developers'], 1)
 ]
 
 
--- a/docs/contributing.rst	Mon Apr 13 21:40:33 2020 +0200
+++ b/docs/contributing.rst	Mon Apr 27 13:25:28 2020 +0200
@@ -236,8 +236,8 @@
 as in an independent database transaction). ``Session`` is the session manager
 and factory. ``Session()`` will create a new session on-demand or return the
 current session for the active thread. Many database operations are methods on
-such session instances - only ``Session.remove()`` should be called directly on
-the manager.
+such session instances. The session will generally be removed by
+TurboGears automatically.
 
 Database model objects
 (almost) always belong to a particular SQLAlchemy session, which means
@@ -266,6 +266,20 @@
 a freshly created model object (before flushing, the ID attribute will
 be ``None``).
 
+Debugging
+^^^^^^^^^
+
+A good way to trace what Kallithea is doing is to keep an eye on the output of
+stdout/stderr from the server process. Perhaps change ``my.ini`` to log at
+``DEBUG`` or ``INFO`` level, especially ``[logger_kallithea]``, but perhaps
+also other loggers. It is often easier to add additional ``log`` or ``print``
+statements than to use a Python debugger.
+
+Sometimes it is simpler to disable ``errorpage.enabled`` and perhaps also
+``trace_errors.enable`` to expose raw errors instead of adding extra
+processing. Enabling ``debug`` can be helpful for showing and exploring
+tracebacks in the browser, but is also insecure and will add extra processing.
+
 TurboGears2 DebugBar
 ^^^^^^^^^^^^^^^^^^^^
 
--- a/docs/setup.rst	Mon Apr 13 21:40:33 2020 +0200
+++ b/docs/setup.rst	Mon Apr 27 13:25:28 2020 +0200
@@ -332,11 +332,11 @@
 
   use_celery = true
 
-and add or change the ``celery.*`` and ``broker.*`` configuration variables.
+and add or change the ``celery.*`` configuration variables.
 
-Remember that the ini files use the format with '.' and not with '_' like
-Celery. So for example setting `BROKER_HOST` in Celery means setting
-`broker.host` in the configuration file.
+Configuration settings are prefixed with 'celery.', so for example setting
+`broker_url` in Celery means setting `celery.broker_url` in the configuration
+file.
 
 To start the Celery process, run::
 
--- a/kallithea/__init__.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/__init__.py	Mon Apr 27 13:25:28 2020 +0200
@@ -40,7 +40,7 @@
     'git': 'Git repository',
 }
 
-CELERY_ON = False
+CELERY_APP = None  # set to Celery app instance if using Celery
 CELERY_EAGER = False
 
 CONFIG = {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/alembic/versions/a0a1bf09c143_db_add_ui_composite_index_and_drop_.py	Mon Apr 27 13:25:28 2020 +0200
@@ -0,0 +1,48 @@
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# 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 General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""db: add Ui composite index and drop UniqueConstraint on Ui.ui_key
+
+Revision ID: a0a1bf09c143
+Revises: d7ec25b66e47
+Create Date: 2020-03-12 22:41:14.421837
+
+"""
+
+# The following opaque hexadecimal identifiers ("revisions") are used
+# by Alembic to track this migration script and its relations to others.
+revision = 'a0a1bf09c143'
+down_revision = 'd7ec25b66e47'
+branch_labels = None
+depends_on = None
+
+import sqlalchemy as sa
+from alembic import op
+
+
+def upgrade():
+    meta = sa.MetaData()
+    meta.reflect(bind=op.get_bind())
+
+    with op.batch_alter_table('ui', schema=None) as batch_op:
+        batch_op.create_index('ui_ui_section_ui_key_idx', ['ui_section', 'ui_key'], unique=False)
+        if any(i.name == 'uq_ui_ui_key' for i in meta.tables['ui'].constraints):
+            batch_op.drop_constraint('uq_ui_ui_key', type_='unique')
+        elif any(i.name == 'ui_ui_key_key' for i in meta.tables['ui'].constraints):  # table was created with old naming before 1a080d4e926e
+            batch_op.drop_constraint('ui_ui_key_key', type_='unique')
+
+
+def downgrade():
+    with op.batch_alter_table('ui', schema=None) as batch_op:
+        batch_op.create_unique_constraint('uq_ui_ui_key', ['ui_key'])
+        batch_op.drop_index('ui_ui_section_ui_key_idx')
--- a/kallithea/bin/kallithea_api.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/bin/kallithea_api.py	Mon Apr 27 13:25:28 2020 +0200
@@ -25,8 +25,6 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
-from __future__ import print_function
-
 import argparse
 import json
 import sys
@@ -61,7 +59,7 @@
                  'be also `%s`' % (FORMAT_PRETTY, FORMAT_JSON),
             default=FORMAT_PRETTY
     )
-    args, other = parser.parse_known_args()
+    args, other = parser.parse_known_args(args=argv[1:])
     return parser, args, other
 
 
--- a/kallithea/bin/kallithea_cli.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/bin/kallithea_cli.py	Mon Apr 27 13:25:28 2020 +0200
@@ -25,3 +25,8 @@
 import kallithea.bin.kallithea_cli_ssh
 # 'cli' is the main entry point for 'kallithea-cli', specified in setup.py as entry_points console_scripts
 from kallithea.bin.kallithea_cli_base import cli
+
+
+# mute pyflakes "imported but unused"
+assert kallithea.bin.kallithea_cli_ssh
+assert cli
--- a/kallithea/bin/kallithea_cli_celery.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/bin/kallithea_cli_celery.py	Mon Apr 27 13:25:28 2020 +0200
@@ -12,11 +12,11 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+import celery.bin.worker
 import click
 
 import kallithea
 import kallithea.bin.kallithea_cli_base as cli_base
-from kallithea.lib import celerypylons
 
 
 @cli_base.register_command(config_file_initialize_app=True)
@@ -32,10 +32,9 @@
     by this CLI command.
     """
 
-    if not kallithea.CELERY_ON:
+    if not kallithea.CELERY_APP:
         raise Exception('Please set use_celery = true in .ini config '
                         'file before running this command')
 
-    app = celerypylons.make_app()
-    cmd = celerypylons.worker.worker(app)
+    cmd = celery.bin.worker.worker(kallithea.CELERY_APP)
     return cmd.run_from_argv(None, command='celery-run -c CONFIG_FILE --', argv=list(celery_args))
--- a/kallithea/bin/kallithea_cli_config.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/bin/kallithea_cli_config.py	Mon Apr 27 13:25:28 2020 +0200
@@ -89,6 +89,16 @@
     mako_variable_values.update({
         'uuid': lambda: uuid.uuid4().hex,
     })
+
+    click.echo('Creating config file using:')
+    for key, value in inifile.default_variables.items():
+        if isinstance(value, str):
+            options = inifile.variable_options.get(key)
+            if options:
+                click.echo('  %s=%s  (options: %s)' % (key, mako_variable_values.get(key, value), ', '.join(options)))
+            else:
+                click.echo('  %s=%s' % (key, mako_variable_values.get(key, value)))
+
     try:
         config_file_abs = os.path.abspath(config_file)
         inifile.create(config_file_abs, mako_variable_values, ini_settings)
--- a/kallithea/bin/kallithea_cli_iis.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/bin/kallithea_cli_iis.py	Mon Apr 27 13:25:28 2020 +0200
@@ -67,6 +67,7 @@
 
     try:
         import isapi_wsgi
+        assert isapi_wsgi
     except ImportError:
         sys.stderr.write('missing requirement: isapi-wsgi not installed\n')
         sys.exit(1)
--- a/kallithea/bin/kallithea_cli_index.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/bin/kallithea_cli_index.py	Mon Apr 27 13:25:28 2020 +0200
@@ -36,7 +36,7 @@
 @click.option('--repo-location', help='Base path of repositories to index. Default: all')
 @click.option('--index-only', help='Comma-separated list of repositories to build index on. Default: all')
 @click.option('--update-only', help='Comma-separated list of repositories to re-build index on. Default: all')
-@click.option('-f', '--full', 'full_index', help='Recreate the index from scratch')
+@click.option('-f', '--full/--no-full', 'full_index', help='Recreate the index from scratch')
 def index_create(repo_location, index_only, update_only, full_index):
     """Create or update full text search index"""
 
--- a/kallithea/bin/kallithea_cli_ishell.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/bin/kallithea_cli_ishell.py	Mon Apr 27 13:25:28 2020 +0200
@@ -20,8 +20,6 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
-from __future__ import print_function
-
 import sys
 
 import kallithea.bin.kallithea_cli_base as cli_base
--- a/kallithea/bin/kallithea_cli_repo.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/bin/kallithea_cli_repo.py	Mon Apr 27 13:25:28 2020 +0200
@@ -26,10 +26,11 @@
 
 import click
 
+import kallithea
 import kallithea.bin.kallithea_cli_base as cli_base
 from kallithea.lib.utils import REMOVED_REPO_PAT, repo2db_mapper
 from kallithea.lib.utils2 import ask_ok
-from kallithea.model.db import Repository, Ui
+from kallithea.model.db import Repository
 from kallithea.model.meta import Session
 from kallithea.model.scm import ScmModel
 
@@ -125,7 +126,7 @@
         date_part = name[4:19]  # 4:19 since we don't parse milliseconds
         return datetime.datetime.strptime(date_part, '%Y%m%d_%H%M%S')
 
-    repos_location = Ui.get_repos_location()
+    repos_location = kallithea.CONFIG['base_path']
     to_remove = []
     for dn_, dirs, f in os.walk(repos_location):
         alldirs = list(dirs)
--- a/kallithea/bin/kallithea_gist.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/bin/kallithea_gist.py	Mon Apr 27 13:25:28 2020 +0200
@@ -25,8 +25,6 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
-from __future__ import print_function
-
 import argparse
 import fileinput
 import json
@@ -70,7 +68,7 @@
                        'be also `%s`' % (FORMAT_PRETTY, FORMAT_JSON),
             default=FORMAT_PRETTY
     )
-    args, other = parser.parse_known_args()
+    args, other = parser.parse_known_args(args=argv[1:])
     return parser, args, other
 
 
--- a/kallithea/bin/ldap_sync.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/bin/ldap_sync.py	Mon Apr 27 13:25:28 2020 +0200
@@ -25,8 +25,6 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
-from __future__ import print_function
-
 import urllib.request
 import uuid
 from configparser import ConfigParser
--- a/kallithea/config/app_cfg.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/config/app_cfg.py	Mon Apr 27 13:25:28 2020 +0200
@@ -34,13 +34,15 @@
 import kallithea.lib.locale
 import kallithea.model.base
 import kallithea.model.meta
+from kallithea.lib import celerypylons
 from kallithea.lib.middleware.https_fixup import HttpsFixup
 from kallithea.lib.middleware.permanent_repo_url import PermanentRepoUrl
 from kallithea.lib.middleware.simplegit import SimpleGit
 from kallithea.lib.middleware.simplehg import SimpleHg
 from kallithea.lib.middleware.wrapper import RequestWrapper
-from kallithea.lib.utils import check_git_version, load_rcextensions, make_ui, set_app_settings, set_indexer_config, set_vcs_config
-from kallithea.lib.utils2 import safe_str, str2bool
+from kallithea.lib.utils import check_git_version, load_rcextensions, set_app_settings, set_indexer_config, set_vcs_config
+from kallithea.lib.utils2 import str2bool
+from kallithea.model import db
 
 
 log = logging.getLogger(__name__)
@@ -97,10 +99,8 @@
         # Disable transaction manager -- currently Kallithea takes care of transactions itself
         self['tm.enabled'] = False
 
-        # Set the i18n source language so TG doesn't search beyond 'en' in Accept-Language.
-        # Don't force the default here if configuration force something else.
-        if not self.get('i18n.lang'):
-            self['i18n.lang'] = 'en'
+        # Set the default i18n source language so TG doesn't search beyond 'en' in Accept-Language.
+        self['i18n.lang'] = 'en'
 
 
 base_config = KallitheaAppConfig()
@@ -113,6 +113,7 @@
 try:
     from tgext.debugbar import enable_debugbar
     import kajiki # only to check its existence
+    assert kajiki
 except ImportError:
     pass
 else:
@@ -157,14 +158,14 @@
             sys.exit(1)
 
     # store some globals into kallithea
-    kallithea.CELERY_ON = str2bool(config.get('use_celery'))
-    kallithea.CELERY_EAGER = str2bool(config.get('celery.always.eager'))
+    kallithea.DEFAULT_USER_ID = db.User.get_default_user().user_id
+
+    if str2bool(config.get('use_celery')):
+        kallithea.CELERY_APP = celerypylons.make_app()
     kallithea.CONFIG = config
 
     load_rcextensions(root_path=config['here'])
 
-    repos_path = safe_str(make_ui().configitems(b'paths')[0][1])
-    config['base_path'] = repos_path
     set_app_settings(config)
 
     instance_id = kallithea.CONFIG.get('instance_id', '*')
--- a/kallithea/config/middleware.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/config/middleware.py	Mon Apr 27 13:25:28 2020 +0200
@@ -42,4 +42,6 @@
     ``app_conf`` contains all the application-specific settings (those defined
     under ``[app:main]``.
     """
+    assert app_conf.get('sqlalchemy.url')  # must be called with a Kallithea .ini file, which for example must have this config option
+    assert global_conf.get('here') and global_conf.get('__file__')  # app config should be initialized the paste way ...
     return make_base_app(global_conf, full_stack=full_stack, **app_conf)
--- a/kallithea/config/routing.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/config/routing.py	Mon Apr 27 13:25:28 2020 +0200
@@ -563,13 +563,6 @@
                  controller='admin/repos', action="edit_advanced_fork",
                  conditions=dict(method=["POST"], function=check_repo))
 
-    rmap.connect("edit_repo_caches", "/{repo_name:.*?}/settings/caches",
-                 controller='admin/repos', action="edit_caches",
-                 conditions=dict(method=["GET"], function=check_repo))
-    rmap.connect("update_repo_caches", "/{repo_name:.*?}/settings/caches",
-                 controller='admin/repos', action="edit_caches",
-                 conditions=dict(method=["POST"], function=check_repo))
-
     rmap.connect("edit_repo_remote", "/{repo_name:.*?}/settings/remote",
                  controller='admin/repos', action="edit_remote",
                  conditions=dict(method=["GET"], function=check_repo))
--- a/kallithea/controllers/admin/auth_settings.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/controllers/admin/auth_settings.py	Mon Apr 27 13:25:28 2020 +0200
@@ -37,7 +37,6 @@
 from kallithea.lib import helpers as h
 from kallithea.lib.auth import HasPermissionAnyDecorator, LoginRequired
 from kallithea.lib.base import BaseController, render
-from kallithea.lib.compat import formatted_json
 from kallithea.model.db import Setting
 from kallithea.model.forms import AuthSettingsForm
 from kallithea.model.meta import Session
@@ -87,7 +86,7 @@
         # we want to show , separated list of enabled plugins
         c.defaults['auth_plugins'] = ','.join(c.enabled_plugin_names)
 
-        log.debug(formatted_json(defaults))
+        log.debug('defaults: %s', defaults)
         return formencode.htmlfill.render(
             render('admin/auth/auth_settings.html'),
             defaults=c.defaults,
@@ -103,7 +102,7 @@
     def auth_settings(self):
         """POST create and store auth settings"""
         self.__load_defaults()
-        log.debug("POST Result: %s", formatted_json(dict(request.POST)))
+        log.debug("POST Result: %s", dict(request.POST))
 
         # First, parse only the plugin list (not the plugin settings).
         _auth_plugins_validator = AuthSettingsForm([]).fields['auth_plugins']
--- a/kallithea/controllers/admin/repo_groups.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/controllers/admin/repo_groups.py	Mon Apr 27 13:25:28 2020 +0200
@@ -101,19 +101,17 @@
         _list = RepoGroup.query(sorted=True).all()
         group_iter = RepoGroupList(_list, perm_level='admin')
         repo_groups_data = []
-        total_records = len(group_iter)
         _tmpl_lookup = app_globals.mako_lookup
         template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
 
-        repo_group_name = lambda repo_group_name, children_groups: (
-            template.get_def("repo_group_name")
-            .render_unicode(repo_group_name, children_groups, _=_, h=h, c=c)
-        )
-        repo_group_actions = lambda repo_group_id, repo_group_name, gr_count: (
-            template.get_def("repo_group_actions")
-            .render_unicode(repo_group_id, repo_group_name, gr_count, _=_, h=h, c=c,
-                    ungettext=ungettext)
-        )
+        def repo_group_name(repo_group_name, children_groups):
+            return template.get_def("repo_group_name") \
+                .render_unicode(repo_group_name, children_groups, _=_, h=h, c=c)
+
+        def repo_group_actions(repo_group_id, repo_group_name, gr_count):
+            return template.get_def("repo_group_actions") \
+                .render_unicode(repo_group_id, repo_group_name, gr_count, _=_, h=h, c=c,
+                        ungettext=ungettext)
 
         for repo_gr in group_iter:
             children_groups = [g.name for g in repo_gr.parents] + [repo_gr.name]
--- a/kallithea/controllers/admin/repos.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/controllers/admin/repos.py	Mon Apr 27 13:25:28 2020 +0200
@@ -28,6 +28,7 @@
 import logging
 import traceback
 
+import celery.result
 import formencode
 from formencode import htmlfill
 from tg import request
@@ -35,6 +36,7 @@
 from tg.i18n import ugettext as _
 from webob.exc import HTTPForbidden, HTTPFound, HTTPInternalServerError, HTTPNotFound
 
+import kallithea
 from kallithea.config.routing import url
 from kallithea.lib import helpers as h
 from kallithea.lib.auth import HasPermissionAny, HasRepoPermissionLevelDecorator, LoginRequired, NotAnonymous
@@ -43,7 +45,7 @@
 from kallithea.lib.utils import action_logger
 from kallithea.lib.utils2 import safe_int
 from kallithea.lib.vcs import RepositoryError
-from kallithea.model.db import RepoGroup, Repository, RepositoryField, Setting, User, UserFollowing
+from kallithea.model.db import RepoGroup, Repository, RepositoryField, Setting, UserFollowing
 from kallithea.model.forms import RepoFieldForm, RepoForm, RepoPermsForm
 from kallithea.model.meta import Session
 from kallithea.model.repo import RepoModel
@@ -110,17 +112,11 @@
     @NotAnonymous()
     def create(self):
         self.__load_defaults()
-        form_result = {}
         try:
             # CanWriteGroup validators checks permissions of this POST
             form_result = RepoForm(repo_groups=c.repo_groups,
                                    landing_revs=c.landing_revs_choices)() \
                             .to_python(dict(request.POST))
-
-            # create is done sometimes async on celery, db transaction
-            # management is handled there.
-            task = RepoModel().create(form_result, request.authuser.user_id)
-            task_id = task.task_id
         except formencode.Invalid as errors:
             log.info(errors)
             return htmlfill.render(
@@ -131,6 +127,11 @@
                 force_defaults=False,
                 encoding="UTF-8")
 
+        try:
+            # create is done sometimes async on celery, db transaction
+            # management is handled there.
+            task = RepoModel().create(form_result, request.authuser.user_id)
+            task_id = task.task_id
         except Exception:
             log.error(traceback.format_exc())
             msg = (_('Error creating repository %s')
@@ -181,12 +182,10 @@
         task_id = request.GET.get('task_id')
 
         if task_id and task_id not in ['None']:
-            from kallithea import CELERY_ON
-            from kallithea.lib import celerypylons
-            if CELERY_ON:
-                task = celerypylons.result.AsyncResult(task_id)
-                if task.failed():
-                    raise HTTPInternalServerError(task.traceback)
+            if kallithea.CELERY_APP:
+                task_result = celery.result.AsyncResult(task_id, app=kallithea.CELERY_APP)
+                if task_result.failed():
+                    raise HTTPInternalServerError(task_result.traceback)
 
         repo = Repository.get_by_repo_name(repo_name)
         if repo and repo.repo_state == Repository.STATE_CREATED:
@@ -406,7 +405,7 @@
     @HasRepoPermissionLevelDecorator('admin')
     def edit_advanced(self, repo_name):
         c.repo_info = self._load_repo()
-        c.default_user_id = User.get_default_user().user_id
+        c.default_user_id = kallithea.DEFAULT_USER_ID
         c.in_public_journal = UserFollowing.query() \
             .filter(UserFollowing.user_id == c.default_user_id) \
             .filter(UserFollowing.follows_repository == c.repo_info).scalar()
@@ -443,7 +442,7 @@
 
         try:
             repo_id = Repository.get_by_repo_name(repo_name).repo_id
-            user_id = User.get_default_user().user_id
+            user_id = kallithea.DEFAULT_USER_ID
             self.scm_model.toggle_following_repo(repo_id, user_id)
             h.flash(_('Updated repository visibility in public journal'),
                     category='success')
@@ -480,24 +479,6 @@
         raise HTTPFound(location=url('edit_repo_advanced', repo_name=repo_name))
 
     @HasRepoPermissionLevelDecorator('admin')
-    def edit_caches(self, repo_name):
-        c.repo_info = self._load_repo()
-        c.active = 'caches'
-        if request.POST:
-            try:
-                ScmModel().mark_for_invalidation(repo_name)
-                Session().commit()
-                h.flash(_('Cache invalidation successful'),
-                        category='success')
-            except Exception as e:
-                log.error(traceback.format_exc())
-                h.flash(_('An error occurred during cache invalidation'),
-                        category='error')
-
-            raise HTTPFound(location=url('edit_repo_caches', repo_name=c.repo_name))
-        return render('admin/repos/repo_edit.html')
-
-    @HasRepoPermissionLevelDecorator('admin')
     def edit_remote(self, repo_name):
         c.repo_info = self._load_repo()
         c.active = 'remote'
--- a/kallithea/controllers/admin/settings.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/controllers/admin/settings.py	Mon Apr 27 13:25:28 2020 +0200
@@ -120,6 +120,7 @@
                 if sett.ui_active:
                     try:
                         import hgsubversion  # pragma: no cover
+                        assert hgsubversion
                     except ImportError:
                         raise HgsubversionImportError
 
--- a/kallithea/controllers/admin/user_groups.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/controllers/admin/user_groups.py	Mon Apr 27 13:25:28 2020 +0200
@@ -86,20 +86,18 @@
                         .all()
         group_iter = UserGroupList(_list, perm_level='admin')
         user_groups_data = []
-        total_records = len(group_iter)
         _tmpl_lookup = app_globals.mako_lookup
         template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
 
-        user_group_name = lambda user_group_id, user_group_name: (
-            template.get_def("user_group_name")
-            .render_unicode(user_group_id, user_group_name, _=_, h=h, c=c)
-        )
-        user_group_actions = lambda user_group_id, user_group_name: (
-            template.get_def("user_group_actions")
-            .render_unicode(user_group_id, user_group_name, _=_, h=h, c=c)
-        )
+        def user_group_name(user_group_id, user_group_name):
+            return template.get_def("user_group_name") \
+                .render_unicode(user_group_id, user_group_name, _=_, h=h, c=c)
+
+        def user_group_actions(user_group_id, user_group_name):
+            return template.get_def("user_group_actions") \
+                .render_unicode(user_group_id, user_group_name, _=_, h=h, c=c)
+
         for user_gr in group_iter:
-
             user_groups_data.append({
                 "raw_name": user_gr.users_group_name,
                 "group_name": user_group_name(user_gr.users_group_id,
--- a/kallithea/controllers/admin/users.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/controllers/admin/users.py	Mon Apr 27 13:25:28 2020 +0200
@@ -36,6 +36,7 @@
 from tg.i18n import ugettext as _
 from webob.exc import HTTPFound, HTTPNotFound
 
+import kallithea
 from kallithea.config.routing import url
 from kallithea.lib import auth_modules
 from kallithea.lib import helpers as h
@@ -70,19 +71,18 @@
                         .all()
 
         users_data = []
-        total_records = len(c.users_list)
         _tmpl_lookup = app_globals.mako_lookup
         template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
 
         grav_tmpl = '<div class="gravatar">%s</div>'
 
-        username = lambda user_id, username: (
-                template.get_def("user_name")
-                .render_unicode(user_id, username, _=_, h=h, c=c))
+        def username(user_id, username):
+            return template.get_def("user_name") \
+                .render_unicode(user_id, username, _=_, h=h, c=c)
 
-        user_actions = lambda user_id, username: (
-                template.get_def("user_actions")
-                .render_unicode(user_id, username, _=_, h=h, c=c))
+        def user_actions(user_id, username):
+            return template.get_def("user_actions") \
+                .render_unicode(user_id, username, _=_, h=h, c=c)
 
         for user in c.users_list:
             users_data.append({
@@ -388,7 +388,7 @@
             .filter(UserIpMap.user == c.user).all()
 
         c.default_user_ip_map = UserIpMap.query() \
-            .filter(UserIpMap.user == User.get_default_user()).all()
+            .filter(UserIpMap.user_id == kallithea.DEFAULT_USER_ID).all()
 
         defaults = c.user.get_dict()
         return htmlfill.render(
--- a/kallithea/controllers/api/api.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/controllers/api/api.py	Mon Apr 27 13:25:28 2020 +0200
@@ -32,8 +32,8 @@
 from tg import request
 
 from kallithea.controllers.api import JSONRPCController, JSONRPCError
-from kallithea.lib.auth import (
-    AuthUser, HasPermissionAny, HasPermissionAnyDecorator, HasRepoGroupPermissionLevel, HasRepoPermissionLevel, HasUserGroupPermissionLevel)
+from kallithea.lib.auth import (AuthUser, HasPermissionAny, HasPermissionAnyDecorator, HasRepoGroupPermissionLevel, HasRepoPermissionLevel,
+                                HasUserGroupPermissionLevel)
 from kallithea.lib.exceptions import DefaultUserException, UserGroupsAssignedException
 from kallithea.lib.utils import action_logger, repo2db_mapper
 from kallithea.lib.utils2 import OAttr, Optional
@@ -433,7 +433,7 @@
 
     @HasPermissionAnyDecorator('hg.admin')
     def create_user(self, username, email, password=Optional(''),
-                    firstname=Optional(u''), lastname=Optional(u''),
+                    firstname=Optional(''), lastname=Optional(''),
                     active=Optional(True), admin=Optional(False),
                     extern_type=Optional(User.DEFAULT_AUTH_TYPE),
                     extern_name=Optional('')):
@@ -686,7 +686,7 @@
         ]
 
     @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
-    def create_user_group(self, group_name, description=Optional(u''),
+    def create_user_group(self, group_name, description=Optional(''),
                           owner=Optional(OAttr('apiuser')), active=Optional(True)):
         """
         Creates new user group. This command can be executed only using api_key
@@ -2373,7 +2373,7 @@
         return pull_request.get_api_data()
 
     # permission check inside
-    def comment_pullrequest(self, pull_request_id, comment_msg=u'', status=None, close_pr=False):
+    def comment_pullrequest(self, pull_request_id, comment_msg='', status=None, close_pr=False):
         """
         Add comment, close and change status of pull request.
         """
--- a/kallithea/controllers/changeset.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/controllers/changeset.py	Mon Apr 27 13:25:28 2020 +0200
@@ -33,7 +33,7 @@
 from tg import request, response
 from tg import tmpl_context as c
 from tg.i18n import ugettext as _
-from webob.exc import HTTPBadRequest, HTTPForbidden, HTTPFound, HTTPNotFound
+from webob.exc import HTTPBadRequest, HTTPForbidden, HTTPNotFound
 
 import kallithea.lib.helpers as h
 from kallithea.lib import diffs
@@ -215,7 +215,6 @@
             return {
                'location': h.url('my_pullrequests'), # or repo pr list?
             }
-            raise HTTPFound(location=h.url('my_pullrequests')) # or repo pr list?
         raise HTTPForbidden()
 
     text = request.POST.get('text', '').strip()
--- a/kallithea/controllers/feed.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/controllers/feed.py	Mon Apr 27 13:25:28 2020 +0200
@@ -101,7 +101,7 @@
     def _feed(self, repo_name, feeder):
         """Produce a simple feed"""
 
-        @cache_region('long_term', '_get_feed_from_cache')
+        @cache_region('long_term_file', '_get_feed_from_cache')
         def _get_feed_from_cache(*_cache_keys):  # parameters are not really used - only as caching key
             header = dict(
                 title=_('%s %s feed') % (c.site_name, repo_name),
--- a/kallithea/controllers/files.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/controllers/files.py	Mon Apr 27 13:25:28 2020 +0200
@@ -49,10 +49,10 @@
 from kallithea.lib.utils2 import convert_line_endings, detect_mode, safe_int, safe_str, str2bool
 from kallithea.lib.vcs.backends.base import EmptyChangeset
 from kallithea.lib.vcs.conf import settings
-from kallithea.lib.vcs.exceptions import (
-    ChangesetDoesNotExistError, ChangesetError, EmptyRepositoryError, ImproperArchiveTypeError, NodeAlreadyExistsError, NodeDoesNotExistError, NodeError, RepositoryError, VCSError)
+from kallithea.lib.vcs.exceptions import (ChangesetDoesNotExistError, ChangesetError, EmptyRepositoryError, ImproperArchiveTypeError, NodeAlreadyExistsError,
+                                          NodeDoesNotExistError, NodeError, RepositoryError, VCSError)
 from kallithea.lib.vcs.nodes import FileNode
-from kallithea.model.db import Repository
+from kallithea.model import db
 from kallithea.model.repo import RepoModel
 from kallithea.model.scm import ScmModel
 
@@ -233,7 +233,7 @@
         file_node = self.__get_filenode(cs, f_path)
 
         response.content_disposition = \
-            'attachment; filename=%s' % f_path.split(Repository.url_sep())[-1]
+            'attachment; filename=%s' % f_path.split(db.URL_SEP)[-1]
 
         response.content_type = file_node.mimetype
         return file_node.content
--- a/kallithea/controllers/forks.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/controllers/forks.py	Mon Apr 27 13:25:28 2020 +0200
@@ -35,13 +35,14 @@
 from tg.i18n import ugettext as _
 from webob.exc import HTTPFound
 
+import kallithea
 import kallithea.lib.helpers as h
 from kallithea.config.routing import url
 from kallithea.lib.auth import HasPermissionAny, HasPermissionAnyDecorator, HasRepoPermissionLevel, HasRepoPermissionLevelDecorator, LoginRequired
 from kallithea.lib.base import BaseRepoController, render
 from kallithea.lib.page import Page
 from kallithea.lib.utils2 import safe_int
-from kallithea.model.db import Repository, Ui, User, UserFollowing
+from kallithea.model.db import Repository, Ui, UserFollowing
 from kallithea.model.forms import RepoForkForm
 from kallithea.model.repo import RepoModel
 from kallithea.model.scm import AvailableRepoGroupChoices, ScmModel
@@ -76,7 +77,7 @@
             h.not_mapped_error(c.repo_name)
             raise HTTPFound(location=url('repos'))
 
-        c.default_user_id = User.get_default_user().user_id
+        c.default_user_id = kallithea.DEFAULT_USER_ID
         c.in_public_journal = UserFollowing.query() \
             .filter(UserFollowing.user_id == c.default_user_id) \
             .filter(UserFollowing.follows_repository == c.repo_info).scalar()
--- a/kallithea/controllers/login.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/controllers/login.py	Mon Apr 27 13:25:28 2020 +0200
@@ -79,10 +79,11 @@
             # import Login Form validator class
             login_form = LoginForm()()
             try:
+                # login_form will check username/password using ValidAuth and report failure to the user
                 c.form_result = login_form.to_python(dict(request.POST))
-                # form checks for username/password, now we're authenticated
                 username = c.form_result['username']
-                user = User.get_by_username_or_email(username, case_insensitive=True)
+                user = User.get_by_username_or_email(username)
+                assert user is not None  # the same user get just passed in the form validation
             except formencode.Invalid as errors:
                 defaults = errors.value
                 # remove password from filling in form again
@@ -101,9 +102,11 @@
                 # Exception itself
                 h.flash(e, 'error')
             else:
+                # login_form already validated the password - now set the session cookie accordingly
                 auth_user = log_in_user(user, c.form_result['remember'], is_external_auth=False, ip_addr=request.ip_addr)
-                # TODO: handle auth_user is None as failed authentication?
-                raise HTTPFound(location=c.came_from)
+                if auth_user:
+                    raise HTTPFound(location=c.came_from)
+                h.flash(_('Authentication failed.'), 'error')
         else:
             # redirect if already logged in
             if not request.authuser.is_anonymous:
--- a/kallithea/controllers/search.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/controllers/search.py	Mon Apr 27 13:25:28 2020 +0200
@@ -94,7 +94,7 @@
                 if c.repo_name:
                     # use "repository_rawname:" instead of "repository:"
                     # for case-sensitive matching
-                    cur_query = u'repository_rawname:%s %s' % (c.repo_name, cur_query)
+                    cur_query = 'repository_rawname:%s %s' % (c.repo_name, cur_query)
                 try:
                     query = qp.parse(cur_query)
                     # extract words for highlight
--- a/kallithea/controllers/summary.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/controllers/summary.py	Mon Apr 27 13:25:28 2020 +0200
@@ -66,7 +66,7 @@
         repo_name = db_repo.repo_name
         log.debug('Looking for README file')
 
-        @cache_region('long_term', '_get_readme_from_cache')
+        @cache_region('long_term_file', '_get_readme_from_cache')
         def _get_readme_from_cache(*_cache_keys):  # parameters are not really used - only as caching key
             readme_data = None
             readme_file = None
--- a/kallithea/front-end/package-lock.json	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/front-end/package-lock.json	Mon Apr 27 13:25:28 2020 +0200
@@ -3,18 +3,49 @@
   "requires": true,
   "lockfileVersion": 1,
   "dependencies": {
+    "@babel/code-frame": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
+      "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
+      "dev": true,
+      "requires": {
+        "@babel/highlight": "^7.8.3"
+      }
+    },
+    "@babel/highlight": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
+      "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.0.0",
+        "esutils": "^2.0.2",
+        "js-tokens": "^4.0.0"
+      }
+    },
     "abbrev": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
       "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
       "dev": true
     },
+    "acorn": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz",
+      "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==",
+      "dev": true
+    },
+    "acorn-jsx": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz",
+      "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==",
+      "dev": true
+    },
     "ajv": {
       "version": "6.10.2",
       "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
       "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
       "dev": true,
-      "optional": true,
       "requires": {
         "fast-deep-equal": "^2.0.1",
         "fast-json-stable-stringify": "^2.0.0",
@@ -28,6 +59,21 @@
       "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
       "dev": true
     },
+    "ansi-escapes": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz",
+      "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==",
+      "dev": true,
+      "requires": {
+        "type-fest": "^0.8.1"
+      }
+    },
+    "ansi-regex": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+      "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+      "dev": true
+    },
     "ansi-styles": {
       "version": "3.2.1",
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
@@ -37,6 +83,15 @@
         "color-convert": "^1.9.0"
       }
     },
+    "argparse": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "dev": true,
+      "requires": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
     "array-find-index": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
@@ -66,6 +121,12 @@
       "dev": true,
       "optional": true
     },
+    "astral-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
+      "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
+      "dev": true
+    },
     "asynckit": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -123,6 +184,12 @@
         "concat-map": "0.0.1"
       }
     },
+    "callsites": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+      "dev": true
+    },
     "caseless": {
       "version": "0.12.0",
       "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
@@ -141,6 +208,12 @@
         "supports-color": "^5.3.0"
       }
     },
+    "chardet": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+      "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+      "dev": true
+    },
     "clean-css": {
       "version": "3.4.28",
       "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz",
@@ -162,6 +235,21 @@
         }
       }
     },
+    "cli-cursor": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+      "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+      "dev": true,
+      "requires": {
+        "restore-cursor": "^3.1.0"
+      }
+    },
+    "cli-width": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+      "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
+      "dev": true
+    },
     "clone": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
@@ -220,6 +308,19 @@
       "dev": true,
       "optional": true
     },
+    "cross-spawn": {
+      "version": "6.0.5",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+      "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+      "dev": true,
+      "requires": {
+        "nice-try": "^1.0.4",
+        "path-key": "^2.0.1",
+        "semver": "^5.5.0",
+        "shebang-command": "^1.2.0",
+        "which": "^1.2.9"
+      }
+    },
     "dashdash": {
       "version": "1.14.1",
       "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -262,6 +363,12 @@
       "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=",
       "dev": true
     },
+    "deep-is": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+      "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+      "dev": true
+    },
     "delayed-stream": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -279,6 +386,64 @@
         "wrappy": "1"
       }
     },
+    "doctrine": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+      "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+      "dev": true,
+      "requires": {
+        "esutils": "^2.0.2"
+      }
+    },
+    "dom-serializer": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
+      "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
+      "dev": true,
+      "requires": {
+        "domelementtype": "^2.0.1",
+        "entities": "^2.0.0"
+      },
+      "dependencies": {
+        "domelementtype": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz",
+          "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==",
+          "dev": true
+        },
+        "entities": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz",
+          "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==",
+          "dev": true
+        }
+      }
+    },
+    "domelementtype": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+      "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
+      "dev": true
+    },
+    "domhandler": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+      "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+      "dev": true,
+      "requires": {
+        "domelementtype": "1"
+      }
+    },
+    "domutils": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+      "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+      "dev": true,
+      "requires": {
+        "dom-serializer": "0",
+        "domelementtype": "1"
+      }
+    },
     "ecc-jsbn": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -290,6 +455,18 @@
         "safer-buffer": "^2.1.0"
       }
     },
+    "emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "dev": true
+    },
+    "entities": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+      "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
+      "dev": true
+    },
     "errno": {
       "version": "0.1.7",
       "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
@@ -306,6 +483,149 @@
       "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
       "dev": true
     },
+    "eslint": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz",
+      "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.0.0",
+        "ajv": "^6.10.0",
+        "chalk": "^2.1.0",
+        "cross-spawn": "^6.0.5",
+        "debug": "^4.0.1",
+        "doctrine": "^3.0.0",
+        "eslint-scope": "^5.0.0",
+        "eslint-utils": "^1.4.3",
+        "eslint-visitor-keys": "^1.1.0",
+        "espree": "^6.1.2",
+        "esquery": "^1.0.1",
+        "esutils": "^2.0.2",
+        "file-entry-cache": "^5.0.1",
+        "functional-red-black-tree": "^1.0.1",
+        "glob-parent": "^5.0.0",
+        "globals": "^12.1.0",
+        "ignore": "^4.0.6",
+        "import-fresh": "^3.0.0",
+        "imurmurhash": "^0.1.4",
+        "inquirer": "^7.0.0",
+        "is-glob": "^4.0.0",
+        "js-yaml": "^3.13.1",
+        "json-stable-stringify-without-jsonify": "^1.0.1",
+        "levn": "^0.3.0",
+        "lodash": "^4.17.14",
+        "minimatch": "^3.0.4",
+        "mkdirp": "^0.5.1",
+        "natural-compare": "^1.4.0",
+        "optionator": "^0.8.3",
+        "progress": "^2.0.0",
+        "regexpp": "^2.0.1",
+        "semver": "^6.1.2",
+        "strip-ansi": "^5.2.0",
+        "strip-json-comments": "^3.0.1",
+        "table": "^5.2.3",
+        "text-table": "^0.2.0",
+        "v8-compile-cache": "^2.0.3"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
+        }
+      }
+    },
+    "eslint-plugin-html": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-6.0.0.tgz",
+      "integrity": "sha512-PQcGippOHS+HTbQCStmH5MY1BF2MaU8qW/+Mvo/8xTa/ioeMXdSP+IiaBw2+nh0KEMfYQKuTz1Zo+vHynjwhbg==",
+      "dev": true,
+      "requires": {
+        "htmlparser2": "^3.10.1"
+      }
+    },
+    "eslint-scope": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
+      "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==",
+      "dev": true,
+      "requires": {
+        "esrecurse": "^4.1.0",
+        "estraverse": "^4.1.1"
+      }
+    },
+    "eslint-utils": {
+      "version": "1.4.3",
+      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
+      "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
+      "dev": true,
+      "requires": {
+        "eslint-visitor-keys": "^1.1.0"
+      }
+    },
+    "eslint-visitor-keys": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
+      "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
+      "dev": true
+    },
+    "espree": {
+      "version": "6.1.2",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz",
+      "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==",
+      "dev": true,
+      "requires": {
+        "acorn": "^7.1.0",
+        "acorn-jsx": "^5.1.0",
+        "eslint-visitor-keys": "^1.1.0"
+      }
+    },
+    "esprima": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+      "dev": true
+    },
+    "esquery": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.1.0.tgz",
+      "integrity": "sha512-MxYW9xKmROWF672KqjO75sszsA8Mxhw06YFeS5VHlB98KDHbOSurm3ArsjO60Eaf3QmGMCP1yn+0JQkNLo/97Q==",
+      "dev": true,
+      "requires": {
+        "estraverse": "^4.0.0"
+      }
+    },
+    "esrecurse": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+      "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+      "dev": true,
+      "requires": {
+        "estraverse": "^4.1.0"
+      }
+    },
+    "estraverse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+      "dev": true
+    },
+    "esutils": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+      "dev": true
+    },
     "extend": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -313,6 +633,17 @@
       "dev": true,
       "optional": true
     },
+    "external-editor": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+      "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+      "dev": true,
+      "requires": {
+        "chardet": "^0.7.0",
+        "iconv-lite": "^0.4.24",
+        "tmp": "^0.0.33"
+      }
+    },
     "extsprintf": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
@@ -324,15 +655,54 @@
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
       "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
-      "dev": true,
-      "optional": true
+      "dev": true
     },
     "fast-json-stable-stringify": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
       "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
+      "dev": true
+    },
+    "fast-levenshtein": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+      "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+      "dev": true
+    },
+    "figures": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+      "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
       "dev": true,
-      "optional": true
+      "requires": {
+        "escape-string-regexp": "^1.0.5"
+      }
+    },
+    "file-entry-cache": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
+      "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
+      "dev": true,
+      "requires": {
+        "flat-cache": "^2.0.1"
+      }
+    },
+    "flat-cache": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
+      "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
+      "dev": true,
+      "requires": {
+        "flatted": "^2.0.0",
+        "rimraf": "2.6.3",
+        "write": "1.0.3"
+      }
+    },
+    "flatted": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz",
+      "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==",
+      "dev": true
     },
     "forever-agent": {
       "version": "0.6.1",
@@ -359,6 +729,12 @@
       "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
       "dev": true
     },
+    "functional-red-black-tree": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+      "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+      "dev": true
+    },
     "getpass": {
       "version": "0.1.7",
       "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
@@ -383,6 +759,24 @@
         "path-is-absolute": "^1.0.0"
       }
     },
+    "glob-parent": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz",
+      "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==",
+      "dev": true,
+      "requires": {
+        "is-glob": "^4.0.1"
+      }
+    },
+    "globals": {
+      "version": "12.3.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz",
+      "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==",
+      "dev": true,
+      "requires": {
+        "type-fest": "^0.8.1"
+      }
+    },
     "graceful-fs": {
       "version": "4.2.3",
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
@@ -425,6 +819,20 @@
       "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==",
       "dev": true
     },
+    "htmlparser2": {
+      "version": "3.10.1",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+      "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+      "dev": true,
+      "requires": {
+        "domelementtype": "^1.3.1",
+        "domhandler": "^2.3.0",
+        "domutils": "^1.5.1",
+        "entities": "^1.1.1",
+        "inherits": "^2.0.1",
+        "readable-stream": "^3.1.1"
+      }
+    },
     "http-signature": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
@@ -437,6 +845,21 @@
         "sshpk": "^1.7.0"
       }
     },
+    "iconv-lite": {
+      "version": "0.4.24",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+      "dev": true,
+      "requires": {
+        "safer-buffer": ">= 2.1.2 < 3"
+      }
+    },
+    "ignore": {
+      "version": "4.0.6",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+      "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+      "dev": true
+    },
     "image-size": {
       "version": "0.5.5",
       "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
@@ -444,6 +867,22 @@
       "dev": true,
       "optional": true
     },
+    "import-fresh": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
+      "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
+      "dev": true,
+      "requires": {
+        "parent-module": "^1.0.0",
+        "resolve-from": "^4.0.0"
+      }
+    },
+    "imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+      "dev": true
+    },
     "inflight": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -460,6 +899,54 @@
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
       "dev": true
     },
+    "inquirer": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.4.tgz",
+      "integrity": "sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ==",
+      "dev": true,
+      "requires": {
+        "ansi-escapes": "^4.2.1",
+        "chalk": "^2.4.2",
+        "cli-cursor": "^3.1.0",
+        "cli-width": "^2.0.0",
+        "external-editor": "^3.0.3",
+        "figures": "^3.0.0",
+        "lodash": "^4.17.15",
+        "mute-stream": "0.0.8",
+        "run-async": "^2.2.0",
+        "rxjs": "^6.5.3",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^5.1.0",
+        "through": "^2.3.6"
+      }
+    },
+    "is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+      "dev": true
+    },
+    "is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "dev": true
+    },
+    "is-glob": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+      "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+      "dev": true,
+      "requires": {
+        "is-extglob": "^2.1.1"
+      }
+    },
+    "is-promise": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+      "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+      "dev": true
+    },
     "is-typedarray": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
@@ -467,6 +954,12 @@
       "dev": true,
       "optional": true
     },
+    "isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+      "dev": true
+    },
     "isstream": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
@@ -489,6 +982,22 @@
       "resolved": "https://registry.npmjs.org/jquery.flot/-/jquery.flot-0.8.3.tgz",
       "integrity": "sha512-/tEE8J5NjwvStHDaCHkvTJpD7wDS4hE1OEL8xEmhgQfUe0gLUem923PIceNez1mz4yBNx6Hjv7pJcowLNd+nbg=="
     },
+    "js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "dev": true
+    },
+    "js-yaml": {
+      "version": "3.13.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+      "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+      "dev": true,
+      "requires": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      }
+    },
     "jsbn": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
@@ -513,8 +1022,13 @@
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
       "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
-      "dev": true,
-      "optional": true
+      "dev": true
+    },
+    "json-stable-stringify-without-jsonify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+      "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+      "dev": true
     },
     "json-stringify-safe": {
       "version": "5.0.1",
@@ -562,6 +1076,16 @@
         "clean-css": "^3.0.1"
       }
     },
+    "levn": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+      "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+      "dev": true,
+      "requires": {
+        "prelude-ls": "~1.1.2",
+        "type-check": "~0.3.2"
+      }
+    },
     "license-checker": {
       "version": "25.0.1",
       "resolved": "https://registry.npmjs.org/license-checker/-/license-checker-25.0.1.tgz",
@@ -580,6 +1104,12 @@
         "treeify": "^1.1.0"
       }
     },
+    "lodash": {
+      "version": "4.17.15",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+      "dev": true
+    },
     "mime": {
       "version": "1.6.0",
       "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
@@ -604,6 +1134,12 @@
         "mime-db": "1.40.0"
       }
     },
+    "mimic-fn": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+      "dev": true
+    },
     "minimatch": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@@ -634,6 +1170,24 @@
       "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
       "dev": true
     },
+    "mute-stream": {
+      "version": "0.0.8",
+      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+      "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+      "dev": true
+    },
+    "natural-compare": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+      "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+      "dev": true
+    },
+    "nice-try": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+      "dev": true
+    },
     "nopt": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
@@ -672,6 +1226,29 @@
         "wrappy": "1"
       }
     },
+    "onetime": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
+      "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
+      "dev": true,
+      "requires": {
+        "mimic-fn": "^2.1.0"
+      }
+    },
+    "optionator": {
+      "version": "0.8.3",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+      "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+      "dev": true,
+      "requires": {
+        "deep-is": "~0.1.3",
+        "fast-levenshtein": "~2.0.6",
+        "levn": "~0.3.0",
+        "prelude-ls": "~1.1.2",
+        "type-check": "~0.3.2",
+        "word-wrap": "~1.2.3"
+      }
+    },
     "os-homedir": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
@@ -694,12 +1271,27 @@
         "os-tmpdir": "^1.0.0"
       }
     },
+    "parent-module": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+      "dev": true,
+      "requires": {
+        "callsites": "^3.0.0"
+      }
+    },
     "path-is-absolute": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
       "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
       "dev": true
     },
+    "path-key": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+      "dev": true
+    },
     "path-parse": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
@@ -713,6 +1305,18 @@
       "dev": true,
       "optional": true
     },
+    "prelude-ls": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+      "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+      "dev": true
+    },
+    "progress": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+      "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+      "dev": true
+    },
     "promise": {
       "version": "7.3.1",
       "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
@@ -741,8 +1345,7 @@
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
       "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
-      "dev": true,
-      "optional": true
+      "dev": true
     },
     "qs": {
       "version": "6.5.2",
@@ -779,6 +1382,17 @@
         "slash": "^1.0.0"
       }
     },
+    "readable-stream": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+      "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      }
+    },
     "readdir-scoped-modules": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz",
@@ -791,6 +1405,12 @@
         "once": "^1.3.0"
       }
     },
+    "regexpp": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
+      "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
+      "dev": true
+    },
     "request": {
       "version": "2.88.0",
       "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
@@ -829,19 +1449,60 @@
         "path-parse": "^1.0.6"
       }
     },
+    "resolve-from": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+      "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+      "dev": true
+    },
+    "restore-cursor": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+      "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+      "dev": true,
+      "requires": {
+        "onetime": "^5.1.0",
+        "signal-exit": "^3.0.2"
+      }
+    },
+    "rimraf": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+      "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.1.3"
+      }
+    },
+    "run-async": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
+      "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
+      "dev": true,
+      "requires": {
+        "is-promise": "^2.1.0"
+      }
+    },
+    "rxjs": {
+      "version": "6.5.4",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz",
+      "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==",
+      "dev": true,
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
     "safe-buffer": {
       "version": "5.2.0",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
       "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
-      "dev": true,
-      "optional": true
+      "dev": true
     },
     "safer-buffer": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
-      "dev": true,
-      "optional": true
+      "dev": true
     },
     "select2": {
       "version": "3.5.1",
@@ -859,12 +1520,52 @@
       "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
       "dev": true
     },
+    "shebang-command": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+      "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+      "dev": true,
+      "requires": {
+        "shebang-regex": "^1.0.0"
+      }
+    },
+    "shebang-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+      "dev": true
+    },
+    "signal-exit": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+      "dev": true
+    },
     "slash": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
       "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
       "dev": true
     },
+    "slice-ansi": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
+      "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^3.2.0",
+        "astral-regex": "^1.0.0",
+        "is-fullwidth-code-point": "^2.0.0"
+      },
+      "dependencies": {
+        "is-fullwidth-code-point": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+          "dev": true
+        }
+      }
+    },
     "slide": {
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
@@ -938,6 +1639,12 @@
         "spdx-ranges": "^2.0.0"
       }
     },
+    "sprintf-js": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+      "dev": true
+    },
     "sshpk": {
       "version": "1.16.1",
       "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
@@ -956,6 +1663,60 @@
         "tweetnacl": "~0.14.0"
       }
     },
+    "string-width": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+      "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+      "dev": true,
+      "requires": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "dependencies": {
+        "strip-ansi": {
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^5.0.0"
+          }
+        }
+      }
+    },
+    "string_decoder": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "~5.2.0"
+      }
+    },
+    "strip-ansi": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+      "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "^4.1.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+          "dev": true
+        }
+      }
+    },
+    "strip-json-comments": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz",
+      "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==",
+      "dev": true
+    },
     "supports-color": {
       "version": "5.5.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -965,6 +1726,64 @@
         "has-flag": "^3.0.0"
       }
     },
+    "table": {
+      "version": "5.4.6",
+      "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
+      "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
+      "dev": true,
+      "requires": {
+        "ajv": "^6.10.2",
+        "lodash": "^4.17.14",
+        "slice-ansi": "^2.1.0",
+        "string-width": "^3.0.0"
+      },
+      "dependencies": {
+        "emoji-regex": {
+          "version": "7.0.3",
+          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+          "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+          "dev": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+          "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+          "dev": true
+        },
+        "string-width": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+          "dev": true,
+          "requires": {
+            "emoji-regex": "^7.0.1",
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^5.1.0"
+          }
+        }
+      }
+    },
+    "text-table": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+      "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+      "dev": true
+    },
+    "through": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+      "dev": true
+    },
+    "tmp": {
+      "version": "0.0.33",
+      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+      "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+      "dev": true,
+      "requires": {
+        "os-tmpdir": "~1.0.2"
+      }
+    },
     "tough-cookie": {
       "version": "2.4.3",
       "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
@@ -991,6 +1810,12 @@
       "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==",
       "dev": true
     },
+    "tslib": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.0.tgz",
+      "integrity": "sha512-BmndXUtiTn/VDDrJzQE7Mm22Ix3PxgLltW9bSNLoeCY31gnG2OPx0QqJnuc9oMIKioYrz487i6K9o4Pdn0j+Kg==",
+      "dev": true
+    },
     "tunnel-agent": {
       "version": "0.6.0",
       "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@@ -1008,16 +1833,36 @@
       "dev": true,
       "optional": true
     },
+    "type-check": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+      "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+      "dev": true,
+      "requires": {
+        "prelude-ls": "~1.1.2"
+      }
+    },
+    "type-fest": {
+      "version": "0.8.1",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+      "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+      "dev": true
+    },
     "uri-js": {
       "version": "4.2.2",
       "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
       "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
       "dev": true,
-      "optional": true,
       "requires": {
         "punycode": "^2.1.0"
       }
     },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+      "dev": true
+    },
     "util-extend": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz",
@@ -1031,6 +1876,12 @@
       "dev": true,
       "optional": true
     },
+    "v8-compile-cache": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz",
+      "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==",
+      "dev": true
+    },
     "validate-npm-package-license": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
@@ -1053,11 +1904,35 @@
         "extsprintf": "^1.2.0"
       }
     },
+    "which": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+      "dev": true,
+      "requires": {
+        "isexe": "^2.0.0"
+      }
+    },
+    "word-wrap": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+      "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+      "dev": true
+    },
     "wrappy": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
       "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
       "dev": true
+    },
+    "write": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
+      "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
+      "dev": true,
+      "requires": {
+        "mkdirp": "^0.5.1"
+      }
     }
   }
 }
--- a/kallithea/front-end/package.json	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/front-end/package.json	Mon Apr 27 13:25:28 2020 +0200
@@ -14,6 +14,8 @@
     "select2-bootstrap-css": "1.4.6"
   },
   "devDependencies": {
+    "eslint": "6.8.0",
+    "eslint-plugin-html": "6.0.0",
     "less": "3.10.3",
     "less-plugin-clean-css": "1.5.1",
     "license-checker": "25.0.1"
--- a/kallithea/front-end/style.less	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/front-end/style.less	Mon Apr 27 13:25:28 2020 +0200
@@ -937,8 +937,8 @@
   background-color: @kallithea-theme-main-color;
   border: 0;
 }
-#content #context-pages .follow .show-following,
-#content #context-pages .following .show-follow {
+#content .follow .show-following,
+#content .following .show-follow {
   display: none;
 }
 
--- a/kallithea/i18n/be/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/be/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -5,7 +5,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2017-08-20 10:44+0000\n"
 "Last-Translator: Viktar Vauchkevich <victorenator@gmail.com>\n"
 "Language-Team: Belarusian <https://hosted.weblate.org/projects/kallithea/"
@@ -65,7 +65,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr "Pull-запыт %s паспяхова выдалены"
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr "Няма такой рэвізіі ў гэтым рэпазітары"
@@ -258,7 +258,7 @@
 msgid "Tags"
 msgstr "Тэгі"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr "Памылка падчас стварэння форка рэпазітара %s"
@@ -311,25 +311,31 @@
 msgid "Journal"
 msgstr "Журнал"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+#, fuzzy
+#| msgid "Authentication"
+msgid "Authentication failed."
+msgstr "Аўтэнтыфікацыя"
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr "Няслушная капча"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "Рэгістрацыя ў %s прайшла паспяхова"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr "Код для скідання пароля адпраўлены"
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Няслушны код скідання пароля"
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Пароль абноўлены"
 
@@ -481,11 +487,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr "Статыстычныя дадзеныя адключаны для гэтага рэпазітара"
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr "Налады аўтарызацыі паспяхова абноўлены"
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr "памылка пры абнаўленні налад аўтарызацыі"
 
@@ -561,8 +567,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr "Памылка пры абнаўленні gist-запісу %s"
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 "Вы не можаце змяніць дадзеныя гэтага карыстальніка, паколькі ён важны для "
@@ -699,11 +705,11 @@
 msgid "Allowed with automatic account activation"
 msgstr "Дазволена, з аўтаматычнай актывацыяй уліковага запісу"
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr "Ручная актывацыя вонкавага ўліковага запісу"
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr "Аўтаматычная актывацыя вонкавага ўліковага запісу"
 
@@ -725,186 +731,178 @@
 msgid "Error occurred during update of permissions"
 msgstr "Адбылася памылка падчас абнаўлення прывілеяў"
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr "Адбылася памылка пры стварэнні групы рэпазітароў %s"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr "Створаная новая група рэпазітароў %s"
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Група рэпазітароў %s абноўленая"
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr "Адбылася памылка пры абнаўленні групы рэпазітароў %s"
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "Група ўтрымлівае %s рэпазітароў і не можа быць выдаленая"
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr "Група ўтрымлівае ў сабе %s падгруп і не можа быць выдаленая"
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Група рэпазітароў %s выдаленая"
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr "Памылка пры выдаленні групы рэпазітароў %s"
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Адміністратар не можа адклікаць свае прывелеі"
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr "Прывілеі групы рэпазітароў абноўленыя"
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr "Памылка пры водгуку прывелея"
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Памылка пры стварэнні рэпазітара %s"
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Рэпазітар %s створаны з %s"
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Зроблены форк рэпазітара %s на %s"
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr "Рэпазітар %s створаны"
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Рэпазітар %s паспяхова абноўлены"
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "Памылка падчас абнаўлення рэпазітара %s"
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr "Форкі %s адлучаныя"
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr "Выдаленыя форки рэпазітара %s"
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Рэпазітар %s выдалены"
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr "Немагчыма выдаліць %s, ён усё яшчэ мае форкі"
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "Памылка падчас выдалення %s"
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr "Прывілеі рэпазітара абноўленыя"
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, fuzzy, python-format
 #| msgid "An error occurred during creation of field"
 msgid "An error occurred during creation of field: %r"
 msgstr "Памылка пры стварэнні поля"
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr "Памылка пры выдаленні поля"
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr "-- Не форк --"
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr "Бачнасць рэпазітара ў публічным часопісе абноўлена"
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr "Памылка пры даданні рэпазітара ў агульнадаступны часопіс"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr "Нічога"
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "Рэпазітар %s адзначаны як форк %s"
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr "Памылка пры выкананні аперацыі"
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr "Кэш скінуты"
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr "Памылка пры скіданні кэша"
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr "Занесеныя змены з аддаленага рэпазітара"
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr "Памылка пры занясенні змен з аддаленага рэпазітара"
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr "Адбылася памылка пры выдаленні статыстыкі рэпазітара"
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr "Абноўлены налады VCS"
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
@@ -912,109 +910,109 @@
 "Немагчыма ўключыць падтрымку hgsubversion. Бібліятэка hgsubversion "
 "адсутнічае"
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr "Памылка пры абнаўленні наладаў праграмы"
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr "Рэпазітары паспяхова перасканаваныя, дададзена: %s, выдалена: %s."
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr "Скінуць кэш для %s рэпазітароў"
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr "Абноўленыя налады праграмы"
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr "Налады візуалізацыі абноўленыя"
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr "Адбылася памылка пры абнаўленні наладаў візуалізацыі"
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr "Калі ласка, увядзіце e-mail-адрас"
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr "Задача адпраўкі e-mail створаная"
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "Няма дадзеных"
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr "Дададзены новы хук"
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr "Абноўленыя хукі"
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr "Памылка пры стварэнні хука"
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr "Запланаванае пераіндэксаванне базы Whoosh"
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr "Створана група карыстальнікаў %s"
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr "Памылка пры стварэнні групы карыстальнікаў %s"
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr "Група карыстальнікаў %s абноўленая"
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr "Памылка пры абнаўленні групы карыстальнікаў %s"
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr "Група карыстальнікаў паспяхова выдаленая"
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr "Памылка пры выдаленні групы карыстальнікаў"
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr "Мэтавая група не можа быць той жа самай"
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr "Прывілеі групы карыстальнікаў абноўленыя"
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr "Абноўленыя прывілеі"
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr "Памылка пры захаванні прывілеяў"
@@ -1058,12 +1056,12 @@
 msgid "Removed IP address from user whitelist"
 msgstr "Выдалены IP %s з белага спісу карыстальніка"
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 "Вы павінны быць зарэгістраваным карыстальнікам, каб выканаць гэта дзеянне"
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr "Старонка даступная толькі аўтарызаваным карыстальнікам"
 
@@ -1102,166 +1100,166 @@
 msgid "No changes detected"
 msgstr "Змен не выяўлена"
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "Выдаленая галіна: %s"
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr "Створаны тэг: %s"
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, python-format
 msgid "Changeset %s not found"
 msgstr "Набор змен %s не знойдзены"
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "Паказаць адрозненні разам %s->%s"
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr "Параўнанне"
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr "і"
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr "на %s больш"
 
-#: kallithea/lib/helpers.py:735
+#: kallithea/lib/helpers.py:759
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "версіі"
 
-#: kallithea/lib/helpers.py:759
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr "Імя форка %s"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr "Pull-запыт %s"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:814
 msgid "[deleted] repository"
 msgstr "[выдалены] рэпазітар"
 
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
 msgid "[created] repository"
 msgstr "[створаны] рэпазітар"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:818
 msgid "[created] repository as fork"
 msgstr "[створаны] рэпазітар як форк"
 
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
 msgid "[forked] repository"
 msgstr "[форкнуты] рэпазітар"
 
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
 msgid "[updated] repository"
 msgstr "[абноўлены] рэпазітар"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:824
 msgid "[downloaded] archive from repository"
 msgstr "[загружаны] архіў з рэпазітара"
 
-#: kallithea/lib/helpers.py:802
+#: kallithea/lib/helpers.py:826
 msgid "[delete] repository"
 msgstr "[выдалены] рэпазітар"
 
-#: kallithea/lib/helpers.py:810
+#: kallithea/lib/helpers.py:834
 msgid "[created] user"
 msgstr "[створаны] карыстальнік"
 
-#: kallithea/lib/helpers.py:812
+#: kallithea/lib/helpers.py:836
 msgid "[updated] user"
 msgstr "[абноўлены] карыстальнік"
 
-#: kallithea/lib/helpers.py:814
+#: kallithea/lib/helpers.py:838
 msgid "[created] user group"
 msgstr "[створана] група карыстальнікаў"
 
-#: kallithea/lib/helpers.py:816
+#: kallithea/lib/helpers.py:840
 msgid "[updated] user group"
 msgstr "[абноўлена] група карыстальнікаў"
 
-#: kallithea/lib/helpers.py:818
+#: kallithea/lib/helpers.py:842
 msgid "[commented] on revision in repository"
 msgstr "[каментар] да рэвізіі ў рэпазітары"
 
-#: kallithea/lib/helpers.py:820
+#: kallithea/lib/helpers.py:844
 msgid "[commented] on pull request for"
 msgstr "[каментар] у pull-запыце для"
 
-#: kallithea/lib/helpers.py:822
+#: kallithea/lib/helpers.py:846
 msgid "[closed] pull request for"
 msgstr "[зачынены] pull-запыт для"
 
-#: kallithea/lib/helpers.py:824
+#: kallithea/lib/helpers.py:848
 msgid "[pushed] into"
 msgstr "[адпраўлена] у"
 
-#: kallithea/lib/helpers.py:826
+#: kallithea/lib/helpers.py:850
 msgid "[committed via Kallithea] into repository"
 msgstr "[каміт праз Kallithea] у рэпазітары"
 
-#: kallithea/lib/helpers.py:828
+#: kallithea/lib/helpers.py:852
 msgid "[pulled from remote] into repository"
 msgstr "[занесены з аддаленага рэпазітара] у рэпазітар"
 
-#: kallithea/lib/helpers.py:830
+#: kallithea/lib/helpers.py:854
 msgid "[pulled] from"
 msgstr "[занесены] з"
 
-#: kallithea/lib/helpers.py:832
+#: kallithea/lib/helpers.py:856
 msgid "[started following] repository"
 msgstr "[дададзены ў назіранні] рэпазітар"
 
-#: kallithea/lib/helpers.py:834
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr "[выдалены з назірання] рэпазітар"
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr " і на %s больш"
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "Няма файлаў"
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr "новы файл"
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr "зменены"
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr "выдалены"
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr "пераназваны"
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1301,7 +1299,7 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
@@ -1309,7 +1307,7 @@
 msgstr[1] "%d гады"
 msgstr[2] "%d гадоў"
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
@@ -1317,7 +1315,7 @@
 msgstr[1] "%d месяцы"
 msgstr[2] "%d месяцаў"
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
@@ -1325,7 +1323,7 @@
 msgstr[1] "%d дні"
 msgstr[2] "%d дзён"
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
@@ -1333,7 +1331,7 @@
 msgstr[1] "%d гадзіны"
 msgstr[2] "%d гадзін"
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
@@ -1341,7 +1339,7 @@
 msgstr[1] "%d хвіліны"
 msgstr[2] "%d хвілін"
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
@@ -1349,27 +1347,27 @@
 msgstr[1] "%d секунды"
 msgstr[2] "%d секунд"
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr "у %s"
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr "%s назад"
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr "у %s і %s"
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s і %s назад"
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr "цяпер"
 
@@ -1382,133 +1380,133 @@
 msgid "[Mention]"
 msgstr "[Згадванне]"
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr "верхні ўзровень"
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr "Адміністратар Kallithea"
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 #, fuzzy
 msgid "Default user has read access to new repositories"
 msgstr "Несанкцыянаваны доступ да рэсурсу"
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 #, fuzzy
 msgid "Default user has write access to new repositories"
 msgstr "Несанкцыянаваны доступ да рэсурсу"
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr "Толькі адміністратары могуць ствараць групы репазітароў"
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr "Неадміністратары могуць ствараць групы репазітароў"
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr "Толькі адміністратары могуць ствараць групы карыстальнікаў"
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr "Неадміністратары могуць ствараць групы карыстальнікаў"
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr "Толькі адміністратары могуць ствараць рэпазітары верхняга ўзроўню"
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr "Неадміністратары могуць ствараць рэпазітары верхняга ўзроўню"
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr "Месцазнаходжанне рэпазітароў"
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr "Рэгістрацыя адключаная"
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr "Рэгістрацыя карыстальніка з ручной актывацыяй уліковага запісу"
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr "Рэгістрацыя карыстальніка з аўтаматычнай актывацыяй"
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr "Не прагледжана"
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr "На разглядзе"
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 #, fuzzy
 #| msgid "Approved"
 msgid "Not approved"
 msgstr "Ухвалена"
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr "Ухвалена"
 
@@ -1534,7 +1532,7 @@
 msgid "Name must not contain only digits"
 msgstr "Імя не можа ўтрымліваць толькі лічбы"
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, fuzzy, python-format
 #| msgid "[Comment] %(repo_name)s pull request %(pr_nice_id)s from %(ref)s"
 msgid ""
@@ -1542,26 +1540,26 @@
 "%(branch)s"
 msgstr "[пракаментавана] у запыце на занясенне змен для"
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr "Новы карыстальнік \"%(new_username)s\" зарэгістраваны"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid ""
 "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:169
+#: kallithea/model/notification.py:168
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr "Зачынены"
 
@@ -1646,18 +1644,18 @@
 msgid "SSH key with fingerprint %r found"
 msgstr "Набор змен %s не знойдзены"
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr "Рэгістрацыя новага карыстальніка"
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 "Вы не можаце выдаліць карыстальніка, паколькі гэта крытычна для працы "
 "ўсёй праграмы"
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
@@ -1667,7 +1665,7 @@
 "таму не можа быць выдалены. Змяніце ўладальніка ці выдаліце гэтыя "
 "рэпазітары: %s"
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
@@ -1677,7 +1675,7 @@
 "і таму не можа быць выдалены. Змяніце ўладальніка ці выдаліце гэтая "
 "групы: %s"
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
@@ -1687,36 +1685,36 @@
 "карыстальнікаў і таму не можа быць выдалены. Змяніце ўладальніка ці "
 "выдаліце гэтыя групы: %s"
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr "Спасылка скіду пароля"
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr "Паведамленне пра скіданне пароля"
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr "Значэнне не можа быць пустым спісам"
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "Карыстальнік з імем \"%(username)s\" ужо існуе"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "Імя \"%(username)s\" недапушчальнае"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
@@ -1725,25 +1723,25 @@
 "падкрэслення, кропкі і працяжнік; а гэтак жа павінна пачынацца з літары, "
 "лічбы або са знака падкрэслення"
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr "Імя \"%(username)s\" недапушчальнае"
 
-#: kallithea/model/validators.py:131
+#: kallithea/model/validators.py:132
 msgid "Invalid user group name"
 msgstr "Няслушнае імя групы карыстальнікаў"
 
-#: kallithea/model/validators.py:132
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr "Група карыстальнікаў \"%(usergroup)s\" ужо існуе"
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
@@ -1752,61 +1750,61 @@
 "падкрэслення, кропкі і працяжнік; а гэтак жа павінна пачынацца з літары "
 "ці лічбы"
 
-#: kallithea/model/validators.py:174
+#: kallithea/model/validators.py:175
 msgid "Cannot assign this group as parent"
 msgstr "Немагчыма выкарыстоўваць гэту групу як бацькоўскую"
 
-#: kallithea/model/validators.py:175
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr "Група \"%(group_name)s\" ужо існуе"
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr "Рэпазітар з  імем \"%(group_name)s\" ужо існуе"
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr "Недапушчальныя знакі (не ascii) у паролі"
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr "Няслушна зададзены стары пароль"
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr "Паролі не супадаюць"
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr "Няслушнае імя ці пароль"
 
-#: kallithea/model/validators.py:313
+#: kallithea/model/validators.py:310
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr "Імя рэпазітара %(repo)s забароненае"
 
-#: kallithea/model/validators.py:315
+#: kallithea/model/validators.py:312
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr "Рэпазітар %(repo)s ужо існуе"
 
-#: kallithea/model/validators.py:316
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr "Рэпазітар \"%(repo)s\" ужо існуе ў групе \"%(group)s\""
 
-#: kallithea/model/validators.py:318
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr "Група рэпазітароў \"%(repo)s\" ужо існуе"
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr "Няслушны URL рэпазітара"
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
@@ -1814,40 +1812,40 @@
 "Няслушны URL рэпазітара. Ён мусіць быць карэктным URL http, https, ssh, "
 "svn+http ці svn+https"
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr "Тып форка будзе супадаць з бацькоўскім"
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr "У вас недастаткова правоў для стварэння рэпазітароў у гэтай групе"
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr "недастаткова правоў для стварэння рэпазітара ў каранёвым каталогу"
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr "У Вас недастаткова прывілеяў для стварэння групы ў гэтым месцы"
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr "Дадзенае імя карыстальніка ці групы карыстальнікаў недапушчальна"
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr "Гэты шлях хібны"
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr "Гэты e-mail ужо ўжываецца"
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "Email-адрас \"%(email)s\" не знойдзены"
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
@@ -1855,11 +1853,11 @@
 "Для ўваходу па LDAP павінна быць паказана значэнне атрыбута CN - гэта "
 "эквівалент імя карыстальніка"
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr "Калі ласка, увядзіце існы IPv4 ці IPv6 адрас"
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
@@ -1867,17 +1865,17 @@
 "Значэнне маскі падсеткі павінна быць у межах ад 0 да 32 (%(bits)r - "
 "няслушна)"
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 "Ключавое імя можа толькі складацца з літар, знака падкрэслення, працяжнік "
 "ці лікаў"
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr "Файла няма ў каталогу"
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1938,7 +1936,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1946,14 +1944,14 @@
 msgid "Description"
 msgstr "Апісанне"
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr "Апошняя змена"
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr "Стан"
 
@@ -1963,7 +1961,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1987,7 +1985,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr "Імя карыстальніка"
@@ -2113,7 +2111,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr "E-mail"
@@ -2364,7 +2362,7 @@
 msgstr "Стварыць новы gist-запіс"
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr "Створаны"
 
@@ -2448,13 +2446,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2470,14 +2468,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2794,7 +2792,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr "Група рэпазітароў"
@@ -2819,7 +2817,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr "Група карыстальнікаў"
 
@@ -2996,7 +2994,7 @@
 msgstr "Створана"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3171,14 +3169,10 @@
 msgstr "Дадатковыя палі"
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
-msgstr "Кэшы"
+msgid "Remote"
+msgstr "Выдалены"
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr "Выдалены"
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3218,7 +3212,7 @@
 "публічным журнал."
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "Пацвердзіце выдаленне гэтага рэпазітара: %s"
@@ -3250,43 +3244,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr "Скінуць кэш рэпазітара"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr "Ручное скіданне кэша рэпазітара. Пры першым доступе кэш адновіцца."
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr "Спіс кэшаваных значэнняў"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr "Прэфікс"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr ""
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr "Ключ"
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr "Актыўны"
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3817,6 +3782,15 @@
 msgid "Short, optional description for this user group."
 msgstr "Кароткае дадатковае апісанне для гэтай групы карыстальнікаў."
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr "Актыўны"
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3838,7 +3812,7 @@
 msgstr "Удзельнікі"
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr "Пацвердзіце выдаленне наступнай групы карыстальнікаў: %s"
@@ -3912,7 +3886,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr "Пацвердзіце выдаленне карыстальніка %s"
@@ -4012,10 +3986,12 @@
 msgstr "Пошук"
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr "Назіраць"
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr "Не назіраць"
 
@@ -4719,23 +4695,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr "Змен яшчэ не было"
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr "Падпісацца на стужку RSS %s"
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr "Падпісацца на стужку Atom %s"
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr "Ствараецца"
 
@@ -4773,6 +4749,13 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "Comment"
+msgid "View Comment"
+msgstr "Каментаваць"
+
 #: kallithea/templates/email_templates/comment.html:27
 #, fuzzy
 #| msgid "Status change"
@@ -4785,32 +4768,42 @@
 msgid "The pull request has been closed."
 msgstr "Гэты pull-запыт быў зачынены і не можа быць абноўлены."
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+#, fuzzy
+#| msgid "Password Reset"
+msgid "Password Reset Request"
+msgstr "Скінуць пароль"
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr "Добры дзень, %s"
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr "Мы атрымалі запыт на скіданне пароля для вашага акаўнта."
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4845,6 +4838,12 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+#| msgid "New Pull Request"
+msgid "View Pull Request"
+msgstr "Новы pull-запыт"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, fuzzy, python-format
 #| msgid "%s mentioned you on %s pull request \"%s\""
@@ -4863,12 +4862,24 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr "[каментар] у pull-запыце для"
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+#, fuzzy
+#| msgid "New user registration"
+msgid "New User Registration"
+msgstr "Рэгістрацыя новага карыстальніка"
+
+#: kallithea/templates/email_templates/registration.html:23
 #, fuzzy
 #| msgid "Group name"
 msgid "Full Name"
 msgstr "Імя групы"
 
+#: kallithea/templates/email_templates/registration.html:42
+#, fuzzy
+#| msgid "View this user here"
+msgid "View User Profile"
+msgstr "Падрабязней пра карыстальніка"
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5489,35 +5500,35 @@
 msgid "Show more"
 msgstr "Паказаць яшчэ"
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr "commit'ы"
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr "файлы дададзены"
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr "файлы зменены"
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr "файлы выдалены"
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr "commit"
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr "файл выдалены"
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr "файл зменены"
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr "файл выдалены"
 
@@ -5620,6 +5631,30 @@
 msgid "Download %s as %s"
 msgstr "Спампаваць %s як %s"
 
+#~ msgid "Cache invalidation successful"
+#~ msgstr "Кэш скінуты"
+
+#~ msgid "An error occurred during cache invalidation"
+#~ msgstr "Памылка пры скіданні кэша"
+
+#~ msgid "Caches"
+#~ msgstr "Кэшы"
+
+#~ msgid "Invalidate Repository Cache"
+#~ msgstr "Скінуць кэш рэпазітара"
+
+#~ msgid ""
+#~ "Manually invalidate cache for this repository. On first access, the "
+#~ "repository will be cached again."
+#~ msgstr ""
+#~ "Ручное скіданне кэша рэпазітара. Пры першым доступе кэш адновіцца."
+
+#~ msgid "List of Cached Values"
+#~ msgstr "Спіс кэшаваных значэнняў"
+
+#~ msgid "Prefix"
+#~ msgstr "Прэфікс"
+
 #~ msgid "This repository has been locked by %s on %s"
 #~ msgstr "Рэпазітар заблакаваў %s у %s"
 
@@ -5918,9 +5953,6 @@
 #~ msgid "The comment was made with status"
 #~ msgstr "Каментар пакінуты са статусам"
 
-#~ msgid "View this user here"
-#~ msgstr "Падрабязней пра карыстальніка"
-
 #~ msgid "Repository Size"
 #~ msgstr "Памер рэпазітара"
 
--- a/kallithea/i18n/bg/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/bg/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -7,7 +7,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.4.99\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: Automatically generated\n"
 "Language-Team: none\n"
@@ -62,7 +62,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr ""
@@ -248,7 +248,7 @@
 msgid "Tags"
 msgstr ""
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr ""
@@ -301,25 +301,29 @@
 msgid "Journal"
 msgstr ""
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+msgid "Authentication failed."
+msgstr ""
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr ""
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr ""
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr ""
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr ""
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr ""
 
@@ -461,11 +465,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -541,8 +545,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
@@ -674,11 +678,11 @@
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr ""
 
@@ -700,291 +704,283 @@
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 msgid "Hook already exists"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr ""
@@ -1028,11 +1024,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr ""
 
@@ -1067,166 +1063,166 @@
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, python-format
 msgid "Changeset %s not found"
 msgstr ""
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:735
-#: kallithea/templates/changelog/changelog.html:43
-msgid "revisions"
-msgstr ""
-
 #: kallithea/lib/helpers.py:759
+#: kallithea/templates/changelog/changelog.html:43
+msgid "revisions"
+msgstr ""
+
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:794
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
-msgid "[updated] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:800
-msgid "[downloaded] archive from repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:802
-msgid "[delete] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:810
-msgid "[created] user"
-msgstr ""
-
-#: kallithea/lib/helpers.py:812
-msgid "[updated] user"
-msgstr ""
-
 #: kallithea/lib/helpers.py:814
-msgid "[created] user group"
-msgstr ""
-
-#: kallithea/lib/helpers.py:816
-msgid "[updated] user group"
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
+msgid "[created] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:818
-msgid "[commented] on revision in repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:820
-msgid "[commented] on pull request for"
-msgstr ""
-
-#: kallithea/lib/helpers.py:822
-msgid "[closed] pull request for"
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
+msgid "[updated] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:824
-msgid "[pushed] into"
+msgid "[downloaded] archive from repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:826
-msgid "[committed via Kallithea] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:828
-msgid "[pulled from remote] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:830
-msgid "[pulled] from"
-msgstr ""
-
-#: kallithea/lib/helpers.py:832
-msgid "[started following] repository"
+msgid "[delete] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:834
+msgid "[created] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:836
+msgid "[updated] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:838
+msgid "[created] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:840
+msgid "[updated] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:842
+msgid "[commented] on revision in repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:844
+msgid "[commented] on pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:846
+msgid "[closed] pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:848
+msgid "[pushed] into"
+msgstr ""
+
+#: kallithea/lib/helpers.py:850
+msgid "[committed via Kallithea] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:852
+msgid "[pulled from remote] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:854
+msgid "[pulled] from"
+msgstr ""
+
+#: kallithea/lib/helpers.py:856
+msgid "[started following] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1263,69 +1259,69 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr ""
 
@@ -1338,129 +1334,129 @@
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr ""
 
@@ -1486,33 +1482,33 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:167
+#, python-format
+msgid ""
+"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
+"%(pr_source_branch)s by %(pr_owner_username)s"
+msgstr ""
+
 #: kallithea/model/notification.py:168
 #, python-format
 msgid ""
-"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
-"%(pr_source_branch)s by %(pr_owner_username)s"
-msgstr ""
-
-#: kallithea/model/notification.py:169
-#, python-format
-msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr ""
 
@@ -1586,213 +1582,213 @@
 msgid "SSH key with fingerprint %r found"
 msgstr ""
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
 "owners or remove those repositories: %s"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
 "owners or remove those repository groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
 "owners or remove those user groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr ""
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
 msgstr ""
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:131
-msgid "Invalid user group name"
-msgstr ""
-
 #: kallithea/model/validators.py:132
+msgid "Invalid user group name"
+msgstr ""
+
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:174
-msgid "Cannot assign this group as parent"
-msgstr ""
-
 #: kallithea/model/validators.py:175
+msgid "Cannot assign this group as parent"
+msgstr ""
+
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr ""
 
+#: kallithea/model/validators.py:310
+#, python-format
+msgid "Repository name %(repo)s is not allowed"
+msgstr ""
+
+#: kallithea/model/validators.py:312
+#, python-format
+msgid "Repository named %(repo)s already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:313
 #, python-format
-msgid "Repository name %(repo)s is not allowed"
+msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
 #: kallithea/model/validators.py:315
 #, python-format
-msgid "Repository named %(repo)s already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:316
-#, python-format
-msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
-msgstr ""
-
-#: kallithea/model/validators.py:318
-#, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
 msgstr ""
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1852,7 +1848,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1860,14 +1856,14 @@
 msgid "Description"
 msgstr ""
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr ""
 
@@ -1877,7 +1873,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1901,7 +1897,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr ""
@@ -2025,7 +2021,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr ""
@@ -2272,7 +2268,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr ""
 
@@ -2356,13 +2352,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2378,14 +2374,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2686,7 +2682,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr ""
@@ -2707,7 +2703,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr ""
 
@@ -2880,7 +2876,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3043,14 +3039,10 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
+msgid "Remote"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3088,7 +3080,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr ""
@@ -3119,43 +3111,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr ""
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3668,6 +3631,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr ""
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3689,7 +3661,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr ""
@@ -3763,7 +3735,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr ""
@@ -3863,10 +3835,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr ""
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr ""
 
@@ -4534,23 +4508,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4582,6 +4556,11 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+msgid "View Comment"
+msgstr ""
+
 #: kallithea/templates/email_templates/comment.html:27
 msgid "Status change:"
 msgstr ""
@@ -4590,32 +4569,40 @@
 msgid "The pull request has been closed."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+msgid "Password Reset Request"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4646,6 +4633,10 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+msgid "View Pull Request"
+msgstr ""
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, python-format
 msgid "Mention in Comment on Pull Request %s \"%s\""
@@ -4661,10 +4652,18 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr ""
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+msgid "New User Registration"
+msgstr ""
+
+#: kallithea/templates/email_templates/registration.html:23
 msgid "Full Name"
 msgstr ""
 
+#: kallithea/templates/email_templates/registration.html:42
+msgid "View User Profile"
+msgstr ""
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5275,35 +5274,35 @@
 msgid "Show more"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr ""
 
--- a/kallithea/i18n/cs/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/cs/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -5,7 +5,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2015-11-12 08:51+0000\n"
 "Last-Translator: Michal Čihař <michal@cihar.com>\n"
 "Language-Team: Czech <https://hosted.weblate.org/projects/kallithea/"
@@ -63,7 +63,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr "Úspěšně aktualizované heslo"
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr "Taková revize neexistuje"
@@ -253,7 +253,7 @@
 msgid "Tags"
 msgstr "Tagy"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr ""
@@ -306,25 +306,29 @@
 msgid "Journal"
 msgstr ""
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+msgid "Authentication failed."
+msgstr ""
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr "Špatná captcha"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr ""
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr ""
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr ""
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Úspěšně aktualizované heslo"
 
@@ -466,11 +470,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -546,8 +550,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
@@ -680,11 +684,11 @@
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr ""
 
@@ -706,293 +710,285 @@
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Chyba při vytváření repozitáře %s"
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, fuzzy, python-format
 #| msgid "Error occurred during gist creation"
 msgid "An error occurred during creation of field: %r"
 msgstr "Došlo k chybě při vytváření gist"
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr "Nic"
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, fuzzy, python-format
 #| msgid "Watched Repositories"
 msgid "Invalidated %s repositories"
 msgstr "Repozitáře"
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 msgid "Hook already exists"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr ""
@@ -1036,11 +1032,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr ""
 
@@ -1075,167 +1071,167 @@
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, fuzzy, python-format
 #| msgid "Set changeset status"
 msgid "Changeset %s not found"
 msgstr "Změny"
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:735
-#: kallithea/templates/changelog/changelog.html:43
-msgid "revisions"
-msgstr ""
-
 #: kallithea/lib/helpers.py:759
+#: kallithea/templates/changelog/changelog.html:43
+msgid "revisions"
+msgstr ""
+
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:794
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
-msgid "[updated] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:800
-msgid "[downloaded] archive from repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:802
-msgid "[delete] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:810
-msgid "[created] user"
-msgstr ""
-
-#: kallithea/lib/helpers.py:812
-msgid "[updated] user"
-msgstr ""
-
 #: kallithea/lib/helpers.py:814
-msgid "[created] user group"
-msgstr ""
-
-#: kallithea/lib/helpers.py:816
-msgid "[updated] user group"
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
+msgid "[created] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:818
-msgid "[commented] on revision in repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:820
-msgid "[commented] on pull request for"
-msgstr ""
-
-#: kallithea/lib/helpers.py:822
-msgid "[closed] pull request for"
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
+msgid "[updated] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:824
-msgid "[pushed] into"
+msgid "[downloaded] archive from repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:826
-msgid "[committed via Kallithea] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:828
-msgid "[pulled from remote] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:830
-msgid "[pulled] from"
-msgstr ""
-
-#: kallithea/lib/helpers.py:832
-msgid "[started following] repository"
+msgid "[delete] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:834
+msgid "[created] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:836
+msgid "[updated] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:838
+msgid "[created] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:840
+msgid "[updated] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:842
+msgid "[commented] on revision in repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:844
+msgid "[commented] on pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:846
+msgid "[closed] pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:848
+msgid "[pushed] into"
+msgstr ""
+
+#: kallithea/lib/helpers.py:850
+msgid "[committed via Kallithea] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:852
+msgid "[pulled from remote] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:854
+msgid "[pulled] from"
+msgstr ""
+
+#: kallithea/lib/helpers.py:856
+msgid "[started following] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1272,7 +1268,7 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
@@ -1280,7 +1276,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
@@ -1288,7 +1284,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
@@ -1296,7 +1292,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
@@ -1304,7 +1300,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
@@ -1312,7 +1308,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
@@ -1320,27 +1316,27 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr ""
 
@@ -1353,131 +1349,131 @@
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 #, fuzzy
 msgid "Only admins can fork repositories"
 msgstr "Chyba při vytváření repozitáře %s"
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 #, fuzzy
 msgid "Non-admins can fork repositories"
 msgstr "Chyba při vytváření repozitáře %s"
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr ""
 
@@ -1503,33 +1499,33 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:167
+#, python-format
+msgid ""
+"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
+"%(pr_source_branch)s by %(pr_owner_username)s"
+msgstr ""
+
 #: kallithea/model/notification.py:168
 #, python-format
 msgid ""
-"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
-"%(pr_source_branch)s by %(pr_owner_username)s"
-msgstr ""
-
-#: kallithea/model/notification.py:169
-#, python-format
-msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr ""
 
@@ -1604,214 +1600,214 @@
 msgid "SSH key with fingerprint %r found"
 msgstr "Změny"
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
 "owners or remove those repositories: %s"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
 "owners or remove those repository groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
 "owners or remove those user groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr ""
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
 msgstr ""
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:131
-msgid "Invalid user group name"
-msgstr ""
-
 #: kallithea/model/validators.py:132
+msgid "Invalid user group name"
+msgstr ""
+
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:174
-msgid "Cannot assign this group as parent"
-msgstr ""
-
 #: kallithea/model/validators.py:175
+msgid "Cannot assign this group as parent"
+msgstr ""
+
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr ""
 
+#: kallithea/model/validators.py:310
+#, python-format
+msgid "Repository name %(repo)s is not allowed"
+msgstr ""
+
+#: kallithea/model/validators.py:312
+#, python-format
+msgid "Repository named %(repo)s already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:313
 #, python-format
-msgid "Repository name %(repo)s is not allowed"
+msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
 #: kallithea/model/validators.py:315
 #, python-format
-msgid "Repository named %(repo)s already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:316
-#, python-format
-msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
-msgstr ""
-
-#: kallithea/model/validators.py:318
-#, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 #, fuzzy
 msgid "Invalid repository URL"
 msgstr "Prázdný repozitář"
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
 msgstr ""
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1871,7 +1867,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1879,14 +1875,14 @@
 msgid "Description"
 msgstr ""
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr ""
 
@@ -1896,7 +1892,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1920,7 +1916,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr ""
@@ -2044,7 +2040,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr ""
@@ -2293,7 +2289,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr ""
 
@@ -2377,13 +2373,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2399,14 +2395,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2712,7 +2708,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr ""
@@ -2733,7 +2729,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr ""
 
@@ -2906,7 +2902,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3074,14 +3070,10 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
+msgid "Remote"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3119,7 +3111,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr ""
@@ -3152,43 +3144,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr ""
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3716,6 +3679,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr ""
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3737,7 +3709,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr ""
@@ -3811,7 +3783,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr ""
@@ -3911,10 +3883,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr ""
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr ""
 
@@ -4600,23 +4574,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4653,6 +4627,11 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+msgid "View Comment"
+msgstr ""
+
 #: kallithea/templates/email_templates/comment.html:27
 #, fuzzy
 #| msgid "Status change"
@@ -4665,32 +4644,40 @@
 msgid "The pull request has been closed."
 msgstr "Repozitář byl uzamčen"
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+msgid "Password Reset Request"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4723,6 +4710,12 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+#| msgid "on pull request"
+msgid "View Pull Request"
+msgstr "Změna stavu-> %s"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, python-format
 msgid "Mention in Comment on Pull Request %s \"%s\""
@@ -4739,10 +4732,18 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr "Změna stavu-> %s"
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+msgid "New User Registration"
+msgstr ""
+
+#: kallithea/templates/email_templates/registration.html:23
 msgid "Full Name"
 msgstr ""
 
+#: kallithea/templates/email_templates/registration.html:42
+msgid "View User Profile"
+msgstr ""
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5356,35 +5357,35 @@
 msgid "Show more"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr ""
 
--- a/kallithea/i18n/da/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/da/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -4,7 +4,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3.99\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2019-03-14 01:03+0000\n"
 "Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n"
 "Language-Team: Danish <https://hosted.weblate.org/projects/kallithea/"
@@ -63,7 +63,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr "Pull-forespørgsel %s slettet successfuldt"
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr "En sådan revision findes ikke for dette repository"
@@ -258,7 +258,7 @@
 msgid "Tags"
 msgstr "Tags"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr "Der opstod en fejl under repository forking %s"
@@ -313,25 +313,29 @@
 msgid "Journal"
 msgstr "Journal"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+msgid "Authentication failed."
+msgstr ""
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr "Dårlig captcha"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "Du har succesfuldt registreret med %s"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr "En bekræftelseskode til ændring af adgangskode er sendt"
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Ugyldig token for ændring af adgangskode"
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Successfuld ændring af adgangskode"
 
@@ -481,11 +485,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr "Statistik er slået fra for dette repository"
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr "Auth-indstillinger opdateret successfuldt"
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr "Der opstod en fejl under opdatering af auth-indstillinger"
 
@@ -561,8 +565,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr "Der opstod en fejl under opdatering af gist %s"
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 "Du kan ikke redigere denne bruger, da den er afgørende for hele "
@@ -699,11 +703,11 @@
 msgid "Allowed with automatic account activation"
 msgstr "Tilladt med automatisk kontoaktivering"
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr "Manuel aktivering af ekstern konto"
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr "Automatisk aktivering af ekstern konto"
 
@@ -725,188 +729,180 @@
 msgid "Error occurred during update of permissions"
 msgstr "Der opstod en fejl under opdatering af tilladelser"
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr "Der opstod en fejl under oprettelse af repository-gruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr "Oprettet repository-gruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Opdateret repository-gruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr "Der opstod en fejl under opdatering af repository-gruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "Denne gruppe indeholder %s repositories og kan ikke slettes"
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr "Denne gruppe indeholder %s undergrupper og kan ikke slettes"
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Fjernet repository-gruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr "Der opstod en fejl under sletning af repository-gruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Kan ikke tilbagekalde tilladelse for én selv som admin"
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr "Repository-gruppe tilladelser opdateret"
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr "Der opstod en fejl under tilbagekaldelse af tilladelse"
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Fejl ved oprettelse af repository %s"
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Oprettet repository %s fra %s"
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Forked repository %s som %s"
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr "Oprettet repository %s"
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Repository %s opdateret"
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "Der opstod en fejl under opdatering af repository %s"
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr "Fraskilt %s forks"
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr "Slettet %s forks"
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Slettet repository %s"
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr "Kan ikke slette repository %s, da den stadig har forks"
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "Der opstod en fejl under sletning af %s"
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr "Repository tilladelser opdateret"
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr "Feltvaliderings fejl: %s"
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr "Der opstod en fejl under oprettelse af felt: %r"
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr "Der opstod en fejl under fjernelse af feltet"
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr "-- Ikke en fork --"
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr "Opdateret repository's synlighed i den offentlige journal"
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 "Der opstod en fejl under indstilling af dette repository, i den "
 "offentlige journal"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr "Intet"
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "Mærket repository %s som fork af %s"
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr "Der opstod en fejl under denne operation"
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr "Ugyldiggørelse af cache er succesfuld"
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr "Der opstod en fejl under cache ugyldiggørelse"
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 #, fuzzy
 msgid "Pulled from remote location"
 msgstr "Pulled fra remote placering"
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr "Der opstod en fejl under pull fra remote placering"
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr "Der opstod en fejl under sletning af repository statistik"
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr "Opdateret VCS-indstillinger"
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
@@ -914,109 +910,109 @@
 "Ude af stand til at aktivere hgsubversion understøttelse. \"hgsubversion"
 "\" biblioteket mangler"
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr "Der opstod en fejl ved opdatering af applikationsindstillinger"
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr "Repositories genscannet successfuldt. Tilføjet: %s. Fjernet: %s."
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr "Ugyldiggjort %s repositories"
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr "Opdateret applikationsindstillinger"
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr "Opdateret visualiseringsindstillinger"
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr "Der opstod en fejl under opdatering af visualiseringsindstillinger"
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr "Indtast email-adresse"
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr "Send email-opgave oprettet"
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "Ingen data er klar endnu"
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr "Tilføjet nyt hook"
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr "Opdateret hooks"
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr "Der opstod en fejl under oprettelse af et hook"
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr "Whoosh reindex-opgave skeduleret"
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr "Oprettet brugergruppe %s"
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr "Der opstod en fejl under oprettelse af brugergruppe %s"
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr "Opdateret brugergruppe %s"
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr "Der opstod en fejl under opdatering af brugergruppe %s"
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr "Brugergruppe slettet succesfuldt"
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr "Der opstod en fejl under sletning af brugergruppe"
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr "Brugergrupper-tilladelser opdateret"
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr "Tilladelser opdateret"
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr "Der opstod en fejl under gemning af tilladelser"
@@ -1060,11 +1056,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr "Fjernet IP-adresse fra bruger-whitelist"
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr "Du skal være registreret bruger for at kunne udføre denne handling"
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr "Du skal være logget ind for at se denne side"
 
@@ -1101,166 +1097,166 @@
 msgid "No changes detected"
 msgstr "Ingen ændringer fundet"
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "Slettet branch: %s"
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr "Oprettet tag: %s"
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, python-format
 msgid "Changeset %s not found"
 msgstr "Changeset %s ikke fundet"
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "Vis alle kombineret changesets %s->%s"
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr "Sammenlign visning"
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr "og"
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr "%s flere"
 
-#: kallithea/lib/helpers.py:735
+#: kallithea/lib/helpers.py:759
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "revisioner"
 
-#: kallithea/lib/helpers.py:759
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr "Fork-navn %s"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr "Pull-forespørgsel %s"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:814
 msgid "[deleted] repository"
 msgstr "[slettet] repository"
 
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
 msgid "[created] repository"
 msgstr "[oprettet] repository"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:818
 msgid "[created] repository as fork"
 msgstr "[oprettet] repository som fork"
 
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
 msgid "[forked] repository"
 msgstr "[forked] repository"
 
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
 msgid "[updated] repository"
 msgstr "[opdateret] repository"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:824
 msgid "[downloaded] archive from repository"
 msgstr "[hentet] arkiv fra repository"
 
-#: kallithea/lib/helpers.py:802
+#: kallithea/lib/helpers.py:826
 msgid "[delete] repository"
 msgstr "[slettet] repository"
 
-#: kallithea/lib/helpers.py:810
+#: kallithea/lib/helpers.py:834
 msgid "[created] user"
 msgstr "[oprettet] bruger"
 
-#: kallithea/lib/helpers.py:812
+#: kallithea/lib/helpers.py:836
 msgid "[updated] user"
 msgstr "[opdateret] bruger"
 
-#: kallithea/lib/helpers.py:814
+#: kallithea/lib/helpers.py:838
 msgid "[created] user group"
 msgstr "[oprettet] brugergruppe"
 
-#: kallithea/lib/helpers.py:816
+#: kallithea/lib/helpers.py:840
 msgid "[updated] user group"
 msgstr "[opdateret] brugergruppe"
 
-#: kallithea/lib/helpers.py:818
+#: kallithea/lib/helpers.py:842
 msgid "[commented] on revision in repository"
 msgstr "[kommenterede] på revision i repository"
 
-#: kallithea/lib/helpers.py:820
+#: kallithea/lib/helpers.py:844
 msgid "[commented] on pull request for"
 msgstr "[kommenterede] på pull-forespørgsel for"
 
-#: kallithea/lib/helpers.py:822
+#: kallithea/lib/helpers.py:846
 msgid "[closed] pull request for"
 msgstr "[lukket] pull-forespørgsel for"
 
-#: kallithea/lib/helpers.py:824
+#: kallithea/lib/helpers.py:848
 msgid "[pushed] into"
 msgstr "[pushed] ind i"
 
-#: kallithea/lib/helpers.py:826
+#: kallithea/lib/helpers.py:850
 msgid "[committed via Kallithea] into repository"
 msgstr "[committed via kallithea] ind i repository"
 
-#: kallithea/lib/helpers.py:828
+#: kallithea/lib/helpers.py:852
 msgid "[pulled from remote] into repository"
 msgstr "[pulled fra remote] ind i repository"
 
-#: kallithea/lib/helpers.py:830
+#: kallithea/lib/helpers.py:854
 msgid "[pulled] from"
 msgstr "[pulled] fra"
 
-#: kallithea/lib/helpers.py:832
+#: kallithea/lib/helpers.py:856
 msgid "[started following] repository"
 msgstr "[begyndt at følge] repository"
 
-#: kallithea/lib/helpers.py:834
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr "[stoppet at følge] repository"
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr " og %s flere"
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "Ingen filer"
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr "ny fil"
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr "mod"
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr "del"
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr "omdøb"
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1299,69 +1295,69 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr "i %s"
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr "%s siden"
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr "i %s og %s"
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s og %s siden"
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr "lige nu"
 
@@ -1374,132 +1370,132 @@
 msgid "[Mention]"
 msgstr "[Omtale]"
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr "top-niveau"
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr "Kallithea Administrator"
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr "Standard-bruger har ikke adgang til nye repositories"
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr "Standard-bruger har læse-adgang til nye repositories"
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr "Standard-bruger har skrive-adgang til nye repositories"
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr "Standard-bruger har admin-adgang til nye repositories"
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr "Standard-bruger har ikke adgang til nye repository-grupper"
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr "Standard-bruger har læse-adgang til nye repository-grupper"
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr "Standard-bruger har skrive-adgang til nye repository-grupper"
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr "Standard-bruger har admin-adgang til nye repository-grupper"
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr "Standard-bruger har ikke adgang til nye brugergrupper"
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr "Standard-bruger har læse-adgang til nye brugergrupper"
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr "Standard-bruger har skrive-adgang til nye brugergrupper"
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr "Standard-bruger har admin-adgang til nye brugergrupper"
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr "Kun administratorer kan oprette repository-grupper"
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr "Ikke-administratorer kan oprette repository-grupper"
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr "Kun administratorer kan oprette brugergrupper"
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr "Ikke-administratorer kan oprette brugergrupper"
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr "Kun administratorer kan oprette top-niveau repositories"
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr "Ikke-administratorer kan oprette top-niveau repositories"
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 "Repository oprettelse aktiveret med skriveadgang til en repository-gruppe"
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 "Repository oprettelse deaktiveret med skriveadgang til en repository-"
 "gruppe"
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr "Kun admins kan fork repositories"
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 msgid "Non-admins can fork repositories"
 msgstr "Ikke-administratorer kan forke repositories"
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr "Registrering deaktiveret"
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr "Brugerregistrering med manuel kontoaktivering"
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr "Brugerregistrering med automatisk kontoaktivering"
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr "Ikke gennemgået"
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr "Under gennemgang"
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 msgid "Not approved"
 msgstr "Ikke godkendt"
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr "Godkendt"
 
@@ -1525,7 +1521,7 @@
 msgid "Name must not contain only digits"
 msgstr "Navn må ikke kun indeholde cifre"
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
@@ -1534,12 +1530,12 @@
 "[Kommentar] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" på "
 "%(branch)s"
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr "Ny bruger %(new_username)s registreret"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid ""
 "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
@@ -1548,7 +1544,7 @@
 "[Gennemgang] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" fra "
 "%(pr_source_branch)s af %(pr_owner_username)s"
 
-#: kallithea/model/notification.py:169
+#: kallithea/model/notification.py:168
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
@@ -1557,7 +1553,7 @@
 "[Kommentar] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" fra "
 "%(pr_source_branch)s af %(pr_owner_username)s"
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr "Lukning"
 
@@ -1634,213 +1630,213 @@
 msgid "SSH key with fingerprint %r found"
 msgstr "Changeset %s ikke fundet"
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
 "owners or remove those repositories: %s"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
 "owners or remove those repository groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
 "owners or remove those user groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr ""
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
 msgstr ""
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:131
-msgid "Invalid user group name"
-msgstr ""
-
 #: kallithea/model/validators.py:132
+msgid "Invalid user group name"
+msgstr ""
+
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:174
-msgid "Cannot assign this group as parent"
-msgstr ""
-
 #: kallithea/model/validators.py:175
+msgid "Cannot assign this group as parent"
+msgstr ""
+
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr ""
 
+#: kallithea/model/validators.py:310
+#, python-format
+msgid "Repository name %(repo)s is not allowed"
+msgstr ""
+
+#: kallithea/model/validators.py:312
+#, python-format
+msgid "Repository named %(repo)s already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:313
 #, python-format
-msgid "Repository name %(repo)s is not allowed"
+msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
 #: kallithea/model/validators.py:315
 #, python-format
-msgid "Repository named %(repo)s already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:316
-#, python-format
-msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
-msgstr ""
-
-#: kallithea/model/validators.py:318
-#, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
 msgstr ""
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1900,7 +1896,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1908,14 +1904,14 @@
 msgid "Description"
 msgstr ""
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr ""
 
@@ -1925,7 +1921,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1949,7 +1945,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr ""
@@ -2073,7 +2069,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr ""
@@ -2320,7 +2316,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr ""
 
@@ -2404,13 +2400,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2426,14 +2422,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2734,7 +2730,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr ""
@@ -2755,7 +2751,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr ""
 
@@ -2928,7 +2924,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3091,14 +3087,10 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
+msgid "Remote"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3136,7 +3128,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr ""
@@ -3167,43 +3159,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr ""
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3716,6 +3679,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr ""
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3737,7 +3709,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr ""
@@ -3811,7 +3783,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr ""
@@ -3911,10 +3883,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr ""
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr ""
 
@@ -4585,23 +4559,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4633,6 +4607,13 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "%s committed on %s"
+msgid "View Comment"
+msgstr "%s committed den %s"
+
 #: kallithea/templates/email_templates/comment.html:27
 msgid "Status change:"
 msgstr ""
@@ -4641,32 +4622,40 @@
 msgid "The pull request has been closed."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+msgid "Password Reset Request"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4699,6 +4688,12 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+#| msgid "Pull request %s"
+msgid "View Pull Request"
+msgstr "Pull-forespørgsel %s"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, python-format
 msgid "Mention in Comment on Pull Request %s \"%s\""
@@ -4714,10 +4709,18 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr ""
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+msgid "New User Registration"
+msgstr ""
+
+#: kallithea/templates/email_templates/registration.html:23
 msgid "Full Name"
 msgstr ""
 
+#: kallithea/templates/email_templates/registration.html:42
+msgid "View User Profile"
+msgstr ""
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5328,35 +5331,35 @@
 msgid "Show more"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr ""
 
@@ -5457,6 +5460,12 @@
 msgid "Download %s as %s"
 msgstr ""
 
+#~ msgid "Cache invalidation successful"
+#~ msgstr "Ugyldiggørelse af cache er succesfuld"
+
+#~ msgid "An error occurred during cache invalidation"
+#~ msgstr "Der opstod en fejl under cache ugyldiggørelse"
+
 #~ msgid "This repository has been locked by %s on %s"
 #~ msgstr "Dette repository er låst af %s den %s"
 
--- a/kallithea/i18n/de/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/de/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -4,7 +4,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2019-05-29 22:52+0000\n"
 "Last-Translator: ssantos <ssantos@web.de>\n"
 "Language-Team: German <https://hosted.weblate.org/projects/kallithea/"
@@ -63,7 +63,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr "Pull-Request %s erfolgreich gelöscht"
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr "Die angegebene Version existiert nicht in diesem Repository"
@@ -266,7 +266,7 @@
 msgid "Tags"
 msgstr "Tags"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr "Während des Forkens des Repositorys trat ein Fehler auf: %s"
@@ -319,25 +319,31 @@
 msgid "Journal"
 msgstr "Logbuch"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+#, fuzzy
+#| msgid "Authentication"
+msgid "Authentication failed."
+msgstr "Authentifizierung"
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr "Falsches Captcha"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "Sie haben sich erfolgreich bei %s registriert"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr "Ihr Link um das Passwort zurückzusetzen wurde versendet"
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Ungültiges Token zum Zurücksetzen des Passworts."
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Erfolgreich Kennwort geändert"
 
@@ -493,11 +499,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr "Statistiken sind deaktiviert für dieses Repository"
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr "Anmeldeeinstellungen erfolgreich geändert"
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr "Fehler bei der Änderung der Anmeldeeinstellungen aufgetreten"
 
@@ -573,8 +579,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr "Fehler beim Aktualisieren der Kerndaten %s"
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 "Sie können diesen Benutzer nicht editieren, da er von entscheidender "
@@ -711,11 +717,11 @@
 msgid "Allowed with automatic account activation"
 msgstr "Erlaubt mit automatischer Kontoaktivierung"
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr "Manuelle Aktivierung externen Kontos"
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr "Automatische Aktivierung externen Kontos"
 
@@ -737,190 +743,182 @@
 msgid "Error occurred during update of permissions"
 msgstr "Fehler bei der Änderung der globalen Berechtigungen"
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr "Fehler bei der Erstellung der Repositoriumsgruppe %s"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr "Repositoriumsgruppe %s erstellt"
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Repositoriumsgruppe %s aktualisiert"
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr "Fehler bei der Aktualisierung der Repositoriumsgruppe %s"
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "Die Gruppe enthält %s Repositorys und kann nicht gelöscht werden"
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr "Diese Gruppe enthält %s Untergruppen und kann nicht gelöscht werden"
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Repositoriumsgruppe %s entfernt"
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr "Fehler beim Löschen der Repositoriumsgruppe %s"
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Als Administrator kann man sich keine Berechtigungen entziehen"
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr "Berechtigungen der Repositoriumsgruppe aktualisiert"
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr "Fehler beim Entzug der Berechtigungen"
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Fehler beim Erstellen des Repositoriums %s"
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Repositorium %s von %s erstellt"
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Aufgespaltenes Repositorium %s zu %s"
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr "Repositorium erzeugt %s"
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Repository %s wurde erfolgreich aktualisiert"
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "Fehler bei der Aktualisierung des Repositoriums %s"
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr "%s Spaltung abgetrennt"
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr "%s Spaltung gelöscht"
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Repositorium %s gelöscht"
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr "%s konnte nicht gelöscht werden, da es noch Forks besitzt"
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "Beim Löschen von %s trat ein Fehler auf"
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr "Repositoriumsberechtigungen aktualisiert"
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr "Feldvalidierung fehlgeschlagen: %s"
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, fuzzy, python-format
 #| msgid "An error occurred during creation of field"
 msgid "An error occurred during creation of field: %r"
 msgstr "Fehler während der Erzeugung des Feldes"
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr "Fehler beim Entfernen des Feldes"
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr "-- Keine Abspaltung --"
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr "Sichtbarkeit des Repositorys im Öffentlichen Logbuch aktualisiert"
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 "Es trat ein Fehler während der Aktualisierung der Sicherbarkeit dieses "
 "Repositorys im Öffentlichen Logbuch auf"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr "Nichts"
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "Markiere Repository %s als Abzweig von Repository %s"
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr "Während dieser operation trat ein Fehler auf"
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr "Cache Entfernung war erfolgreich"
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr "Währen der Cache Invalidierung trat ein Fehler auf"
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr "Von entferntem Ort übertragen"
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr ""
 "Es trat ein Fehler auf während das Repository von einem Entfernten "
 "Speicherort übertragen wurde"
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr "Während des löschens der Repository Statistiken trat ein Fehler auf"
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr "VCS-Einstellungen aktualisiert"
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
@@ -928,120 +926,120 @@
 "hgsubversion-Unterstützung konnte nicht aktiviert werden. Die "
 "\"hgsubversion\"-Bibliothek fehlt"
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr ""
 "Ein Fehler ist während der Aktualisierung der Applikationseinstellungen "
 "aufgetreten"
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 "Die Repositories wurden erfolgreich überprüft. Hinzugefügt: %s. Entfernt: "
 "%s."
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, fuzzy, python-format
 #| msgid "Invalidate Repository Cache"
 msgid "Invalidated %s repositories"
 msgstr "Ungültiger Repositorycache"
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr "Anwendungseinstellungen aktualisiert"
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr "Visualisierungseinstellungen aktualisiert"
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 "Es ist ein Fehler während der Aktualisierung der Layouteinstellung "
 "aufgetreten"
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr "Bitte gebe eine E-Mailadresse an"
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr "Task zum Versenden von E-Mails erstellt"
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "Es stehen noch keine Daten zur Verfügung"
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 "Die eingebauten Hooks sind schreibgeschützt. Bitte verwenden Sie einen "
 "anderen Hook-Namen."
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr "Neuer Hook hinzugefügt"
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr "Die Hooks wurden aktutalisiert"
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr "Während der Erzeugung des Hooks ist ein Fehler aufgetreten"
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr "Whoosh Reindizierungs Aufgabe wurde zur Ausführung geplant"
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr "Nutzergruppe %s erstellt"
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 "Es ist ein Fehler während der Erstellung der Nutzergruppe %s aufgetreten"
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr "Aktualisierte Nutzergruppe %s"
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 "Während des Updates der Benutzergruppe %s ist ein Fehler aufgetreten"
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr "Die Nutzergruppe wurde erfolgreich entfernt"
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr "Während des Löschens der Benutzergruppe ist ein Fehler aufgetreten"
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr "Zielgruppe kann nicht die gleiche Gruppe sein"
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr "Berechtigungen der Benutzergruppe wurden aktualisiert"
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr "Berechtigungen wurden aktualisiert"
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr ""
@@ -1086,12 +1084,12 @@
 msgid "Removed IP address from user whitelist"
 msgstr "IP-Adresse wurde von der Nutzerwhitelist entfernt"
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 "Sie müssen ein Registrierter Nutzer sein um diese Aktion durchzuführen"
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr "Sie müssen sich anmelden um diese Seite aufzurufen"
 
@@ -1132,167 +1130,167 @@
 msgid "No changes detected"
 msgstr "Keine Änderungen erkannt"
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "Branch %s gelöscht"
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr "Tag %s erstellt"
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, fuzzy, python-format
 #| msgid "Changeset not found"
 msgid "Changeset %s not found"
 msgstr "Änderungssatz nicht gefunden"
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "Zeige alle Kombinierten Änderungensätze %s->%s"
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr "Vergleichsansicht"
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr "und"
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr "%s mehr"
 
-#: kallithea/lib/helpers.py:735
+#: kallithea/lib/helpers.py:759
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "revisionen"
 
-#: kallithea/lib/helpers.py:759
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr "Fork Name %s"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr "Pull Request %s"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:814
 msgid "[deleted] repository"
 msgstr "[gelöscht] Repository"
 
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
 msgid "[created] repository"
 msgstr "[erstellt] Repository"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:818
 msgid "[created] repository as fork"
 msgstr "[erstellt] Repository als Fork"
 
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
 msgid "[forked] repository"
 msgstr "[forked] Repository"
 
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
 msgid "[updated] repository"
 msgstr "[aktualisiert] Repository"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:824
 msgid "[downloaded] archive from repository"
 msgstr "Archiv von Repository [heruntergeladen]"
 
-#: kallithea/lib/helpers.py:802
+#: kallithea/lib/helpers.py:826
 msgid "[delete] repository"
 msgstr "Repository [gelöscht]"
 
-#: kallithea/lib/helpers.py:810
+#: kallithea/lib/helpers.py:834
 msgid "[created] user"
 msgstr "Benutzer [erstellt]"
 
-#: kallithea/lib/helpers.py:812
+#: kallithea/lib/helpers.py:836
 msgid "[updated] user"
 msgstr "Benutzer [akutalisiert]"
 
-#: kallithea/lib/helpers.py:814
+#: kallithea/lib/helpers.py:838
 msgid "[created] user group"
 msgstr "Benutzergruppe [erstellt]"
 
-#: kallithea/lib/helpers.py:816
+#: kallithea/lib/helpers.py:840
 msgid "[updated] user group"
 msgstr "Benutzergruppe [aktualisiert]"
 
-#: kallithea/lib/helpers.py:818
+#: kallithea/lib/helpers.py:842
 msgid "[commented] on revision in repository"
 msgstr "Revision [kommentiert] in Repository"
 
-#: kallithea/lib/helpers.py:820
+#: kallithea/lib/helpers.py:844
 msgid "[commented] on pull request for"
 msgstr "Pull Request [kommentiert] für"
 
-#: kallithea/lib/helpers.py:822
+#: kallithea/lib/helpers.py:846
 msgid "[closed] pull request for"
 msgstr "Pull Request [geschlossen] für"
 
-#: kallithea/lib/helpers.py:824
+#: kallithea/lib/helpers.py:848
 msgid "[pushed] into"
 msgstr "[Pushed] in"
 
-#: kallithea/lib/helpers.py:826
+#: kallithea/lib/helpers.py:850
 msgid "[committed via Kallithea] into repository"
 msgstr "[via Kallithea] in Repository [committed]"
 
-#: kallithea/lib/helpers.py:828
+#: kallithea/lib/helpers.py:852
 msgid "[pulled from remote] into repository"
 msgstr "[Pulled von Remote] in Repository"
 
-#: kallithea/lib/helpers.py:830
+#: kallithea/lib/helpers.py:854
 msgid "[pulled] from"
 msgstr "[Pulled] von"
 
-#: kallithea/lib/helpers.py:832
+#: kallithea/lib/helpers.py:856
 msgid "[started following] repository"
 msgstr "[Following gestartet] für Repository"
 
-#: kallithea/lib/helpers.py:834
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr "[Following gestoppt] für Repository"
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr " und %s weitere"
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "Keine Dateien"
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr "neue Datei"
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr "mod"
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr "entf"
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr "umbenennen"
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1332,69 +1330,69 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] "%d Jahr"
 msgstr[1] "%d Jahre"
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] "%d Monat"
 msgstr[1] "%d Monate"
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] "%d Tag"
 msgstr[1] "%d Tage"
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] "%d Stunde"
 msgstr[1] "%d Stunden"
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] "%d Minute"
 msgstr[1] "%d Minuten"
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] "%d Sekunde"
 msgstr[1] "%d Sekunden"
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr "in %s"
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr "vor %s"
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr "in %s und %s"
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s und %s her"
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr "jetzt gerade"
 
@@ -1407,136 +1405,136 @@
 msgid "[Mention]"
 msgstr "[Mention]"
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr "höchste Ebene"
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr "Kallithea Administrator"
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr "Der Standard-Benutzer hat keinen Zugriff auf neue Repositories"
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr "Der Standard-Benutzer hat Leserechte auf neuen Repositories"
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr "Der Standard-Benutzer hat Schreibrechte auf neuen Repositories"
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr "Der Standard-Benutzer hat Admin-Rechte auf neuen Repositories"
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 "Der Standard-Benutzer hat keinen Zugriff auf neue Repository-Gruppen"
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr "Der Standard-Benutzer hat Leserechte auf neuen Repository-Gruppen"
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr "Der Standard-Benutzer Schreibrechte auf neuen Repository-Gruppen"
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr "Der Standard-Benutzer Admin-Rechte auf neuen Repository-Gruppen"
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr "Der Standard-Benutzer hat keinen Zugriff auf neue Benutzer-Gruppen"
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr "Der Standard-Benutzer hat Leserechte auf neuen Benutzer-Gruppen"
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr "Der Standard-Benutzer hat Schreibrechte auf neuen Benutzer-Gruppen"
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr "Der Standard-Benutzer hat Admin-Rechte auf neuen Benutzer-Gruppen"
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr "Nur Admins können Repository-Gruppen erstellen"
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr "Nicht-Admins können Repository-Gruppen erstellen"
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr "Nur Admins können Benutzer-Gruppen erstellen"
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr "Nicht-Admins können Benutzer-Gruppen erstellen"
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr "Nur Admins können Repositories auf oberster Ebene erstellen"
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr "Nicht-Admins können Repositories oberster Ebene erstellen"
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 "Erstellung von Repositories mit Schreibzugriff für Repositorygruppe "
 "aktiviert"
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 "Erstellung von Repositories mit Schreibzugriff für Repositorygruppe "
 "deaktiviert"
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr "Nur Admins können Repositories forken"
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 msgid "Non-admins can fork repositories"
 msgstr "Nicht-Admins können Repositorys forken"
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr "Registrierung deaktiviert"
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr "Benutzerregistrierung mit manueller Kontoaktivierung"
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr "Benutzerregistrierung mit automatischer Kontoaktivierung"
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr "Nicht Begutachtet"
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr "In Begutachtung"
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 #, fuzzy
 #| msgid "Approved"
 msgid "Not approved"
 msgstr "Akzeptiert"
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr "Akzeptiert"
 
@@ -1562,7 +1560,7 @@
 msgid "Name must not contain only digits"
 msgstr "Name darf nicht nur Ziffern enthalten"
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, fuzzy, python-format
 #| msgid "[Comment] %(repo_name)s changeset %(short_id)s on %(branch)s"
 msgid ""
@@ -1572,26 +1570,26 @@
 "Kommentar für %(repo_name)s Changeset %(short_id)s in %(branch)s erstellt "
 "von %(comment_username)s"
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr "Neuer Benutzer %(new_username)s registriert"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid ""
 "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:169
+#: kallithea/model/notification.py:168
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr "Schließen"
 
@@ -1679,11 +1677,11 @@
 msgid "SSH key with fingerprint %r found"
 msgstr "Änderungssatz nicht gefunden"
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr "Neue Benutzerregistrierung"
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 #, fuzzy
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
@@ -1691,7 +1689,7 @@
 "Sie können diesen Benutzer nicht löschen, da er von entscheidender "
 "Bedeutung für die gesamte Applikation ist"
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
@@ -1701,7 +1699,7 @@
 "nicht entfernt werden. Entweder muss der Besitzer geändert oder das "
 "Repository entfernt werden: %s"
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
@@ -1711,7 +1709,7 @@
 "kann daher nicht entfernt werden. Entweder muss der Besitzer geändert "
 "oder die Repositorygruppen müssen entfernt werden: %s"
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
@@ -1721,16 +1719,16 @@
 "nicht entfernt werden. Entweder muss der Besitzer geändert oder die "
 "Benutzergruppen müssen gelöscht werden: %s"
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr "Link zum Zurücksetzen des Passworts"
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 #, fuzzy
 msgid "Password reset notification"
 msgstr "Link zum Zurücksetzen des Passworts"
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
@@ -1739,21 +1737,21 @@
 "Das Passwort für dein Konto %s wurde mit dem Formular zum Zurücksetzen "
 "des Passworts geändert."
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr "Eine leere Liste ist kein gültiger Wert"
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "Benutezrname \"%(username)s\" existiert bereits"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, fuzzy, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "Benutzername \"%(username)s\" ist ungültig"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 #, fuzzy
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
@@ -1763,25 +1761,25 @@
 "oder Bindestriche enthalten und muss mit einem alphanumerischen Zeichen "
 "oder einem Unterstrich beginnen"
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr "Die Eingabe ist nicht gültig"
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr "Benutzername \"%(username)s\" ist ungültig"
 
-#: kallithea/model/validators.py:131
+#: kallithea/model/validators.py:132
 msgid "Invalid user group name"
 msgstr "Ungültiger Benutzergruppenname"
 
-#: kallithea/model/validators.py:132
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr "Benutzergruppe \"%(usergroup)s\" existiert bereits"
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
@@ -1790,64 +1788,64 @@
 "Unterstriche, Punkte oder Bindestriche enthalten und muss mit einem "
 "alphanumerischen Zeichen beginnen"
 
-#: kallithea/model/validators.py:174
+#: kallithea/model/validators.py:175
 msgid "Cannot assign this group as parent"
 msgstr "Kann diese Gruppe nicht als vorgesetzt setzen"
 
-#: kallithea/model/validators.py:175
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr "Gruppe \"%(group_name)s\" existiert bereits"
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr "Es gibt bereits ein Repository mit \"%(group_name)s\""
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr "Üngültige(nicht ASCII) Zeichen im Passwort"
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr "Ungültiges altes Passwort"
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr "Die Passwörter stimmen nicht überein"
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 #, fuzzy
 msgid "Invalid username or password"
 msgstr "Ungültiges Passwort"
 
-#: kallithea/model/validators.py:313
+#: kallithea/model/validators.py:310
 #, fuzzy, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr "Repository Name \"%(repo)s\" ist nicht erlaubt"
 
-#: kallithea/model/validators.py:315
+#: kallithea/model/validators.py:312
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr "Es gibt bereits ein Repository mit \"%(repo)s\""
 
-#: kallithea/model/validators.py:316
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 "Es gibt bereits ein Repository mit \"%(repo)s\" in der Gruppe \"%(group)s"
 "\""
 
-#: kallithea/model/validators.py:318
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr "Eine Repositorygruppe mit dem Namen \"%(repo)s\" existiert bereits"
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr "Ungültige Repository-URL"
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
@@ -1855,44 +1853,44 @@
 "Ungültige Repository-URL. Es muss eine gültige http, https, ssh, svn+http "
 "oder svn+https URL sein"
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr "Forke um den selben typ wie der Vorgesetze zu haben"
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 "Du hast nicht die erforderlichen Berechtigungen, um in dieser Gruppe ein "
 "Repository zu erzeugen"
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr "keine Berechtigung, um ein Repository auf höchster Ebene anzulegen"
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 "Sie haben keine Berechtigung, um an diesem Ort ein Repository anzulegen"
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr "Dieser Benutzername oder Benutzergruppenname ist nicht gültig"
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr "Dies ist ein Ungültiger Pfad"
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 #, fuzzy
 msgid "This email address is already in use"
 msgstr "Diese E-Mailaddresse ist bereits in Benutzung"
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, fuzzy, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "E-MailAddresse \"%(email)s\" existiert nicht."
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
@@ -1900,11 +1898,11 @@
 "Das LDAP-Login-Attribut des CN muss angeben werden - Es ist der Name des "
 "Attributes äquivalent zu \"Benutzername\""
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr "Bitte eine gültige IPv4- oder IPv6-Adresse angeben"
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
@@ -1912,17 +1910,17 @@
 "Die Größe (in Bits) des Netzwerks muss im Bereich 0-32 liegen (nicht "
 "%(bits)r)"
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 "Der Name eines Schlüssels darf nur aus Buchstaben, Ziffern, Unterstrich "
 "und Bindestrich bestehen"
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr "Dateiname darf kein Unterverzeichnis enthalten"
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1984,7 +1982,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1992,14 +1990,14 @@
 msgid "Description"
 msgstr "Beschreibung"
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr "Letzte Änderung"
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr "Tipp"
 
@@ -2009,7 +2007,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -2033,7 +2031,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr "Benutzername"
@@ -2165,7 +2163,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr "E-Mail"
@@ -2423,7 +2421,7 @@
 msgstr "Neuen Gist erstellen"
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr "Erstellt"
 
@@ -2509,13 +2507,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2531,14 +2529,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2869,7 +2867,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr "Repository Gruppe"
@@ -2893,7 +2891,7 @@
 msgstr "Berechtigungen des Vorgabe-Benutzers für neue Repository-Gruppen."
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr "Benutzergruppe"
 
@@ -3081,7 +3079,7 @@
 msgstr "Erstellt am"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3263,14 +3261,10 @@
 msgstr "Extra-Feld"
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
-msgstr "Zwischenspeicher"
+msgid "Remote"
+msgstr "Entfernt"
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr "Entfernt"
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3311,7 +3305,7 @@
 "öffentlichen Logbuch für jeden einsehbar."
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "Löschen des Repositorys bestätigen: %s"
@@ -3345,45 +3339,14 @@
 "Administrierender es verfallen lässt. Der Administrierende kann es sowohl "
 "permanent löschen oder wiederherstellen."
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr "Ungültiger Repositorycache"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-"Manuell den Zwischenspeicher für dieses Repository verfallen lassen. Beim "
-"ersten Zugriff wird der Zwischenspeicher erneut aufgefüllt."
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr "Liste der zwischengespeicherten Werte"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr "Präfix"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr "Bezeichnung"
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr "Schlüssel"
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr "Aktiv"
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr "Bezeichnung"
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3998,6 +3961,15 @@
 msgid "Short, optional description for this user group."
 msgstr "Kurze, optionale Beschreibung für diese Benutzergruppe."
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr "Aktiv"
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -4020,7 +3992,7 @@
 msgstr "Mitglieder"
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr "Bestätigen, um diese Benutzergruppe zu löschen: %s"
@@ -4094,7 +4066,7 @@
 msgstr "Mitglieder der Benutzergruppe"
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr ""
@@ -4194,10 +4166,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr ""
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr ""
 
@@ -4893,23 +4867,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr "Abonniere den %s RSS Feed"
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr "Abonniere den %s ATOM Feed"
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4947,6 +4921,13 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "Comment"
+msgid "View Comment"
+msgstr "Kommentar"
+
 #: kallithea/templates/email_templates/comment.html:27
 #, fuzzy
 #| msgid "Status change"
@@ -4961,35 +4942,45 @@
 "Dieser Pull Request wurde geschlossen und kann daher nicht aktualisiert "
 "werden."
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+#, fuzzy
+#| msgid "Password Reset"
+msgid "Password Reset Request"
+msgstr "Passwort zurücksetzen"
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr "Hallo %s"
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 #, fuzzy
 msgid "We have received a request to reset the password for your account."
 msgstr ""
 "Wir haben eine Anforderung erhalten, für deinen Account ein neues "
 "Passwort zu erstellen."
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -5023,6 +5014,12 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+#| msgid "New Pull Request"
+msgid "View Pull Request"
+msgstr "Neuer Pull Request"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, fuzzy, python-format
 #| msgid "%(user)s commented on pull request %(age)s"
@@ -5041,12 +5038,22 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr "Pull Request [kommentiert] für"
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+#, fuzzy
+#| msgid "New user registration"
+msgid "New User Registration"
+msgstr "Neue Benutzerregistrierung"
+
+#: kallithea/templates/email_templates/registration.html:23
 #, fuzzy
 #| msgid "Group name"
 msgid "Full Name"
 msgstr "Gruppen name"
 
+#: kallithea/templates/email_templates/registration.html:42
+msgid "View User Profile"
+msgstr ""
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5667,35 +5674,35 @@
 msgid "Show more"
 msgstr "Mehr anzeigen"
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr "Commits"
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr "Dateien hinzugefügt"
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr "Dateien geändert"
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr "Dateien entfernt"
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr "Commit"
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr "Datei hinzugefügt"
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr "Datei geändert"
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr "Datei entfernt"
 
@@ -5799,6 +5806,31 @@
 msgid "Download %s as %s"
 msgstr "%s als %s herunterladen"
 
+#~ msgid "Cache invalidation successful"
+#~ msgstr "Cache Entfernung war erfolgreich"
+
+#~ msgid "An error occurred during cache invalidation"
+#~ msgstr "Währen der Cache Invalidierung trat ein Fehler auf"
+
+#~ msgid "Caches"
+#~ msgstr "Zwischenspeicher"
+
+#~ msgid "Invalidate Repository Cache"
+#~ msgstr "Ungültiger Repositorycache"
+
+#~ msgid ""
+#~ "Manually invalidate cache for this repository. On first access, the "
+#~ "repository will be cached again."
+#~ msgstr ""
+#~ "Manuell den Zwischenspeicher für dieses Repository verfallen lassen. "
+#~ "Beim ersten Zugriff wird der Zwischenspeicher erneut aufgefüllt."
+
+#~ msgid "List of Cached Values"
+#~ msgstr "Liste der zwischengespeicherten Werte"
+
+#~ msgid "Prefix"
+#~ msgstr "Präfix"
+
 #~ msgid "This repository has been locked by %s on %s"
 #~ msgstr "Dieses Repository ist von %s am %s gesperrt worden"
 
--- a/kallithea/i18n/el/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/el/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -4,7 +4,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2019-06-26 19:00+0000\n"
 "Last-Translator: THANOS SIOURDAKIS <siourdakisthanos@gmail.com>\n"
 "Language-Team: Greek <https://hosted.weblate.org/projects/kallithea/"
@@ -63,7 +63,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr "Επιτυχής διαγραφή αιτήματος έλξης %s"
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr "Δεν υπάρχει τέτοια αναθεώρηση για αυτό το αποθετήριο"
@@ -269,7 +269,7 @@
 msgid "Tags"
 msgstr "Ετικέτες"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr "Συνέβει ένα λάθος κατά την διακλάδωση του αποθετηρίου %s"
@@ -322,25 +322,29 @@
 msgid "Journal"
 msgstr "Ημερολόγιο"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+msgid "Authentication failed."
+msgstr ""
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr "Λάθος captcha"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "Εγγραφήκατε επιτυχώς στο %s"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr "Στάλθηκε ένας κωδικός επιβεβαίωσης επαναφοράς του συνθηματικού"
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Άκυρο τεκμήριο (token) επαναφοράς του συνθηματικού"
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Το συνθηματικό ενημερώθηκε επιτυχώς"
 
@@ -491,11 +495,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr "Τα στατιστικά είναι απενεργοποιημένα για αυτό το αποθετήριο"
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr "Οι ρυθμίσεις εξουσιοδότησης ενημερώθηκαν επιτυχώς"
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr "παρουσιάστηκε βλάβη κατά την ενημέρωση των ρυθμίσεων εξουσιοδότησης"
 
@@ -571,8 +575,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr "Σφάλμα συνέβη κατά την ενημέρωση του gist %s"
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 "Δεν μπορείτε να επεξεργαστείτε αυτόν το χρήστη καθώς είναι κρίσιμος για "
@@ -709,11 +713,11 @@
 msgid "Allowed with automatic account activation"
 msgstr "Επιτρέπεται με αυτόματη ενεργοποίηση του λογαριασμού"
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr "Χειροποίητη ενεργοποίηση εξωτερικού λογαριασμού"
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr "Αυτόματη ενεργοποίηση εξωτερικού λογαριασμού"
 
@@ -735,297 +739,289 @@
 msgid "Error occurred during update of permissions"
 msgstr "Συνέβει μια βλάβη κατά την ενημέρωση των δικαιωμάτων"
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr "Συνέβει μια βλάβη κατά την δημιουργία της ομάδας αποθετηρίου %s"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr "Δημιουργήθηκε η ομάδα αποθετηρίου %s"
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Ενημερώθηκε η ομάδα αποθετηρίου %s"
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr "Συνέβει μια βλάβη κατά την ενημέρωση της ομάδας αποθετηρίου %s"
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "Αυτή η ομάδα περιέχει %s αποθετήρια και δε μπορεί να διαγραφεί"
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr "Αυτή η ομάδα περιέχει %s υποομάδες και δε μπορεί να διαγραφεί"
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Αφαιρέθηκε η ομάδα αποθετηρίου %s"
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr "Συνέβει μια βλάβη κατά την διαγραφή της ομάδας αποθετηρίου %s"
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Δεν μπορείτε να ανακαλέσετε την άδεια σας ως διαχειριστής"
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr "Τα δικαιώματα της ομάδας αποθετηρίου ενημερώθηκαν"
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr "Συνέβει μια βλάβη κατά την ανάκληση της άδειας"
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Βλάβη κατά τη δημιουργία του αποθετηρίου %s"
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Δημιουργήθηκε το αποθετήριο %s από το %s"
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Κλωνοποιήθηκε το αποθετηρίο %s ως %s"
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr "Δημιουργήθηκε το αποθετήριο %s"
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Το αποθετήριο %s ενημερώθηκε επιτυχώς"
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "Συνέβει μια βλάβη κατά την ενημέρωση του αποθετηρίου %s"
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr "Αποσυνδέθηκαν %s κλώνοι"
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr "Διαγράφηκαν %s κλώνοι"
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Διαγράφηκε το αποθετήριο %s"
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr "Δε μπορεί να διαγραφεί το αποθετήριο %s που ακόμα έχει κλώνους"
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "Συνέβει μια βλάβη κατά την διαγραφή του %s"
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr "Τα δικαιώματα του αποθετηρίου ενημερώθηκαν"
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, fuzzy, python-format
 #| msgid "An error occurred during creation of field"
 msgid "An error occurred during creation of field: %r"
 msgstr "Συνέβει μια βλάβη κατά τη δημιουργία του πεδίου"
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr "Συνέβει μια βλάβη κατά την απομάκρυνση του πεδίου"
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr "-- Όχι κλώνος --"
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr "Ενημερώθηκε η ορατότητα του αποθετηρίου στο δημόσιο ημερολόγιο"
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 "Συνέβει μια βλάβη κατά την τοποθέτηση αυτού το αποθετηρίου στο δημόσιο "
 "ημερολόγιο"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr "Χωρίς"
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "Σημειώθηκε το αποθετήριο %s σαν κλώνος του %s"
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr "Παρουσιάστηκε ένα σφάλμα κατά τη διάρκεια αυτής της λειτουργίας"
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr "Η ακύρωση της cache ήταν επιτυχής"
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr "Παρουσιάστηκε ένα σφάλμα κατά τη διάρκεια ακύρωσης της cache"
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, fuzzy, python-format
 #| msgid "Deleted repository %s"
 msgid "Invalidated %s repositories"
 msgstr "Διαγράφηκε το αποθετήριο %s"
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "Δεν υπάρχουν ακόμα έτοιμα δεδομένα"
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr ""
@@ -1069,11 +1065,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr ""
 
@@ -1108,166 +1104,166 @@
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, python-format
 msgid "Changeset %s not found"
 msgstr ""
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:735
-#: kallithea/templates/changelog/changelog.html:43
-msgid "revisions"
-msgstr ""
-
 #: kallithea/lib/helpers.py:759
+#: kallithea/templates/changelog/changelog.html:43
+msgid "revisions"
+msgstr ""
+
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:794
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
-msgid "[updated] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:800
-msgid "[downloaded] archive from repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:802
-msgid "[delete] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:810
-msgid "[created] user"
-msgstr ""
-
-#: kallithea/lib/helpers.py:812
-msgid "[updated] user"
-msgstr ""
-
 #: kallithea/lib/helpers.py:814
-msgid "[created] user group"
-msgstr ""
-
-#: kallithea/lib/helpers.py:816
-msgid "[updated] user group"
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
+msgid "[created] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:818
-msgid "[commented] on revision in repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:820
-msgid "[commented] on pull request for"
-msgstr ""
-
-#: kallithea/lib/helpers.py:822
-msgid "[closed] pull request for"
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
+msgid "[updated] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:824
-msgid "[pushed] into"
+msgid "[downloaded] archive from repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:826
-msgid "[committed via Kallithea] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:828
-msgid "[pulled from remote] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:830
-msgid "[pulled] from"
-msgstr ""
-
-#: kallithea/lib/helpers.py:832
-msgid "[started following] repository"
+msgid "[delete] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:834
+msgid "[created] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:836
+msgid "[updated] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:838
+msgid "[created] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:840
+msgid "[updated] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:842
+msgid "[commented] on revision in repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:844
+msgid "[commented] on pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:846
+msgid "[closed] pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:848
+msgid "[pushed] into"
+msgstr ""
+
+#: kallithea/lib/helpers.py:850
+msgid "[committed via Kallithea] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:852
+msgid "[pulled from remote] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:854
+msgid "[pulled] from"
+msgstr ""
+
+#: kallithea/lib/helpers.py:856
+msgid "[started following] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1304,69 +1300,69 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr ""
 
@@ -1379,129 +1375,129 @@
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr ""
 
@@ -1527,33 +1523,33 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:167
+#, python-format
+msgid ""
+"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
+"%(pr_source_branch)s by %(pr_owner_username)s"
+msgstr ""
+
 #: kallithea/model/notification.py:168
 #, python-format
 msgid ""
-"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
-"%(pr_source_branch)s by %(pr_owner_username)s"
-msgstr ""
-
-#: kallithea/model/notification.py:169
-#, python-format
-msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr ""
 
@@ -1641,213 +1637,213 @@
 msgid "SSH key with fingerprint %r found"
 msgstr ""
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
 "owners or remove those repositories: %s"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
 "owners or remove those repository groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
 "owners or remove those user groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr ""
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
 msgstr ""
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:131
-msgid "Invalid user group name"
-msgstr ""
-
 #: kallithea/model/validators.py:132
+msgid "Invalid user group name"
+msgstr ""
+
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:174
-msgid "Cannot assign this group as parent"
-msgstr ""
-
 #: kallithea/model/validators.py:175
+msgid "Cannot assign this group as parent"
+msgstr ""
+
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr ""
 
+#: kallithea/model/validators.py:310
+#, python-format
+msgid "Repository name %(repo)s is not allowed"
+msgstr ""
+
+#: kallithea/model/validators.py:312
+#, python-format
+msgid "Repository named %(repo)s already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:313
 #, python-format
-msgid "Repository name %(repo)s is not allowed"
+msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
 #: kallithea/model/validators.py:315
 #, python-format
-msgid "Repository named %(repo)s already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:316
-#, python-format
-msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
-msgstr ""
-
-#: kallithea/model/validators.py:318
-#, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
 msgstr ""
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1907,7 +1903,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1915,14 +1911,14 @@
 msgid "Description"
 msgstr ""
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr ""
 
@@ -1932,7 +1928,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1956,7 +1952,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr ""
@@ -2080,7 +2076,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr ""
@@ -2327,7 +2323,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr ""
 
@@ -2411,13 +2407,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2433,14 +2429,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2741,7 +2737,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr ""
@@ -2762,7 +2758,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr ""
 
@@ -2935,7 +2931,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3103,14 +3099,10 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
+msgid "Remote"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3148,7 +3140,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr ""
@@ -3179,43 +3171,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr ""
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3732,6 +3695,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr ""
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3753,7 +3725,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr ""
@@ -3827,7 +3799,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr ""
@@ -3927,10 +3899,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr ""
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr ""
 
@@ -4609,23 +4583,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4661,6 +4635,13 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "%s committed on %s"
+msgid "View Comment"
+msgstr "%s συνέβαλε στο %s"
+
 #: kallithea/templates/email_templates/comment.html:27
 msgid "Status change:"
 msgstr ""
@@ -4671,32 +4652,40 @@
 msgid "The pull request has been closed."
 msgstr "Αυτό το αίτημα έλξης έχει κλείσει και δεν μπορεί να ενημερωθεί."
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+msgid "Password Reset Request"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4729,6 +4718,12 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+#| msgid "Finish pull request"
+msgid "View Pull Request"
+msgstr "Λάθος στη δημιουργία αιτήματος έλξης - pull request: %s"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, fuzzy, python-format
 #| msgid "Error creating pull request: %s"
@@ -4746,10 +4741,18 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr "Λάθος στη δημιουργία αιτήματος έλξης - pull request: %s"
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+msgid "New User Registration"
+msgstr ""
+
+#: kallithea/templates/email_templates/registration.html:23
 msgid "Full Name"
 msgstr ""
 
+#: kallithea/templates/email_templates/registration.html:42
+msgid "View User Profile"
+msgstr ""
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5361,35 +5364,35 @@
 msgid "Show more"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr ""
 
@@ -5490,6 +5493,12 @@
 msgid "Download %s as %s"
 msgstr ""
 
+#~ msgid "Cache invalidation successful"
+#~ msgstr "Η ακύρωση της cache ήταν επιτυχής"
+
+#~ msgid "An error occurred during cache invalidation"
+#~ msgstr "Παρουσιάστηκε ένα σφάλμα κατά τη διάρκεια ακύρωσης της cache"
+
 #~ msgid "This repository has been locked by %s on %s"
 #~ msgstr "Το αποθετήριο κλειδώθηκε από %s την %s"
 
--- a/kallithea/i18n/es/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/es/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -4,7 +4,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2018-04-18 11:43+0000\n"
 "Last-Translator: Jesús Sánchez <jsanchezfdz95@gmail.com>\n"
 "Language-Team: Spanish <https://hosted.weblate.org/projects/kallithea/"
@@ -63,7 +63,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr "Petición de pull %s eliminada correctamente"
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr "La revisión no existe en este repositorio"
@@ -258,7 +258,7 @@
 msgid "Tags"
 msgstr "Etiquetas"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr "Ocurrió un error mientras se bifurcaba el repositorio %s"
@@ -311,25 +311,29 @@
 msgid "Journal"
 msgstr "Registro"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+msgid "Authentication failed."
+msgstr ""
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr "CAPTCHA erróneo"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "El registro en %s se ha efectuado correctamente"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr "Se ha enviado una confirmación de restauración de contraseña"
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Señal de restauración de contraseña inválida"
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Contraseña actualizada correctamente"
 
@@ -481,11 +485,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr "Las estadísticas están deshabilitadas en este repositorio"
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr "Los ajustes de autentificación se han actualizado correctamente"
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr "ocurrió un error al actualizar los ajustes de autentificación"
 
@@ -561,8 +565,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
@@ -696,11 +700,11 @@
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr ""
 
@@ -722,294 +726,286 @@
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, fuzzy, python-format
 #| msgid "An error occurred during repository forking %s"
 msgid "An error occurred during creation of field: %r"
 msgstr "Ocurrió un error mientras se bifurcaba el repositorio %s"
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "Todavía no hay datos disponibles"
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr ""
@@ -1053,11 +1049,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr ""
 
@@ -1092,166 +1088,166 @@
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, python-format
 msgid "Changeset %s not found"
 msgstr ""
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:735
-#: kallithea/templates/changelog/changelog.html:43
-msgid "revisions"
-msgstr ""
-
 #: kallithea/lib/helpers.py:759
+#: kallithea/templates/changelog/changelog.html:43
+msgid "revisions"
+msgstr ""
+
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:794
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
-msgid "[updated] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:800
-msgid "[downloaded] archive from repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:802
-msgid "[delete] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:810
-msgid "[created] user"
-msgstr ""
-
-#: kallithea/lib/helpers.py:812
-msgid "[updated] user"
-msgstr ""
-
 #: kallithea/lib/helpers.py:814
-msgid "[created] user group"
-msgstr ""
-
-#: kallithea/lib/helpers.py:816
-msgid "[updated] user group"
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
+msgid "[created] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:818
-msgid "[commented] on revision in repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:820
-msgid "[commented] on pull request for"
-msgstr ""
-
-#: kallithea/lib/helpers.py:822
-msgid "[closed] pull request for"
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
+msgid "[updated] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:824
-msgid "[pushed] into"
+msgid "[downloaded] archive from repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:826
-msgid "[committed via Kallithea] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:828
-msgid "[pulled from remote] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:830
-msgid "[pulled] from"
-msgstr ""
-
-#: kallithea/lib/helpers.py:832
-msgid "[started following] repository"
+msgid "[delete] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:834
+msgid "[created] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:836
+msgid "[updated] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:838
+msgid "[created] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:840
+msgid "[updated] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:842
+msgid "[commented] on revision in repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:844
+msgid "[commented] on pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:846
+msgid "[closed] pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:848
+msgid "[pushed] into"
+msgstr ""
+
+#: kallithea/lib/helpers.py:850
+msgid "[committed via Kallithea] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:852
+msgid "[pulled from remote] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:854
+msgid "[pulled] from"
+msgstr ""
+
+#: kallithea/lib/helpers.py:856
+msgid "[started following] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1288,69 +1284,69 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr ""
 
@@ -1363,129 +1359,129 @@
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr ""
 
@@ -1511,33 +1507,33 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:167
+#, python-format
+msgid ""
+"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
+"%(pr_source_branch)s by %(pr_owner_username)s"
+msgstr ""
+
 #: kallithea/model/notification.py:168
 #, python-format
 msgid ""
-"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
-"%(pr_source_branch)s by %(pr_owner_username)s"
-msgstr ""
-
-#: kallithea/model/notification.py:169
-#, python-format
-msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr ""
 
@@ -1622,213 +1618,213 @@
 msgid "SSH key with fingerprint %r found"
 msgstr ""
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
 "owners or remove those repositories: %s"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
 "owners or remove those repository groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
 "owners or remove those user groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr ""
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
 msgstr ""
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:131
-msgid "Invalid user group name"
-msgstr ""
-
 #: kallithea/model/validators.py:132
+msgid "Invalid user group name"
+msgstr ""
+
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:174
-msgid "Cannot assign this group as parent"
-msgstr ""
-
 #: kallithea/model/validators.py:175
+msgid "Cannot assign this group as parent"
+msgstr ""
+
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr ""
 
+#: kallithea/model/validators.py:310
+#, python-format
+msgid "Repository name %(repo)s is not allowed"
+msgstr ""
+
+#: kallithea/model/validators.py:312
+#, python-format
+msgid "Repository named %(repo)s already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:313
 #, python-format
-msgid "Repository name %(repo)s is not allowed"
+msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
 #: kallithea/model/validators.py:315
 #, python-format
-msgid "Repository named %(repo)s already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:316
-#, python-format
-msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
-msgstr ""
-
-#: kallithea/model/validators.py:318
-#, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
 msgstr ""
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1888,7 +1884,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1896,14 +1892,14 @@
 msgid "Description"
 msgstr ""
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr ""
 
@@ -1913,7 +1909,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1937,7 +1933,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr ""
@@ -2061,7 +2057,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr ""
@@ -2308,7 +2304,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr ""
 
@@ -2392,13 +2388,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2414,14 +2410,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2722,7 +2718,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr ""
@@ -2743,7 +2739,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr ""
 
@@ -2916,7 +2912,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3081,14 +3077,10 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
+msgid "Remote"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3126,7 +3118,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr ""
@@ -3157,43 +3149,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr ""
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3710,6 +3673,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr ""
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3731,7 +3703,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr ""
@@ -3805,7 +3777,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr ""
@@ -3905,10 +3877,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr ""
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr ""
 
@@ -4584,23 +4558,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4636,6 +4610,13 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "%s committed on %s"
+msgid "View Comment"
+msgstr "%s anotó en %s"
+
 #: kallithea/templates/email_templates/comment.html:27
 msgid "Status change:"
 msgstr ""
@@ -4646,32 +4627,40 @@
 msgid "The pull request has been closed."
 msgstr "La petición pull esta cerrada y no se puede actualizar."
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+msgid "Password Reset Request"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4704,6 +4693,12 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+#| msgid "Pull request updated"
+msgid "View Pull Request"
+msgstr "Petición pull actualizada"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, fuzzy, python-format
 #| msgid "Error creating pull request: %s"
@@ -4721,10 +4716,18 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr "Error al crear la petición de pull: %s"
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+msgid "New User Registration"
+msgstr ""
+
+#: kallithea/templates/email_templates/registration.html:23
 msgid "Full Name"
 msgstr ""
 
+#: kallithea/templates/email_templates/registration.html:42
+msgid "View User Profile"
+msgstr ""
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5335,35 +5338,35 @@
 msgid "Show more"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr ""
 
--- a/kallithea/i18n/fr/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/fr/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -4,7 +4,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2019-10-13 16:52+0000\n"
 "Last-Translator: Nathan <bonnemainsnathan@gmail.com>\n"
 "Language-Team: French <https://hosted.weblate.org/projects/kallithea/"
@@ -61,7 +61,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr "La requête de pull %s a été supprimée avec succès"
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr "Une telle révision n'existe pas pour ce dépôt"
@@ -257,7 +257,7 @@
 msgid "Tags"
 msgstr "Tags"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr "Une erreur est survenue durant le fork du dépôt %s"
@@ -310,26 +310,32 @@
 msgid "Journal"
 msgstr "Historique"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+#, fuzzy
+#| msgid "Authentication"
+msgid "Authentication failed."
+msgstr "Authentification"
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr "Mauvais captcha"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "Vous vous êtes inscrit avec succès avec %s"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr ""
 "Un lien de confirmation de réinitialisation de mot de passe a été envoyé"
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Clé de réinitialisation de mot de passe invalide"
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Mot de passe mis à jour avec succès"
 
@@ -479,11 +485,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr "La mise à jour des statistiques est désactivée pour ce dépôt"
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr "Mise à jour des paramètres d'authentification effectuée avec succès"
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr ""
 "une erreur est survenue pendant la mise à jour des réglages "
@@ -562,8 +568,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr "Une erreur est survenue durant la mise à jour du gist %s"
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 "Vous ne pouvez pas éditer cet utilisateur ; il est nécessaire pour le bon "
@@ -702,11 +708,11 @@
 msgid "Allowed with automatic account activation"
 msgstr "Autorisé avec activation de compte automatique"
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr "Activation manuelle du compte externe"
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr "Activation automatique du compte externe"
 
@@ -728,190 +734,182 @@
 msgid "Error occurred during update of permissions"
 msgstr "Une erreur est survenue durant la mise à jour des permissions"
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr "Une erreur est survenue durant la création du groupe de dépôts %s"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr "Groupe de dépôts %s créé"
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Groupe de dépôts %s mis à jour"
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 "Une erreur est survenue durant la mise à jour du groupe de dépôts %s"
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "Ce groupe contient %s dépôts et ne peut être supprimé"
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr "Ce groupe contient %s sous-groupes et ne peut pas être supprimé"
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Groupe de dépôts %s supprimé"
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 "Une erreur est survenue durant la suppression du groupe de dépôts %s"
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Impossible de révoquer votre permission d'administrateur"
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr "Permissions du groupe de dépôts mises à jour"
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr "Une erreur est survenue durant la révocation de la permission"
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Erreur de création du dépôt %s"
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Dépôt %s créé depuis %s"
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "dépôt %s forké en tant que %s"
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr "Dépôt %s créé"
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Dépôt %s mis à jour avec succès"
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "Une erreur est survenue durant la mise à jour du dépôt %s"
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr "%s forks détachés"
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr "%s forks supprimés"
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Dépôt %s supprimé"
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr "Impossible de supprimer le dépôt %s : des forks y sont attachés"
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "Erreur pendant la suppression de %s"
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr "Permissions du dépôt mises à jour"
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr "Erreur de validation du champ : %s"
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr "Une erreur est survenue durant la création du champ : %r"
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr "Une erreur est survenue durant la suppression du champ"
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr "-- Pas un fork --"
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr "La visibilité du dépôt dans le journal public a été mise à jour"
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 "Une erreur est survenue durant la configuration du journal public pour ce "
 "dépôt"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr "[Aucun dépôt]"
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "Le dépôt %s a été marké comme fork de %s"
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr "Une erreur est survenue durant cette opération"
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr "Invalidation du cache réalisée avec succès"
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr "Une erreur est survenue durant l’invalidation du cache"
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr "Les changements distants ont été récupérés"
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr "Une erreur est survenue durant le pull depuis la source distante"
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 "Une erreur est survenue durant la suppression des statistiques du dépôt"
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr "Réglages des gestionnaires de versions mis à jour"
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
@@ -919,116 +917,116 @@
 "Impossible d'activer la prise en charge de hgsubversion. La bibliothèque "
 "« hgsubversion » est manquante"
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr ""
 "Une erreur est survenue durant la mise à jour des réglages de "
 "l'application"
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr "Dépôts ré-analysés avec succès. Ajouté : %s. Supprimé : %s."
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr "%s dépôts invalidés"
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr "Réglages mis à jour"
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr "Réglages d’affichage mis à jour"
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 "Une erreur est survenue durant la mise à jour des réglages de "
 "visualisation"
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr "Veuillez entrer votre adresse e-mail"
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr "Tâche d'envoi d'e-mail créée"
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 msgid "Hook already exists"
 msgstr "Le hook existe déjà"
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 "Les hooks intégrés sont en lecture seule. Merci de choisir un autre nom "
 "pour le hook."
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr "Le nouveau hook a été ajouté"
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr "Hooks mis à jour"
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr "Une erreur est survenue durant la création du hook"
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr "La tâche de réindexation Whoosh a été planifiée"
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr "Groupe d'utilisateurs %s créé"
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 "Une erreur est survenue durant la création du groupe d'utilisateurs %s"
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr "Groupe d'utilisateurs %s mis à jour"
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 "Une erreur est survenue durant la mise à jour du groupe d'utilisateurs %s"
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr "Groupe d'utilisateurs supprimé avec succès"
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr ""
 "Une erreur est survenue durant la suppression du groupe d'utilisateurs"
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr "Le groupe cible ne peut pas être le même"
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr "Permissions du groupe d'utilisateurs mises à jour"
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr "Permissions mises à jour"
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr "Une erreur est survenue durant l’enregistrement des permissions"
@@ -1072,12 +1070,12 @@
 msgid "Removed IP address from user whitelist"
 msgstr "L'adresse IP a été supprimée de la liste blanche"
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 "Vous devez être un utilisateur enregistré pour effectuer cette action"
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr "Vous devez être connecté pour visualiser cette page"
 
@@ -1118,166 +1116,166 @@
 msgid "No changes detected"
 msgstr "Aucun changement détecté"
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "Branche supprimée : %s"
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr "Étiquette créée : %s"
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, python-format
 msgid "Changeset %s not found"
 msgstr "Ensemble de changements %s non trouvé"
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "Afficher les changements combinés %s->%s"
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr "Vue de comparaison"
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr "et"
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr "%s de plus"
 
-#: kallithea/lib/helpers.py:735
+#: kallithea/lib/helpers.py:759
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "révisions"
 
-#: kallithea/lib/helpers.py:759
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr "Nom du fork %s"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr "Requête de pull %s"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:814
 msgid "[deleted] repository"
 msgstr "[a supprimé] le dépôt"
 
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
 msgid "[created] repository"
 msgstr "[a créé] le dépôt"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:818
 msgid "[created] repository as fork"
 msgstr "[a créé] le dépôt en tant que fork"
 
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
 msgid "[forked] repository"
 msgstr "[a forké] le dépôt"
 
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
 msgid "[updated] repository"
 msgstr "[a mis à jour] le dépôt"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:824
 msgid "[downloaded] archive from repository"
 msgstr "[téléchargée] archive depuis le dépôt"
 
-#: kallithea/lib/helpers.py:802
+#: kallithea/lib/helpers.py:826
 msgid "[delete] repository"
 msgstr "[a supprimé] le dépôt"
 
-#: kallithea/lib/helpers.py:810
+#: kallithea/lib/helpers.py:834
 msgid "[created] user"
 msgstr "[a créé] l’utilisateur"
 
-#: kallithea/lib/helpers.py:812
+#: kallithea/lib/helpers.py:836
 msgid "[updated] user"
 msgstr "[a mis à jour] l’utilisateur"
 
-#: kallithea/lib/helpers.py:814
+#: kallithea/lib/helpers.py:838
 msgid "[created] user group"
 msgstr "[créé] groupe d'utilisateurs"
 
-#: kallithea/lib/helpers.py:816
+#: kallithea/lib/helpers.py:840
 msgid "[updated] user group"
 msgstr "[mis à jour] groupe d'utilisateurs"
 
-#: kallithea/lib/helpers.py:818
+#: kallithea/lib/helpers.py:842
 msgid "[commented] on revision in repository"
 msgstr "[a commenté] une révision du dépôt"
 
-#: kallithea/lib/helpers.py:820
+#: kallithea/lib/helpers.py:844
 msgid "[commented] on pull request for"
 msgstr "[a commenté] la requête de pull pour"
 
-#: kallithea/lib/helpers.py:822
+#: kallithea/lib/helpers.py:846
 msgid "[closed] pull request for"
 msgstr "[a fermé] la requête de pull de"
 
-#: kallithea/lib/helpers.py:824
+#: kallithea/lib/helpers.py:848
 msgid "[pushed] into"
 msgstr "[a pushé] dans"
 
-#: kallithea/lib/helpers.py:826
+#: kallithea/lib/helpers.py:850
 msgid "[committed via Kallithea] into repository"
 msgstr "[a commité via Kallithea] dans le dépôt"
 
-#: kallithea/lib/helpers.py:828
+#: kallithea/lib/helpers.py:852
 msgid "[pulled from remote] into repository"
 msgstr "[a pullé depuis un site distant] dans le dépôt"
 
-#: kallithea/lib/helpers.py:830
+#: kallithea/lib/helpers.py:854
 msgid "[pulled] from"
 msgstr "[a pullé] depuis"
 
-#: kallithea/lib/helpers.py:832
+#: kallithea/lib/helpers.py:856
 msgid "[started following] repository"
 msgstr "[suit maintenant] le dépôt"
 
-#: kallithea/lib/helpers.py:834
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr "[ne suit plus] le dépôt"
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr " et %s de plus"
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "Aucun fichier"
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr "nouveau fichier"
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr "mod"
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr "suppr."
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr "renommer"
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1317,69 +1315,69 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] "%d an"
 msgstr[1] "%d ans"
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] "%d mois"
 msgstr[1] "%d mois"
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] "%d jour"
 msgstr[1] "%d jours"
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] "%d heure"
 msgstr[1] "%d heures"
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] "%d minute"
 msgstr[1] "%d minutes"
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] "%d seconde"
 msgstr[1] "%d secondes"
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr "dans %s"
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr "Il y a %s"
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr "dans %s et %s"
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr "Il y a %s et %s"
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr "à l’instant"
 
@@ -1392,154 +1390,154 @@
 msgid "[Mention]"
 msgstr "[Mention]"
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr "niveau supérieur"
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr "Administrateur Kallithea"
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr "L'utilisateur par défaut n'a pas accès aux nouveaux dépôts"
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr "L'utilisateur par défaut a un accès en lecture aux nouveaux dépôts"
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr "L'utilisateur par défaut a un accès en écriture aux nouveaux dépôts"
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 "L'utilisateur par défaut a un accès administrateur aux nouveaux dépôts"
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 "L'utilisateur par défaut n'a pas accès aux nouveaux groupes de dépôts"
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 "L'utilisateur par défaut a accès en lecture seule aux nouveaux groupes de "
 "dépôts"
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 "L'utilisateur par défaut a accès en écriture aux nouveaux groupes de "
 "dépôts"
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 "L'utilisateur par défaut a accès administrateur aux nouveaux groupes de "
 "dépôts"
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 "L'utilisateur par défaut n'a pas accès aux nouveaux groupes d'utilisateurs"
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 "L'utilisateur par défaut a accès en lecture seule aux nouveaux groupes "
 "d'utilisateurs"
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 "L'utilisateur par défaut a accès en écriture aux nouveaux groupes "
 "d'utilisateurs"
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 "L'utilisateur par défaut a un accès administrateur aux nouveaux groupes "
 "d'utilisateurs"
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr "Seul un administrateur peut créer un groupe de dépôts"
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr ""
 "Les utilisateurs non-administrateurs peuvent créer des groupes de dépôts"
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr "Seul un administrateur peut créer des groupes d'utilisateurs"
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr ""
 "Les utilisateurs non-administrateurs peuvent créer des groupes "
 "d'utilisateurs"
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr "Seul un administrateur peut créer des dépôts de niveau supérieur"
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 "Les utilisateurs non-administrateurs peuvent créer des dépôts de niveau "
 "supérieur"
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 "Création de dépôts activée avec l'accès en écriture vers un groupe de "
 "dépôts"
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 "Création de dépôts désactivée avec l'accès en écriture vers un groupe de "
 "dépôts"
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr "Seul un administrateur peut faire un fork de dépôt"
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 msgid "Non-admins can fork repositories"
 msgstr "Les utilisateurs non-administrateurs peuvent faire un fork de dépôt"
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr "Enregistrement désactivé"
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr "Enregistrement des utilisateurs avec activation de compte manuelle"
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr ""
 "Enregistrement des utilisateurs avec activation de compte automatique"
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr "Pas encore relue"
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr "En cours de relecture"
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 msgid "Not approved"
 msgstr "Non approuvée"
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr "Approuvée"
 
@@ -1565,7 +1563,7 @@
 msgid "Name must not contain only digits"
 msgstr "Le nom ne doit pas contenir seulement des chiffres"
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
@@ -1574,12 +1572,12 @@
 "[Commentaire] Changeset %(short_id)s « %(message_short)s » de "
 "%(repo_name)s dans %(branch)s"
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr "Nouvel utilisateur %(new_username)s enregistré"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid ""
 "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
@@ -1588,7 +1586,7 @@
 "[Revue] %(repo_name)s PR %(pr_nice_id)s « %(pr_title_short)s » depuis "
 "%(pr_source_branch)s par %(pr_owner_username)s"
 
-#: kallithea/model/notification.py:169
+#: kallithea/model/notification.py:168
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
@@ -1597,7 +1595,7 @@
 "[Commentaire] %(repo_name)s PR %(pr_nice_id)s « %(pr_title_short)s » "
 "depuis %(pr_source_branch)s par %(pr_owner_username)s"
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr "Fermeture"
 
@@ -1678,18 +1676,18 @@
 msgid "SSH key with fingerprint %r found"
 msgstr "Ensemble de changements %s non trouvé"
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr "Nouveau enregistrement d'utilisateur"
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 "Vous ne pouvez pas supprimer cet utilisateur ; il est nécessaire pour le "
 "bon fonctionnement de l’application"
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
@@ -1698,7 +1696,7 @@
 "L’utilisateur \"%s\" possède %s dépôts et ne peut être supprimé. Changez "
 "les propriétaires ou supprimez ces dépôts : %s"
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
@@ -1707,7 +1705,7 @@
 "L’utilisateur \"%s\" possède %s groupes de dépôt et ne peut être "
 "supprimé. Changez les propriétaires ou supprimez ces dépôts : %s"
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
@@ -1717,15 +1715,15 @@
 "être supprimé. Changez les propriétaires de ces groupes d'utilisateurs ou "
 "supprimez-les : %s"
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr "Lien de remise à zéro du mot de passe"
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr "Notification de réinitialisation du mot de passe"
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
@@ -1734,21 +1732,21 @@
 "Le mot de passe de votre compte %s a été changé via le formulaire de "
 "réinitialisation du mot de passe."
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr "Cette valeur ne peut être une liste vide"
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "Le nom d’utilisateur « %(username)s » existe déjà"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "Le nom d’utilisateur « %(username)s » n’est pas valide"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
@@ -1757,25 +1755,25 @@
 "des underscores (_), points, traits d'union et doit commencer avec un "
 "caractère alphanumérique ou un underscore"
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr "L'entrée n'est pas valide"
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr "Le nom d’utilisateur « %(username)s » n’est pas valide"
 
-#: kallithea/model/validators.py:131
+#: kallithea/model/validators.py:132
 msgid "Invalid user group name"
 msgstr "Nom de groupe d'utilisateurs invalide"
 
-#: kallithea/model/validators.py:132
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr "Le groupe d'utilisateurs « %(usergroup)s » existe déjà"
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
@@ -1784,61 +1782,61 @@
 "alphanumériques, des tirets, des points, des traits d'union et doit "
 "commencer avec un caractère alphanumérique"
 
-#: kallithea/model/validators.py:174
+#: kallithea/model/validators.py:175
 msgid "Cannot assign this group as parent"
 msgstr "Impossible d’assigner ce groupe en tant que parent"
 
-#: kallithea/model/validators.py:175
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr "Le groupe « %(group_name)s » existe déjà"
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr "Un dépôt portant le nom « %(group_name)s » existe déjà"
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr "Caractères incorrects (non-ASCII) dans le mot de passe"
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr "Ancien mot de passe invalide"
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr "Les mots de passe ne correspondent pas"
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr "Nom d'utilisateur ou mot de passe invalide"
 
-#: kallithea/model/validators.py:313
+#: kallithea/model/validators.py:310
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr "Le nom de dépôt « %(repo)s » n’est pas autorisé"
 
-#: kallithea/model/validators.py:315
+#: kallithea/model/validators.py:312
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr "Un dépôt portant le nom « %(repo)s » existe déjà"
 
-#: kallithea/model/validators.py:316
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr "Le dépôt « %(repo)s » existe déjà dans le groupe « %(group)s »"
 
-#: kallithea/model/validators.py:318
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr "Un groupe de dépôts avec le nom « %(repo)s » existe déjà"
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr "URL de dépôt invalide"
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
@@ -1846,42 +1844,42 @@
 "URL de dépôt invalide. Ce doit être une URL valide de type http, https, "
 "ssh, svn+http ou svn+https"
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr "Le fork doit être du même type que le parent"
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr "Vous n’avez pas la permission de créer un dépôt dans ce"
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr "pas de permission de créer un dépôt dans la racine"
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 "Vous n'avez pas les permissions pour créer un groupe dans cet endroit"
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr ""
 "Ce nom d'utilisateur ou nom de groupe d'utilisateurs n'est pas valide"
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr "Ceci n’est pas un chemin valide"
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr "Cette adresse e-mail est déjà enregistrée"
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "L’adresse e-mail « %(email)s » n’existe pas"
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
@@ -1889,28 +1887,28 @@
 "L’attribut Login du CN doit être spécifié. Cet attribut correspond au nom "
 "d’utilisateur"
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr "Veuillez entrer une adresse IPv4 ou IPv6 valide"
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 "La taille du réseau (bits) doit être entre 0 et 32 (et non %(bits)r)"
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 "Le nom de la clé ne peut consister que de letters, de traits d'union, de "
 "tirets ou de nombres"
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr "Le nom du fichier ne peut être à l'intérieur d'un répertoire"
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1973,7 +1971,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1981,14 +1979,14 @@
 msgid "Description"
 msgstr "Description"
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr "Dernière modification"
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr "Sommet"
 
@@ -1998,7 +1996,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -2022,7 +2020,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr "Nom d’utilisateur"
@@ -2152,7 +2150,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr "E-mail"
@@ -2408,7 +2406,7 @@
 msgstr "Créer un nouveau gist"
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr "Créé"
 
@@ -2492,13 +2490,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2514,14 +2512,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2847,7 +2845,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr "Groupe de dépôt"
@@ -2873,7 +2871,7 @@
 "dépôts."
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr "Groupe d'utilisateurs"
 
@@ -3063,7 +3061,7 @@
 msgstr "Créé le"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3239,14 +3237,10 @@
 msgstr "Champs supplémentaires"
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
-msgstr "Caches"
+msgid "Remote"
+msgstr "Dépôt distant"
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr "Dépôt distant"
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3287,7 +3281,7 @@
 "journal public."
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "Voulez-vous vraiment supprimer le dépôt %s ?"
@@ -3321,45 +3315,14 @@
 "l'administrateur le fasse expirer. L'administrateur peut soit le "
 "supprimer définitivement, soit le restaurer."
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr "Invalider le cache du dépôt"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-"Invalider manuellement le cache de ce dépôt. Au prochain accès sur ce "
-"dépôt, il sera à nouveau mis en cache."
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr "Liste des valeurs en cache"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr "Préfixe"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr "Libellé"
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr "Clé"
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr "Actif"
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr "Libellé"
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3972,6 +3935,15 @@
 msgid "Short, optional description for this user group."
 msgstr "Description courte pour ce groupe d'utilisateur (optionnel)."
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr "Actif"
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3993,7 +3965,7 @@
 msgstr "Membres"
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr "Voulez-vous vraiment supprimer ce groupe utilisateur : %s ?"
@@ -4067,7 +4039,7 @@
 msgstr "Membre des groupes d'utilisateurs"
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr "Voulez-vous vraiment supprimer l’utilisateur « %s » ?"
@@ -4167,10 +4139,12 @@
 msgstr "Rechercher"
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr "Suivre"
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr "Arrêter de suivre"
 
@@ -4851,23 +4825,23 @@
 msgid "Repository creation in progress..."
 msgstr "Création du dépôt en cours..."
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr "Dépôt vide"
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr "S’abonner au flux RSS de %s"
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr "S’abonner au flux ATOM de %s"
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr "En cours de création"
 
@@ -4899,6 +4873,13 @@
 msgid "by"
 msgstr "par"
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "Comment"
+msgid "View Comment"
+msgstr "Commentaire"
+
 #: kallithea/templates/email_templates/comment.html:27
 msgid "Status change:"
 msgstr "Changement de statut :"
@@ -4907,18 +4888,30 @@
 msgid "The pull request has been closed."
 msgstr "La requête de pull a été fermée."
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+#, fuzzy
+#| msgid "Commit Message"
+msgid "Message"
+msgstr "Message de commit"
+
+#: kallithea/templates/email_templates/password_reset.html:4
+#, fuzzy
+#| msgid "Password Reset"
+msgid "Password Reset Request"
+msgstr "Remettre le mot de passe à zéro"
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr "Bonjour %s"
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr ""
 "Nous avons reçu une demande de réinitialisation du mot de passe de votre "
 "compte."
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
@@ -4926,11 +4919,11 @@
 "Cependant, ce compte est géré hors de ce système et le mot de passe ne "
 "peut pas être changé ici."
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr "Pour choisir un nouveau mot de passe, cliquez sur le lien suivant"
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
@@ -4938,7 +4931,7 @@
 "Si vous ne pouvez pas utiliser le lien ci-dessus, merci de saisir le code "
 "suivant dans le formulaire de réinitialisation de mot de passe"
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4971,6 +4964,12 @@
 msgid "to"
 msgstr "vers"
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+#| msgid "New Pull Request"
+msgid "View Pull Request"
+msgstr "Nouvelle requête de pull"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, python-format
 msgid "Mention in Comment on Pull Request %s \"%s\""
@@ -4986,10 +4985,22 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr "Commentaire sur la requête de pull %s « %s »"
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+#, fuzzy
+#| msgid "New user registration"
+msgid "New User Registration"
+msgstr "Nouveau enregistrement d'utilisateur"
+
+#: kallithea/templates/email_templates/registration.html:23
 msgid "Full Name"
 msgstr "Nom complet"
 
+#: kallithea/templates/email_templates/registration.html:42
+#, fuzzy
+#| msgid "View this user here"
+msgid "View User Profile"
+msgstr "Visualiser cet utilisateur ici"
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5617,35 +5628,35 @@
 msgid "Show more"
 msgstr "Afficher plus"
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr "commits"
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr "fichiers ajoutés"
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr "fichiers modifiés"
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr "fichiers supprimés"
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr "commit"
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr "fichier ajouté"
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr "fichié modifié"
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr "fichier supprimé"
 
@@ -5749,6 +5760,31 @@
 msgid "Download %s as %s"
 msgstr "Télécharge %s comme %s"
 
+#~ msgid "Cache invalidation successful"
+#~ msgstr "Invalidation du cache réalisée avec succès"
+
+#~ msgid "An error occurred during cache invalidation"
+#~ msgstr "Une erreur est survenue durant l’invalidation du cache"
+
+#~ msgid "Caches"
+#~ msgstr "Caches"
+
+#~ msgid "Invalidate Repository Cache"
+#~ msgstr "Invalider le cache du dépôt"
+
+#~ msgid ""
+#~ "Manually invalidate cache for this repository. On first access, the "
+#~ "repository will be cached again."
+#~ msgstr ""
+#~ "Invalider manuellement le cache de ce dépôt. Au prochain accès sur ce "
+#~ "dépôt, il sera à nouveau mis en cache."
+
+#~ msgid "List of Cached Values"
+#~ msgstr "Liste des valeurs en cache"
+
+#~ msgid "Prefix"
+#~ msgstr "Préfixe"
+
 #~ msgid "This repository has been locked by %s on %s"
 #~ msgstr "Ce dépôt a été verrouillé par %s sur %s"
 
@@ -6221,9 +6257,6 @@
 #~ msgid "The comment was made with status"
 #~ msgstr "Le commentaire a été fait avec le statut"
 
-#~ msgid "View this user here"
-#~ msgstr "Visualiser cet utilisateur ici"
-
 #~ msgid "Previous revision"
 #~ msgstr "Révision précédente"
 
--- a/kallithea/i18n/hu/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/hu/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -5,7 +5,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2015-04-11 00:59+0200\n"
 "Last-Translator: Balázs Úr <urbalazs@gmail.com>\n"
 "Language-Team: Hungarian <https://hosted.weblate.org/projects/kallithea/"
@@ -62,7 +62,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr ""
@@ -248,7 +248,7 @@
 msgid "Tags"
 msgstr ""
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr ""
@@ -301,25 +301,29 @@
 msgid "Journal"
 msgstr ""
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+msgid "Authentication failed."
+msgstr ""
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr ""
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr ""
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr ""
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr ""
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr ""
 
@@ -461,11 +465,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -541,8 +545,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
@@ -674,11 +678,11 @@
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr ""
 
@@ -700,292 +704,284 @@
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, fuzzy, python-format
 #| msgid "Private Repository"
 msgid "Invalidated %s repositories"
 msgstr "Tároló törlése"
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 msgid "Hook already exists"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr ""
@@ -1029,11 +1025,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr ""
 
@@ -1068,166 +1064,166 @@
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, python-format
 msgid "Changeset %s not found"
 msgstr ""
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:735
-#: kallithea/templates/changelog/changelog.html:43
-msgid "revisions"
-msgstr ""
-
 #: kallithea/lib/helpers.py:759
+#: kallithea/templates/changelog/changelog.html:43
+msgid "revisions"
+msgstr ""
+
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:794
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
-msgid "[updated] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:800
-msgid "[downloaded] archive from repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:802
-msgid "[delete] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:810
-msgid "[created] user"
-msgstr ""
-
-#: kallithea/lib/helpers.py:812
-msgid "[updated] user"
-msgstr ""
-
 #: kallithea/lib/helpers.py:814
-msgid "[created] user group"
-msgstr ""
-
-#: kallithea/lib/helpers.py:816
-msgid "[updated] user group"
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
+msgid "[created] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:818
-msgid "[commented] on revision in repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:820
-msgid "[commented] on pull request for"
-msgstr ""
-
-#: kallithea/lib/helpers.py:822
-msgid "[closed] pull request for"
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
+msgid "[updated] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:824
-msgid "[pushed] into"
+msgid "[downloaded] archive from repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:826
-msgid "[committed via Kallithea] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:828
-msgid "[pulled from remote] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:830
-msgid "[pulled] from"
-msgstr ""
-
-#: kallithea/lib/helpers.py:832
-msgid "[started following] repository"
+msgid "[delete] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:834
+msgid "[created] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:836
+msgid "[updated] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:838
+msgid "[created] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:840
+msgid "[updated] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:842
+msgid "[commented] on revision in repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:844
+msgid "[commented] on pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:846
+msgid "[closed] pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:848
+msgid "[pushed] into"
+msgstr ""
+
+#: kallithea/lib/helpers.py:850
+msgid "[committed via Kallithea] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:852
+msgid "[pulled from remote] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:854
+msgid "[pulled] from"
+msgstr ""
+
+#: kallithea/lib/helpers.py:856
+msgid "[started following] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1264,69 +1260,69 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr ""
 
@@ -1339,129 +1335,129 @@
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr ""
 
@@ -1487,33 +1483,33 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:167
+#, python-format
+msgid ""
+"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
+"%(pr_source_branch)s by %(pr_owner_username)s"
+msgstr ""
+
 #: kallithea/model/notification.py:168
 #, python-format
 msgid ""
-"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
-"%(pr_source_branch)s by %(pr_owner_username)s"
-msgstr ""
-
-#: kallithea/model/notification.py:169
-#, python-format
-msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr ""
 
@@ -1587,213 +1583,213 @@
 msgid "SSH key with fingerprint %r found"
 msgstr ""
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
 "owners or remove those repositories: %s"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
 "owners or remove those repository groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
 "owners or remove those user groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr ""
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
 msgstr ""
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:131
-msgid "Invalid user group name"
-msgstr ""
-
 #: kallithea/model/validators.py:132
+msgid "Invalid user group name"
+msgstr ""
+
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:174
-msgid "Cannot assign this group as parent"
-msgstr ""
-
 #: kallithea/model/validators.py:175
+msgid "Cannot assign this group as parent"
+msgstr ""
+
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr ""
 
+#: kallithea/model/validators.py:310
+#, python-format
+msgid "Repository name %(repo)s is not allowed"
+msgstr ""
+
+#: kallithea/model/validators.py:312
+#, python-format
+msgid "Repository named %(repo)s already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:313
 #, python-format
-msgid "Repository name %(repo)s is not allowed"
+msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
 #: kallithea/model/validators.py:315
 #, python-format
-msgid "Repository named %(repo)s already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:316
-#, python-format
-msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
-msgstr ""
-
-#: kallithea/model/validators.py:318
-#, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
 msgstr ""
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1853,7 +1849,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1861,14 +1857,14 @@
 msgid "Description"
 msgstr ""
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr ""
 
@@ -1878,7 +1874,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1902,7 +1898,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr ""
@@ -2026,7 +2022,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr ""
@@ -2273,7 +2269,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr ""
 
@@ -2357,13 +2353,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2379,14 +2375,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2687,7 +2683,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr ""
@@ -2708,7 +2704,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr ""
 
@@ -2881,7 +2877,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3047,14 +3043,10 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
+msgid "Remote"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3092,7 +3084,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr ""
@@ -3123,43 +3115,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr ""
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3677,6 +3640,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr ""
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3698,7 +3670,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr ""
@@ -3772,7 +3744,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr ""
@@ -3872,10 +3844,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr ""
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr ""
 
@@ -4548,23 +4522,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4598,6 +4572,13 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "No comments."
+msgid "View Comment"
+msgstr "Nincsenek hozzászólások."
+
 #: kallithea/templates/email_templates/comment.html:27
 #, fuzzy
 #| msgid "Status change"
@@ -4610,32 +4591,40 @@
 msgid "The pull request has been closed."
 msgstr "Ennek a tárolónak %s elágazása van"
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+msgid "Password Reset Request"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4666,6 +4655,10 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+msgid "View Pull Request"
+msgstr ""
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, python-format
 msgid "Mention in Comment on Pull Request %s \"%s\""
@@ -4681,10 +4674,18 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr ""
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+msgid "New User Registration"
+msgstr ""
+
+#: kallithea/templates/email_templates/registration.html:23
 msgid "Full Name"
 msgstr ""
 
+#: kallithea/templates/email_templates/registration.html:42
+msgid "View User Profile"
+msgstr ""
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5297,35 +5298,35 @@
 msgid "Show more"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr ""
 
--- a/kallithea/i18n/ja/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/ja/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -4,7 +4,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2019-08-27 07:23+0000\n"
 "Last-Translator: leela <53352@protonmail.com>\n"
 "Language-Team: Japanese <https://hosted.weblate.org/projects/kallithea/"
@@ -63,7 +63,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr "プルリクエストの削除に成功しました"
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr "お探しのリビジョンはこのリポジトリにはありません"
@@ -259,7 +259,7 @@
 msgid "Tags"
 msgstr "タグ"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr "リポジトリ %s のフォーク中にエラーが発生しました"
@@ -312,25 +312,31 @@
 msgid "Journal"
 msgstr "ジャーナル"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+#, fuzzy
+#| msgid "Authentication"
+msgid "Authentication failed."
+msgstr "認証"
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr "キャプチャが一致しません"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "%sへの登録を受け付けました"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr "パスワードリセットの確認コードが送信されました"
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "無効なパスワードリセットトークン"
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "パスワードを更新しました"
 
@@ -481,11 +487,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr "このリポジトリの統計は無効化されています"
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr "認証設定の更新に成功しました"
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr "認証設定の更新中にエラーが発生しました"
 
@@ -561,8 +567,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr "Gist %s の更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr "このユーザーはアプリケーション全体で非常に重要なので編集できません"
 
@@ -697,11 +703,11 @@
 msgid "Allowed with automatic account activation"
 msgstr "自動でアカウントをアクティベートする"
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr "外部アカウントを手動でアクティベートする"
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr "外部アカウントを自動でアクティベートする"
 
@@ -723,187 +729,179 @@
 msgid "Error occurred during update of permissions"
 msgstr "権限の更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr "リポジトリグループ %s の作成中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr "リポジトリグループ %s を作成しました"
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr "リポジトリグループ %s を更新しました"
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr "リポジトリグループ %s の更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "このグループは %s 個のリポジトリを含んでいるため削除できません"
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr "このグループは %s 個のサブグループを含んでいるため削除できません"
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr "リポジトリグループ %s を削除しました"
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr "リポジトリグループ %s の削除中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "自分自身の管理者としての権限を取り消すことはできません"
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr "リポジトリグループ権限を更新しました"
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr "権限の取消中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr "リポジトリ %s の作成中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "リポジトリ %s を %s から作成しました"
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "リポジトリ %s を %s としてフォークしました"
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr "リポジトリ %s を作成しました"
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "リポジトリ %s の更新に成功しました"
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "リポジトリ %s の更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr "%s 個のフォークを切り離しました"
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr "%s 個のフォークを削除しました"
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr "リポジトリ %s を削除しました"
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 "フォークしたリポジトリが存在するため、 リポジトリ %s は削除できません"
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "%s の削除中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr "リポジトリ権限を更新しました"
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, fuzzy, python-format
 #| msgid "An error occurred during creation of field"
 msgid "An error occurred during creation of field: %r"
 msgstr "フィールドの作成中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr "フィールドの削除中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr "-- フォークではありません --"
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr "公開ジャーナルでのリポジトリの可視性を更新しました"
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr "このリポジトリの公開ジャーナルの設定中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr "ありません"
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "%s リポジトリを %s のフォークとする"
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr "操作中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr "キャッシュの無効化に成功しました"
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr "キャッシュの無効化中にエラーが発生しました"
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr "リモートから取得"
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr "リモートから取得中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr "リポジトリステートの削除中にエラーが発生しました"
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr "VCS設定を更新しました"
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
@@ -911,110 +909,110 @@
 "\"hgsubversion\"ライブラリが見つからないため、hgsubversionサポートを有効に"
 "出来ません"
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr "アプリケーション設定の更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr "リポジトリの再スキャンに成功しました。 追加: %s 削除: %s。"
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, fuzzy, python-format
 #| msgid "Invalidate cache for all repositories"
 msgid "Invalidated %s repositories"
 msgstr "すべてのリポジトリのキャッシュを無効化する"
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr "アプリケーション設定を更新しました"
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr "表示設定を更新しました"
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr "表示設定の更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr "メールアドレスを入力してください"
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr "メール送信タスクを作成しました"
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "まだデータの準備ができていません"
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr "新しいフックを追加しました"
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr "フックを更新しました"
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr "フックの作成中にエラーが発生しました"
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr "Whooshの再インデックスタスクを予定に入れました"
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr "ユーザーグループ %s を作成しました"
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr "ユーザーグループ %s の作成中にエラーが発生しました"
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr "ユーザーグループ %s を更新しました"
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr "ユーザーグループ %s の更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr "ユーザーグループの削除に成功しました"
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr "ユーザーグループの削除中にエラーが発生しました"
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr "対象に同じ物を選ぶことはできません"
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr "ユーザーグループ権限を更新しました"
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr "権限を更新しました"
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr "権限の保存時にエラーが発生しました"
@@ -1058,12 +1056,12 @@
 msgid "Removed IP address from user whitelist"
 msgstr "ユーザーホワイトリストからIPアドレスを削除しました"
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 "このアクションを実行するためには登録済みのユーザーである必要があります"
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr "このページを閲覧するためにはサインインが必要です"
 
@@ -1103,167 +1101,167 @@
 msgid "No changes detected"
 msgstr "検出された変更はありません"
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "削除されたブランチ: %s"
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr "作成したタグ: %s"
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, fuzzy, python-format
 #| msgid "Changeset not found"
 msgid "Changeset %s not found"
 msgstr "リビジョンが見つかりません"
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "%s から %s までのすべてのチェンジセットを表示"
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr "比較ビュー"
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr "と"
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr "%s 以上"
 
-#: kallithea/lib/helpers.py:735
+#: kallithea/lib/helpers.py:759
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "リビジョン"
 
-#: kallithea/lib/helpers.py:759
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr "フォーク名 %s"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr "プルリクエスト #%s"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:814
 msgid "[deleted] repository"
 msgstr "リポジトリを[削除]"
 
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
 msgid "[created] repository"
 msgstr "リポジトリを[作成]"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:818
 msgid "[created] repository as fork"
 msgstr "フォークしてリポジトリを[作成]"
 
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
 msgid "[forked] repository"
 msgstr "リポジトリを[フォーク]"
 
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
 msgid "[updated] repository"
 msgstr "リポジトリを[更新]"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:824
 msgid "[downloaded] archive from repository"
 msgstr "リポジトリからアーカイブを[ダウンロード]"
 
-#: kallithea/lib/helpers.py:802
+#: kallithea/lib/helpers.py:826
 msgid "[delete] repository"
 msgstr "リポジトリを[削除]"
 
-#: kallithea/lib/helpers.py:810
+#: kallithea/lib/helpers.py:834
 msgid "[created] user"
 msgstr "ユーザーを[作成]"
 
-#: kallithea/lib/helpers.py:812
+#: kallithea/lib/helpers.py:836
 msgid "[updated] user"
 msgstr "ユーザーを[更新]"
 
-#: kallithea/lib/helpers.py:814
+#: kallithea/lib/helpers.py:838
 msgid "[created] user group"
 msgstr "ユーザーグループを[作成]"
 
-#: kallithea/lib/helpers.py:816
+#: kallithea/lib/helpers.py:840
 msgid "[updated] user group"
 msgstr "ユーザーグループを[更新]"
 
-#: kallithea/lib/helpers.py:818
+#: kallithea/lib/helpers.py:842
 msgid "[commented] on revision in repository"
 msgstr "リポジトリのリビジョンに[コメント]"
 
-#: kallithea/lib/helpers.py:820
+#: kallithea/lib/helpers.py:844
 msgid "[commented] on pull request for"
 msgstr "プルリクエストに[コメント]"
 
-#: kallithea/lib/helpers.py:822
+#: kallithea/lib/helpers.py:846
 msgid "[closed] pull request for"
 msgstr "プルリクエストを[クローズ]"
 
-#: kallithea/lib/helpers.py:824
+#: kallithea/lib/helpers.py:848
 msgid "[pushed] into"
 msgstr "[プッシュ]"
 
-#: kallithea/lib/helpers.py:826
+#: kallithea/lib/helpers.py:850
 msgid "[committed via Kallithea] into repository"
 msgstr "リポジトリに[Kallithea経由でコミット]"
 
-#: kallithea/lib/helpers.py:828
+#: kallithea/lib/helpers.py:852
 msgid "[pulled from remote] into repository"
 msgstr "リポジトリに[リモートからプル]"
 
-#: kallithea/lib/helpers.py:830
+#: kallithea/lib/helpers.py:854
 msgid "[pulled] from"
 msgstr "[プル]"
 
-#: kallithea/lib/helpers.py:832
+#: kallithea/lib/helpers.py:856
 msgid "[started following] repository"
 msgstr "リポジトリの[フォローを開始]"
 
-#: kallithea/lib/helpers.py:834
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr "リポジトリの[フォローを停止]"
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr " と %s 以上"
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "ファイルはありません"
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr "新しいファイル"
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr "変更"
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr "削除"
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr "リネーム"
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1303,63 +1301,63 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] "%d 年"
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] "%d ヶ月"
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] "%d 日"
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] "%d 時間"
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] "%d 分"
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] "%d 秒"
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr "%s 以内"
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr "%s 前"
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr "%s と %s の間"
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s と %s 前"
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr "たったいま"
 
@@ -1372,136 +1370,136 @@
 msgid "[Mention]"
 msgstr "[Mention]"
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr "top level"
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr "Kallithea 管理者"
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr "デフォルトユーザーは新しいリポジトリにアクセスできません"
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr ""
 "デフォルトユーザーは新しいリポジトリに読み取りアクセスする権限があります"
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr ""
 "デフォルトユーザーは新しいリポジトリに書き込みアクセスする権限があります"
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr "管理者のみがリポジトリのグループを作成できます"
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr "非管理者がリポジトリのグループを作成できます"
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr "管理者だけがユーザー グループを作成することができます"
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr "非管理者ユーザーがグループを作成することができます"
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr "管理者だけがトップレベルにリポジトリを作成することができます"
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr "非管理者がトップレベルにリポジトリを作成することができます"
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 "リポジトリグループの書き込みパーミッションを使ったリポジトリ作成が有効です"
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 "リポジトリグループの書き込みパーミッションを使ったリポジトリ作成は無効です"
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr "管理者のみがリポジトリをフォークすることができます"
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 #, fuzzy
 msgid "Non-admins can fork repositories"
 msgstr "非管理者がリポジトリをフォークすることができます"
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr "新規登録を無効にする"
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr "ユーザーの新規登録時に手動でアカウントをアクティベートする"
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr "ユーザーの新規登録時に自動でアカウントをアクティベートする"
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr "未レビュー"
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr "レビュー中"
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 #, fuzzy
 #| msgid "Approved"
 msgid "Not approved"
 msgstr "承認"
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr "承認"
 
@@ -1527,7 +1525,7 @@
 msgid "Name must not contain only digits"
 msgstr "数字だけの名前は使えません"
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, fuzzy, python-format
 #| msgid "[Comment] %(repo_name)s pull request %(pr_nice_id)s from %(ref)s"
 msgid ""
@@ -1535,26 +1533,26 @@
 "%(branch)s"
 msgstr "プルリクエストに[コメント]"
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr "新しいユーザー %(new_username)s が登録されました"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid ""
 "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:169
+#: kallithea/model/notification.py:168
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr "クローズ"
 
@@ -1635,11 +1633,11 @@
 msgid "SSH key with fingerprint %r found"
 msgstr "リビジョンが見つかりません"
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr "新規ユーザー登録"
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 #, fuzzy
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
@@ -1647,7 +1645,7 @@
 "このユーザーを削除できません。このユーザーはアプリケーションにとって必要不"
 "可欠です。"
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
@@ -1656,7 +1654,7 @@
 "ユーザー \"%s\" はまだ %s 個のリポジトリの所有者のため削除することはできま"
 "せん。リポジトリの所有者を変更するか削除してください: %s"
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
@@ -1665,7 +1663,7 @@
 "ユーザー \"%s\" はまだ %s 個のリポジトリグループの所有者のため削除すること"
 "はできません。リポジトリグループの所有者を変更するか削除してください: %s"
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
@@ -1674,36 +1672,36 @@
 "ユーザー \"%s\" はまだ %s 個のユーザーグループの所有者のため削除することは"
 "できません。ユーザーグループの所有者を変更するか削除してください。 %s"
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr "パスワードリセットのリンク"
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr "パスワードの再設定通知"
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr "空のリストにはできません"
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "ユーザー名 \"%(username)s\" はすでに使われています"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "ユーザー名 %(username)s は使用できません"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
@@ -1712,25 +1710,25 @@
 "か使えません。また、アルファベットまたはアンダースコア(_)から始まる必要が"
 "あります"
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr "入力が正しくありません"
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr "ユーザー名 %(username)s は不正です"
 
-#: kallithea/model/validators.py:131
+#: kallithea/model/validators.py:132
 msgid "Invalid user group name"
 msgstr "不正なユーザーグループ名です"
 
-#: kallithea/model/validators.py:132
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr "ユーザーグループ \"%(usergroup)s\" はすでに存在します"
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
@@ -1738,101 +1736,101 @@
 "ユーザーグループ名はアルファベット、アンダースコア(_)、ピリオド(.)、ダッ"
 "シュ(-)しか使えません。また、アルファベットから始まる必要があります"
 
-#: kallithea/model/validators.py:174
+#: kallithea/model/validators.py:175
 msgid "Cannot assign this group as parent"
 msgstr "このグループは親にできません"
 
-#: kallithea/model/validators.py:175
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr "グループ \"%(group_name)s\" はすでに存在します"
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr "グループ名 \"%(group_name)s\" を持つリポジトリはすでに存在します"
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr "パスワードに利用出来ない文字列(non-ascii)です"
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr "古いpasswordが間違っています"
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr "パスワードが一致しません"
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr "ユーザー名とパスワードの組み合わせが無効です"
 
-#: kallithea/model/validators.py:313
+#: kallithea/model/validators.py:310
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr "リポジトリ名 %(repo)s は許可されていません"
 
-#: kallithea/model/validators.py:315
+#: kallithea/model/validators.py:312
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr "リポジトリ %(repo)s はすでに存在します"
 
-#: kallithea/model/validators.py:316
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 "リポジトリ \"%(repo)s\" は グループ \"%(group)s\" にすでに存在します"
 
-#: kallithea/model/validators.py:318
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr "リポジトリグループ名 \"%(repo)s\" はすでに存在します"
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr "無効なリポジトリのURL"
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr "フォークは親と同じ種別の必要があります"
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr "このグループにリポジトリを作成する権限がありません"
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr "ルートにリポジトリを作成する権限がありません"
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr "この場所にグループを作成する権限がありません"
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr "ユーザー名かユーザーグループが不正です"
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr "不正なパスです"
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr "このメールアドレスはすでに取得されています"
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "メールアドレス \"%(email)s\" がみつかりません"
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
@@ -1840,11 +1838,11 @@
 "LDAPのこのCNに対するログイン属性は必須です。 - これは \"ユーザー名\" と同"
 "じです"
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr "有効なIPv4かIPv6のアドレスを入力してください"
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
@@ -1852,17 +1850,17 @@
 "ネットワークサイズ (bits) は0-32の範囲にする必要があります ( %(bits)r は不"
 "正です)"
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 "キー名にはアルファベット、アンダースコア(_)、ピリオド(.)、ダッシュ(-)、数"
 "字が使えます"
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr "ファイル名はディレクトリ内にすることはできません"
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1924,7 +1922,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1932,14 +1930,14 @@
 msgid "Description"
 msgstr "説明"
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr "最後の変更点"
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr "Tip"
 
@@ -1949,7 +1947,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1973,7 +1971,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr "ユーザー名"
@@ -2099,7 +2097,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr "メールアドレス"
@@ -2351,7 +2349,7 @@
 msgstr "新しい Gist を作成"
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr "作成日"
 
@@ -2437,13 +2435,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2459,14 +2457,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2785,7 +2783,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr "リポジトリグループ"
@@ -2812,7 +2810,7 @@
 "親のリポジトリグループにセットされているパーミッションをコピーします。"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr "ユーザーグループ"
 
@@ -2993,7 +2991,7 @@
 msgstr "作成日"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3172,14 +3170,10 @@
 msgstr "拡張フィールド"
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
-msgstr "キャッシュ"
+msgid "Remote"
+msgstr "リモート"
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr "リモート"
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3218,7 +3212,7 @@
 "公開ジャーナルでは、このリポジトリに対して行った操作のすべてが公開されます"
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "このリポジトリを削除してもよろしいですか? : %s"
@@ -3248,45 +3242,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr "リポジトリのキャッシュを無効化"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-"このリポジトリのキャッシュを手動で無効化します。リポジトリへの初回アクセス"
-"時に再びキャッシュされます。"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr "キャッシュしている値の一覧"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr "プレフィックス"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr "ラベル"
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr "キー"
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr "アクティブ"
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr "ラベル"
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3881,6 +3844,15 @@
 msgid "Short, optional description for this user group."
 msgstr "このユーザーグループの簡潔な説明を書いてください。"
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr "アクティブ"
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3902,7 +3874,7 @@
 msgstr "メンバー"
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr "このユーザーグループを削除してもよろしいですか?: %s"
@@ -3976,7 +3948,7 @@
 msgstr "グループのメンバー数"
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr "このユーザーを削除してもよろしいですか? : %s"
@@ -4076,10 +4048,12 @@
 msgstr "検索"
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr "フォロー"
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr "アンフォロー"
 
@@ -4777,23 +4751,23 @@
 msgid "Repository creation in progress..."
 msgstr "リポジトリを作成しています..."
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr "まだチェンジセットがありません"
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr "%s の RSS フィードを購読"
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr "%s の ATOM フィードを購読"
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr "作成中"
 
@@ -4831,6 +4805,13 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "Comment"
+msgid "View Comment"
+msgstr "コメント"
+
 #: kallithea/templates/email_templates/comment.html:27
 #, fuzzy
 #| msgid "Status change"
@@ -4844,32 +4825,44 @@
 msgstr ""
 "このプルリクエストはすでにクローズされていて、更新することはできません。"
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+#, fuzzy
+#| msgid "Commit Message"
+msgid "Message"
+msgstr "コミットメッセージ"
+
+#: kallithea/templates/email_templates/password_reset.html:4
+#, fuzzy
+#| msgid "Password Reset"
+msgid "Password Reset Request"
+msgstr "パスワードのリセット"
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr "こんにちは %s"
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr "あなたのアカウントのパスワードリセットリクエストを受け取りました。"
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr "新しいパスワードを設定するために、次のリンクをクリックしてください"
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4906,6 +4899,12 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+#| msgid "New Pull Request"
+msgid "View Pull Request"
+msgstr "新しいプルリクエスト"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, fuzzy, python-format
 #| msgid "%s mentioned you on %s pull request \"%s\""
@@ -4924,12 +4923,24 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr "プルリクエストに[コメント]"
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+#, fuzzy
+#| msgid "New user registration"
+msgid "New User Registration"
+msgstr "新規ユーザー登録"
+
+#: kallithea/templates/email_templates/registration.html:23
 #, fuzzy
 #| msgid "Group name"
 msgid "Full Name"
 msgstr "グループ名"
 
+#: kallithea/templates/email_templates/registration.html:42
+#, fuzzy
+#| msgid "View this user here"
+msgid "View User Profile"
+msgstr "このユーザを閲覧する"
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5559,35 +5570,35 @@
 msgid "Show more"
 msgstr "もっと表示"
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr "コミット"
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr "追加されたファイル"
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr "変更されたファイル"
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr "削除されたファイル"
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr "コミット"
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr "追加されたファイル"
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr "変更されたファイル"
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr "削除されたファイル"
 
@@ -5690,6 +5701,31 @@
 msgid "Download %s as %s"
 msgstr "%s を %s でダウンロード"
 
+#~ msgid "Cache invalidation successful"
+#~ msgstr "キャッシュの無効化に成功しました"
+
+#~ msgid "An error occurred during cache invalidation"
+#~ msgstr "キャッシュの無効化中にエラーが発生しました"
+
+#~ msgid "Caches"
+#~ msgstr "キャッシュ"
+
+#~ msgid "Invalidate Repository Cache"
+#~ msgstr "リポジトリのキャッシュを無効化"
+
+#~ msgid ""
+#~ "Manually invalidate cache for this repository. On first access, the "
+#~ "repository will be cached again."
+#~ msgstr ""
+#~ "このリポジトリのキャッシュを手動で無効化します。リポジトリへの初回アク"
+#~ "セス時に再びキャッシュされます。"
+
+#~ msgid "List of Cached Values"
+#~ msgstr "キャッシュしている値の一覧"
+
+#~ msgid "Prefix"
+#~ msgstr "プレフィックス"
+
 #~ msgid "This repository has been locked by %s on %s"
 #~ msgstr "このリポジトリは %s によって %s にロックされました"
 
@@ -6065,9 +6101,6 @@
 #~ msgid "The comment was made with status"
 #~ msgstr "プルリクエストを以下のステータスで閉じました:"
 
-#~ msgid "View this user here"
-#~ msgstr "このユーザを閲覧する"
-
 #~ msgid "Edit on Branch:%s"
 #~ msgstr "ブランチ:%s で編集"
 
--- a/kallithea/i18n/kallithea.pot	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/kallithea.pot	Mon Apr 27 13:25:28 2020 +0200
@@ -8,14 +8,14 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.5.99\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.7.0\n"
+"Generated-By: Babel 2.8.0\n"
 
 #: kallithea/controllers/changelog.py:67
 #: kallithea/controllers/pullrequests.py:247 kallithea/lib/base.py:602
@@ -61,7 +61,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr ""
@@ -246,7 +246,7 @@
 msgid "Tags"
 msgstr ""
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr ""
@@ -298,25 +298,29 @@
 msgid "Journal"
 msgstr ""
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+msgid "Authentication failed."
+msgstr ""
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr ""
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr ""
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr ""
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr ""
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr ""
 
@@ -457,11 +461,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -537,8 +541,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
@@ -670,11 +674,11 @@
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr ""
 
@@ -696,291 +700,283 @@
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 msgid "Hook already exists"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr ""
@@ -1024,11 +1020,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr ""
 
@@ -1061,165 +1057,165 @@
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, python-format
 msgid "Changeset %s not found"
 msgstr ""
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:735 kallithea/templates/changelog/changelog.html:43
+#: kallithea/lib/helpers.py:759 kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr ""
 
-#: kallithea/lib/helpers.py:759
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:794
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
-msgid "[updated] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:800
-msgid "[downloaded] archive from repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:802
-msgid "[delete] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:810
-msgid "[created] user"
-msgstr ""
-
-#: kallithea/lib/helpers.py:812
-msgid "[updated] user"
-msgstr ""
-
 #: kallithea/lib/helpers.py:814
-msgid "[created] user group"
-msgstr ""
-
-#: kallithea/lib/helpers.py:816
-msgid "[updated] user group"
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
+msgid "[created] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:818
-msgid "[commented] on revision in repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:820
-msgid "[commented] on pull request for"
-msgstr ""
-
-#: kallithea/lib/helpers.py:822
-msgid "[closed] pull request for"
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
+msgid "[updated] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:824
-msgid "[pushed] into"
+msgid "[downloaded] archive from repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:826
-msgid "[committed via Kallithea] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:828
-msgid "[pulled from remote] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:830
-msgid "[pulled] from"
-msgstr ""
-
-#: kallithea/lib/helpers.py:832
-msgid "[started following] repository"
+msgid "[delete] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:834
+msgid "[created] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:836
+msgid "[updated] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:838
+msgid "[created] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:840
+msgid "[updated] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:842
+msgid "[commented] on revision in repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:844
+msgid "[commented] on pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:846
+msgid "[closed] pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:848
+msgid "[pushed] into"
+msgstr ""
+
+#: kallithea/lib/helpers.py:850
+msgid "[committed via Kallithea] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:852
+msgid "[pulled from remote] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:854
+msgid "[pulled] from"
+msgstr ""
+
+#: kallithea/lib/helpers.py:856
+msgid "[started following] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1256,69 +1252,69 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr ""
 
@@ -1331,127 +1327,127 @@
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr ""
 
@@ -1477,33 +1473,33 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:167
+#, python-format
+msgid ""
+"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
+"%(pr_source_branch)s by %(pr_owner_username)s"
+msgstr ""
+
 #: kallithea/model/notification.py:168
 #, python-format
 msgid ""
-"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
-"%(pr_source_branch)s by %(pr_owner_username)s"
-msgstr ""
-
-#: kallithea/model/notification.py:169
-#, python-format
-msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr ""
 
@@ -1576,211 +1572,211 @@
 msgid "SSH key with fingerprint %r found"
 msgstr ""
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
 "owners or remove those repositories: %s"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch"
 " owners or remove those repository groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
 "owners or remove those user groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr ""
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or"
 " dashes and must begin with an alphanumeric character or underscore"
 msgstr ""
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:131
-msgid "Invalid user group name"
-msgstr ""
-
 #: kallithea/model/validators.py:132
+msgid "Invalid user group name"
+msgstr ""
+
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:174
-msgid "Cannot assign this group as parent"
-msgstr ""
-
 #: kallithea/model/validators.py:175
+msgid "Cannot assign this group as parent"
+msgstr ""
+
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr ""
 
+#: kallithea/model/validators.py:310
+#, python-format
+msgid "Repository name %(repo)s is not allowed"
+msgstr ""
+
+#: kallithea/model/validators.py:312
+#, python-format
+msgid "Repository named %(repo)s already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:313
 #, python-format
-msgid "Repository name %(repo)s is not allowed"
+msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
 #: kallithea/model/validators.py:315
 #, python-format
-msgid "Repository named %(repo)s already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:316
-#, python-format
-msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
-msgstr ""
-
-#: kallithea/model/validators.py:318
-#, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
 msgstr ""
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1840,7 +1836,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1848,14 +1844,14 @@
 msgid "Description"
 msgstr ""
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr ""
 
@@ -1865,7 +1861,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1889,7 +1885,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr ""
@@ -2013,7 +2009,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr ""
@@ -2260,7 +2256,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr ""
 
@@ -2344,13 +2340,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2366,14 +2362,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2673,7 +2669,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr ""
@@ -2694,7 +2690,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr ""
 
@@ -2864,7 +2860,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3026,14 +3022,10 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
+msgid "Remote"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3071,7 +3063,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr ""
@@ -3102,43 +3094,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr ""
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3649,6 +3612,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr ""
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3670,7 +3642,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr ""
@@ -3744,7 +3716,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr ""
@@ -3842,10 +3814,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr ""
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr ""
 
@@ -4512,23 +4486,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4560,6 +4534,11 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+msgid "View Comment"
+msgstr ""
+
 #: kallithea/templates/email_templates/comment.html:27
 msgid "Status change:"
 msgstr ""
@@ -4568,32 +4547,40 @@
 msgid "The pull request has been closed."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+msgid "Password Reset Request"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4624,6 +4611,10 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+msgid "View Pull Request"
+msgstr ""
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, python-format
 msgid "Mention in Comment on Pull Request %s \"%s\""
@@ -4639,10 +4630,18 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr ""
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+msgid "New User Registration"
+msgstr ""
+
+#: kallithea/templates/email_templates/registration.html:23
 msgid "Full Name"
 msgstr ""
 
+#: kallithea/templates/email_templates/registration.html:42
+msgid "View User Profile"
+msgstr ""
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5253,35 +5252,35 @@
 msgid "Show more"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr ""
 
--- a/kallithea/i18n/lb/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/lb/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -3,7 +3,7 @@
 msgid ""
 msgstr ""
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "Language: lb\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -55,7 +55,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr ""
@@ -243,7 +243,7 @@
 msgid "Tags"
 msgstr ""
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr ""
@@ -296,25 +296,29 @@
 msgid "Journal"
 msgstr ""
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+msgid "Authentication failed."
+msgstr ""
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr ""
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr ""
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr ""
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr ""
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr ""
 
@@ -457,11 +461,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -537,8 +541,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
@@ -670,11 +674,11 @@
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr ""
 
@@ -696,291 +700,283 @@
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 msgid "Hook already exists"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr ""
@@ -1024,11 +1020,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr ""
 
@@ -1063,166 +1059,166 @@
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, python-format
 msgid "Changeset %s not found"
 msgstr ""
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:735
-#: kallithea/templates/changelog/changelog.html:43
-msgid "revisions"
-msgstr ""
-
 #: kallithea/lib/helpers.py:759
+#: kallithea/templates/changelog/changelog.html:43
+msgid "revisions"
+msgstr ""
+
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:794
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
-msgid "[updated] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:800
-msgid "[downloaded] archive from repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:802
-msgid "[delete] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:810
-msgid "[created] user"
-msgstr ""
-
-#: kallithea/lib/helpers.py:812
-msgid "[updated] user"
-msgstr ""
-
 #: kallithea/lib/helpers.py:814
-msgid "[created] user group"
-msgstr ""
-
-#: kallithea/lib/helpers.py:816
-msgid "[updated] user group"
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
+msgid "[created] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:818
-msgid "[commented] on revision in repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:820
-msgid "[commented] on pull request for"
-msgstr ""
-
-#: kallithea/lib/helpers.py:822
-msgid "[closed] pull request for"
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
+msgid "[updated] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:824
-msgid "[pushed] into"
+msgid "[downloaded] archive from repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:826
-msgid "[committed via Kallithea] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:828
-msgid "[pulled from remote] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:830
-msgid "[pulled] from"
-msgstr ""
-
-#: kallithea/lib/helpers.py:832
-msgid "[started following] repository"
+msgid "[delete] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:834
+msgid "[created] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:836
+msgid "[updated] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:838
+msgid "[created] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:840
+msgid "[updated] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:842
+msgid "[commented] on revision in repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:844
+msgid "[commented] on pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:846
+msgid "[closed] pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:848
+msgid "[pushed] into"
+msgstr ""
+
+#: kallithea/lib/helpers.py:850
+msgid "[committed via Kallithea] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:852
+msgid "[pulled from remote] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:854
+msgid "[pulled] from"
+msgstr ""
+
+#: kallithea/lib/helpers.py:856
+msgid "[started following] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1259,69 +1255,69 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr ""
 
@@ -1334,129 +1330,129 @@
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr ""
 
@@ -1482,33 +1478,33 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:167
+#, python-format
+msgid ""
+"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
+"%(pr_source_branch)s by %(pr_owner_username)s"
+msgstr ""
+
 #: kallithea/model/notification.py:168
 #, python-format
 msgid ""
-"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
-"%(pr_source_branch)s by %(pr_owner_username)s"
-msgstr ""
-
-#: kallithea/model/notification.py:169
-#, python-format
-msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr ""
 
@@ -1582,213 +1578,213 @@
 msgid "SSH key with fingerprint %r found"
 msgstr ""
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
 "owners or remove those repositories: %s"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
 "owners or remove those repository groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
 "owners or remove those user groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr ""
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
 msgstr ""
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:131
-msgid "Invalid user group name"
-msgstr ""
-
 #: kallithea/model/validators.py:132
+msgid "Invalid user group name"
+msgstr ""
+
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:174
-msgid "Cannot assign this group as parent"
-msgstr ""
-
 #: kallithea/model/validators.py:175
+msgid "Cannot assign this group as parent"
+msgstr ""
+
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr ""
 
+#: kallithea/model/validators.py:310
+#, python-format
+msgid "Repository name %(repo)s is not allowed"
+msgstr ""
+
+#: kallithea/model/validators.py:312
+#, python-format
+msgid "Repository named %(repo)s already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:313
 #, python-format
-msgid "Repository name %(repo)s is not allowed"
+msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
 #: kallithea/model/validators.py:315
 #, python-format
-msgid "Repository named %(repo)s already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:316
-#, python-format
-msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
-msgstr ""
-
-#: kallithea/model/validators.py:318
-#, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
 msgstr ""
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1848,7 +1844,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1856,14 +1852,14 @@
 msgid "Description"
 msgstr ""
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr ""
 
@@ -1873,7 +1869,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1897,7 +1893,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr ""
@@ -2021,7 +2017,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr ""
@@ -2268,7 +2264,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr ""
 
@@ -2354,13 +2350,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2376,14 +2372,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2684,7 +2680,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr ""
@@ -2705,7 +2701,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr ""
 
@@ -2878,7 +2874,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3041,14 +3037,10 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
+msgid "Remote"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3086,7 +3078,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr ""
@@ -3117,43 +3109,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr ""
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3666,6 +3629,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr ""
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3687,7 +3659,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr ""
@@ -3761,7 +3733,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr ""
@@ -3861,10 +3833,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr ""
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr ""
 
@@ -4538,25 +4512,25 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 #, fuzzy
 #| msgid "There are no changesets yet"
 msgid "No changesets yet"
 msgstr "Et sinn nach keng Ännerungen do"
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4588,6 +4562,11 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+msgid "View Comment"
+msgstr ""
+
 #: kallithea/templates/email_templates/comment.html:27
 msgid "Status change:"
 msgstr ""
@@ -4596,32 +4575,40 @@
 msgid "The pull request has been closed."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+msgid "Password Reset Request"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4652,6 +4639,10 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+msgid "View Pull Request"
+msgstr ""
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, python-format
 msgid "Mention in Comment on Pull Request %s \"%s\""
@@ -4667,10 +4658,18 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr ""
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+msgid "New User Registration"
+msgstr ""
+
+#: kallithea/templates/email_templates/registration.html:23
 msgid "Full Name"
 msgstr ""
 
+#: kallithea/templates/email_templates/registration.html:42
+msgid "View User Profile"
+msgstr ""
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5285,35 +5284,35 @@
 msgid "Show more"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr ""
 
--- a/kallithea/i18n/nb_NO/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/nb_NO/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -4,7 +4,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3.99\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2019-04-30 22:25+0000\n"
 "Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n"
 "Language-Team: Norwegian Bokmål <https://hosted.weblate.org/projects/"
@@ -63,7 +63,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr "Slettet flettingsforespørsel %s"
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr "En slik revisjon funnes ikke for denne pakkebrønnen"
@@ -260,7 +260,7 @@
 msgid "Tags"
 msgstr "Etiketter"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr "En uventet feil inntraff under forgrening av pakkebrønnen %s"
@@ -314,26 +314,32 @@
 msgid "Journal"
 msgstr "Loggbok"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+#, fuzzy
+#| msgid "Authentication"
+msgid "Authentication failed."
+msgstr "Identitetsbekreftelse"
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 #, fuzzy
 msgid "Bad captcha"
 msgstr "Feilaktig CAPTCHA"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, fuzzy, python-format
 msgid "You have successfully registered with %s"
 msgstr "Du har registrer deg på %s"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr "Passordbekreftelseskode sendt"
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Ugyldig passordtilbakestillingssymbol"
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Passord oppdatert"
 
@@ -477,11 +483,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr "Statistikk er avskrudd for denne pakkebrønnen"
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr "Autentiseringsinnstillinger oppdatert"
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr "feil inntraff under oppdatering av autentiseringsinnstillinger"
 
@@ -557,8 +563,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr "Feil inntraff under oppdatering av gist-en %s"
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 "Du kan ikke endre denne brukeren siden den er avgjørende for hele "
@@ -697,11 +703,11 @@
 msgid "Allowed with automatic account activation"
 msgstr "Tillatt med automatisk kontoaktivering"
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr "Manuell aktivering av ekstern konto"
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr "Automatisk aktivering av ekstern konto"
 
@@ -724,298 +730,290 @@
 msgid "Error occurred during update of permissions"
 msgstr "Feil inntraff under oppdatering av tilganger"
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr "Feil inntraff under opprettelse av pakkebrønnsgruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr "Opprettet pakkebrønnsgruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Oppdaterte pakkebrønnsgruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr "Feil inntraff under oppdatering av pakkebrønnsgruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "Denne gruppen inneholder %s pakkebrønner og kan ikke slettes"
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr "Denne grunnen inneholder %s undergrupper og kan ikke slettes"
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Fjernet pakkebrønnsgruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr "Feil inntraff under sletting av pakkebrønnsgruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 #, fuzzy
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Kan ikke tilbakekalle egen administratortilgang"
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr "Pakkebrønnsgruppetilganger oppdatert"
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr "En feil inntraff under tilbakekalling av tilgang"
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Feil under opprettelse av pakkebrønnen %s"
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Opprettet pakkebrønnen %s fra %s"
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Forgrenet pakkebrønnen %s som %s"
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr "Opprettet pakkebrønnen %s"
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Pakkebrønnen %s ble oppdatert"
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "Feil under oppdatering av pakkebrønnen %s"
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr "Avhektet %s forgreninger"
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr "Slettet %s forgreninger"
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Slettet pakkebrønnen %s"
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr "Kan ikke slette pakkebrønne %s, som fremdeles har forgreninger"
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "En feil inntraff under sletting av %s"
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr "Pakkebrønnstilganger oppdatert"
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr "Feil inntraff under fjerning av felt"
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr "-- Ikke en forgrening --"
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr "Oppdaterte pakkebrønnssynlighet i offentlig loggbok"
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 #, fuzzy
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 "En feil inntraff under innlemmelse av denne pakkebrønnen i offentlig "
 "loggbok"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr "Ingenting"
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "Markerte pakkebrønnen %s som en forgrening av %s"
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr "En feil inntraff under denne operasjonen"
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr "Oppdaterte VCS-innstillinger"
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr "Skriv inn e-postadresse"
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "Ingen data klar enda"
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr "Opprettet brukergruppe %s"
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr "Oppdaterte brukergruppe %s"
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 #, fuzzy
 msgid "Successfully deleted user group"
 msgstr "Brukergruppe slettet"
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr ""
@@ -1059,11 +1057,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr "Fjernet IP-adressen fra brukerhvitlisten"
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr ""
 
@@ -1098,174 +1096,174 @@
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, python-format
 msgid "Changeset %s not found"
 msgstr ""
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:735
-#: kallithea/templates/changelog/changelog.html:43
-msgid "revisions"
-msgstr ""
-
 #: kallithea/lib/helpers.py:759
+#: kallithea/templates/changelog/changelog.html:43
+msgid "revisions"
+msgstr ""
+
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr "Forgreningsnavn %s"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr "Flettingsforespørsel %s"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:814
 #, fuzzy
 msgid "[deleted] repository"
 msgstr "[slettet] pakkebrønn"
 
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
 #, fuzzy
 msgid "[created] repository"
 msgstr "[opprettet] pakkebrønn"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:818
 msgid "[created] repository as fork"
 msgstr "[opprettet] pakkebrønn som forgrening"
 
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
 #, fuzzy
 msgid "[forked] repository"
 msgstr "[forgrenet] pakkebrønn"
 
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
 #, fuzzy
 msgid "[updated] repository"
 msgstr "[oppdaterte] pakkebrønn"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:824
 #, fuzzy
 msgid "[downloaded] archive from repository"
 msgstr "[lastet ned] arkiv fra pakkebrønn"
 
-#: kallithea/lib/helpers.py:802
+#: kallithea/lib/helpers.py:826
 #, fuzzy
 msgid "[delete] repository"
 msgstr "[slett] pakkebrønn"
 
-#: kallithea/lib/helpers.py:810
+#: kallithea/lib/helpers.py:834
 msgid "[created] user"
 msgstr "[opprettet] bruker"
 
-#: kallithea/lib/helpers.py:812
+#: kallithea/lib/helpers.py:836
 msgid "[updated] user"
 msgstr "[oppdaterte] bruker"
 
-#: kallithea/lib/helpers.py:814
+#: kallithea/lib/helpers.py:838
 msgid "[created] user group"
 msgstr "[opprettet] brukergruppe"
 
-#: kallithea/lib/helpers.py:816
+#: kallithea/lib/helpers.py:840
 msgid "[updated] user group"
 msgstr "[oppdaterte] brukergruppe"
 
-#: kallithea/lib/helpers.py:818
+#: kallithea/lib/helpers.py:842
 #, fuzzy
 msgid "[commented] on revision in repository"
 msgstr "[kommenterte] en revisjon i pakkebrønn"
 
-#: kallithea/lib/helpers.py:820
+#: kallithea/lib/helpers.py:844
 msgid "[commented] on pull request for"
 msgstr "[kommenterte] flettingsforespørsel for"
 
-#: kallithea/lib/helpers.py:822
+#: kallithea/lib/helpers.py:846
 msgid "[closed] pull request for"
 msgstr "[lukket] flettingsforespørsel for"
 
-#: kallithea/lib/helpers.py:824
+#: kallithea/lib/helpers.py:848
 msgid "[pushed] into"
 msgstr "[dyttet] til"
 
-#: kallithea/lib/helpers.py:826
+#: kallithea/lib/helpers.py:850
 #, fuzzy
 msgid "[committed via Kallithea] into repository"
 msgstr "[innsendt via Kallithea] inn i pakkebrønn"
 
-#: kallithea/lib/helpers.py:828
+#: kallithea/lib/helpers.py:852
 msgid "[pulled from remote] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:830
+#: kallithea/lib/helpers.py:854
 msgid "[pulled] from"
 msgstr ""
 
-#: kallithea/lib/helpers.py:832
+#: kallithea/lib/helpers.py:856
 msgid "[started following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:834
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "Ingen filer"
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr "ny fil"
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1302,69 +1300,69 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] "%d år"
 msgstr[1] "%d år"
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] "%d måned"
 msgstr[1] "%d måneder"
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] "%d dag"
 msgstr[1] "%d dager"
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] "%d time"
 msgstr[1] "%d timer"
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] "%d minutt"
 msgstr[1] "%d minutter"
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] "%d sekund"
 msgstr[1] "%d sekunder"
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr "om %s"
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr "for %s siden"
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr "om %s og %s"
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s og %s siden"
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr "akkurat nå"
 
@@ -1377,130 +1375,130 @@
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr "toppnivå"
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr "Kallithea-administrator"
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 #, fuzzy
 msgid "Default user has no access to new repositories"
 msgstr "Forvalgt bruker har ingen tilgang til nye pakkebrønner"
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 msgid "Not approved"
 msgstr "Ikke godkjent"
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr "Godkjent"
 
@@ -1526,33 +1524,33 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:167
+#, python-format
+msgid ""
+"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
+"%(pr_source_branch)s by %(pr_owner_username)s"
+msgstr ""
+
 #: kallithea/model/notification.py:168
 #, python-format
 msgid ""
-"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
-"%(pr_source_branch)s by %(pr_owner_username)s"
-msgstr ""
-
-#: kallithea/model/notification.py:169
-#, python-format
-msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr "Lukker"
 
@@ -1626,213 +1624,213 @@
 msgid "SSH key with fingerprint %r found"
 msgstr ""
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
 "owners or remove those repositories: %s"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
 "owners or remove those repository groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
 "owners or remove those user groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr ""
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "Brukernavnet \"%(username)s\" finnes allerede"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "Brukernavnet \"%(username)s\" kan ikke brukes"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
 msgstr ""
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:131
+#: kallithea/model/validators.py:132
 msgid "Invalid user group name"
 msgstr "Ugyldig brukergruppenavn"
 
-#: kallithea/model/validators.py:132
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr "Brukergruppen \"%(usergroup)s\" finnes allerede"
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:174
-msgid "Cannot assign this group as parent"
-msgstr ""
-
 #: kallithea/model/validators.py:175
+msgid "Cannot assign this group as parent"
+msgstr ""
+
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr "Ugyldig gammelt passord"
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr "Passordene samsvarer ikke"
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr "Ugyldig brukernavn eller passord"
 
-#: kallithea/model/validators.py:313
+#: kallithea/model/validators.py:310
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr ""
 
+#: kallithea/model/validators.py:312
+#, python-format
+msgid "Repository named %(repo)s already exists"
+msgstr ""
+
+#: kallithea/model/validators.py:313
+#, python-format
+msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
+msgstr ""
+
 #: kallithea/model/validators.py:315
 #, python-format
-msgid "Repository named %(repo)s already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:316
-#, python-format
-msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
-msgstr ""
-
-#: kallithea/model/validators.py:318
-#, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr "Ugyldig pakkebrønnsnettadresse"
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr "Dette er ikke en gyldig sti"
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr "E-postadressen er allerede i bruk"
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, fuzzy, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "Fant ikke e-postadressen \"%(email)s\""
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
 msgstr ""
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr "Skriv inn en gyldig IPv4- eller IPv6-adresse"
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1893,7 +1891,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1901,14 +1899,14 @@
 msgid "Description"
 msgstr "Beskrivelse"
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr "Siste endring"
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr "Tips"
 
@@ -1918,7 +1916,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1942,7 +1940,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr "Brukernavn"
@@ -2072,7 +2070,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr "E-post"
@@ -2320,7 +2318,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr "Opprettet"
 
@@ -2404,13 +2402,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2426,14 +2424,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2741,7 +2739,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr ""
@@ -2762,7 +2760,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr "Brukergruppe"
 
@@ -2935,7 +2933,7 @@
 msgstr "Opprettet den"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, fuzzy, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3098,14 +3096,10 @@
 msgstr "Ekstra felter"
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
+msgid "Remote"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3143,7 +3137,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr ""
@@ -3174,43 +3168,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr "Etikett"
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr "Nøkkel"
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr "Aktiv"
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr "Etikett"
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3726,6 +3691,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr "Aktiv"
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3747,7 +3721,7 @@
 msgstr "Medlemmer"
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, fuzzy, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr "Bekreft sletting av denne brukergruppen: %s"
@@ -3821,7 +3795,7 @@
 msgstr "Medlem av brukergrupper"
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, fuzzy, python-format
 msgid "Confirm to delete this user: %s"
 msgstr "Bekreft sletting av denne brukeren: %s"
@@ -3923,10 +3897,12 @@
 msgstr "Søk"
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr "Følg"
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr ""
 
@@ -4608,23 +4584,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4656,6 +4632,13 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "%s committed on %s"
+msgid "View Comment"
+msgstr "%s sendte inn %s"
+
 #: kallithea/templates/email_templates/comment.html:27
 msgid "Status change:"
 msgstr ""
@@ -4664,32 +4647,42 @@
 msgid "The pull request has been closed."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+#, fuzzy
+#| msgid "Password Reset"
+msgid "Password Reset Request"
+msgstr "Passordstilbakestilling"
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4722,6 +4715,11 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+msgid "View Pull Request"
+msgstr "Flettingsforespørsler"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, python-format
 msgid "Mention in Comment on Pull Request %s \"%s\""
@@ -4737,10 +4735,20 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr ""
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+#, fuzzy
+#| msgid "Registration"
+msgid "New User Registration"
+msgstr "Registrering"
+
+#: kallithea/templates/email_templates/registration.html:23
 msgid "Full Name"
 msgstr ""
 
+#: kallithea/templates/email_templates/registration.html:42
+msgid "View User Profile"
+msgstr ""
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5351,35 +5359,35 @@
 msgid "Show more"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr ""
 
--- a/kallithea/i18n/nl_BE/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/nl_BE/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -5,7 +5,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2019-10-05 19:28+0000\n"
 "Last-Translator: Thomas De Schampheleire <patrickdepinguin@gmail.com>\n"
 "Language-Team: Flemish <https://hosted.weblate.org/projects/kallithea/"
@@ -63,7 +63,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr "Deze revisie bestaat niet in deze repository"
@@ -256,7 +256,7 @@
 msgid "Tags"
 msgstr "Tags"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr "Er is een fout opgetreden tijdens het forken van de repository %s"
@@ -309,25 +309,29 @@
 msgid "Journal"
 msgstr "Logboek"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+msgid "Authentication failed."
+msgstr ""
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr "Incorrecte captcha"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "U bent succesvol geregistreerd bij %s"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr "Een paswoordherstel bevestigingscode is verzonden"
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Ongeldig paswoordherstel token"
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Paswoord succesvol aangepast"
 
@@ -469,11 +473,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -549,8 +553,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
@@ -682,11 +686,11 @@
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr ""
 
@@ -708,291 +712,283 @@
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr "Er is een fout opgetreden tijdens het aanmaken van veld: %r"
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 msgid "Hook already exists"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr ""
@@ -1036,11 +1032,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr ""
 
@@ -1075,166 +1071,166 @@
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, python-format
 msgid "Changeset %s not found"
 msgstr "Changeset %s werd niet gevonden"
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:735
-#: kallithea/templates/changelog/changelog.html:43
-msgid "revisions"
-msgstr ""
-
 #: kallithea/lib/helpers.py:759
+#: kallithea/templates/changelog/changelog.html:43
+msgid "revisions"
+msgstr ""
+
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:794
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
-msgid "[updated] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:800
-msgid "[downloaded] archive from repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:802
-msgid "[delete] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:810
-msgid "[created] user"
-msgstr ""
-
-#: kallithea/lib/helpers.py:812
-msgid "[updated] user"
-msgstr ""
-
 #: kallithea/lib/helpers.py:814
-msgid "[created] user group"
-msgstr ""
-
-#: kallithea/lib/helpers.py:816
-msgid "[updated] user group"
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
+msgid "[created] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:818
-msgid "[commented] on revision in repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:820
-msgid "[commented] on pull request for"
-msgstr ""
-
-#: kallithea/lib/helpers.py:822
-msgid "[closed] pull request for"
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
+msgid "[updated] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:824
-msgid "[pushed] into"
+msgid "[downloaded] archive from repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:826
-msgid "[committed via Kallithea] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:828
-msgid "[pulled from remote] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:830
-msgid "[pulled] from"
-msgstr ""
-
-#: kallithea/lib/helpers.py:832
-msgid "[started following] repository"
+msgid "[delete] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:834
+msgid "[created] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:836
+msgid "[updated] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:838
+msgid "[created] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:840
+msgid "[updated] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:842
+msgid "[commented] on revision in repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:844
+msgid "[commented] on pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:846
+msgid "[closed] pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:848
+msgid "[pushed] into"
+msgstr ""
+
+#: kallithea/lib/helpers.py:850
+msgid "[committed via Kallithea] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:852
+msgid "[pulled from remote] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:854
+msgid "[pulled] from"
+msgstr ""
+
+#: kallithea/lib/helpers.py:856
+msgid "[started following] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1271,69 +1267,69 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr ""
 
@@ -1346,129 +1342,129 @@
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr ""
 
@@ -1494,33 +1490,33 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:167
+#, python-format
+msgid ""
+"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
+"%(pr_source_branch)s by %(pr_owner_username)s"
+msgstr ""
+
 #: kallithea/model/notification.py:168
 #, python-format
 msgid ""
-"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
-"%(pr_source_branch)s by %(pr_owner_username)s"
-msgstr ""
-
-#: kallithea/model/notification.py:169
-#, python-format
-msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr ""
 
@@ -1595,213 +1591,213 @@
 msgid "SSH key with fingerprint %r found"
 msgstr "SSH key %r werd niet gevonden"
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
 "owners or remove those repositories: %s"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
 "owners or remove those repository groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
 "owners or remove those user groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr ""
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
 msgstr ""
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:131
-msgid "Invalid user group name"
-msgstr ""
-
 #: kallithea/model/validators.py:132
+msgid "Invalid user group name"
+msgstr ""
+
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:174
-msgid "Cannot assign this group as parent"
-msgstr ""
-
 #: kallithea/model/validators.py:175
+msgid "Cannot assign this group as parent"
+msgstr ""
+
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr ""
 
+#: kallithea/model/validators.py:310
+#, python-format
+msgid "Repository name %(repo)s is not allowed"
+msgstr ""
+
+#: kallithea/model/validators.py:312
+#, python-format
+msgid "Repository named %(repo)s already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:313
 #, python-format
-msgid "Repository name %(repo)s is not allowed"
+msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
 #: kallithea/model/validators.py:315
 #, python-format
-msgid "Repository named %(repo)s already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:316
-#, python-format
-msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
-msgstr ""
-
-#: kallithea/model/validators.py:318
-#, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
 msgstr ""
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1861,7 +1857,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1869,14 +1865,14 @@
 msgid "Description"
 msgstr ""
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr ""
 
@@ -1886,7 +1882,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1910,7 +1906,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr ""
@@ -2034,7 +2030,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr ""
@@ -2281,7 +2277,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr ""
 
@@ -2365,13 +2361,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2387,14 +2383,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2695,7 +2691,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr ""
@@ -2716,7 +2712,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr ""
 
@@ -2889,7 +2885,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3052,14 +3048,10 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
+msgid "Remote"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3097,7 +3089,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr ""
@@ -3128,43 +3120,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr ""
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3677,6 +3640,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr ""
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3698,7 +3670,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr ""
@@ -3772,7 +3744,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr ""
@@ -3872,10 +3844,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr ""
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr ""
 
@@ -4543,23 +4517,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4591,6 +4565,13 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "comment"
+msgid "View Comment"
+msgstr "opmerking"
+
 #: kallithea/templates/email_templates/comment.html:27
 msgid "Status change:"
 msgstr "Statuswijziging:"
@@ -4599,32 +4580,40 @@
 msgid "The pull request has been closed."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+msgid "Password Reset Request"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4655,6 +4644,12 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+#| msgid "Pull request"
+msgid "View Pull Request"
+msgstr "Pull request"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, python-format
 msgid "Mention in Comment on Pull Request %s \"%s\""
@@ -4670,10 +4665,18 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr "Opmerking bij pull request %s \"%s\""
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+msgid "New User Registration"
+msgstr ""
+
+#: kallithea/templates/email_templates/registration.html:23
 msgid "Full Name"
 msgstr ""
 
+#: kallithea/templates/email_templates/registration.html:42
+msgid "View User Profile"
+msgstr ""
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5284,35 +5287,35 @@
 msgid "Show more"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr ""
 
--- a/kallithea/i18n/pl/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/pl/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -4,7 +4,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2020-01-27 15:21+0000\n"
 "Last-Translator: robertus <robertuss12@gmail.com>\n"
 "Language-Team: Polish <https://hosted.weblate.org/projects/kallithea/"
@@ -64,7 +64,7 @@
 msgstr ""
 "Prośba o skasowanie połączenia gałęzi %s została wykonana prawidłowo"
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr ""
@@ -257,7 +257,7 @@
 msgid "Tags"
 msgstr "Etykiety"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr "Wystąpił błąd podczas rozgałęzienia %s repozytorium"
@@ -310,25 +310,31 @@
 msgid "Journal"
 msgstr "Dziennik"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+#, fuzzy
+#| msgid "Authentication"
+msgid "Authentication failed."
+msgstr "Autentykacja"
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr ""
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "Udało Ci się zarejestrować w %s"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr "Twój link zresetowania hasła został wysłany"
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Nieprawidłowy token resetowania hasła"
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Pomyślnie zaktualizowano hasło"
 
@@ -472,11 +478,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr "Statystyki są wyłączone dla tego repozytorium"
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr "Ustawienia autentykacji poprawnie zaktualizowane"
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr "wystąpił błąd podczas uaktualniania ustawień autentykacji"
 
@@ -552,8 +558,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 "Nie możesz edytować tego użytkownika ponieważ jest kluczowy dla całej "
@@ -689,11 +695,11 @@
 msgid "Allowed with automatic account activation"
 msgstr "Dozwolona z automatyczną aktywacją konta"
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr "Ręczna aktywacja nowego konta"
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr "Automatyczna aktywacja nowego konta"
 
@@ -715,295 +721,287 @@
 msgid "Error occurred during update of permissions"
 msgstr "Wystąpił błąd podczas aktualizacji uprawnień"
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr "Wystąpił błąd podczas tworzenia grupy repo %s"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr "Utworzono grupę repo %s"
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Zaktualizowano grupę repo %s"
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr "Wystąpił błąd podczas aktualizacji grupy repo %s"
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "Ta grupa zawiera %s repozytorium i nie może być usunięta"
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr "Ta grupa zawiera %s repozytorium i nie może być usunięta"
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Usunięto grupę repo %s"
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr "Wystąpił błąd podczas usuwania z repozytorium grupy %s"
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Nie można cofnąć zezwolenia dla admina jako admin"
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr "Aktualizacja uprawnień grup repozytorium"
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr "Wystąpił błąd podczas cofania zezwolenia"
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Błąd podczas tworzenia repozytorium %s"
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "utworzone repozytorium %s z %s"
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Gałęzi %s w repozytorium %s"
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr "Utworzone repozytorium %s"
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Repozytorium %s zostało pomyślnie zaktualizowane"
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "Wystąpił błąd podczas aktualizacji repozytorium %s"
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr "Oderwane rozgałęzienie %s"
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr "Usunięte rozgałęzienia %s"
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Usunięte repozytorium %s"
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 "Nie można usunąć repozytorium %s nadal zawiera załączniki rozgałęzienia"
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "Wystąpił błąd podczas usuwania %s"
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr "Uprawnienia repozytorium zostały zaktualizowane"
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr "Wystąpił błąd podczas tworzenia pola: %r"
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr "Wystąpił błąd podczas usuwania pola"
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr "-- Brak rozgałęzienia --"
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr "Zaktualizowano widoczność stron w publicznym dzienniku"
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 "Wystąpił błąd podczas ustawiania tego repozytorium w dzienniku publicznym"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr "Brak"
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "Oznaczono %s repo jako rozwidlenie %s"
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr "Wystąpił błąd podczas tej operacji"
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr "Cache wyczyszczony poprawnie"
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr "Wystąpił błąd podczas unieważniania cache"
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr "Pobieranie z lokalizacji zdalnej"
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr "Wystąpił błąd podczas pobierania z lokalizacji zdalnej"
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr "Wystąpił błąd podczas usuwania z repozytorium statystyk"
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr "Aktualizacja ustawień VCS"
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr "Wystąpił błąd podczas aktualizacji ustawień aplikacji"
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 "Repozytoria z powodzeniem zostały ponownie zeskanowane dodano: %s, "
 "usunięto: %s."
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr "Unieważnione %s repozytoria"
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr "Aktualizacja ustawień aplikacji"
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr "Aktualizacja ustawień wizualizacji"
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr "Wystąpił błąd podczas aktualizacji ustawień wizualizacji"
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr "Proszę podać adres email"
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 msgid "Hook already exists"
 msgstr "Hook już istnieje"
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr "Dodano nowy hook"
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr "Aktualizacja hooku"
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr "Wystąpił błąd podczas tworzenia hooku"
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr "Zadanie ponownej indeksacji whoosh zostało zaplanowane"
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr "Utworzono grupę użytkowników %s"
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr "Wystąpił błąd podczas tworzenia grupy użytkowników %s"
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr "Zaktualizowano grupę użytkowników %s"
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr "Wystąpił błąd podczas aktualizacji grupy użytkowników %s"
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr "Grupa użytkowników została usunięta z powodzeniem"
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr "Wystąpił błąd podczas usuwania grupy użytkowników"
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr "Grupa docelowa nie może być taka sama"
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr "Aktualizacja uprawnień grupy użytkowników"
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr "Aktualizacja uprawnień"
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr "Wystąpił błąd podczas zapisywania uprawnień"
@@ -1047,11 +1045,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr "Usunięto adres ip z listy dozwolonych adresów dla użytkownika"
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr "Musisz być zarejestrowanym użytkownikiem, żeby wykonać to działanie"
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr "Musisz być zalogowany, żeby oglądać stronę"
 
@@ -1091,166 +1089,166 @@
 msgid "No changes detected"
 msgstr "Nie wykryto zmian"
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "Usunięta gałąź: %s"
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr "Utworzony tag: %s"
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, python-format
 msgid "Changeset %s not found"
 msgstr "Nie znaleziono changeset %s"
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "Pokaż wszystkie zestawienia zmian changesets %s->%s"
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr "Wyświetl porównanie"
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr "i"
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr "%s więcej"
 
-#: kallithea/lib/helpers.py:735
+#: kallithea/lib/helpers.py:759
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "rewizja"
 
-#: kallithea/lib/helpers.py:759
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr "nazwa rozgałęzienia %s"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, fuzzy, python-format
 msgid "Pull request %s"
 msgstr "Połączonych gałęzi #%s"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:814
 msgid "[deleted] repository"
 msgstr "[usunięte] repozytorium"
 
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
 msgid "[created] repository"
 msgstr "[utworzone] repozytorium"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:818
 msgid "[created] repository as fork"
 msgstr "[utworzone] repozytorium jako rozgałęzienie"
 
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
 msgid "[forked] repository"
 msgstr "[rozgałęzione] repozytorium"
 
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
 msgid "[updated] repository"
 msgstr "[zaktualizowane] repozytorium"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:824
 msgid "[downloaded] archive from repository"
 msgstr "[pobierz] archiwum z repozytorium"
 
-#: kallithea/lib/helpers.py:802
+#: kallithea/lib/helpers.py:826
 msgid "[delete] repository"
 msgstr "[skasowane] repozytorium"
 
-#: kallithea/lib/helpers.py:810
+#: kallithea/lib/helpers.py:834
 msgid "[created] user"
 msgstr "[utworzony] użytkownik"
 
-#: kallithea/lib/helpers.py:812
+#: kallithea/lib/helpers.py:836
 msgid "[updated] user"
 msgstr "[zaktualizowany] użytkownik"
 
-#: kallithea/lib/helpers.py:814
+#: kallithea/lib/helpers.py:838
 msgid "[created] user group"
 msgstr "[utworzona] grupa użytkowników"
 
-#: kallithea/lib/helpers.py:816
+#: kallithea/lib/helpers.py:840
 msgid "[updated] user group"
 msgstr "[zaktualizowana] grupa użytkowników"
 
-#: kallithea/lib/helpers.py:818
+#: kallithea/lib/helpers.py:842
 msgid "[commented] on revision in repository"
 msgstr "[komentarz] do zmiany w repozytorium"
 
-#: kallithea/lib/helpers.py:820
+#: kallithea/lib/helpers.py:844
 msgid "[commented] on pull request for"
 msgstr "[komentarz] wniosek o połączenie gałęzi"
 
-#: kallithea/lib/helpers.py:822
+#: kallithea/lib/helpers.py:846
 msgid "[closed] pull request for"
 msgstr "[zamknięty] wniosek o połączenie gałęzi"
 
-#: kallithea/lib/helpers.py:824
+#: kallithea/lib/helpers.py:848
 msgid "[pushed] into"
 msgstr "[wysłane zmiany] w"
 
-#: kallithea/lib/helpers.py:826
+#: kallithea/lib/helpers.py:850
 msgid "[committed via Kallithea] into repository"
 msgstr "[synchronizacja przez Kallithea] z repozytorium"
 
-#: kallithea/lib/helpers.py:828
+#: kallithea/lib/helpers.py:852
 msgid "[pulled from remote] into repository"
 msgstr "[pobieranie z zdalnego] do repozytorium"
 
-#: kallithea/lib/helpers.py:830
+#: kallithea/lib/helpers.py:854
 msgid "[pulled] from"
 msgstr "[pobrano]"
 
-#: kallithea/lib/helpers.py:832
+#: kallithea/lib/helpers.py:856
 msgid "[started following] repository"
 msgstr "[start następnego] repozytorium"
 
-#: kallithea/lib/helpers.py:834
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr "[zatrzymany po] repozytorium"
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr " i %s więcej"
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "Brak plików"
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr "nowy plik"
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr "modyfikuj"
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr "kasuj"
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr "zmień nazwę"
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1290,7 +1288,7 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
@@ -1298,7 +1296,7 @@
 msgstr[1] "%d lata"
 msgstr[2] "%d lat"
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
@@ -1306,7 +1304,7 @@
 msgstr[1] "%d miesięcy"
 msgstr[2] "%d miesięcy"
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
@@ -1314,7 +1312,7 @@
 msgstr[1] "%d dni"
 msgstr[2] "%d dni"
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
@@ -1322,7 +1320,7 @@
 msgstr[1] "%d godziny"
 msgstr[2] "%d godzin"
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
@@ -1330,7 +1328,7 @@
 msgstr[1] "%d minuty"
 msgstr[2] "%d minut"
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
@@ -1338,27 +1336,27 @@
 msgstr[1] "%d sekund"
 msgstr[2] "%d sekund"
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr "w %s"
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr "%s temu"
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr "w %s i %s"
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s i %s temu"
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr "przed chwilą"
 
@@ -1371,140 +1369,140 @@
 msgid "[Mention]"
 msgstr "[Wymieniony]"
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr "najwyższy poziom"
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr "Administrator Kallithea"
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr "Użytkownik domyślny ma dostęp do odczytu nowych repozytoriów"
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr "Użytkownik domyślny ma dostęp do zapisu nowych repozytoriów"
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 #, fuzzy
 msgid "Only admins can create repository groups"
 msgstr "Tylko admini mogą tworzyć grupy repozytoriów"
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 #, fuzzy
 msgid "Non-admins can create repository groups"
 msgstr ""
 "Użytkownicy bez uprawnień administratora mogą tworzyć grupy repozytoriów"
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 #, fuzzy
 msgid "Only admins can create user groups"
 msgstr "Tylko admini mogą tworzyć grupy użytkowników"
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 #, fuzzy
 msgid "Non-admins can create user groups"
 msgstr ""
 "Użytkownicy bez uprawnień administratora mogą tworzyć grupy użytkowników"
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 #, fuzzy
 msgid "Only admins can fork repositories"
 msgstr "Tylko admini mogą rozgałęziać repozytoria"
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 #, fuzzy
 msgid "Non-admins can fork repositories"
 msgstr ""
 "Użytkownicy bez uprawnień administratora mogą rozgałęziać repozytoria"
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr "Rejestracja wyłączona"
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr "Rejestracja użytkownika z ręczną aktywacją konta"
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr "Rejestracja użytkownika z automatyczną aktywacją konta"
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr "Brak Korekty"
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr "Objęty Przeglądem"
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 #, fuzzy
 #| msgid "Approved"
 msgid "Not approved"
 msgstr "Niezaakceptowano"
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr "Zaakceptowano"
 
@@ -1530,7 +1528,7 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, fuzzy, python-format
 #| msgid "[Comment] %(repo_name)s pull request %(pr_nice_id)s from %(ref)s"
 msgid ""
@@ -1538,26 +1536,26 @@
 "%(branch)s"
 msgstr "[komentarz] wniosek o połączenie gałęzi"
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr "Użytkownik %(new_username)s zarejestrował się"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid ""
 "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:169
+#: kallithea/model/notification.py:168
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 #, fuzzy
 msgid "Closing"
 msgstr "Zamykanie"
@@ -1638,18 +1636,18 @@
 msgid "SSH key with fingerprint %r found"
 msgstr "Nie znaleziono changeset %s"
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr "nowy użytkownik się zarejestrował"
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 "Nie możesz usunąć tego użytkownika ponieważ jest kluczowy dla całej "
 "aplikacji"
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
@@ -1658,7 +1656,7 @@
 "użytkownik \"%s\" wciąż posiada repozytoria następujące %s i nie może "
 "zostać usunięty. Zmień właściciela lub usuń te repozytoria: %s"
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
@@ -1667,7 +1665,7 @@
 "użytkownik \"%s\" wciąż posiada repozytoria następujące %s i nie może "
 "zostać usunięty. Zmień właściciela lub usuń te repozytoria: %s"
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
@@ -1676,37 +1674,37 @@
 "użytkownik \"%s\" wciąż posiada repozytoria następujące %s i nie może "
 "zostać usunięty. Zmień właściciela lub usuń te grupy użytkowników: %s"
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr "łącze resetowania hasła"
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 #, fuzzy
 msgid "Password reset notification"
 msgstr "Powiadomienie o resetowaniu hasła"
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr "Wartość listy nie może być pusta"
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "Użytkownik \"%(username)s\" już istnieje"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, fuzzy, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "Nazwa użytkownika \"%(username)s\" nie może być użyta"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 #, fuzzy
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
@@ -1716,25 +1714,25 @@
 "kropki lub myślniki i musi zaczynać się znakiem alfanumerycznym lub "
 "podkreśleniem"
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr "Nazwa użytkownika %(username)s jest nieprawidłowa"
 
-#: kallithea/model/validators.py:131
+#: kallithea/model/validators.py:132
 msgid "Invalid user group name"
 msgstr "Niewłaściwa nazwa grupy"
 
-#: kallithea/model/validators.py:132
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr "Nazwa grupy \"%(usergroup)s\" już istnieje"
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
@@ -1742,102 +1740,102 @@
 "nazwa grupy może zawierać tylko znaki alfanumeryczne, podkreślenia, "
 "kropki lub myślniki i musi zaczynać się znakiem alfanumerycznym"
 
-#: kallithea/model/validators.py:174
+#: kallithea/model/validators.py:175
 msgid "Cannot assign this group as parent"
 msgstr "Nie można przypisać do tej grupy jako rodzic"
 
-#: kallithea/model/validators.py:175
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr "Nazwa grupy \"%(group_name)s\" już istnieje"
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr "Repozytorium o nazwie \"%(group_name)s\" już istnieje"
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr "Nieprawidłowe znaki (nie-ascii) w haśle"
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr "Hasła różnią się"
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 #, fuzzy
 msgid "Invalid username or password"
 msgstr "nieprawidłowa nazwa użytkownika lub hasło"
 
-#: kallithea/model/validators.py:313
+#: kallithea/model/validators.py:310
 #, fuzzy, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr "Nazwa repozytorium  %(repo)s jest zabroniona"
 
-#: kallithea/model/validators.py:315
+#: kallithea/model/validators.py:312
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr "Repozytorium o nazwie %(repo)s już istnieje"
 
-#: kallithea/model/validators.py:316
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr "Repozytorium  \"%(repo)s\" już istnieje w grupie \"%(group)s\""
 
-#: kallithea/model/validators.py:318
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr "Grupa repozytoriów z nazwą \"%(repo)s\" już istnieje"
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 #, fuzzy
 msgid "Invalid repository URL"
 msgstr "Nieprawidłowy URL repozytorium"
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr "Fork musi być tego samego typu, jak rodzic"
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr "Nie masz uprawnień do tworzenia repozytorium w tej grupie"
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr "nie masz uprawnień do tworzenia repozytorium w tej lokacji roota"
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr "Nie masz uprawnień do tworzenia grupy w tym miejscu"
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr "Ta nazwa użytkownika lub grupy użytkowników nie jest prawidłowa"
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr "To nie jest prawidłowa ścieżka"
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr "Ten adres e-mail jest już zajęty"
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "e-mail \"%(email)s\" nie istnieje"
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
@@ -1845,28 +1843,28 @@
 "Atrybut logowania CN do LDAP należy określić, jest to nazwa atrybutu, "
 "który jest odpowiednikiem  \"username\""
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr "Proszę podać poprawny adres IPv4 lub IPv6"
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 "Rozmiar sieci (bits) może mieścić się w zakresie od 0-32 (nie %(bits)r)"
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 "Klucz nazwy może składać się tylko z liter, podkreślenia, myślnika lub "
 "numerów"
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr "Nazwa pliku nie może znajdować się w katalogu"
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1926,7 +1924,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1934,14 +1932,14 @@
 msgid "Description"
 msgstr "Opis"
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr "Ostatnia aktywność"
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr "Ostatnia zmiana"
 
@@ -1951,7 +1949,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1975,7 +1973,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr "Nazwa użytkownika"
@@ -2102,7 +2100,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr "E-mail"
@@ -2352,7 +2350,7 @@
 msgstr "Utwórz Nowy Gist"
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr "Utworzono"
 
@@ -2436,13 +2434,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2458,14 +2456,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2777,7 +2775,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr "Repozytorium grupy"
@@ -2801,7 +2799,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr "Grupa użytkownika"
 
@@ -2978,7 +2976,7 @@
 msgstr "Utworzono"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3160,14 +3158,10 @@
 msgstr "Dodatkowe pola"
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
-msgstr ""
+msgid "Remote"
+msgstr "Zdalnie"
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr "Zdalnie"
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3212,7 +3206,7 @@
 "wszystkich w dzienniku publicznym."
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "Potwierdź usunięcie repozytorium: %s"
@@ -3245,48 +3239,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-#, fuzzy
-msgid "Invalidate Repository Cache"
-msgstr "Unieważnij pamięć podręczną repozytorium"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-#, fuzzy
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-"Ręcznie unieważnienie cache dla tego repozytorium. Przy pierwszym "
-"dostępie do repozytorium zostanie dodane do bufora ponownie."
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-#, fuzzy
-msgid "List of Cached Values"
-msgstr "Lista buforowanych wartości"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr "Prefiks"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr ""
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr "Klucz"
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr "Aktywny"
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3831,6 +3791,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr "Aktywny"
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3853,7 +3822,7 @@
 msgstr "Użytkownicy"
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr "Potwierdź usunięcie grupy użytkowników: %s"
@@ -3928,7 +3897,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr "Potwierdź usunięcie tego użytkownika: %s"
@@ -4031,10 +4000,12 @@
 msgstr "Szukaj"
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr "Obserwuj"
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr "Nie obserwuj"
 
@@ -4776,23 +4747,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr "Nie ma jeszcze zestawienia zmian"
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr "Subskrybuj %s kanał rss"
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr "Subskrybuj %s kanał atom"
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4830,6 +4801,13 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "Comment"
+msgid "View Comment"
+msgstr "Komentarz"
+
 #: kallithea/templates/email_templates/comment.html:27
 #, fuzzy
 #| msgid "Status change"
@@ -4842,33 +4820,43 @@
 msgid "The pull request has been closed."
 msgstr "Żądanie połączenia zmian zostało zamknięte."
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+#, fuzzy
+#| msgid "Password Reset"
+msgid "Password Reset Request"
+msgstr "Łącze resetowania hasła"
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr "Witaj %s"
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 #, fuzzy
 msgid "We have received a request to reset the password for your account."
 msgstr "Otrzymaliśmy prośbę o utworzenie nowego hasła do twojego konta."
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4901,6 +4889,11 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+msgid "View Pull Request"
+msgstr "Nowa prośba o połączenie gałęzi"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, fuzzy, python-format
 #| msgid "%(user)s commented on pull request %(age)s"
@@ -4919,12 +4912,24 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr "[komentarz] wniosek o połączenie gałęzi"
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+#, fuzzy
+#| msgid "New user registration"
+msgid "New User Registration"
+msgstr "nowy użytkownik się zarejestrował"
+
+#: kallithea/templates/email_templates/registration.html:23
 #, fuzzy
 #| msgid "Group name"
 msgid "Full Name"
 msgstr "Nazwa grupy"
 
+#: kallithea/templates/email_templates/registration.html:42
+#, fuzzy
+#| msgid "View this user here"
+msgid "View User Profile"
+msgstr "Zobacz tego użytkownika tutaj"
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5570,35 +5575,35 @@
 msgid "Show more"
 msgstr "Pokaż więcej"
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr "komunikaty"
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr "pliki dodane"
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr "pliki zmienione"
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr "pliki usunięte"
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr "komunikaty"
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr "plik dodany"
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr "plik zmieniony"
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr "plik usunięty"
 
@@ -5706,6 +5711,31 @@
 msgid "Download %s as %s"
 msgstr "Pobierz %s jak %s"
 
+#~ msgid "Cache invalidation successful"
+#~ msgstr "Cache wyczyszczony poprawnie"
+
+#~ msgid "An error occurred during cache invalidation"
+#~ msgstr "Wystąpił błąd podczas unieważniania cache"
+
+#, fuzzy
+#~ msgid "Invalidate Repository Cache"
+#~ msgstr "Unieważnij pamięć podręczną repozytorium"
+
+#, fuzzy
+#~ msgid ""
+#~ "Manually invalidate cache for this repository. On first access, the "
+#~ "repository will be cached again."
+#~ msgstr ""
+#~ "Ręcznie unieważnienie cache dla tego repozytorium. Przy pierwszym "
+#~ "dostępie do repozytorium zostanie dodane do bufora ponownie."
+
+#, fuzzy
+#~ msgid "List of Cached Values"
+#~ msgstr "Lista buforowanych wartości"
+
+#~ msgid "Prefix"
+#~ msgstr "Prefiks"
+
 #~ msgid "This repository has been locked by %s on %s"
 #~ msgstr "Repozytorium zostało zablokowane przez %s na %s"
 
@@ -5980,9 +6010,6 @@
 #~ msgid "The comment was made with status"
 #~ msgstr "Wniosek połączenia został zamknięty ze statusem"
 
-#~ msgid "View this user here"
-#~ msgstr "Zobacz tego użytkownika tutaj"
-
 #~ msgid "Repository Size"
 #~ msgstr "Rozmiar Repozytorium"
 
--- a/kallithea/i18n/pt_BR/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/pt_BR/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -4,7 +4,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2014-02-13 14:34+0000\n"
 "Last-Translator: Marcin Kuźmiński <marcin@python-works.com>\n"
 "Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
@@ -61,7 +61,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr "Pull request excluído com sucesso"
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr ""
@@ -257,7 +257,7 @@
 msgid "Tags"
 msgstr "Etiquetas"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr "Ocorreu um erro ao bifurcar o repositório %s"
@@ -310,27 +310,33 @@
 msgid "Journal"
 msgstr "Diário"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+#, fuzzy
+#| msgid "HTTP authentication realm"
+msgid "Authentication failed."
+msgstr "Realm de autenticação HTTP"
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr ""
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "Você foi registrado no %s com sucesso"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 #, fuzzy
 msgid "A password reset confirmation code has been sent"
 msgstr "Seu link de reinicialização de senha foi enviado"
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 #, fuzzy
 msgid "Invalid password reset token"
 msgstr "Link para trocar senha"
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr ""
 
@@ -479,11 +485,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr "As estatísticas estão desabillitadas para este repositório"
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -561,8 +567,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 "Você não pode editar esse usuário pois ele é crucial para toda a aplicação"
@@ -697,11 +703,11 @@
 msgid "Allowed with automatic account activation"
 msgstr "Permitido com ativação automática de conta"
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr "Ativação manual de conta externa"
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr "Ativação automática de conta externa"
 
@@ -723,297 +729,289 @@
 msgid "Error occurred during update of permissions"
 msgstr "Ocorreu um erro durante a atualização das permissões"
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr "Ocorreu um erro durante a criação do grupo de repositórios %s"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr "Grupo de repositórios %s criado"
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Grupo de repositórios %s atualizado"
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr "Ocorreu um erro durante a atualização do grupo de repositórios %s"
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "Esse grupo contém %s repositórios e não pode ser excluído"
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr "Este grupo contém %s subgrupos e não pode ser excluído"
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Grupo de repositórios %s excluído"
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr "Ocorreu um erro durante a exclusão do grupo de repositórios %s"
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Você não pode revocar sua própria permissão de administrador"
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr "Permissões atualizadas do Grupo de Repositórios"
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr "Ocorreu um erro durante a revocação das permissões"
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Erro ao criar repositório %s"
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Repositório %s criado de %s"
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Repositório %s bifurcado como %s"
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr "Repositório %s criado"
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Repositório %s atualizado com sucesso"
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "Ocorreu um erro durante a atualização do repositório %s"
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr "%s bifurcações excluídas"
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Repositório %s excluído"
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, fuzzy, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 "Nao é possível excluir %s pois ele ainda contém bifurcações vinculadas"
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "Ocorreu um erro durante a exclusão de %s"
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr "Permissões do repositório atualizadas"
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, fuzzy, python-format
 #| msgid "An error occurred during creation of field"
 msgid "An error occurred during creation of field: %r"
 msgstr "Ocorreu um erro durante a criação do campo"
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr "Ocorreu um erro durante a remoção do campo"
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr "Atualizada a visibilidade do repositório no diário público"
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr "Ocorreu um erro ao ajustar esse repositório no diário público"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr "Nada"
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "Marcado repositório %s como bifurcação de %s"
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr "Ocorreu um erro durante essa operação"
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr "Ocorreu um erro ao invalidar o cache"
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr "Realizado pull de localização remota"
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr "Ocorreu um erro ao realizar pull de localização remota"
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr "Ocorreu um erro ao excluir estatísticas de repositório"
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr "Configurações de VCS atualizadas"
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr ""
 "Ocorreu um erro durante a atualização das configurações da aplicação"
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, fuzzy, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr "Repositórios varridos com sucesso adicionados: %s ; removidos: %s"
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, fuzzy, python-format
 #| msgid "Invalidate cache for all repositories"
 msgid "Invalidated %s repositories"
 msgstr "Invalidar o cache para todos os repositórios"
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr "Configurações da aplicação atualizadas"
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr "Configurações de visualização atualizadas"
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 "Ocorreu um erro durante a atualização das configurações de visualização"
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 #, fuzzy
 msgid "Hook already exists"
 msgstr "Ainda não há dados carregados"
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr "Adicionado novo gancho"
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr "Atualizados os ganchos"
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr "Ocorreu um erro durante a criação do hook"
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr "Tarefa de reindexação do whoosh agendada"
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr "Grupo de usuários %s criado"
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr "Ocorreu um erro durante a criação do grupo de usuários %s"
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr "Grupo de usuários %s atualizado"
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr "Ocorreu um erro durante a atualização do grupo de usuários %s"
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr "Grupo de usuários excluído com sucesso"
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr "Ocorreu um erro durante a exclusão do grupo de usuários"
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr "O grupo destino não pode ser o mesmo"
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr "Permissões do Grupo de Usuários atualizadas"
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr "Permissões atualizadas"
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr "Ocorreu um erro durante o salvamento das permissões"
@@ -1057,11 +1055,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr "Você precisa ser um usuário registrado para realizar essa ação"
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr "Você precisa estar logado para ver essa página"
 
@@ -1101,168 +1099,168 @@
 msgid "No changes detected"
 msgstr "Nenhuma alteração detectada"
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "Excluído ramo: %s"
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr "Tag criada: %s"
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, fuzzy, python-format
 #| msgid "Changeset not found"
 msgid "Changeset %s not found"
 msgstr "Conjunto de alterações não encontrado"
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "Ver todos os conjuntos de mudanças combinados %s->%s"
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 #, fuzzy
 msgid "Compare view"
 msgstr "comparar exibir"
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr "e"
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr "%s mais"
 
-#: kallithea/lib/helpers.py:735
+#: kallithea/lib/helpers.py:759
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "revisões"
 
-#: kallithea/lib/helpers.py:759
+#: kallithea/lib/helpers.py:783
 #, fuzzy, python-format
 msgid "Fork name %s"
 msgstr "nome da bifurcação %s"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, fuzzy, python-format
 msgid "Pull request %s"
 msgstr "Pull request #%s"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:814
 msgid "[deleted] repository"
 msgstr "repositório [excluído]"
 
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
 msgid "[created] repository"
 msgstr "repositório [criado]"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:818
 msgid "[created] repository as fork"
 msgstr "repositório [criado] como uma bifurcação"
 
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
 msgid "[forked] repository"
 msgstr "repositório [bifurcado]"
 
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
 msgid "[updated] repository"
 msgstr "repositório [atualizado]"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:824
 msgid "[downloaded] archive from repository"
 msgstr "[baixado] archive do repositório"
 
-#: kallithea/lib/helpers.py:802
+#: kallithea/lib/helpers.py:826
 msgid "[delete] repository"
 msgstr "[excluir] repositório"
 
-#: kallithea/lib/helpers.py:810
+#: kallithea/lib/helpers.py:834
 msgid "[created] user"
 msgstr "usuário [criado]"
 
-#: kallithea/lib/helpers.py:812
+#: kallithea/lib/helpers.py:836
 msgid "[updated] user"
 msgstr "usuário [atualizado]"
 
-#: kallithea/lib/helpers.py:814
+#: kallithea/lib/helpers.py:838
 msgid "[created] user group"
 msgstr "[criado] grupo de usuários"
 
-#: kallithea/lib/helpers.py:816
+#: kallithea/lib/helpers.py:840
 msgid "[updated] user group"
 msgstr "[atualizado] grupo de usuários"
 
-#: kallithea/lib/helpers.py:818
+#: kallithea/lib/helpers.py:842
 msgid "[commented] on revision in repository"
 msgstr "[comentado] em revisão no repositório"
 
-#: kallithea/lib/helpers.py:820
+#: kallithea/lib/helpers.py:844
 msgid "[commented] on pull request for"
 msgstr "[comentado] no pull request para"
 
-#: kallithea/lib/helpers.py:822
+#: kallithea/lib/helpers.py:846
 msgid "[closed] pull request for"
 msgstr "[fechado] pull request para"
 
-#: kallithea/lib/helpers.py:824
+#: kallithea/lib/helpers.py:848
 msgid "[pushed] into"
 msgstr "[realizado push] para"
 
-#: kallithea/lib/helpers.py:826
+#: kallithea/lib/helpers.py:850
 msgid "[committed via Kallithea] into repository"
 msgstr "[commitado via Kallithea] no repositório"
 
-#: kallithea/lib/helpers.py:828
+#: kallithea/lib/helpers.py:852
 msgid "[pulled from remote] into repository"
 msgstr "[pulled do remote] no repositório"
 
-#: kallithea/lib/helpers.py:830
+#: kallithea/lib/helpers.py:854
 msgid "[pulled] from"
 msgstr "[realizado pull] a partir de"
 
-#: kallithea/lib/helpers.py:832
+#: kallithea/lib/helpers.py:856
 msgid "[started following] repository"
 msgstr "[passou a seguir] o repositório"
 
-#: kallithea/lib/helpers.py:834
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr "[parou de seguir] o repositório"
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr " e mais %s"
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "Nenhum arquivo"
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr "novo arquivo"
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr "mod"
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr "excluir"
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr "renomear"
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1302,69 +1300,69 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] "%d ano"
 msgstr[1] "%d anos"
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] "%d mês"
 msgstr[1] "%d meses"
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] "%d dia"
 msgstr[1] "%d dias"
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] "%d hora"
 msgstr[1] "%d horas"
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] "%d minuto"
 msgstr[1] "%d minutos"
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] "%d segundo"
 msgstr[1] "%d segundos"
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr "em %s"
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr "%s atrás"
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr "em %s e %s"
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s e %s atrás"
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr "agora há pouco"
 
@@ -1377,143 +1375,143 @@
 msgid "[Mention]"
 msgstr "[Menção]"
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr "nível superior"
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr "Administrador do Kallithea"
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 #, fuzzy
 msgid "Default user has read access to new repositories"
 msgstr "Acesso não autorizado ao recurso"
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 #, fuzzy
 msgid "Default user has write access to new repositories"
 msgstr "Acesso não autorizado ao recurso"
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 #, fuzzy
 msgid "Only admins can create repository groups"
 msgstr "Grupo de repositórios %s criado"
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 #, fuzzy
 msgid "Non-admins can create repository groups"
 msgstr "Grupo de repositórios %s criado"
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 #, fuzzy
 msgid "Only admins can create user groups"
 msgstr "Criar grupos de usuários"
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 #, fuzzy
 msgid "Non-admins can create user groups"
 msgstr "Criar grupos de usuários"
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 #, fuzzy
 msgid "Only admins can fork repositories"
 msgstr "Criar repositórios"
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 #, fuzzy
 msgid "Non-admins can fork repositories"
 msgstr "Invalidar o cache para todos os repositórios"
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr "Registro desatilitado"
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 #, fuzzy
 msgid "User registration with manual account activation"
 msgstr "Registro de Usuário com ativação manual de conta"
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 #, fuzzy
 msgid "User registration with automatic account activation"
 msgstr "Registro de Usuário com ativação automática de conta"
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 #, fuzzy
 msgid "Not reviewed"
 msgstr "Não Revisado"
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 #, fuzzy
 msgid "Under review"
 msgstr "Sob Revisão"
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 #, fuzzy
 #| msgid "Approved"
 msgid "Not approved"
 msgstr "Aprovado"
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr "Aprovado"
 
@@ -1539,7 +1537,7 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, fuzzy, python-format
 #| msgid "[Comment] %(repo_name)s pull request %(pr_nice_id)s from %(ref)s"
 msgid ""
@@ -1547,26 +1545,26 @@
 "%(branch)s"
 msgstr "[comentado] no pull request para"
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, fuzzy, python-format
 msgid "New user %(new_username)s registered"
 msgstr "O username \"%(new_username)s\" não é válido"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid ""
 "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:169
+#: kallithea/model/notification.py:168
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 #, fuzzy
 msgid "Closing"
 msgstr "Usando"
@@ -1647,11 +1645,11 @@
 msgid "SSH key with fingerprint %r found"
 msgstr "Conjunto de alterações não encontrado"
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr "Novo registro de usuário"
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 #, fuzzy
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
@@ -1659,7 +1657,7 @@
 "Você não pode remover esse usuário, pois ele é crucial para toda a "
 "aplicação"
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
@@ -1668,7 +1666,7 @@
 "usuário \"%s\" ainda é dono de %s repositórios e não pode ser removido. "
 "Troque os donos ou remova esses repositórios. %s"
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
@@ -1677,7 +1675,7 @@
 "usuário \"%s\" ainda é dono de %s repositórios e não pode ser removido. "
 "Troque os donos ou remova esses repositórios. %s"
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
@@ -1686,37 +1684,37 @@
 "usuário \"%s\" ainda é dono de %s repositórios e não pode ser removido. "
 "Troque os donos ou remova esses repositórios. %s"
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr "Link para trocar senha"
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 #, fuzzy
 msgid "Password reset notification"
 msgstr "Link para trocar senha"
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr "O valor não pode ser uma lista vazia"
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "O username \\\"%(username)s\\\" já existe"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, fuzzy, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "O username \"%(username)s\" não é válido"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 #, fuzzy
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
@@ -1725,25 +1723,25 @@
 "Nome de usuário pode conter somente caracteres alfanuméricos, sublinha, "
 "pontos e hífens e deve iniciar com caractere alfanumérico"
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr "O username \"%(username)s\" não é válido"
 
-#: kallithea/model/validators.py:131
+#: kallithea/model/validators.py:132
 msgid "Invalid user group name"
 msgstr "Nome inválido de grupo de usuários"
 
-#: kallithea/model/validators.py:132
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr "O grupo de usuários \"%(usergroup)s\" já existe"
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
@@ -1752,103 +1750,103 @@
 "underscores, pontos ou hífens, e deve começar om um caractere alfa-"
 "numérico"
 
-#: kallithea/model/validators.py:174
+#: kallithea/model/validators.py:175
 msgid "Cannot assign this group as parent"
 msgstr "Não é possível associar esse grupo como progenitor"
 
-#: kallithea/model/validators.py:175
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr "O grupo \\\"%(group_name)s\\\" já existe"
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr "Um repositório com o nome \"%(group_name)s\" já existe"
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr "Caracteres inválidos (não-ascii) na senha"
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr "Senhas não conferem"
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 #, fuzzy
 msgid "Invalid username or password"
 msgstr "senha inválida"
 
-#: kallithea/model/validators.py:313
+#: kallithea/model/validators.py:310
 #, fuzzy, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr "O nome de repositório %(repo)s não é permitido"
 
-#: kallithea/model/validators.py:315
+#: kallithea/model/validators.py:312
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr "Um repositório chamado %(repo)s já existe"
 
-#: kallithea/model/validators.py:316
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr "Um repositório \"%(repo)s\" já existe no grupo \"%(group)s\""
 
-#: kallithea/model/validators.py:318
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr "Um Grupo de Repositórios chamado \"%(repo)s\" já existe"
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 #, fuzzy
 msgid "Invalid repository URL"
 msgstr "repositório privado"
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr "A bifurcação deve ser do mesmo tipo que o pai"
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr "Você não tem permissão para criar um repositório neste grupo"
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr "você não tem permissão para criar um repositório na raiz"
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr "Você não tem permissão para criar um grupo neste local"
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr "Este nome de usuário ou de grupo de usuários não é válido"
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr "Esse não é um caminho válido"
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 #, fuzzy
 msgid "This email address is already in use"
 msgstr "Esse endereço de e-mail já está tomado"
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, fuzzy, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "o e-mail \"%(email)s\" não existe."
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
@@ -1856,26 +1854,26 @@
 "O atributo de login LDAP do CN deve ser especificado - isto é o nome do "
 "atributo que é equivalente ao 'nome de usuário'"
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr "Por favor, forneça um endereço válido IPv4 ou IPv6"
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 "O tamanho da rede (bits) deve estar no intervalo 0-32 (não %(bits)r)"
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr "O nome da chave só pode conter letras, underscore, hífen ou dígitos"
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr "O nome de arquivo não pode estar dentro de um diretório"
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1935,7 +1933,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1943,14 +1941,14 @@
 msgid "Description"
 msgstr "Descrição"
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr "Última Alteração"
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr "Ponta"
 
@@ -1960,7 +1958,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1984,7 +1982,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr "Nome de usuário"
@@ -2115,7 +2113,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr "E-mail"
@@ -2368,7 +2366,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr "Criado"
 
@@ -2452,13 +2450,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2474,14 +2472,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2805,7 +2803,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr "Grupo de repositórios"
@@ -2830,7 +2828,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr "Grupo de usuários"
 
@@ -3009,7 +3007,7 @@
 msgstr "Criado em"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3191,14 +3189,10 @@
 msgstr "Campos extras"
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
-msgstr ""
+msgid "Remote"
+msgstr "Remoto"
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr "Remoto"
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3245,7 +3239,7 @@
 "diário público"
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "Confirma excluir esse repositório: %s"
@@ -3277,48 +3271,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-#, fuzzy
-msgid "Invalidate Repository Cache"
-msgstr "Invalidar cache do repositório"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-#, fuzzy
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-"Invalidar manualmente o cache deste repositório. No próximo acesso o "
-"repositório será cacheado novamente"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-#, fuzzy
-msgid "List of Cached Values"
-msgstr "Lista de valores cacheados"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr "Prefixo"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr ""
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr "Chave"
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr "Ativo"
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3862,6 +3822,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr "Ativo"
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3884,7 +3853,7 @@
 msgstr "Membros"
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr "Confirme para excluir este grupo de usuário: %s"
@@ -3959,7 +3928,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr "Confirma excluir este usuário: %s"
@@ -4062,10 +4031,12 @@
 msgstr "Pesquisar"
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr "Seguir"
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr "Parar de seguir"
 
@@ -4802,23 +4773,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr "Nenhum conjunto de alterações ainda."
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr "Assinar o feed rss de %s"
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr "Assinar o feed atom de %s"
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4856,6 +4827,13 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "Comment"
+msgid "View Comment"
+msgstr "Comentário"
+
 #: kallithea/templates/email_templates/comment.html:27
 #, fuzzy
 #| msgid "Status change"
@@ -4868,33 +4846,43 @@
 msgid "The pull request has been closed."
 msgstr "Repositório não está travado"
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+#, fuzzy
+#| msgid "Password Reset"
+msgid "Password Reset Request"
+msgstr "Senha Trocada"
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr "Olá %s"
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 #, fuzzy
 msgid "We have received a request to reset the password for your account."
 msgstr "Recebemos uma requisição para criar uma nova senha para sua conta."
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4927,6 +4915,11 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+msgid "View Pull Request"
+msgstr "Novo pull request"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, fuzzy, python-format
 #| msgid "%(user)s commented on pull request %(age)s"
@@ -4945,12 +4938,24 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr "[comentado] no pull request para"
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+#, fuzzy
+#| msgid "New user registration"
+msgid "New User Registration"
+msgstr "Novo registro de usuário"
+
+#: kallithea/templates/email_templates/registration.html:23
 #, fuzzy
 #| msgid "Group name"
 msgid "Full Name"
 msgstr "Nome do grupo"
 
+#: kallithea/templates/email_templates/registration.html:42
+#, fuzzy
+#| msgid "View this user here"
+msgid "View User Profile"
+msgstr "Veja este usuário aqui"
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5594,35 +5599,35 @@
 msgid "Show more"
 msgstr "Mostrar mais"
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr "commits"
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr "arquivos adicionados"
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr "arquivos alterados"
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr "arquivos removidos"
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr "commit"
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr "arquivo adicionado"
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr "arquivo alterado"
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr "arquivo removido"
 
@@ -5730,6 +5735,28 @@
 msgid "Download %s as %s"
 msgstr "Descarregar %s como %s"
 
+#~ msgid "An error occurred during cache invalidation"
+#~ msgstr "Ocorreu um erro ao invalidar o cache"
+
+#, fuzzy
+#~ msgid "Invalidate Repository Cache"
+#~ msgstr "Invalidar cache do repositório"
+
+#, fuzzy
+#~ msgid ""
+#~ "Manually invalidate cache for this repository. On first access, the "
+#~ "repository will be cached again."
+#~ msgstr ""
+#~ "Invalidar manualmente o cache deste repositório. No próximo acesso o "
+#~ "repositório será cacheado novamente"
+
+#, fuzzy
+#~ msgid "List of Cached Values"
+#~ msgstr "Lista de valores cacheados"
+
+#~ msgid "Prefix"
+#~ msgstr "Prefixo"
+
 #~ msgid "This repository has been locked by %s on %s"
 #~ msgstr "Este repositório foi travado por %s em %s"
 
@@ -6002,9 +6029,6 @@
 #~ msgid "The comment was made with status"
 #~ msgstr "O pull request foi fechado com o estado"
 
-#~ msgid "View this user here"
-#~ msgstr "Veja este usuário aqui"
-
 #~ msgid "Repository Size"
 #~ msgstr "Tamanho do Repositório"
 
--- a/kallithea/i18n/ru/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/ru/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -4,7 +4,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2020-02-13 13:50+0000\n"
 "Last-Translator: Private <adamantine.sword@gmail.com>\n"
 "Language-Team: Russian <https://hosted.weblate.org/projects/kallithea/"
@@ -13,8 +13,8 @@
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<="
-"4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
 "X-Generator: Weblate 3.11-dev\n"
 
 #: kallithea/controllers/changelog.py:67
@@ -62,7 +62,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr "Pull-запрос %s успешно удалён"
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr "Нет такой ревизии в этом репозитории"
@@ -256,7 +256,7 @@
 msgid "Tags"
 msgstr "Метки"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr "Произошла ошибка во время создания форка репозитория %s"
@@ -309,25 +309,31 @@
 msgid "Journal"
 msgstr "Журнал"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+#, fuzzy
+#| msgid "Authentication"
+msgid "Authentication failed."
+msgstr "Аутентификация"
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr "Неверная капча"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "Регистрация в %s прошла успешно"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr "Код для сброса пароля отправлена"
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Неверный код сброса пароля"
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Пароль обновлён"
 
@@ -470,11 +476,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr "Статистические данные отключены для этого репозитария"
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr "Настройки авторизации успешно обновлены"
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr "произошла ошибка при обновлении настроек авторизации"
 
@@ -550,8 +556,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr "Произошла ошибка при обновлении gist-записи %s"
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 "Вы не можете изменить данные этого пользователя, поскольку он важен для "
@@ -685,11 +691,11 @@
 msgid "Allowed with automatic account activation"
 msgstr "Разрешена, с автоматической активацией учётной записи"
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr "Ручная активация внешней учетной записи"
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr "Автоматическая активация внешней учетной записи"
 
@@ -711,185 +717,177 @@
 msgid "Error occurred during update of permissions"
 msgstr "Произошла ошибка во время обновления привилегий"
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr "Произошла ошибка при создании группы репозиториев %s"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr "Создана новая группа репозиториев %s"
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Группа репозиториев %s обновлена"
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr "Произошла ошибка при обновлении группы репозиториев %s"
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "Данная группа содержит %s репозитариев и не может быть удалена"
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr "Группа содержит в себе %s подгрупп и не может быть удалён"
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Группа репозиториев %s удалена"
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr "Произошла ошибка при удалении группы репозиториев %s"
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Администратор не может отозвать свои привелегии"
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr "Привилегии группы репозиториев обновлены"
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr "Произошла ошибка при отзыве привелегии"
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Произошла ошибка при создании репозитория %s"
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Репозиторий %s создан из %s"
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Создан форк репозитория %s с именем %s"
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr "Репозиторий %s создан"
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Репозитарий %s успешно обновлён"
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "Произошла ошибка во время обновления репозитория %s"
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr "Форки %s отсоединены"
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr "Удалены форки репозитория %s"
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Репозиторий %s удалён"
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr "Невозможно удалить репозиторий %s, поскольку существуют его форки"
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "Произошла ошибка во время удаления %s"
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr "Привилегии репозитория обновлены"
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr "Ошибка валидации поля: %s"
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr "Произошла ошибка при создании поля: %r"
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr "Произошла ошибка при удалении поля"
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr "-- Не является форком --"
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr "Видимость репозитория в публичном журнале обновлена"
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr "Произошла ошибка при установке репозитария в общедоступный журнал"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr "Отсутствуют"
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "Репозиторий %s отмечен как форк от %s"
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr "Произошла ошибка при выполнении операции"
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr "Кэш сброшен"
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr "Произошла ошибка при очистке кэша"
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr "Внесены изменения из удалённого репозитория"
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr "Произошла ошибка при внесении изменений из удалённого репозитория"
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr "Произошла ошибка при удалении статистики репозитория"
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr "Обновлены настройки VCS"
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
@@ -897,109 +895,109 @@
 "Невозможно включить поддержку hgsubversion. Библиотека «hgsubversion» "
 "отсутствует"
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr "Произошла ошибка при обновлении настроек приложения"
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr "Репозитории успешно пересканированы, добавлено: %s, удалено: %s."
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr "Сброшена валидация для %s репозиториев"
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr "Обновленные параметры настройки приложения"
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr "Настройки визуализации обновлены"
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr "Произошла ошибка при обновлении настроек визуализации"
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr "Пожалуйста, введите адрес электронной почты"
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr "Задача отправки Email создана"
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 msgid "Hook already exists"
 msgstr "Хук уже существует"
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 "Встроенные хуки предназначены только для чтения. Пожалуйста, используйте "
 "другое имя."
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr "Добавлена новая ловушка"
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr "Обновлённые ловушки"
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr "произошла ошибка при создании хука"
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr "Переиндексация базы Whoosh успешно запланирована"
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr "Создана группа пользователей %s"
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr "Произошла ошибка при создании группы пользователей %s"
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr "Группа пользователей %s обновлена"
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr "Произошла ошибка при обновлении группы пользователей %s"
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr "Группа пользователей успешно удалена"
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr "Произошла ошибка при удалении группы пользователей"
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr "Целевая группа не может быть такой же"
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr "Привилегии группы пользователей обновлены"
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr "Обновлены привилегии"
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr "Произошла ошибка при сохранении привилегий"
@@ -1043,13 +1041,13 @@
 msgid "Removed IP address from user whitelist"
 msgstr "Удален IP %s из белого списка пользователя"
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 "Вы должны быть зарегистрированным пользователем, чтобы выполнить это "
 "действие"
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr "Страница доступна только авторизованным пользователям"
 
@@ -1086,166 +1084,166 @@
 msgid "No changes detected"
 msgstr "Изменений не обнаружено"
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "Удалена ветка: %s"
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr "Создан тег: %s"
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, python-format
 msgid "Changeset %s not found"
 msgstr "Набор изменений %s не найден"
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "Показать отличия вместе %s->%s"
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr "Сравнить вид"
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr "и"
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr "на %s больше"
 
-#: kallithea/lib/helpers.py:735
+#: kallithea/lib/helpers.py:759
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "версии"
 
-#: kallithea/lib/helpers.py:759
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr "Имя форка %s"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr "Pull-запрос %s"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:814
 msgid "[deleted] repository"
 msgstr "[удален] репозиторий"
 
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
 msgid "[created] repository"
 msgstr "[создан] репозиторий"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:818
 msgid "[created] repository as fork"
 msgstr "[создан] репозиторий в качестве форка"
 
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
 msgid "[forked] repository"
 msgstr "[создан форк] репозитория"
 
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
 msgid "[updated] repository"
 msgstr "[обновлён] репозиторий"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:824
 msgid "[downloaded] archive from repository"
 msgstr "[загружен] архив из репозитория"
 
-#: kallithea/lib/helpers.py:802
+#: kallithea/lib/helpers.py:826
 msgid "[delete] repository"
 msgstr "[удален] репозиторий"
 
-#: kallithea/lib/helpers.py:810
+#: kallithea/lib/helpers.py:834
 msgid "[created] user"
 msgstr "[создан] пользователь"
 
-#: kallithea/lib/helpers.py:812
+#: kallithea/lib/helpers.py:836
 msgid "[updated] user"
 msgstr "[обновлён] пользователь"
 
-#: kallithea/lib/helpers.py:814
+#: kallithea/lib/helpers.py:838
 msgid "[created] user group"
 msgstr "[создана] группа пользователей"
 
-#: kallithea/lib/helpers.py:816
+#: kallithea/lib/helpers.py:840
 msgid "[updated] user group"
 msgstr "[обновлена] группа пользователей"
 
-#: kallithea/lib/helpers.py:818
+#: kallithea/lib/helpers.py:842
 msgid "[commented] on revision in repository"
 msgstr "[комментарий] к ревизии в репозитории"
 
-#: kallithea/lib/helpers.py:820
+#: kallithea/lib/helpers.py:844
 msgid "[commented] on pull request for"
 msgstr "[прокомментировано] в pull-запросе для"
 
-#: kallithea/lib/helpers.py:822
+#: kallithea/lib/helpers.py:846
 msgid "[closed] pull request for"
 msgstr "[закрыт] pull-запрос для"
 
-#: kallithea/lib/helpers.py:824
+#: kallithea/lib/helpers.py:848
 msgid "[pushed] into"
 msgstr "[отправлено] в"
 
-#: kallithea/lib/helpers.py:826
+#: kallithea/lib/helpers.py:850
 msgid "[committed via Kallithea] into repository"
 msgstr "[внесены изменения с помощью Kallithea] в репозитории"
 
-#: kallithea/lib/helpers.py:828
+#: kallithea/lib/helpers.py:852
 msgid "[pulled from remote] into repository"
 msgstr "[внесены изменения из удалённого репозитория] в репозиторий"
 
-#: kallithea/lib/helpers.py:830
+#: kallithea/lib/helpers.py:854
 msgid "[pulled] from"
 msgstr "[внесены изменения] из"
 
-#: kallithea/lib/helpers.py:832
+#: kallithea/lib/helpers.py:856
 msgid "[started following] repository"
 msgstr "[подписка] на репозиторий"
 
-#: kallithea/lib/helpers.py:834
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr "[отписка] от репозитория"
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr " и на %s больше"
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "Нет файлов"
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr "новый файл"
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr "изменён"
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr "удалён"
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr "переименован"
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1289,7 +1287,7 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr "Некорректный ключ SSH — код base64 соответствует не %r, а %r"
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
@@ -1297,7 +1295,7 @@
 msgstr[1] "%d года"
 msgstr[2] "%d лет"
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
@@ -1305,7 +1303,7 @@
 msgstr[1] "%d месяца"
 msgstr[2] "%d месяцев"
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
@@ -1313,7 +1311,7 @@
 msgstr[1] "%d дня"
 msgstr[2] "%d дней"
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
@@ -1321,7 +1319,7 @@
 msgstr[1] "%d часа"
 msgstr[2] "%d часов"
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
@@ -1329,7 +1327,7 @@
 msgstr[1] "%d минуты"
 msgstr[2] "%d минут"
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
@@ -1337,27 +1335,27 @@
 msgstr[1] "%d секунды"
 msgstr[2] "%d секунд"
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr "в %s"
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr "%s назад"
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr "в %s и %s"
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s и %s назад"
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr "только что"
 
@@ -1370,151 +1368,151 @@
 msgid "[Mention]"
 msgstr "[Упоминание]"
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr "верхний уровень"
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr "Администратор Kallithea"
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr ""
 "Неавторизованные пользователи не имеют прав доступа к новым репозиториям"
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr "Неавторизованные пользователи имеют право чтения новых репозиториев"
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr ""
 "Неавторизованные пользователи имеют право записи в новые репозитории"
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 "Неавторизованные пользователи имеют права администратора к новым "
 "репозиториям"
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 "Неавторизованные пользователи не имеют прав доступа к новым группам "
 "репозиториев"
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 "Неавторизованные пользователи имеют право чтения в новых группах "
 "репозиториев"
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 "Неавторизованные пользователи имеют право записи в новых группах "
 "репозиториев"
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 "Неавторизованные пользователи имеют права администратора к новым групппам "
 "репозиториев"
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 "Неавторизованные пользователи не имеют прав доступа к новым группам "
 "пользователей"
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 "Неавторизованные пользователи имеют право чтения в новых группах "
 "пользователей"
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 "Неавторизованные пользователи имеют право записи в новых группах "
 "пользователей"
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 "Неавторизованные пользователи имеют права администратора к новым групппам "
 "пользователей"
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr "Только администраторы могут создавать группы репозиториев"
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr "Группы репозиториев могут создаваться любыми пользователями"
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr "Группы пользователей могут создаваться только администраторами"
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr "Группы пользователей могут создаваться любыми пользователями"
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr "Только администраторы могут создавать репозитории верхнего уровня"
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr "Любой пользователь может создавать репозитории верхнего уровня"
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 "Создание репозиториев доступно с правом на запись в группу репозиториев"
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 "Создание репозиториев недоступно с правом на запись в группу репозиториев"
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr "Форки репозиториев могут создаваться только администраторами"
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 msgid "Non-admins can fork repositories"
 msgstr "Форки репозиториев могут создаваться любыми пользователями"
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr "Регистрация отключена"
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr "Регистрация пользователя с ручной активацией учётной записи"
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr "Регистрация пользователя с автоматической активацией"
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr "Не проверено"
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr "На проверке"
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 msgid "Not approved"
 msgstr "Не одобрено"
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr "Одобрено"
 
@@ -1540,7 +1538,7 @@
 msgid "Name must not contain only digits"
 msgstr "Имя не может состоять только из цифр"
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
@@ -1549,12 +1547,12 @@
 "[Комментарий] к набору изменений %(short_id)s «%(message_short)s» "
 "репозитория %(repo_name)s в %(branch)s"
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr "Новый пользователь \"%(new_username)s\" зарегистрирован"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid ""
 "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
@@ -1563,7 +1561,7 @@
 "[Ревью] к PR %(pr_nice_id)s «%(pr_title_short)s» из %(pr_source_branch)s "
 "репозитория %(repo_name)s от %(pr_owner_username)s"
 
-#: kallithea/model/notification.py:169
+#: kallithea/model/notification.py:168
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
@@ -1572,7 +1570,7 @@
 "[Комментарий] к PR %(pr_nice_id)s «%(pr_title_short)s» из "
 "%(pr_source_branch)s репозитория %(repo_name)s от %(pr_owner_username)s"
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr "Закрыт"
 
@@ -1650,18 +1648,18 @@
 msgid "SSH key with fingerprint %r found"
 msgstr "Найден ключ SSH с отпечатком %r"
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr "Регистрация нового пользователя"
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 "Вы не можете удалить этого пользователя, поскольку это критично для "
 "работы всего приложения"
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
@@ -1670,7 +1668,7 @@
 "Пользователь \"%s\" всё ещё является владельцем %s репозиториев и поэтому "
 "не может быть удалён. Смените владельца или удалите эти репозитории: %s"
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
@@ -1680,7 +1678,7 @@
 "поэтому не может быть удалён. Смените владельца или удалите данные "
 "группы: %s"
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
@@ -1690,36 +1688,36 @@
 "поэтому не может быть удалён. Смените владельца или удалите данные "
 "группы: %s"
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr "Ссылка сброса пароля"
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr "Уведомление о сбросе пароля"
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr "Пароль к вашему аккаунту %s был изменён через форму сброса пароля."
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr "Значение не может быть пустым списком"
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "Пользователь с именем \"%(username)s\" уже существует"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "Имя «%(username)s» недопустимо"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
@@ -1728,25 +1726,25 @@
 "подчеркивания, точки и тире, а также должно начинаться с буквы, цифры или "
 "с символа подчеркивания"
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr "Введено некорректное значение"
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr "Имя \"%(username)s\" недопустимо"
 
-#: kallithea/model/validators.py:131
+#: kallithea/model/validators.py:132
 msgid "Invalid user group name"
 msgstr "Неверное имя группы пользователей"
 
-#: kallithea/model/validators.py:132
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr "Группа пользователей \"%(usergroup)s\" уже существует"
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
@@ -1754,61 +1752,61 @@
 "имя группы пользователей может содержать только буквы, цифры, символы "
 "подчеркивания, точки и тире; а так же должно начинаться с буквы или цифры"
 
-#: kallithea/model/validators.py:174
+#: kallithea/model/validators.py:175
 msgid "Cannot assign this group as parent"
 msgstr "Невозможно использовать эту группу как родителя"
 
-#: kallithea/model/validators.py:175
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr "Группа \"%(group_name)s\" уже существует"
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr "Репозиторий с именем «%(group_name)s» уже существует"
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr "Недопустимые символы (не ascii) в пароле"
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr "Неверно задан старый пароль"
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr "Пароли не совпадают"
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr "Неверное имя пользователя или пароль"
 
-#: kallithea/model/validators.py:313
+#: kallithea/model/validators.py:310
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr "Имя репозитория %(repo)s недопустимо"
 
-#: kallithea/model/validators.py:315
+#: kallithea/model/validators.py:312
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr "Репозитарий %(repo)s уже существует"
 
-#: kallithea/model/validators.py:316
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr "Репозитарий \"%(repo)s\" уже существует в группе \"%(group)s\""
 
-#: kallithea/model/validators.py:318
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr "Группа репозиториев \"%(repo)s\" уже существует"
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr "Недопустимый URL репозитория"
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
@@ -1816,40 +1814,40 @@
 "Недопустимый URL репозитория. Требуется корректный http, https, ssh, svn"
 "+http или svn+https URL"
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr "Форк будет иметь тот же тип, что и родительский"
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr "У вас недостаточно прав для создания репозиториев в этой группе"
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr "недостаточно прав для создания репозитория в корневом каталоге"
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr "У Вас недостаточно привилегий для создания группы в этом месте"
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr "Данное имя пользователя или группы пользователей недопустимо"
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr "Этот путь ошибочен"
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr "Этот адрес почты уже занят"
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "Адрес «%(email)s» не зарегистрирован"
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
@@ -1857,11 +1855,11 @@
 "Для входа по LDAP должно быть указано значение аттрибута CN - это "
 "эквивалент имени пользователя"
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr "Пожалуйста, введите существующий IPv4 или IPv6 адре"
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
@@ -1869,17 +1867,17 @@
 "Значение маски подсети должно быть в пределах от 0 до 32 (%(bits)r - "
 "неверно)"
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 "Ключевое имя может только состоять из букв, символа подчеркивания, тире "
 "или чисел"
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr "Файла нет в каталоге"
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr "Плагины %(loaded)s и %(next_to_load)s экспортируют одно и то же имя"
@@ -1940,7 +1938,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1948,14 +1946,14 @@
 msgid "Description"
 msgstr "Описание"
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr "Последнее изменение"
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr "Состояние"
 
@@ -1965,7 +1963,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1989,7 +1987,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr "Имя пользователя"
@@ -2117,7 +2115,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr "E-mail"
@@ -2372,7 +2370,7 @@
 msgstr "Создать новую gist-запись"
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr "Создано"
 
@@ -2456,13 +2454,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2478,14 +2476,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2800,7 +2798,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr "Группа репозиториев"
@@ -2824,7 +2822,7 @@
 msgstr "Права пользователя по умолчанию для новых групп репозиториев."
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr "Группа пользователей"
 
@@ -3010,7 +3008,7 @@
 msgstr "Создано"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3185,14 +3183,10 @@
 msgstr "Дополнительные поля"
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
-msgstr "Кэш"
+msgid "Remote"
+msgstr "Удалённый репозиторий"
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr "Удалённый репозиторий"
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3232,7 +3226,7 @@
 "публичном журнале."
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "Подтвердите удаление этого репозитория: %s"
@@ -3267,44 +3261,14 @@
 "администратором. Администратор может либо удалить, либо восстановить "
 "репозиторий."
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr "Сбросить кэш репозитория"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-"Ручной сброс кэша репозитория. При первом доступе кэш восстановится."
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr "Список кешированных значений"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr "Префикс"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr "Имя"
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr "Ключ"
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr "Активный"
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr "Имя"
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3896,6 +3860,15 @@
 msgid "Short, optional description for this user group."
 msgstr "Краткое, опциональное описание этой группы."
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr "Активный"
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3917,7 +3890,7 @@
 msgstr "Участники"
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr "Подтвердите удаление следующей группы пользователей: %s"
@@ -3991,7 +3964,7 @@
 msgstr "Член группы"
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr "Подтвердите удаление пользователя %s"
@@ -4091,10 +4064,12 @@
 msgstr "Поиск"
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr "Подписаться"
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr "Отписаться"
 
@@ -4778,23 +4753,23 @@
 msgid "Repository creation in progress..."
 msgstr "Создание репозитория в процессе..."
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr "Изменений ещё не было"
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr "Подписаться на ленту RSS %s"
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr "Подписаться на ленту Atom %s"
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr "Создание"
 
@@ -4826,6 +4801,13 @@
 msgid "by"
 msgstr "от"
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "Comment"
+msgid "View Comment"
+msgstr "Комментировать"
+
 #: kallithea/templates/email_templates/comment.html:27
 msgid "Status change:"
 msgstr "Изменение статуса:"
@@ -4834,16 +4816,28 @@
 msgid "The pull request has been closed."
 msgstr "Этот pull-запрос закрыт."
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+#, fuzzy
+#| msgid "Commit Message"
+msgid "Message"
+msgstr "Зафиксировать сообщение"
+
+#: kallithea/templates/email_templates/password_reset.html:4
+#, fuzzy
+#| msgid "Password Reset"
+msgid "Password Reset Request"
+msgstr "Сброс пароля"
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr "Здравствуйте, %s"
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr "Мы получили запрос на сброс пароля для вашего аккаунта."
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
@@ -4851,11 +4845,11 @@
 "Однако, поскольку этот аккаунт управляется извне, мы не можем изменить "
 "пароль здесь."
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr "Перейдите по ссылке, чтобы задать новый пароль"
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
@@ -4863,7 +4857,7 @@
 "В случае, если перейти по ссылке не удаётся, введите в форме сброса "
 "пароля следующий код"
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4896,6 +4890,12 @@
 msgid "to"
 msgstr "к"
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+#| msgid "New Pull Request"
+msgid "View Pull Request"
+msgstr "Новый pull-запрос"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, python-format
 msgid "Mention in Comment on Pull Request %s \"%s\""
@@ -4911,10 +4911,22 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr "Комментарий к pull-запросу %s «%s»"
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+#, fuzzy
+#| msgid "New user registration"
+msgid "New User Registration"
+msgstr "Регистрация нового пользователя"
+
+#: kallithea/templates/email_templates/registration.html:23
 msgid "Full Name"
 msgstr "Полное имя"
 
+#: kallithea/templates/email_templates/registration.html:42
+#, fuzzy
+#| msgid "View this user here"
+msgid "View User Profile"
+msgstr "Подробнее о пользователе"
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5537,35 +5549,35 @@
 msgid "Show more"
 msgstr "Показать еще"
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr "commit'ы"
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr "файлы добавлены"
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr "файлы изменены"
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr "файлы удалены"
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr "commit"
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr "файл удалён"
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr "файл изменён"
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr "файл удалён"
 
@@ -5666,6 +5678,30 @@
 msgid "Download %s as %s"
 msgstr "Скачать %s как %s"
 
+#~ msgid "Cache invalidation successful"
+#~ msgstr "Кэш сброшен"
+
+#~ msgid "An error occurred during cache invalidation"
+#~ msgstr "Произошла ошибка при очистке кэша"
+
+#~ msgid "Caches"
+#~ msgstr "Кэш"
+
+#~ msgid "Invalidate Repository Cache"
+#~ msgstr "Сбросить кэш репозитория"
+
+#~ msgid ""
+#~ "Manually invalidate cache for this repository. On first access, the "
+#~ "repository will be cached again."
+#~ msgstr ""
+#~ "Ручной сброс кэша репозитория. При первом доступе кэш восстановится."
+
+#~ msgid "List of Cached Values"
+#~ msgstr "Список кешированных значений"
+
+#~ msgid "Prefix"
+#~ msgstr "Префикс"
+
 #~ msgid "This repository has been locked by %s on %s"
 #~ msgstr "Репозиторий заблокировал %s в %s"
 
@@ -5934,9 +5970,6 @@
 #~ msgid "The comment was made with status"
 #~ msgstr "Комментарий оставлен со статусом"
 
-#~ msgid "View this user here"
-#~ msgstr "Подробнее о пользователе"
-
 #~ msgid "Repository Size"
 #~ msgstr "Размер репозитория"
 
--- a/kallithea/i18n/sk/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/sk/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -5,7 +5,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2015-04-01 12:59+0200\n"
 "Last-Translator: Andrej Shadura <andrew@shadura.me>\n"
 "Language-Team: Slovak <https://hosted.weblate.org/projects/kallithea/"
@@ -63,7 +63,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr "Úspešne zmazaný súbor %s"
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr "Taká revízia neexistuje"
@@ -253,7 +253,7 @@
 msgid "Tags"
 msgstr "Tagy"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr ""
@@ -306,26 +306,30 @@
 msgid "Journal"
 msgstr ""
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+msgid "Authentication failed."
+msgstr ""
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 #, fuzzy
 msgid "Bad captcha"
 msgstr "zlá captcha"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr ""
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr ""
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr ""
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Úspešne aktualizované heslo"
 
@@ -467,11 +471,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -547,8 +551,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr "Došlo k chybe pri aktualizácii gist %s"
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
@@ -682,11 +686,11 @@
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr ""
 
@@ -708,293 +712,285 @@
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, fuzzy, python-format
 #| msgid "Error occurred during gist creation"
 msgid "An error occurred during creation of field: %r"
 msgstr "Došlo k chybe pri vytváraní gist"
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr "Nič"
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, fuzzy, python-format
 #| msgid "Watched Repositories"
 msgid "Invalidated %s repositories"
 msgstr "Repozitáre"
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 msgid "Hook already exists"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr ""
@@ -1038,11 +1034,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr ""
 
@@ -1077,167 +1073,167 @@
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, fuzzy, python-format
 #| msgid "Set changeset status"
 msgid "Changeset %s not found"
 msgstr "Zmeny"
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:735
-#: kallithea/templates/changelog/changelog.html:43
-msgid "revisions"
-msgstr ""
-
 #: kallithea/lib/helpers.py:759
+#: kallithea/templates/changelog/changelog.html:43
+msgid "revisions"
+msgstr ""
+
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:794
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
-msgid "[updated] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:800
-msgid "[downloaded] archive from repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:802
-msgid "[delete] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:810
-msgid "[created] user"
-msgstr ""
-
-#: kallithea/lib/helpers.py:812
-msgid "[updated] user"
-msgstr ""
-
 #: kallithea/lib/helpers.py:814
-msgid "[created] user group"
-msgstr ""
-
-#: kallithea/lib/helpers.py:816
-msgid "[updated] user group"
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
+msgid "[created] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:818
-msgid "[commented] on revision in repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:820
-msgid "[commented] on pull request for"
-msgstr ""
-
-#: kallithea/lib/helpers.py:822
-msgid "[closed] pull request for"
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
+msgid "[updated] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:824
-msgid "[pushed] into"
+msgid "[downloaded] archive from repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:826
-msgid "[committed via Kallithea] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:828
-msgid "[pulled from remote] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:830
-msgid "[pulled] from"
-msgstr ""
-
-#: kallithea/lib/helpers.py:832
-msgid "[started following] repository"
+msgid "[delete] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:834
+msgid "[created] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:836
+msgid "[updated] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:838
+msgid "[created] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:840
+msgid "[updated] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:842
+msgid "[commented] on revision in repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:844
+msgid "[commented] on pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:846
+msgid "[closed] pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:848
+msgid "[pushed] into"
+msgstr ""
+
+#: kallithea/lib/helpers.py:850
+msgid "[committed via Kallithea] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:852
+msgid "[pulled from remote] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:854
+msgid "[pulled] from"
+msgstr ""
+
+#: kallithea/lib/helpers.py:856
+msgid "[started following] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1274,7 +1270,7 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
@@ -1282,7 +1278,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
@@ -1290,7 +1286,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
@@ -1298,7 +1294,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
@@ -1306,7 +1302,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
@@ -1314,7 +1310,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
@@ -1322,27 +1318,27 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr ""
 
@@ -1355,131 +1351,131 @@
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 #, fuzzy
 msgid "Only admins can fork repositories"
 msgstr "Repozitáre"
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 #, fuzzy
 msgid "Non-admins can fork repositories"
 msgstr "Repozitáre"
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr ""
 
@@ -1505,33 +1501,33 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:167
+#, python-format
+msgid ""
+"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
+"%(pr_source_branch)s by %(pr_owner_username)s"
+msgstr ""
+
 #: kallithea/model/notification.py:168
 #, python-format
 msgid ""
-"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
-"%(pr_source_branch)s by %(pr_owner_username)s"
-msgstr ""
-
-#: kallithea/model/notification.py:169
-#, python-format
-msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr ""
 
@@ -1606,214 +1602,214 @@
 msgid "SSH key with fingerprint %r found"
 msgstr "Zmeny"
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
 "owners or remove those repositories: %s"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
 "owners or remove those repository groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
 "owners or remove those user groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr ""
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
 msgstr ""
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:131
-msgid "Invalid user group name"
-msgstr ""
-
 #: kallithea/model/validators.py:132
+msgid "Invalid user group name"
+msgstr ""
+
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:174
-msgid "Cannot assign this group as parent"
-msgstr ""
-
 #: kallithea/model/validators.py:175
+msgid "Cannot assign this group as parent"
+msgstr ""
+
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr ""
 
+#: kallithea/model/validators.py:310
+#, python-format
+msgid "Repository name %(repo)s is not allowed"
+msgstr ""
+
+#: kallithea/model/validators.py:312
+#, python-format
+msgid "Repository named %(repo)s already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:313
 #, python-format
-msgid "Repository name %(repo)s is not allowed"
+msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
 #: kallithea/model/validators.py:315
 #, python-format
-msgid "Repository named %(repo)s already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:316
-#, python-format
-msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
-msgstr ""
-
-#: kallithea/model/validators.py:318
-#, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 #, fuzzy
 msgid "Invalid repository URL"
 msgstr "Odblokovať repozitár"
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
 msgstr ""
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1873,7 +1869,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1881,14 +1877,14 @@
 msgid "Description"
 msgstr ""
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr ""
 
@@ -1898,7 +1894,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1922,7 +1918,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr ""
@@ -2046,7 +2042,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr ""
@@ -2295,7 +2291,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr ""
 
@@ -2379,13 +2375,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2401,14 +2397,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2712,7 +2708,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr ""
@@ -2733,7 +2729,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr ""
 
@@ -2906,7 +2902,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3074,14 +3070,10 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
+msgid "Remote"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3119,7 +3111,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr ""
@@ -3151,43 +3143,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr ""
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3712,6 +3675,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr ""
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3733,7 +3705,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr ""
@@ -3807,7 +3779,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr ""
@@ -3907,10 +3879,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr ""
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr ""
 
@@ -4599,23 +4573,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4652,6 +4626,13 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "No comments."
+msgid "View Comment"
+msgstr "Nie sú žiadne komentáre."
+
 #: kallithea/templates/email_templates/comment.html:27
 #, fuzzy
 #| msgid "Status change"
@@ -4664,32 +4645,40 @@
 msgid "The pull request has been closed."
 msgstr "Tento repozitár bol uzamknutý používateľom %s dňa %s"
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+msgid "Password Reset Request"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4722,6 +4711,12 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+#| msgid "on pull request"
+msgid "View Pull Request"
+msgstr "Zmena stavu"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, python-format
 msgid "Mention in Comment on Pull Request %s \"%s\""
@@ -4738,10 +4733,18 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr "Zmena stavu"
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+msgid "New User Registration"
+msgstr ""
+
+#: kallithea/templates/email_templates/registration.html:23
 msgid "Full Name"
 msgstr ""
 
+#: kallithea/templates/email_templates/registration.html:42
+msgid "View User Profile"
+msgstr ""
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5354,35 +5357,35 @@
 msgid "Show more"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr ""
 
--- a/kallithea/i18n/tr/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/tr/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -7,7 +7,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.4.99\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2019-11-05 08:03+0000\n"
 "Last-Translator: Hüseyin Tunç <huseyin.tunc@bulutfon.com>\n"
 "Language-Team: Turkish <https://hosted.weblate.org/projects/kallithea/"
@@ -65,7 +65,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr ""
@@ -251,7 +251,7 @@
 msgid "Tags"
 msgstr ""
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr ""
@@ -304,25 +304,29 @@
 msgid "Journal"
 msgstr ""
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+msgid "Authentication failed."
+msgstr ""
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr ""
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr ""
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr ""
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr ""
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr ""
 
@@ -464,11 +468,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -544,8 +548,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
@@ -677,11 +681,11 @@
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr ""
 
@@ -703,291 +707,283 @@
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 msgid "Hook already exists"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr ""
@@ -1031,11 +1027,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr ""
 
@@ -1070,166 +1066,166 @@
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, python-format
 msgid "Changeset %s not found"
 msgstr ""
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:735
-#: kallithea/templates/changelog/changelog.html:43
-msgid "revisions"
-msgstr ""
-
 #: kallithea/lib/helpers.py:759
+#: kallithea/templates/changelog/changelog.html:43
+msgid "revisions"
+msgstr ""
+
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:794
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
-msgid "[updated] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:800
-msgid "[downloaded] archive from repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:802
-msgid "[delete] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:810
-msgid "[created] user"
-msgstr ""
-
-#: kallithea/lib/helpers.py:812
-msgid "[updated] user"
-msgstr ""
-
 #: kallithea/lib/helpers.py:814
-msgid "[created] user group"
-msgstr ""
-
-#: kallithea/lib/helpers.py:816
-msgid "[updated] user group"
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
+msgid "[created] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:818
-msgid "[commented] on revision in repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:820
-msgid "[commented] on pull request for"
-msgstr ""
-
-#: kallithea/lib/helpers.py:822
-msgid "[closed] pull request for"
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
+msgid "[updated] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:824
-msgid "[pushed] into"
+msgid "[downloaded] archive from repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:826
-msgid "[committed via Kallithea] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:828
-msgid "[pulled from remote] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:830
-msgid "[pulled] from"
-msgstr ""
-
-#: kallithea/lib/helpers.py:832
-msgid "[started following] repository"
+msgid "[delete] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:834
+msgid "[created] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:836
+msgid "[updated] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:838
+msgid "[created] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:840
+msgid "[updated] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:842
+msgid "[commented] on revision in repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:844
+msgid "[commented] on pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:846
+msgid "[closed] pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:848
+msgid "[pushed] into"
+msgstr ""
+
+#: kallithea/lib/helpers.py:850
+msgid "[committed via Kallithea] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:852
+msgid "[pulled from remote] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:854
+msgid "[pulled] from"
+msgstr ""
+
+#: kallithea/lib/helpers.py:856
+msgid "[started following] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1266,69 +1262,69 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr ""
 
@@ -1341,129 +1337,129 @@
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr ""
 
@@ -1489,33 +1485,33 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:167
+#, python-format
+msgid ""
+"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
+"%(pr_source_branch)s by %(pr_owner_username)s"
+msgstr ""
+
 #: kallithea/model/notification.py:168
 #, python-format
 msgid ""
-"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
-"%(pr_source_branch)s by %(pr_owner_username)s"
-msgstr ""
-
-#: kallithea/model/notification.py:169
-#, python-format
-msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr ""
 
@@ -1589,213 +1585,213 @@
 msgid "SSH key with fingerprint %r found"
 msgstr ""
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
 "owners or remove those repositories: %s"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
 "owners or remove those repository groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
 "owners or remove those user groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr ""
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
 msgstr ""
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:131
-msgid "Invalid user group name"
-msgstr ""
-
 #: kallithea/model/validators.py:132
+msgid "Invalid user group name"
+msgstr ""
+
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:174
-msgid "Cannot assign this group as parent"
-msgstr ""
-
 #: kallithea/model/validators.py:175
+msgid "Cannot assign this group as parent"
+msgstr ""
+
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr ""
 
+#: kallithea/model/validators.py:310
+#, python-format
+msgid "Repository name %(repo)s is not allowed"
+msgstr ""
+
+#: kallithea/model/validators.py:312
+#, python-format
+msgid "Repository named %(repo)s already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:313
 #, python-format
-msgid "Repository name %(repo)s is not allowed"
+msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
 #: kallithea/model/validators.py:315
 #, python-format
-msgid "Repository named %(repo)s already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:316
-#, python-format
-msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
-msgstr ""
-
-#: kallithea/model/validators.py:318
-#, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
 msgstr ""
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1855,7 +1851,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1863,14 +1859,14 @@
 msgid "Description"
 msgstr ""
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr ""
 
@@ -1880,7 +1876,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1904,7 +1900,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr ""
@@ -2028,7 +2024,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr ""
@@ -2275,7 +2271,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr ""
 
@@ -2359,13 +2355,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2381,14 +2377,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2689,7 +2685,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr ""
@@ -2710,7 +2706,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr ""
 
@@ -2883,7 +2879,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3046,14 +3042,10 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
+msgid "Remote"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3091,7 +3083,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr ""
@@ -3122,43 +3114,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr ""
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3671,6 +3634,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr ""
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3692,7 +3664,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr ""
@@ -3766,7 +3738,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr ""
@@ -3866,10 +3838,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr ""
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr ""
 
@@ -4537,23 +4511,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4585,6 +4559,11 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+msgid "View Comment"
+msgstr ""
+
 #: kallithea/templates/email_templates/comment.html:27
 msgid "Status change:"
 msgstr ""
@@ -4593,32 +4572,40 @@
 msgid "The pull request has been closed."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+msgid "Password Reset Request"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4649,6 +4636,10 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+msgid "View Pull Request"
+msgstr ""
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, python-format
 msgid "Mention in Comment on Pull Request %s \"%s\""
@@ -4664,10 +4655,18 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr ""
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+msgid "New User Registration"
+msgstr ""
+
+#: kallithea/templates/email_templates/registration.html:23
 msgid "Full Name"
 msgstr ""
 
+#: kallithea/templates/email_templates/registration.html:42
+msgid "View User Profile"
+msgstr ""
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5278,35 +5277,35 @@
 msgid "Show more"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr ""
 
--- a/kallithea/i18n/uk/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/uk/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -4,7 +4,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3.2\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2019-11-13 10:04+0000\n"
 "Last-Translator: Oleksandr Shtalinberg <o.shtalinberg@gmail.com>\n"
 "Language-Team: Ukrainian <https://hosted.weblate.org/projects/kallithea/"
@@ -62,7 +62,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr "Успішно вилучено pull request %s"
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr "Така редакція не існує для цього репозиторію"
@@ -250,7 +250,7 @@
 msgid "Tags"
 msgstr "Теги"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr "Під час forking репозиторію %s сталася помилка"
@@ -303,25 +303,31 @@
 msgid "Journal"
 msgstr "Журнал"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+#, fuzzy
+#| msgid "HTTP authentication realm"
+msgid "Authentication failed."
+msgstr "Область автентифікації HTTP"
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr "Погана капча"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "Ви успішно зареєстровані з  %s"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr "Надісланий код підтвердження скидання пароля"
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Недійсний маркер скидання пароля"
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Пароль успішно оновлений"
 
@@ -466,11 +472,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr "Статистичні дані для цього репозиторію вимкнено"
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr "Параметри автентифікації успішно оновлено"
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr "під час оновлення параметрів автентифікації сталася помилка"
 
@@ -546,8 +552,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr "Сталася помилка під час оновлення gist %s"
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 "Ви не можете редагувати цього користувача, оскільки це важливо для всієї "
@@ -681,11 +687,11 @@
 msgid "Allowed with automatic account activation"
 msgstr "Дозволено з автоматичною активацію облікового запису"
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr "Ручна Активація зовнішнього акаунту"
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr "Автоматична Активація зовнішнього акаунту"
 
@@ -707,186 +713,178 @@
 msgid "Error occurred during update of permissions"
 msgstr "Сталася помилка під час оновлення прав"
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr "Сталася помилка при створенні repository group %s"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr "Створена група репозиторіїв %s"
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Оновлено групу репозиторіїв %s"
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr "Сталася помилка при оновленні repository group %s"
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "Ця група містить %s репозиторії, і їх неможливо видалити"
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr "Ця група містить %s підгрупи і не може бути видалена"
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Видалена група репозиторіїв %s"
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr "Сталася помилка під час видалення групи репохиторіїв %s"
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Неможливо відкликати дозвіл для себе як адміністратора"
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr "Оновлено дозволи групи репозиторіїв"
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr "Сталася помилка під час відкликання прав"
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Помилка створення репозиторію  %s"
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Створено репозиторій  %s з %s"
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Роздвоєно репозиторій %s як %s"
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr "Створено репозиторій %s"
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Репозиторій %s успішно оновлений"
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "Сталася помилка при оновленні репозиторію %s"
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr "Від'єднано %s forks"
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr "Видалено %s forks"
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Видалений репозиторій %s"
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr "Неможливо видалити репозиторій %s, що ще має forks"
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "Сталася помилка під час видалення %s"
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr "Права доступів до репозиторіїв оновлено"
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr "Помилка перевірки поля: %s"
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr "Сталася помилка під час створення поля: %r"
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr "Під час видалення поля виникла помилка"
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr "-- Не fork --"
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr "Оновлено видимість репозиторія в публічному журналі"
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 "Сталася помилка під час налаштувань цього репозиторію в публічному журналі"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr "Нічого"
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "Позначено репозиторій %s як відгалуження від %s"
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr "Сталася помилка під час виконання цієї операції"
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr "Інвалідація кешу успішна"
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr "Сталася помилка під час Анулювання кеша"
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr "Витягнуто з віддаленого місця"
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr "Сталася помилка під час витягування з віддаленого розташування"
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr "Під час видалення статистики репозиторію сталася помилка"
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr "Оновлені налаштування VCS"
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
@@ -894,109 +892,109 @@
 "Не вдається активувати підтримку hgsubversion. Бібліотека \"hgsubversion"
 "\" відсутня"
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr "Під час оновлення параметрів застосунку сталася помилка"
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr "Репозиторії успішно перескановано. Додано: %s. Видалено: %s."
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr "До оновлення %s репозиторіїв"
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr "Оновлені параметри застосунку"
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr "Оновлені параметри візуалізації"
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr "Під час оновлення параметрів візуалізації сталася помилка"
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr "Будь ласка, введіть адресу електронної пошти"
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr "Надіслати електронною поштою завдання створено"
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 msgid "Hook already exists"
 msgstr "Hook вже існує"
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 "Вбудовані hooks доступні лише для читання. Будь ласка, використовуйте "
 "інше ім'я hook."
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr "Додано новий hook"
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr "Оновлено hooks"
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr "Сталася помилка під час створення hook"
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr "Завдання реіндекса Whoosh заплановано"
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr "Створена Група користувачів %s"
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr "Під час створення групи користувачів  %s сталася помилка"
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr "Оновлена група користувачів %s"
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr "Сталася помилка під час оновлення групи користувачів %s"
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr "Група користувачів успішно видалена"
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr "Під час видалення групи користувачів сталася помилка"
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr "Цільова група не може бути однаковою"
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr "Права на групи користувачів оновлені"
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr "Оновлені дозволи"
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr "Сталася помилка під час збереження дозволів"
@@ -1040,11 +1038,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr "Вилучено IP-адресу з білого списку користувачів"
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr "Для виконання цієї дії потрібно бути зареєстрованим користувачем"
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr "Ви повинні бути зареєстровані для перегляду цієї сторінки"
 
@@ -1081,166 +1079,166 @@
 msgid "No changes detected"
 msgstr "Не виявлено змін"
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "Видалено гілку: %s"
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr "Створено тег: %s"
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, python-format
 msgid "Changeset %s not found"
 msgstr "Набір змін %s не знайдено"
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "Показати всі комбіновані набори змін %s- >%s"
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr "Порівняйте вигляд"
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr "і"
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr "%s більше"
 
-#: kallithea/lib/helpers.py:735
+#: kallithea/lib/helpers.py:759
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "редакції"
 
-#: kallithea/lib/helpers.py:759
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr "Ім'я розгалуження %s"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr "Pull request %s"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:814
 msgid "[deleted] repository"
 msgstr "[видалений] репозиторій"
 
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
 msgid "[created] repository"
 msgstr "[створено] репозиторій"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:818
 msgid "[created] repository as fork"
 msgstr "[створено] репозиторій як fork"
 
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
 msgid "[forked] repository"
 msgstr "[forked] репозиторій"
 
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
 msgid "[updated] repository"
 msgstr "[оновлено] репозиторій"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:824
 msgid "[downloaded] archive from repository"
 msgstr "[завантажити] архів з репозиторію"
 
-#: kallithea/lib/helpers.py:802
+#: kallithea/lib/helpers.py:826
 msgid "[delete] repository"
 msgstr "[видалити] репозиторій"
 
-#: kallithea/lib/helpers.py:810
+#: kallithea/lib/helpers.py:834
 msgid "[created] user"
 msgstr "[створено] користувач"
 
-#: kallithea/lib/helpers.py:812
+#: kallithea/lib/helpers.py:836
 msgid "[updated] user"
 msgstr "[оновлений] користувач"
 
-#: kallithea/lib/helpers.py:814
+#: kallithea/lib/helpers.py:838
 msgid "[created] user group"
 msgstr "[створено] групу користувачів"
 
-#: kallithea/lib/helpers.py:816
+#: kallithea/lib/helpers.py:840
 msgid "[updated] user group"
 msgstr "[оновлено] група користувачів"
 
-#: kallithea/lib/helpers.py:818
+#: kallithea/lib/helpers.py:842
 msgid "[commented] on revision in repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:820
+#: kallithea/lib/helpers.py:844
 msgid "[commented] on pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:822
+#: kallithea/lib/helpers.py:846
 msgid "[closed] pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:824
+#: kallithea/lib/helpers.py:848
 msgid "[pushed] into"
 msgstr ""
 
-#: kallithea/lib/helpers.py:826
+#: kallithea/lib/helpers.py:850
 msgid "[committed via Kallithea] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:828
+#: kallithea/lib/helpers.py:852
 msgid "[pulled from remote] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:830
+#: kallithea/lib/helpers.py:854
 msgid "[pulled] from"
 msgstr ""
 
-#: kallithea/lib/helpers.py:832
+#: kallithea/lib/helpers.py:856
 msgid "[started following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:834
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "Файлів немає"
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr "новий файл"
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr "перейменувати"
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1277,7 +1275,7 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
@@ -1285,7 +1283,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
@@ -1293,7 +1291,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
@@ -1301,7 +1299,7 @@
 msgstr[1] "%d днів"
 msgstr[2] "%d дня"
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
@@ -1309,7 +1307,7 @@
 msgstr[1] "%d годин"
 msgstr[2] "%d години"
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
@@ -1317,7 +1315,7 @@
 msgstr[1] "%d хвилин"
 msgstr[2] "%d хвилини"
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
@@ -1325,27 +1323,27 @@
 msgstr[1] "%d секунд"
 msgstr[2] "%d секунди"
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr "в %s"
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr "%s тому"
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr "у %s і %s"
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s і %s тому"
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr "прямо зараз"
 
@@ -1358,133 +1356,133 @@
 msgid "[Mention]"
 msgstr "[Згадування]"
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr "верхній рівень"
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr "Kallithea Адміністратор"
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr "Користувач за промовчанням не має доступу до нових репозиторіїв"
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr ""
 "Користувач за замовчанням має доступ на перегляд  нових репозиторіїв"
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr ""
 "Користувач за замовчуванням має доступ до запису до нових репозиторіїв"
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 "Користувач за промовчанням має доступ адміністратора до нових репозиторіїв"
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 "Користувач за замовчуванням не має доступу до нових груп репозиторіїв"
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr ""
 
@@ -1510,33 +1508,33 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:167
+#, python-format
+msgid ""
+"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
+"%(pr_source_branch)s by %(pr_owner_username)s"
+msgstr ""
+
 #: kallithea/model/notification.py:168
 #, python-format
 msgid ""
-"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
-"%(pr_source_branch)s by %(pr_owner_username)s"
-msgstr ""
-
-#: kallithea/model/notification.py:169
-#, python-format
-msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr ""
 
@@ -1610,213 +1608,213 @@
 msgid "SSH key with fingerprint %r found"
 msgstr ""
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
 "owners or remove those repositories: %s"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
 "owners or remove those repository groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
 "owners or remove those user groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr ""
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
 msgstr ""
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:131
-msgid "Invalid user group name"
-msgstr ""
-
 #: kallithea/model/validators.py:132
+msgid "Invalid user group name"
+msgstr ""
+
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:174
-msgid "Cannot assign this group as parent"
-msgstr ""
-
 #: kallithea/model/validators.py:175
+msgid "Cannot assign this group as parent"
+msgstr ""
+
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr ""
 
+#: kallithea/model/validators.py:310
+#, python-format
+msgid "Repository name %(repo)s is not allowed"
+msgstr ""
+
+#: kallithea/model/validators.py:312
+#, python-format
+msgid "Repository named %(repo)s already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:313
 #, python-format
-msgid "Repository name %(repo)s is not allowed"
+msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
 #: kallithea/model/validators.py:315
 #, python-format
-msgid "Repository named %(repo)s already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:316
-#, python-format
-msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
-msgstr ""
-
-#: kallithea/model/validators.py:318
-#, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
 msgstr ""
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1876,7 +1874,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1884,14 +1882,14 @@
 msgid "Description"
 msgstr ""
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr ""
 
@@ -1901,7 +1899,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1925,7 +1923,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr ""
@@ -2049,7 +2047,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr ""
@@ -2297,7 +2295,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr ""
 
@@ -2381,13 +2379,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2403,14 +2401,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2711,7 +2709,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr "Група репозиторіїв"
@@ -2732,7 +2730,7 @@
 msgstr "Дозволи для користувача за промовчанням на нові групи репозиторіів."
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr "Група користувачів"
 
@@ -2910,7 +2908,7 @@
 msgstr "Створено о"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3082,14 +3080,10 @@
 msgstr "Додаткові поля"
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
-msgstr "Кеши"
+msgid "Remote"
+msgstr "Віддалений"
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr "Віддалений"
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3129,7 +3123,7 @@
 "публічному журналі."
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "Підтвердити видалення цього сховища: %s"
@@ -3161,45 +3155,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-msgid "Invalidate Repository Cache"
-msgstr "Скинути Кеш Репозиторію"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-"Вручну скинути кеш для цього репозиторію. При першому доступі, сховище "
-"буде знову кешовано."
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr "Список кешованих значень"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr "Префікс"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr "Мітка"
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr "Ключ"
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr "Активний"
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr "Мітка"
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3738,6 +3701,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr "Активний"
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3759,7 +3731,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr ""
@@ -3833,7 +3805,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr ""
@@ -3933,10 +3905,12 @@
 msgstr "Пошук"
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr "Слідувати"
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr "Не слідкувати"
 
@@ -4612,23 +4586,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4660,6 +4634,13 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "comment"
+msgid "View Comment"
+msgstr "коментар"
+
 #: kallithea/templates/email_templates/comment.html:27
 msgid "Status change:"
 msgstr "Зміна статусу:"
@@ -4668,32 +4649,40 @@
 msgid "The pull request has been closed."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+msgid "Password Reset Request"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4724,6 +4713,12 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+#| msgid "Pull Requests"
+msgid "View Pull Request"
+msgstr "Запити Pull Requests"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, python-format
 msgid "Mention in Comment on Pull Request %s \"%s\""
@@ -4739,10 +4734,20 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr ""
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+#, fuzzy
+#| msgid "Registration"
+msgid "New User Registration"
+msgstr "Реєстрація"
+
+#: kallithea/templates/email_templates/registration.html:23
 msgid "Full Name"
 msgstr ""
 
+#: kallithea/templates/email_templates/registration.html:42
+msgid "View User Profile"
+msgstr ""
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5354,35 +5359,35 @@
 msgid "Show more"
 msgstr "Показати більше"
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr "файли змінено"
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr "вилучені файли"
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr "Фіксація"
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr "файл додано"
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr "файл змінено"
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr "файл видалено"
 
@@ -5482,3 +5487,28 @@
 #, python-format
 msgid "Download %s as %s"
 msgstr ""
+
+#~ msgid "Cache invalidation successful"
+#~ msgstr "Інвалідація кешу успішна"
+
+#~ msgid "An error occurred during cache invalidation"
+#~ msgstr "Сталася помилка під час Анулювання кеша"
+
+#~ msgid "Caches"
+#~ msgstr "Кеши"
+
+#~ msgid "Invalidate Repository Cache"
+#~ msgstr "Скинути Кеш Репозиторію"
+
+#~ msgid ""
+#~ "Manually invalidate cache for this repository. On first access, the "
+#~ "repository will be cached again."
+#~ msgstr ""
+#~ "Вручну скинути кеш для цього репозиторію. При першому доступі, сховище "
+#~ "буде знову кешовано."
+
+#~ msgid "List of Cached Values"
+#~ msgstr "Список кешованих значень"
+
+#~ msgid "Prefix"
+#~ msgstr "Префікс"
--- a/kallithea/i18n/zh_CN/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/zh_CN/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -4,7 +4,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2019-08-14 19:00+0000\n"
 "Last-Translator: Elizabeth Sherrock <lizzyd710@gmail.com>\n"
 "Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/"
@@ -64,7 +64,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr "成功删除拉取请求"
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr "在此代码库内,此修改并不存在"
@@ -252,7 +252,7 @@
 msgid "Tags"
 msgstr "标签"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr "在复刻版本库%s的时候发生错误"
@@ -305,25 +305,29 @@
 msgid "Journal"
 msgstr "日志"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+msgid "Authentication failed."
+msgstr ""
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr "验证码错误"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "您已成功注册 %s"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr "密码重置确认码已经发送"
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "无效的密码重置令牌"
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "成功更新密码"
 
@@ -472,11 +476,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr "该版本库统计功能已经禁用"
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr "验证设置更新成功"
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr "验证设置更新时发生错误"
 
@@ -553,8 +557,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr "gist %s 更新时发生错误"
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr "由于是系统帐号,无法编辑该用户"
 
@@ -689,11 +693,11 @@
 msgid "Allowed with automatic account activation"
 msgstr "已允许自动激活账号"
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr "外部账号手动激活"
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr "外部账号自动激活"
 
@@ -715,294 +719,286 @@
 msgid "Error occurred during update of permissions"
 msgstr "权限更新时发生错误"
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "这个组内有%s个版本库因而无法删除"
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "版本库%s成功更新"
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, fuzzy, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr "无法删除%s因为它还有其他分复刻本库"
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "在删除%s的时候发生错误"
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, fuzzy, python-format
 #| msgid "An error occurred during deletion of user"
 msgid "An error occurred during creation of field: %r"
 msgstr "删除用户时发生错误"
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr "成功更新在公共日志中的可见性"
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr "设置版本库到公共日志时发生错误"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr "无"
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "成功将版本库%s标记为复刻自%s"
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr "在搜索操作中发生错误"
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr "清除缓存时发生错误"
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr "成功拉取自远程路径"
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr "从远程路径拉取时发生错误"
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr "删除版本库统计时发生错误"
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr "成功更新版本控制系统设置"
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, fuzzy, python-format
 msgid "Invalidated %s repositories"
 msgstr "清除版本库缓存"
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr "更新应用设置"
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr "成功更新可视化设置"
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "数据尚未就绪"
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr "新建钩子"
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr "更新钩子"
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr "Whoosh重新索引任务调度"
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr "保存权限时发生错误"
@@ -1046,11 +1042,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr "必须是注册用户才能进行此操作"
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr "必须登录才能访问该页面"
 
@@ -1087,167 +1083,167 @@
 msgid "No changes detected"
 msgstr "未发现差异"
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "已经删除分支%s"
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr "创建标签%s"
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, fuzzy, python-format
 msgid "Changeset %s not found"
 msgstr "未找到修订集"
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "显示所有合并的修订集 %s->%s"
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 #, fuzzy
 msgid "Compare view"
 msgstr "比较显示"
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr "还有"
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr "%s个"
 
-#: kallithea/lib/helpers.py:735
+#: kallithea/lib/helpers.py:759
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "修订"
 
-#: kallithea/lib/helpers.py:759
+#: kallithea/lib/helpers.py:783
 #, fuzzy, python-format
 msgid "Fork name %s"
 msgstr "复刻名称%s"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, fuzzy, python-format
 msgid "Pull request %s"
 msgstr "拉取请求#%s"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:814
 msgid "[deleted] repository"
 msgstr "[删除]版本库"
 
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
 msgid "[created] repository"
 msgstr "[创建]版本库"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:818
 msgid "[created] repository as fork"
 msgstr "[创建]复刻版本库"
 
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
 msgid "[forked] repository"
 msgstr "[复刻]版本库"
 
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
 msgid "[updated] repository"
 msgstr "[更新]版本库"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:824
 msgid "[downloaded] archive from repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:802
+#: kallithea/lib/helpers.py:826
 msgid "[delete] repository"
 msgstr "[删除]版本库"
 
-#: kallithea/lib/helpers.py:810
+#: kallithea/lib/helpers.py:834
 msgid "[created] user"
 msgstr "[创建]用户"
 
-#: kallithea/lib/helpers.py:812
+#: kallithea/lib/helpers.py:836
 msgid "[updated] user"
 msgstr "[更新]用户"
 
-#: kallithea/lib/helpers.py:814
+#: kallithea/lib/helpers.py:838
 msgid "[created] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:816
+#: kallithea/lib/helpers.py:840
 msgid "[updated] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:818
+#: kallithea/lib/helpers.py:842
 msgid "[commented] on revision in repository"
 msgstr "[评论]了版本库中的修订"
 
-#: kallithea/lib/helpers.py:820
+#: kallithea/lib/helpers.py:844
 msgid "[commented] on pull request for"
 msgstr "[评论]拉取请求"
 
-#: kallithea/lib/helpers.py:822
+#: kallithea/lib/helpers.py:846
 msgid "[closed] pull request for"
 msgstr "[关闭] 拉取请求"
 
-#: kallithea/lib/helpers.py:824
+#: kallithea/lib/helpers.py:848
 msgid "[pushed] into"
 msgstr "[推送]到"
 
-#: kallithea/lib/helpers.py:826
+#: kallithea/lib/helpers.py:850
 msgid "[committed via Kallithea] into repository"
 msgstr "[通过Kallithea提交]到版本库"
 
-#: kallithea/lib/helpers.py:828
+#: kallithea/lib/helpers.py:852
 msgid "[pulled from remote] into repository"
 msgstr "[远程拉取]到版本库"
 
-#: kallithea/lib/helpers.py:830
+#: kallithea/lib/helpers.py:854
 msgid "[pulled] from"
 msgstr "[拉取]自"
 
-#: kallithea/lib/helpers.py:832
+#: kallithea/lib/helpers.py:856
 msgid "[started following] repository"
 msgstr "[开始关注]版本库"
 
-#: kallithea/lib/helpers.py:834
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr "[停止关注]版本库"
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr " 还有%s个"
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "无文件"
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1286,63 +1282,63 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] "%d年"
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] "%d月"
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] "%d天"
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] "%d时"
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] "%d分"
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] "%d秒"
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr "%s"
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr "%s前"
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr "%s零%s"
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s零%s前"
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr "刚才"
 
@@ -1355,139 +1351,139 @@
 msgid "[Mention]"
 msgstr "[提及]"
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr "Kallithea 管理员"
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 #, fuzzy
 msgid "Default user has read access to new repositories"
 msgstr "未授权的资源访问"
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 #, fuzzy
 msgid "Default user has write access to new repositories"
 msgstr "未授权的资源访问"
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 #, fuzzy
 msgid "Only admins can create repository groups"
 msgstr "没有在该版本库组中创建版本库的权限"
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 #, fuzzy
 msgid "Non-admins can create repository groups"
 msgstr "没有在该版本库组中创建版本库的权限"
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 #, fuzzy
 msgid "Only admins can fork repositories"
 msgstr "创建版本库"
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 #, fuzzy
 msgid "Non-admins can fork repositories"
 msgstr "创建版本库"
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 #, fuzzy
 msgid "Not reviewed"
 msgstr "未检视"
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 #, fuzzy
 msgid "Under review"
 msgstr "检视中"
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 #, fuzzy
 #| msgid "Approved"
 msgid "Not approved"
 msgstr "已批准"
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr "已批准"
 
@@ -1513,7 +1509,7 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, fuzzy, python-format
 #| msgid "[Comment] %(repo_name)s changeset %(short_id)s on %(branch)s"
 msgid ""
@@ -1521,26 +1517,26 @@
 "%(branch)s"
 msgstr "[评论] %(repo_name)s 修订集 %(short_id)s 在 %(branch)s"
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, fuzzy, python-format
 msgid "New user %(new_username)s registered"
 msgstr "用户名称 %(new_username)s 无效"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid ""
 "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:169
+#: kallithea/model/notification.py:168
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 #, fuzzy
 msgid "Closing"
 msgstr "使用中"
@@ -1623,17 +1619,17 @@
 msgid "SSH key with fingerprint %r found"
 msgstr "未找到修订集"
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 #, fuzzy
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr "由于是系统帐号,无法删除该用户"
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
@@ -1642,7 +1638,7 @@
 "由于用户 \"%s\" 拥有版本库%s因而无法删除,请修改版本库所有者或删除版本"
 "库。%s"
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
@@ -1651,7 +1647,7 @@
 "由于用户 \"%s\" 拥有版本库%s因而无法删除,请修改版本库所有者或删除版本"
 "库。%s"
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
@@ -1660,187 +1656,187 @@
 "由于用户 \"%s\" 拥有版本库%s因而无法删除,请修改版本库所有者或删除版本"
 "库。%s"
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 #, fuzzy
 msgid "Password reset notification"
 msgstr "确认密码"
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr "值不能为空"
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "用户名称%(username)s已经存在"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, fuzzy, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "用户名称 %(username)s 无效"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
 msgstr ""
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr "用户名称 %(username)s 无效"
 
-#: kallithea/model/validators.py:131
+#: kallithea/model/validators.py:132
 msgid "Invalid user group name"
 msgstr ""
 
-#: kallithea/model/validators.py:132
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:174
+#: kallithea/model/validators.py:175
 msgid "Cannot assign this group as parent"
 msgstr "不能将这个组作为parent"
 
-#: kallithea/model/validators.py:175
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr "组 \"%(group_name)s\" 已经存在"
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr "已经存在名为 \"%(group_name)s\" 的版本库"
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr "密码含有无效(非ASCII)字符"
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr "密码不符"
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 #, fuzzy
 msgid "Invalid username or password"
 msgstr "无效密码"
 
-#: kallithea/model/validators.py:313
+#: kallithea/model/validators.py:310
 #, fuzzy, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr "版本库名称不能为%(repo)s"
 
-#: kallithea/model/validators.py:315
+#: kallithea/model/validators.py:312
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr "已经存在版本库%(repo)s"
 
-#: kallithea/model/validators.py:316
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr "版本库组 \"%(group)s\" 中已经存在版本库 \"%(repo)s\""
 
-#: kallithea/model/validators.py:318
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 #, fuzzy
 msgid "Invalid repository URL"
 msgstr "私有版本库"
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr "复刻版本库必须和父版本库类型相同"
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr "没有在该版本库组中创建版本库的权限"
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr "不是一个合法的路径"
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 #, fuzzy
 msgid "This email address is already in use"
 msgstr "该邮件地址已被使用"
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, fuzzy, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "邮件地址\"%(email)s\"不存在"
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
 msgstr "LDAP 登陆属性的 CN 必须指定 - 这个名字作为用户名"
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1900,7 +1896,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1908,14 +1904,14 @@
 msgid "Description"
 msgstr "描述"
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr "最后修改"
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr "Tip"
 
@@ -1925,7 +1921,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1949,7 +1945,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr "帐号"
@@ -2078,7 +2074,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr "电子邮件"
@@ -2328,7 +2324,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr ""
 
@@ -2412,13 +2408,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2434,14 +2430,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2759,7 +2755,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr "版本库组"
@@ -2781,7 +2777,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr ""
 
@@ -2955,7 +2951,7 @@
 msgstr "创建于"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3129,14 +3125,10 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
-msgstr ""
+msgid "Remote"
+msgstr "远程"
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr "远程"
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3179,7 +3171,7 @@
 msgstr "任何人都可以在公共日志上看到这个版本库上的所有动作"
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "确认删除版本库:%s"
@@ -3210,46 +3202,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-#, fuzzy
-msgid "Invalidate Repository Cache"
-msgstr "清除版本库缓存"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-#, fuzzy
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr "手动清除版本库缓存。之后第一次访问的时候将重建缓存"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-#, fuzzy
-msgid "List of Cached Values"
-msgstr "缓存值列表"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr "前缀"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr ""
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr "键"
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr "启用"
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3789,6 +3749,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr "启用"
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3811,7 +3780,7 @@
 msgstr "成员"
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr ""
@@ -3886,7 +3855,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr "确认删除用户:%s"
@@ -3989,10 +3958,12 @@
 msgstr "搜索"
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr ""
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr ""
 
@@ -4700,23 +4671,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr "尚无任何修订集"
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr "订阅%s的RSS"
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr "订阅%s的Atom"
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4754,6 +4725,13 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "Comment"
+msgid "View Comment"
+msgstr "评论"
+
 #: kallithea/templates/email_templates/comment.html:27
 #, fuzzy
 #| msgid "Status change"
@@ -4766,33 +4744,42 @@
 msgid "The pull request has been closed."
 msgstr "版本库未锁定"
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+#, fuzzy
+msgid "Password Reset Request"
+msgstr "确认新密码"
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 #, fuzzy
 msgid "We have received a request to reset the password for your account."
 msgstr "我们收到重置你用户密码的请求。"
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4825,6 +4812,11 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+msgid "View Pull Request"
+msgstr "新建拉取请求"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, fuzzy, python-format
 #| msgid "%(user)s commented on pull request %(age)s"
@@ -4843,12 +4835,24 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr "[评论]拉取请求"
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+#, fuzzy
+#| msgid "Registration"
+msgid "New User Registration"
+msgstr "注册"
+
+#: kallithea/templates/email_templates/registration.html:23
 #, fuzzy
 #| msgid "Group name"
 msgid "Full Name"
 msgstr "组名"
 
+#: kallithea/templates/email_templates/registration.html:42
+#, fuzzy
+#| msgid "View this user here"
+msgid "View User Profile"
+msgstr "查看用户"
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5486,35 +5490,35 @@
 msgid "Show more"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr "提交"
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr "文件已添加"
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr "文件已更改"
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr "文件已删除"
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr "提交"
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr "文件已添加"
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr "文件已更改"
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr "文件已删除"
 
@@ -5622,6 +5626,26 @@
 msgid "Download %s as %s"
 msgstr "下载%s为%s包"
 
+#~ msgid "An error occurred during cache invalidation"
+#~ msgstr "清除缓存时发生错误"
+
+#, fuzzy
+#~ msgid "Invalidate Repository Cache"
+#~ msgstr "清除版本库缓存"
+
+#, fuzzy
+#~ msgid ""
+#~ "Manually invalidate cache for this repository. On first access, the "
+#~ "repository will be cached again."
+#~ msgstr "手动清除版本库缓存。之后第一次访问的时候将重建缓存"
+
+#, fuzzy
+#~ msgid "List of Cached Values"
+#~ msgstr "缓存值列表"
+
+#~ msgid "Prefix"
+#~ msgstr "前缀"
+
 #~ msgid "This repository has been locked by %s on %s"
 #~ msgstr "版本库由%s于%s锁定"
 
@@ -5815,9 +5839,6 @@
 #~ msgid "The comment closed the pull request with status"
 #~ msgstr "[评论]拉取请求"
 
-#~ msgid "View this user here"
-#~ msgstr "查看用户"
-
 #~ msgid "No comments."
 #~ msgstr "%d条评论"
 
--- a/kallithea/i18n/zh_TW/LC_MESSAGES/kallithea.po	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/i18n/zh_TW/LC_MESSAGES/kallithea.po	Mon Apr 27 13:25:28 2020 +0200
@@ -4,7 +4,7 @@
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2020-02-06 01:19+0100\n"
+"POT-Creation-Date: 2020-04-27 13:26+0200\n"
 "PO-Revision-Date: 2017-03-10 18:26+0000\n"
 "Last-Translator: mao <mao@lins.fju.edu.tw>\n"
 "Language-Team: Chinese (Traditional) <https://hosted.weblate.org/projects/"
@@ -63,7 +63,7 @@
 msgid "Successfully deleted pull request %s"
 msgstr "成功遞交至 %s"
 
-#: kallithea/controllers/changeset.py:320 kallithea/controllers/files.py:89
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
 #: kallithea/controllers/files.py:109 kallithea/controllers/files.py:697
 msgid "Such revision does not exist for this repository"
 msgstr ""
@@ -252,7 +252,7 @@
 msgid "Tags"
 msgstr "標籤"
 
-#: kallithea/controllers/forks.py:174
+#: kallithea/controllers/forks.py:175
 #, python-format
 msgid "An error occurred during repository forking %s"
 msgstr ""
@@ -305,25 +305,29 @@
 msgid "Journal"
 msgstr "日誌"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:109
+msgid "Authentication failed."
+msgstr ""
+
+#: kallithea/controllers/login.py:142 kallithea/controllers/login.py:187
 msgid "Bad captcha"
 msgstr ""
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:148
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr ""
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:192
 msgid "A password reset confirmation code has been sent"
 msgstr "密碼重設的確認碼已寄出"
 
-#: kallithea/controllers/login.py:236
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "無效的密碼重設確認碼"
 
 #: kallithea/controllers/admin/my_account.py:157
-#: kallithea/controllers/login.py:241
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr ""
 
@@ -465,11 +469,11 @@
 msgid "Statistics are disabled for this repository"
 msgstr "這個版本庫的統計功能已停用"
 
-#: kallithea/controllers/admin/auth_settings.py:137
+#: kallithea/controllers/admin/auth_settings.py:136
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:148
+#: kallithea/controllers/admin/auth_settings.py:147
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -545,8 +549,8 @@
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:209
-#: kallithea/model/user.py:230
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:205
+#: kallithea/model/user.py:226
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
@@ -679,11 +683,11 @@
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1670
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1578
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1671
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1579
 msgid "Automatic activation of external account"
 msgstr ""
 
@@ -705,292 +709,284 @@
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:167
+#: kallithea/controllers/admin/repo_groups.py:165
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:221
+#: kallithea/controllers/admin/repo_groups.py:219
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:237
+#: kallithea/controllers/admin/repo_groups.py:235
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:247
+#: kallithea/controllers/admin/repo_groups.py:245
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:254
+#: kallithea/controllers/admin/repo_groups.py:252
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:260
+#: kallithea/controllers/admin/repo_groups.py:258
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:349
-#: kallithea/controllers/admin/repo_groups.py:379
-#: kallithea/controllers/admin/user_groups.py:292
+#: kallithea/controllers/admin/repo_groups.py:347
+#: kallithea/controllers/admin/repo_groups.py:377
+#: kallithea/controllers/admin/user_groups.py:290
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:364
+#: kallithea/controllers/admin/repo_groups.py:362
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:396
-#: kallithea/controllers/admin/repos.py:358
-#: kallithea/controllers/admin/user_groups.py:304
+#: kallithea/controllers/admin/repo_groups.py:394
+#: kallithea/controllers/admin/repos.py:357
+#: kallithea/controllers/admin/user_groups.py:302
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:136
+#: kallithea/controllers/admin/repos.py:137
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:194
+#: kallithea/controllers/admin/repos.py:193
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:203
+#: kallithea/controllers/admin/repos.py:202
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:206
+#: kallithea/controllers/admin/repos.py:205
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:235
+#: kallithea/controllers/admin/repos.py:234
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "版本庫 %s 更新完成"
 
-#: kallithea/controllers/admin/repos.py:255
+#: kallithea/controllers/admin/repos.py:254
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:273
+#: kallithea/controllers/admin/repos.py:272
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:276
+#: kallithea/controllers/admin/repos.py:275
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:281
+#: kallithea/controllers/admin/repos.py:280
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:284
+#: kallithea/controllers/admin/repos.py:283
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:289
+#: kallithea/controllers/admin/repos.py:288
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:329
+#: kallithea/controllers/admin/repos.py:328
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:388
+#: kallithea/controllers/admin/repos.py:387
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:391
+#: kallithea/controllers/admin/repos.py:390
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:402
+#: kallithea/controllers/admin/repos.py:401
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:416
+#: kallithea/controllers/admin/repos.py:415
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:448
+#: kallithea/controllers/admin/repos.py:447
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:452
+#: kallithea/controllers/admin/repos.py:451
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:467
 msgid "Nothing"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:470
+#: kallithea/controllers/admin/repos.py:469
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:477
+#: kallithea/controllers/admin/repos.py:476
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:490
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:494
-msgid "An error occurred during cache invalidation"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:507
+#: kallithea/controllers/admin/repos.py:488
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:510
+#: kallithea/controllers/admin/repos.py:491
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:541
+#: kallithea/controllers/admin/repos.py:522
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:131
+#: kallithea/controllers/admin/settings.py:132
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:238
+#: kallithea/controllers/admin/settings.py:136
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:141
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:142
+#: kallithea/controllers/admin/settings.py:234
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:176
+#: kallithea/controllers/admin/settings.py:177
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:188
+#: kallithea/controllers/admin/settings.py:189
 #, fuzzy, python-format
 #| msgid "Invalidate Repository Cache"
 msgid "Invalidated %s repositories"
 msgstr "確認廢止版本庫快取"
 
-#: kallithea/controllers/admin/settings.py:229
+#: kallithea/controllers/admin/settings.py:230
 msgid "Updated application settings"
 msgstr "更新應用設定"
 
-#: kallithea/controllers/admin/settings.py:283
+#: kallithea/controllers/admin/settings.py:284
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:288
+#: kallithea/controllers/admin/settings.py:289
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:312
+#: kallithea/controllers/admin/settings.py:313
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:327
+#: kallithea/controllers/admin/settings.py:328
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:355
+#: kallithea/controllers/admin/settings.py:356
 msgid "Hook already exists"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:357
+#: kallithea/controllers/admin/settings.py:358
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:361
 msgid "Added new hook"
 msgstr "新增hook"
 
-#: kallithea/controllers/admin/settings.py:376
+#: kallithea/controllers/admin/settings.py:377
 msgid "Updated hooks"
 msgstr "更新hook"
 
-#: kallithea/controllers/admin/settings.py:380
+#: kallithea/controllers/admin/settings.py:381
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:404
+#: kallithea/controllers/admin/settings.py:405
 msgid "Whoosh reindex task scheduled"
 msgstr "Whoosh 重新索引工作排程"
 
-#: kallithea/controllers/admin/user_groups.py:136
+#: kallithea/controllers/admin/user_groups.py:134
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:149
+#: kallithea/controllers/admin/user_groups.py:147
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:177
+#: kallithea/controllers/admin/user_groups.py:175
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:199
+#: kallithea/controllers/admin/user_groups.py:197
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:210
+#: kallithea/controllers/admin/user_groups.py:208
 msgid "Successfully deleted user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:215
+#: kallithea/controllers/admin/user_groups.py:213
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:271
+#: kallithea/controllers/admin/user_groups.py:269
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:277
+#: kallithea/controllers/admin/user_groups.py:275
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:386
+#: kallithea/controllers/admin/user_groups.py:384
 #: kallithea/controllers/admin/users.py:336
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:390
+#: kallithea/controllers/admin/user_groups.py:388
 #: kallithea/controllers/admin/users.py:340
 msgid "An error occurred during permissions saving"
 msgstr ""
@@ -1034,11 +1030,11 @@
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:668
+#: kallithea/lib/auth.py:634
 msgid "You need to be a registered user to perform this action"
 msgstr "您必須是註冊使用者才能執行這個動作"
 
-#: kallithea/lib/auth.py:696
+#: kallithea/lib/auth.py:662
 msgid "You need to be signed in to view this page"
 msgstr "您必須登入後才能瀏覽這個頁面"
 
@@ -1075,167 +1071,167 @@
 msgid "No changes detected"
 msgstr "尚未有任何變更"
 
-#: kallithea/lib/helpers.py:646
+#: kallithea/lib/helpers.py:670
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:648
+#: kallithea/lib/helpers.py:672
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:659
+#: kallithea/lib/helpers.py:683
 #, fuzzy, python-format
 #| msgid "Set changeset status"
 msgid "Changeset %s not found"
 msgstr "尚未有任何變更"
 
-#: kallithea/lib/helpers.py:708
+#: kallithea/lib/helpers.py:732
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:714
+#: kallithea/lib/helpers.py:738
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:733
+#: kallithea/lib/helpers.py:757
 msgid "and"
 msgstr "和"
 
-#: kallithea/lib/helpers.py:734
+#: kallithea/lib/helpers.py:758
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:735
+#: kallithea/lib/helpers.py:759
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "修訂"
 
-#: kallithea/lib/helpers.py:759
+#: kallithea/lib/helpers.py:783
 #, python-format
 msgid "Fork name %s"
 msgstr "分支名稱 %s"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:804
 #, python-format
 msgid "Pull request %s"
 msgstr "提取要求 %s"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:814
 msgid "[deleted] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:792 kallithea/lib/helpers.py:804
+#: kallithea/lib/helpers.py:816 kallithea/lib/helpers.py:828
 msgid "[created] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:794
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:796 kallithea/lib/helpers.py:806
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:798 kallithea/lib/helpers.py:808
-msgid "[updated] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:800
-msgid "[downloaded] archive from repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:802
-msgid "[delete] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:810
-msgid "[created] user"
-msgstr ""
-
-#: kallithea/lib/helpers.py:812
-msgid "[updated] user"
-msgstr ""
-
-#: kallithea/lib/helpers.py:814
-msgid "[created] user group"
-msgstr ""
-
-#: kallithea/lib/helpers.py:816
-msgid "[updated] user group"
-msgstr ""
-
 #: kallithea/lib/helpers.py:818
-msgid "[commented] on revision in repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:820
-msgid "[commented] on pull request for"
-msgstr ""
-
-#: kallithea/lib/helpers.py:822
-msgid "[closed] pull request for"
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:820 kallithea/lib/helpers.py:830
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:822 kallithea/lib/helpers.py:832
+msgid "[updated] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:824
-msgid "[pushed] into"
+msgid "[downloaded] archive from repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:826
-msgid "[committed via Kallithea] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:828
-msgid "[pulled from remote] into repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:830
-msgid "[pulled] from"
-msgstr ""
-
-#: kallithea/lib/helpers.py:832
-msgid "[started following] repository"
+msgid "[delete] repository"
 msgstr ""
 
 #: kallithea/lib/helpers.py:834
+msgid "[created] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:836
+msgid "[updated] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:838
+msgid "[created] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:840
+msgid "[updated] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:842
+msgid "[commented] on revision in repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:844
+msgid "[commented] on pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:846
+msgid "[closed] pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:848
+msgid "[pushed] into"
+msgstr ""
+
+#: kallithea/lib/helpers.py:850
+msgid "[committed via Kallithea] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:852
+msgid "[pulled from remote] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:854
+msgid "[pulled] from"
+msgstr ""
+
+#: kallithea/lib/helpers.py:856
+msgid "[started following] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:858
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:954
+#: kallithea/lib/helpers.py:975
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:958
+#: kallithea/lib/helpers.py:979
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:983
+#: kallithea/lib/helpers.py:1004
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:986
+#: kallithea/lib/helpers.py:1007
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:989
+#: kallithea/lib/helpers.py:1010
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:992
+#: kallithea/lib/helpers.py:1013
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:997
+#: kallithea/lib/helpers.py:1018
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1290
+#: kallithea/lib/helpers.py:1314
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1272,63 +1268,63 @@
 msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
 msgstr ""
 
-#: kallithea/lib/utils2.py:242
+#: kallithea/lib/utils2.py:253
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 
-#: kallithea/lib/utils2.py:243
+#: kallithea/lib/utils2.py:254
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 
-#: kallithea/lib/utils2.py:244
+#: kallithea/lib/utils2.py:255
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 
-#: kallithea/lib/utils2.py:245
+#: kallithea/lib/utils2.py:256
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 
-#: kallithea/lib/utils2.py:246
+#: kallithea/lib/utils2.py:257
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 
-#: kallithea/lib/utils2.py:247
+#: kallithea/lib/utils2.py:258
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 
-#: kallithea/lib/utils2.py:263
+#: kallithea/lib/utils2.py:274
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:265
+#: kallithea/lib/utils2.py:276
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:267
+#: kallithea/lib/utils2.py:278
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:270
+#: kallithea/lib/utils2.py:281
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:273
+#: kallithea/lib/utils2.py:284
 msgid "just now"
 msgstr "現在"
 
@@ -1341,130 +1337,130 @@
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1493
+#: kallithea/model/db.py:1411
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1634
+#: kallithea/model/db.py:1542
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1636
+#: kallithea/model/db.py:1544
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1637
+#: kallithea/model/db.py:1545
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1638
+#: kallithea/model/db.py:1546
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1639
+#: kallithea/model/db.py:1547
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1641
+#: kallithea/model/db.py:1549
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1642
+#: kallithea/model/db.py:1550
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1643
+#: kallithea/model/db.py:1551
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1644
+#: kallithea/model/db.py:1552
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1646
+#: kallithea/model/db.py:1554
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1647
+#: kallithea/model/db.py:1555
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1648
+#: kallithea/model/db.py:1556
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1649
+#: kallithea/model/db.py:1557
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1651
+#: kallithea/model/db.py:1559
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1652
+#: kallithea/model/db.py:1560
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1654
+#: kallithea/model/db.py:1562
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1655
+#: kallithea/model/db.py:1563
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1657
+#: kallithea/model/db.py:1565
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1658
+#: kallithea/model/db.py:1566
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1660
+#: kallithea/model/db.py:1568
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1661
+#: kallithea/model/db.py:1569
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1663
+#: kallithea/model/db.py:1571
 msgid "Only admins can fork repositories"
 msgstr "祗有管理者才能分歧版本庫"
 
-#: kallithea/model/db.py:1664
+#: kallithea/model/db.py:1572
 #, fuzzy
 msgid "Non-admins can fork repositories"
 msgstr "建立版本庫"
 
-#: kallithea/model/db.py:1666
+#: kallithea/model/db.py:1574
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1667
+#: kallithea/model/db.py:1575
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1668
+#: kallithea/model/db.py:1576
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2208
+#: kallithea/model/db.py:1992
 msgid "Not reviewed"
 msgstr "未審核"
 
-#: kallithea/model/db.py:2209
+#: kallithea/model/db.py:1993
 msgid "Under review"
 msgstr "審核中"
 
-#: kallithea/model/db.py:2210
+#: kallithea/model/db.py:1994
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2211
+#: kallithea/model/db.py:1995
 msgid "Approved"
 msgstr ""
 
@@ -1490,33 +1486,33 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:163
+#: kallithea/model/notification.py:162
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:166
+#: kallithea/model/notification.py:165
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:167
+#, python-format
+msgid ""
+"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
+"%(pr_source_branch)s by %(pr_owner_username)s"
+msgstr ""
+
 #: kallithea/model/notification.py:168
 #, python-format
 msgid ""
-"[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
-"%(pr_source_branch)s by %(pr_owner_username)s"
-msgstr ""
-
-#: kallithea/model/notification.py:169
-#, python-format
-msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
 "%(pr_source_branch)s by %(pr_owner_username)s"
 msgstr ""
 
-#: kallithea/model/notification.py:189
+#: kallithea/model/notification.py:188
 msgid "Closing"
 msgstr "關閉中"
 
@@ -1591,215 +1587,215 @@
 msgid "SSH key with fingerprint %r found"
 msgstr "尚未有任何變更"
 
-#: kallithea/model/user.py:184
+#: kallithea/model/user.py:180
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:248
+#: kallithea/model/user.py:244
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr "您無法移除這個使用者,因為係供整個應用使用"
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:249
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
 "owners or remove those repositories: %s"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:254
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
 "owners or remove those repository groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:265
+#: kallithea/model/user.py:261
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
 "owners or remove those user groups: %s"
 msgstr ""
 
-#: kallithea/model/user.py:359
+#: kallithea/model/user.py:355
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:406
+#: kallithea/model/user.py:402
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:407
+#: kallithea/model/user.py:403
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
+#: kallithea/model/validators.py:53 kallithea/model/validators.py:54
 msgid "Value cannot be an empty list"
 msgstr ""
 
-#: kallithea/model/validators.py:72
+#: kallithea/model/validators.py:73
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:75
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:77
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
 msgstr ""
 
-#: kallithea/model/validators.py:103
+#: kallithea/model/validators.py:104
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:110
+#: kallithea/model/validators.py:111
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:131
-msgid "Invalid user group name"
-msgstr ""
-
 #: kallithea/model/validators.py:132
+msgid "Invalid user group name"
+msgstr ""
+
+#: kallithea/model/validators.py:133
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:135
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 "使用者羣組名稱可以包括文數字字元、底線、句點或破折號,必須以文數字啟頭"
 
-#: kallithea/model/validators.py:174
+#: kallithea/model/validators.py:175
 msgid "Cannot assign this group as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:175
+#: kallithea/model/validators.py:176
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:178
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:233
+#: kallithea/model/validators.py:230
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:248
+#: kallithea/model/validators.py:245
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:264
+#: kallithea/model/validators.py:261
 msgid "Passwords do not match"
 msgstr "密碼不相符"
 
-#: kallithea/model/validators.py:279
+#: kallithea/model/validators.py:276
 msgid "Invalid username or password"
 msgstr "無效的用戶名稱或密碼"
 
-#: kallithea/model/validators.py:313
+#: kallithea/model/validators.py:310
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr ""
 
+#: kallithea/model/validators.py:312
+#, python-format
+msgid "Repository named %(repo)s already exists"
+msgstr ""
+
+#: kallithea/model/validators.py:313
+#, python-format
+msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
+msgstr ""
+
 #: kallithea/model/validators.py:315
 #, python-format
-msgid "Repository named %(repo)s already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:316
-#, python-format
-msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
-msgstr ""
-
-#: kallithea/model/validators.py:318
-#, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:404
+#: kallithea/model/validators.py:401
 msgid "Invalid repository URL"
 msgstr "無效的版本庫 URL"
 
-#: kallithea/model/validators.py:405
+#: kallithea/model/validators.py:402
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:430
+#: kallithea/model/validators.py:427
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:442
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:447
+#: kallithea/model/validators.py:444
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:497
+#: kallithea/model/validators.py:494
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:537
+#: kallithea/model/validators.py:534
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:630
+#: kallithea/model/validators.py:627
 msgid "This is not a valid path"
 msgstr "不是一個有效的路徑"
 
-#: kallithea/model/validators.py:647
+#: kallithea/model/validators.py:644
 #, fuzzy
 msgid "This email address is already in use"
 msgstr "這個郵件位址已經使用了"
 
-#: kallithea/model/validators.py:667
+#: kallithea/model/validators.py:664
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:704
+#: kallithea/model/validators.py:701
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
 msgstr ""
 
-#: kallithea/model/validators.py:716
+#: kallithea/model/validators.py:713
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:717
+#: kallithea/model/validators.py:714
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:750
+#: kallithea/model/validators.py:747
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:764
+#: kallithea/model/validators.py:761
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:780
+#: kallithea/model/validators.py:777
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1859,7 +1855,7 @@
 #: kallithea/templates/admin/users/user_edit_ssh_keys.html:60
 #: kallithea/templates/email_templates/pull_request.html:37
 #: kallithea/templates/forks/fork.html:34
-#: kallithea/templates/index_base.html:58
+#: kallithea/templates/index_base.html:59
 #: kallithea/templates/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
@@ -1867,14 +1863,14 @@
 msgid "Description"
 msgstr "描述"
 
-#: kallithea/templates/index_base.html:60
+#: kallithea/templates/index_base.html:61
 msgid "Last Change"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
 #: kallithea/templates/admin/repos/repos.html:41
-#: kallithea/templates/index_base.html:62
+#: kallithea/templates/index_base.html:63
 msgid "Tip"
 msgstr ""
 
@@ -1884,7 +1880,7 @@
 #: kallithea/templates/admin/repos/repos.html:42
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:8
 #: kallithea/templates/admin/user_groups/user_groups.html:42
-#: kallithea/templates/index_base.html:63
+#: kallithea/templates/index_base.html:64
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
@@ -1908,7 +1904,7 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
 #: kallithea/templates/base/base.html:364
-#: kallithea/templates/email_templates/registration.html:11
+#: kallithea/templates/email_templates/registration.html:12
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
 msgstr "帳號"
@@ -2036,7 +2032,7 @@
 #: kallithea/templates/admin/settings/settings.html:31
 #: kallithea/templates/admin/users/user_add.html:62
 #: kallithea/templates/admin/users/user_edit_profile.html:25
-#: kallithea/templates/email_templates/registration.html:33
+#: kallithea/templates/email_templates/registration.html:34
 #: kallithea/templates/register.html:66
 msgid "Email"
 msgstr "電子郵件"
@@ -2286,7 +2282,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/gists/index.html:51
-#: kallithea/templates/data_table/_dt_elements.html:78
+#: kallithea/templates/data_table/_dt_elements.html:84
 msgid "Created"
 msgstr ""
 
@@ -2370,13 +2366,13 @@
 #: kallithea/templates/admin/users/user_edit_ips.html:21
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #: kallithea/templates/changeset/changeset_file_comment.html:121
-#: kallithea/templates/data_table/_dt_elements.html:69
-#: kallithea/templates/data_table/_dt_elements.html:89
-#: kallithea/templates/data_table/_dt_elements.html:91
-#: kallithea/templates/data_table/_dt_elements.html:101
-#: kallithea/templates/data_table/_dt_elements.html:103
-#: kallithea/templates/data_table/_dt_elements.html:120
-#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:75
+#: kallithea/templates/data_table/_dt_elements.html:95
+#: kallithea/templates/data_table/_dt_elements.html:97
+#: kallithea/templates/data_table/_dt_elements.html:107
+#: kallithea/templates/data_table/_dt_elements.html:109
+#: kallithea/templates/data_table/_dt_elements.html:126
+#: kallithea/templates/data_table/_dt_elements.html:128
 #: kallithea/templates/files/files_source.html:35
 #: kallithea/templates/files/files_source.html:38
 #: kallithea/templates/files/files_source.html:41
@@ -2392,14 +2388,14 @@
 #: kallithea/templates/base/perms_summary.html:44
 #: kallithea/templates/base/perms_summary.html:81
 #: kallithea/templates/base/perms_summary.html:83
-#: kallithea/templates/data_table/_dt_elements.html:63
-#: kallithea/templates/data_table/_dt_elements.html:64
-#: kallithea/templates/data_table/_dt_elements.html:85
-#: kallithea/templates/data_table/_dt_elements.html:86
-#: kallithea/templates/data_table/_dt_elements.html:97
-#: kallithea/templates/data_table/_dt_elements.html:98
-#: kallithea/templates/data_table/_dt_elements.html:116
-#: kallithea/templates/data_table/_dt_elements.html:117
+#: kallithea/templates/data_table/_dt_elements.html:69
+#: kallithea/templates/data_table/_dt_elements.html:70
+#: kallithea/templates/data_table/_dt_elements.html:91
+#: kallithea/templates/data_table/_dt_elements.html:92
+#: kallithea/templates/data_table/_dt_elements.html:103
+#: kallithea/templates/data_table/_dt_elements.html:104
+#: kallithea/templates/data_table/_dt_elements.html:122
+#: kallithea/templates/data_table/_dt_elements.html:123
 #: kallithea/templates/files/diff_2way.html:56
 #: kallithea/templates/files/files_source.html:37
 #: kallithea/templates/files/files_source.html:40
@@ -2716,7 +2712,7 @@
 #: kallithea/templates/admin/permissions/permissions_globals.html:27
 #: kallithea/templates/admin/repos/repo_add_base.html:28
 #: kallithea/templates/admin/repos/repo_edit_settings.html:33
-#: kallithea/templates/data_table/_dt_elements.html:134
+#: kallithea/templates/data_table/_dt_elements.html:140
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr "版本庫群組"
@@ -2737,7 +2733,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
-#: kallithea/templates/data_table/_dt_elements.html:141
+#: kallithea/templates/data_table/_dt_elements.html:147
 msgid "User group"
 msgstr ""
 
@@ -2911,7 +2907,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:121
+#: kallithea/templates/data_table/_dt_elements.html:127
 #, python-format
 msgid "Confirm to delete this group: %s with %s repository"
 msgid_plural "Confirm to delete this group: %s with %s repositories"
@@ -3082,14 +3078,10 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
-msgid "Caches"
-msgstr ""
+msgid "Remote"
+msgstr "遠端"
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
-msgid "Remote"
-msgstr "遠端"
-
-#: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
 #: kallithea/templates/summary/summary.html:169
 #: kallithea/templates/summary/summary.html:170
@@ -3130,7 +3122,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:46
-#: kallithea/templates/data_table/_dt_elements.html:68
+#: kallithea/templates/data_table/_dt_elements.html:74
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr ""
@@ -3161,44 +3153,14 @@
 "it or restore it."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:4
-#, fuzzy
-msgid "Invalidate Repository Cache"
-msgstr "確認廢止版本庫快取"
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:6
-msgid ""
-"Manually invalidate cache for this repository. On first access, the "
-"repository will be cached again."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:9
-msgid "List of Cached Values"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:12
-msgid "Prefix"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_caches.html:13
+#: kallithea/templates/admin/repos/repo_edit_fields.html:6
+msgid "Label"
+msgstr ""
+
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_caches.html:14
-#: kallithea/templates/admin/user_groups/user_group_add.html:40
-#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
-#: kallithea/templates/admin/user_groups/user_groups.html:41
-#: kallithea/templates/admin/users/user_add.html:69
-#: kallithea/templates/admin/users/user_edit_profile.html:74
-#: kallithea/templates/admin/users/users.html:42
-msgid "Active"
-msgstr "啟用"
-
-#: kallithea/templates/admin/repos/repo_edit_fields.html:6
-msgid "Label"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
@@ -3735,6 +3697,15 @@
 msgid "Short, optional description for this user group."
 msgstr ""
 
+#: kallithea/templates/admin/user_groups/user_group_add.html:40
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:17
+#: kallithea/templates/admin/user_groups/user_groups.html:41
+#: kallithea/templates/admin/users/user_add.html:69
+#: kallithea/templates/admin/users/user_edit_profile.html:74
+#: kallithea/templates/admin/users/users.html:42
+msgid "Active"
+msgstr "啟用"
+
 #: kallithea/templates/admin/user_groups/user_group_edit.html:5
 #, python-format
 msgid "%s user group settings"
@@ -3757,7 +3728,7 @@
 msgstr "成員"
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
-#: kallithea/templates/data_table/_dt_elements.html:102
+#: kallithea/templates/data_table/_dt_elements.html:108
 #, python-format
 msgid "Confirm to delete this user group: %s"
 msgstr ""
@@ -3832,7 +3803,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:21
-#: kallithea/templates/data_table/_dt_elements.html:90
+#: kallithea/templates/data_table/_dt_elements.html:96
 #, python-format
 msgid "Confirm to delete this user: %s"
 msgstr ""
@@ -3933,10 +3904,12 @@
 msgstr "搜尋"
 
 #: kallithea/templates/base/base.html:167
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Follow"
 msgstr ""
 
 #: kallithea/templates/base/base.html:168
+#: kallithea/templates/data_table/_dt_elements.html:36
 msgid "Unfollow"
 msgstr ""
 
@@ -4629,23 +4602,23 @@
 msgid "Repository creation in progress..."
 msgstr ""
 
-#: kallithea/templates/data_table/_dt_elements.html:42
+#: kallithea/templates/data_table/_dt_elements.html:48
 msgid "No changesets yet"
 msgstr "尚未有任何變更"
 
-#: kallithea/templates/data_table/_dt_elements.html:48
-#: kallithea/templates/data_table/_dt_elements.html:50
+#: kallithea/templates/data_table/_dt_elements.html:54
+#: kallithea/templates/data_table/_dt_elements.html:56
 #, python-format
 msgid "Subscribe to %s rss feed"
 msgstr "訂閱 %s rss"
 
-#: kallithea/templates/data_table/_dt_elements.html:56
-#: kallithea/templates/data_table/_dt_elements.html:58
+#: kallithea/templates/data_table/_dt_elements.html:62
+#: kallithea/templates/data_table/_dt_elements.html:64
 #, python-format
 msgid "Subscribe to %s atom feed"
 msgstr "訂閱 %s atom"
 
-#: kallithea/templates/data_table/_dt_elements.html:76
+#: kallithea/templates/data_table/_dt_elements.html:82
 msgid "Creating"
 msgstr ""
 
@@ -4682,6 +4655,13 @@
 msgid "by"
 msgstr ""
 
+#: kallithea/templates/email_templates/changeset_comment.html:36
+#: kallithea/templates/email_templates/pull_request_comment.html:43
+#, fuzzy
+#| msgid "%s committed on %s"
+msgid "View Comment"
+msgstr "%s 評論於 %s"
+
 #: kallithea/templates/email_templates/comment.html:27
 #, fuzzy
 #| msgid "Status change"
@@ -4694,32 +4674,40 @@
 msgid "The pull request has been closed."
 msgstr "儲存所已被鎖定"
 
-#: kallithea/templates/email_templates/password_reset.html:9
+#: kallithea/templates/email_templates/default.html:4
+msgid "Message"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:4
+msgid "Password Reset Request"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:10
 #, python-format
 msgid "Hello %s"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:16
+#: kallithea/templates/email_templates/password_reset.html:17
 msgid "We have received a request to reset the password for your account."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:25
+#: kallithea/templates/email_templates/password_reset.html:26
 msgid ""
 "This account is however managed outside this system and the password "
 "cannot be changed here."
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:28
+#: kallithea/templates/email_templates/password_reset.html:29
 msgid "To set a new password, click the following link"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:33
+#: kallithea/templates/email_templates/password_reset.html:34
 msgid ""
 "Should you not be able to use the link above, please type the following "
 "code into the password reset form"
 msgstr ""
 
-#: kallithea/templates/email_templates/password_reset.html:44
+#: kallithea/templates/email_templates/password_reset.html:45
 msgid ""
 "If it weren't you who requested the password reset, just disregard this "
 "message."
@@ -4752,6 +4740,12 @@
 msgid "to"
 msgstr ""
 
+#: kallithea/templates/email_templates/pull_request.html:85
+#, fuzzy
+#| msgid "Pull request %s"
+msgid "View Pull Request"
+msgstr "提取要求 %s"
+
 #: kallithea/templates/email_templates/pull_request_comment.html:4
 #, python-format
 msgid "Mention in Comment on Pull Request %s \"%s\""
@@ -4769,12 +4763,22 @@
 msgid "Comment on Pull Request %s \"%s\""
 msgstr "提取要求 %s"
 
-#: kallithea/templates/email_templates/registration.html:22
+#: kallithea/templates/email_templates/registration.html:5
+#, fuzzy
+#| msgid "Registration"
+msgid "New User Registration"
+msgstr "註冊"
+
+#: kallithea/templates/email_templates/registration.html:23
 #, fuzzy
 #| msgid "Group name"
 msgid "Full Name"
 msgstr "群組名稱"
 
+#: kallithea/templates/email_templates/registration.html:42
+msgid "View User Profile"
+msgstr ""
+
 #: kallithea/templates/files/diff_2way.html:15
 #, python-format
 msgid "%s File side-by-side diff"
@@ -5397,35 +5401,35 @@
 msgid "Show more"
 msgstr ""
 
-#: kallithea/templates/summary/statistics.html:403
+#: kallithea/templates/summary/statistics.html:395
 msgid "commits"
 msgstr "遞交"
 
-#: kallithea/templates/summary/statistics.html:404
+#: kallithea/templates/summary/statistics.html:396
 msgid "files added"
 msgstr "多個檔案新增"
 
-#: kallithea/templates/summary/statistics.html:405
+#: kallithea/templates/summary/statistics.html:397
 msgid "files changed"
 msgstr "多個檔案修改"
 
-#: kallithea/templates/summary/statistics.html:406
+#: kallithea/templates/summary/statistics.html:398
 msgid "files removed"
 msgstr "移除多個檔案"
 
-#: kallithea/templates/summary/statistics.html:408
+#: kallithea/templates/summary/statistics.html:400
 msgid "commit"
 msgstr "遞交"
 
-#: kallithea/templates/summary/statistics.html:409
+#: kallithea/templates/summary/statistics.html:401
 msgid "file added"
 msgstr "檔案新增"
 
-#: kallithea/templates/summary/statistics.html:410
+#: kallithea/templates/summary/statistics.html:402
 msgid "file changed"
 msgstr "檔案修改"
 
-#: kallithea/templates/summary/statistics.html:411
+#: kallithea/templates/summary/statistics.html:403
 msgid "file removed"
 msgstr "移除檔案"
 
@@ -5532,6 +5536,10 @@
 msgid "Download %s as %s"
 msgstr "下載 %s 為 %s"
 
+#, fuzzy
+#~ msgid "Invalidate Repository Cache"
+#~ msgstr "確認廢止版本庫快取"
+
 #~ msgid "Repository has been locked"
 #~ msgstr "儲存所已被鎖定"
 
--- a/kallithea/lib/auth.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/auth.py	Mon Apr 27 13:25:28 2020 +0200
@@ -30,6 +30,7 @@
 import os
 import string
 
+import bcrypt
 import ipaddr
 from decorator import decorator
 from sqlalchemy.orm import joinedload
@@ -38,14 +39,13 @@
 from tg.i18n import ugettext as _
 from webob.exc import HTTPForbidden, HTTPFound
 
-from kallithea import __platform__, is_unix, is_windows
+import kallithea
 from kallithea.config.routing import url
-from kallithea.lib.caching_query import FromCache
-from kallithea.lib.utils import conditional_cache, get_repo_group_slug, get_repo_slug, get_user_group_slug
+from kallithea.lib.utils import get_repo_group_slug, get_repo_slug, get_user_group_slug
 from kallithea.lib.utils2 import ascii_bytes, ascii_str, safe_bytes
 from kallithea.lib.vcs.utils.lazy import LazyProperty
-from kallithea.model.db import (
-    Permission, RepoGroup, Repository, User, UserApiKeys, UserGroup, UserGroupMember, UserGroupRepoGroupToPerm, UserGroupRepoToPerm, UserGroupToPerm, UserGroupUserGroupToPerm, UserIpMap, UserToPerm)
+from kallithea.model.db import (Permission, UserApiKeys, UserGroup, UserGroupMember, UserGroupRepoGroupToPerm, UserGroupRepoToPerm, UserGroupToPerm,
+                                UserGroupUserGroupToPerm, UserIpMap, UserToPerm)
 from kallithea.model.meta import Session
 from kallithea.model.user import UserModel
 
@@ -87,44 +87,34 @@
 
 def get_crypt_password(password):
     """
-    Cryptographic function used for password hashing based on pybcrypt
-    or Python's own OpenSSL wrapper on windows
+    Cryptographic function used for bcrypt password hashing.
 
     :param password: password to hash
     """
-    if is_windows:
-        return hashlib.sha256(password).hexdigest()
-    elif is_unix:
-        import bcrypt
-        return ascii_str(bcrypt.hashpw(safe_bytes(password), bcrypt.gensalt(10)))
-    else:
-        raise Exception('Unknown or unsupported platform %s'
-                        % __platform__)
+    return ascii_str(bcrypt.hashpw(safe_bytes(password), bcrypt.gensalt(10)))
 
 
 def check_password(password, hashed):
     """
-    Checks matching password with it's hashed value, runs different
-    implementation based on platform it runs on
+    Checks password match the hashed value using bcrypt.
+    Remains backwards compatible and accept plain sha256 hashes which used to
+    be used on Windows.
 
     :param password: password
     :param hashed: password in hashed form
     """
     # sha256 hashes will always be 64 hex chars
     # bcrypt hashes will always contain $ (and be shorter)
-    if is_windows or len(hashed) == 64 and all(x in string.hexdigits for x in hashed):
-        return hashlib.sha256(safe_bytes(password)).hexdigest() == hashed
-    elif is_unix:
-        import bcrypt
-        try:
-            return bcrypt.checkpw(safe_bytes(password), ascii_bytes(hashed))
-        except ValueError as e:
-            # bcrypt will throw ValueError 'Invalid hashed_password salt' on all password errors
-            log.error('error from bcrypt checking password: %s', e)
-            return False
-    else:
-        raise Exception('Unknown or unsupported platform %s'
-                        % __platform__)
+    if len(hashed) == 64 and all(x in string.hexdigits for x in hashed):
+        return hashlib.sha256(password).hexdigest() == hashed
+    try:
+        return bcrypt.checkpw(safe_bytes(password), ascii_bytes(hashed))
+    except ValueError as e:
+        # bcrypt will throw ValueError 'Invalid hashed_password salt' on all password errors
+        log.error('error from bcrypt checking password: %s', e)
+        return False
+    log.error('check_password failed - no method found for hash length %s', len(hashed))
+    return False
 
 
 def _cached_perms_data(user_id, user_is_admin):
@@ -149,12 +139,9 @@
     #======================================================================
     # fetch default permissions
     #======================================================================
-    default_user = User.get_by_username('default', cache=True)
-    default_user_id = default_user.user_id
-
-    default_repo_perms = Permission.get_default_perms(default_user_id)
-    default_repo_groups_perms = Permission.get_default_group_perms(default_user_id)
-    default_user_group_perms = Permission.get_default_user_group_perms(default_user_id)
+    default_repo_perms = Permission.get_default_perms(kallithea.DEFAULT_USER_ID)
+    default_repo_groups_perms = Permission.get_default_group_perms(kallithea.DEFAULT_USER_ID)
+    default_user_group_perms = Permission.get_default_user_group_perms(kallithea.DEFAULT_USER_ID)
 
     if user_is_admin:
         #==================================================================
@@ -166,19 +153,19 @@
 
         # repositories
         for perm in default_repo_perms:
-            r_k = perm.UserRepoToPerm.repository.repo_name
+            r_k = perm.repository.repo_name
             p = 'repository.admin'
             permissions[RK][r_k] = p
 
         # repository groups
         for perm in default_repo_groups_perms:
-            rg_k = perm.UserRepoGroupToPerm.group.group_name
+            rg_k = perm.group.group_name
             p = 'group.admin'
             permissions[GK][rg_k] = p
 
         # user groups
         for perm in default_user_group_perms:
-            u_k = perm.UserUserGroupToPerm.user_group.users_group_name
+            u_k = perm.user_group.users_group_name
             p = 'usergroup.admin'
             permissions[UK][u_k] = p
         return permissions
@@ -189,7 +176,7 @@
 
     # default global permissions taken from the default user
     default_global_perms = UserToPerm.query() \
-        .filter(UserToPerm.user_id == default_user_id) \
+        .filter(UserToPerm.user_id == kallithea.DEFAULT_USER_ID) \
         .options(joinedload(UserToPerm.permission))
 
     for perm in default_global_perms:
@@ -197,27 +184,27 @@
 
     # defaults for repositories, taken from default user
     for perm in default_repo_perms:
-        r_k = perm.UserRepoToPerm.repository.repo_name
-        if perm.Repository.owner_id == user_id:
+        r_k = perm.repository.repo_name
+        if perm.repository.owner_id == user_id:
             p = 'repository.admin'
-        elif perm.Repository.private:
+        elif perm.repository.private:
             p = 'repository.none'
         else:
-            p = perm.Permission.permission_name
+            p = perm.permission.permission_name
         permissions[RK][r_k] = p
 
     # defaults for repository groups taken from default user permission
     # on given group
     for perm in default_repo_groups_perms:
-        rg_k = perm.UserRepoGroupToPerm.group.group_name
-        p = perm.Permission.permission_name
+        rg_k = perm.group.group_name
+        p = perm.permission.permission_name
         permissions[GK][rg_k] = p
 
     # defaults for user groups taken from default user permission
     # on given user group
     for perm in default_user_group_perms:
-        u_k = perm.UserUserGroupToPerm.user_group.users_group_name
-        p = perm.Permission.permission_name
+        u_k = perm.user_group.users_group_name
+        p = perm.permission.permission_name
         permissions[UK][u_k] = p
 
     #======================================================================
@@ -271,30 +258,28 @@
 
     # user group for repositories permissions
     user_repo_perms_from_users_groups = \
-     Session().query(UserGroupRepoToPerm, Permission, Repository,) \
-        .join((Repository, UserGroupRepoToPerm.repository_id ==
-               Repository.repo_id)) \
-        .join((Permission, UserGroupRepoToPerm.permission_id ==
-               Permission.permission_id)) \
+     Session().query(UserGroupRepoToPerm) \
         .join((UserGroup, UserGroupRepoToPerm.users_group_id ==
                UserGroup.users_group_id)) \
         .filter(UserGroup.users_group_active == True) \
         .join((UserGroupMember, UserGroupRepoToPerm.users_group_id ==
                UserGroupMember.users_group_id)) \
         .filter(UserGroupMember.user_id == user_id) \
+        .options(joinedload(UserGroupRepoToPerm.repository)) \
+        .options(joinedload(UserGroupRepoToPerm.permission)) \
         .all()
 
     for perm in user_repo_perms_from_users_groups:
         bump_permission(RK,
-            perm.UserGroupRepoToPerm.repository.repo_name,
-            perm.Permission.permission_name)
+            perm.repository.repo_name,
+            perm.permission.permission_name)
 
     # user permissions for repositories
     user_repo_perms = Permission.get_default_perms(user_id)
     for perm in user_repo_perms:
         bump_permission(RK,
-            perm.UserRepoToPerm.repository.repo_name,
-            perm.Permission.permission_name)
+            perm.repository.repo_name,
+            perm.permission.permission_name)
 
     #======================================================================
     # !! PERMISSIONS FOR REPOSITORY GROUPS !!
@@ -305,59 +290,56 @@
     #======================================================================
     # user group for repo groups permissions
     user_repo_group_perms_from_users_groups = \
-     Session().query(UserGroupRepoGroupToPerm, Permission, RepoGroup) \
-     .join((RepoGroup, UserGroupRepoGroupToPerm.group_id == RepoGroup.group_id)) \
-     .join((Permission, UserGroupRepoGroupToPerm.permission_id
-            == Permission.permission_id)) \
+     Session().query(UserGroupRepoGroupToPerm) \
      .join((UserGroup, UserGroupRepoGroupToPerm.users_group_id ==
             UserGroup.users_group_id)) \
      .filter(UserGroup.users_group_active == True) \
      .join((UserGroupMember, UserGroupRepoGroupToPerm.users_group_id
             == UserGroupMember.users_group_id)) \
      .filter(UserGroupMember.user_id == user_id) \
+     .options(joinedload(UserGroupRepoGroupToPerm.permission)) \
      .all()
 
     for perm in user_repo_group_perms_from_users_groups:
         bump_permission(GK,
-            perm.UserGroupRepoGroupToPerm.group.group_name,
-            perm.Permission.permission_name)
+            perm.group.group_name,
+            perm.permission.permission_name)
 
     # user explicit permissions for repository groups
     user_repo_groups_perms = Permission.get_default_group_perms(user_id)
     for perm in user_repo_groups_perms:
         bump_permission(GK,
-            perm.UserRepoGroupToPerm.group.group_name,
-            perm.Permission.permission_name)
+            perm.group.group_name,
+            perm.permission.permission_name)
 
     #======================================================================
     # !! PERMISSIONS FOR USER GROUPS !!
     #======================================================================
     # user group for user group permissions
     user_group_user_groups_perms = \
-     Session().query(UserGroupUserGroupToPerm, Permission, UserGroup) \
+     Session().query(UserGroupUserGroupToPerm) \
      .join((UserGroup, UserGroupUserGroupToPerm.target_user_group_id
             == UserGroup.users_group_id)) \
-     .join((Permission, UserGroupUserGroupToPerm.permission_id
-            == Permission.permission_id)) \
      .join((UserGroupMember, UserGroupUserGroupToPerm.user_group_id
             == UserGroupMember.users_group_id)) \
      .filter(UserGroupMember.user_id == user_id) \
      .join((UserGroup, UserGroupMember.users_group_id ==
             UserGroup.users_group_id), aliased=True, from_joinpoint=True) \
      .filter(UserGroup.users_group_active == True) \
+     .options(joinedload(UserGroupUserGroupToPerm.permission)) \
      .all()
 
     for perm in user_group_user_groups_perms:
         bump_permission(UK,
-            perm.UserGroupUserGroupToPerm.target_user_group.users_group_name,
-            perm.Permission.permission_name)
+            perm.target_user_group.users_group_name,
+            perm.permission.permission_name)
 
     # user explicit permission for user groups
     user_user_groups_perms = Permission.get_default_user_group_perms(user_id)
     for perm in user_user_groups_perms:
         bump_permission(UK,
-            perm.UserUserGroupToPerm.user_group.users_group_name,
-            perm.Permission.permission_name)
+            perm.user_group.users_group_name,
+            perm.permission.permission_name)
 
     return permissions
 
@@ -405,7 +387,7 @@
         if not dbuser.active:
             log.info('Db user %s not active', dbuser.username)
             return None
-        allowed_ips = AuthUser.get_allowed_ips(dbuser.user_id, cache=True)
+        allowed_ips = AuthUser.get_allowed_ips(dbuser.user_id)
         if not check_ip_access(source_ip=ip_addr, allowed_ips=allowed_ips):
             log.info('Access for %s from %s forbidden - not in %s', dbuser.username, ip_addr, allowed_ips)
             return None
@@ -414,9 +396,8 @@
     def __init__(self, user_id=None, dbuser=None, is_external_auth=False):
         self.is_external_auth = is_external_auth # container auth - don't show logout option
 
-        # These attributes will be overridden by fill_data, below, unless the
-        # requested user cannot be found and the default anonymous user is
-        # not enabled.
+        # These attributes will be overridden below if the requested user is
+        # found or anonymous access (using the default user) is enabled.
         self.user_id = None
         self.username = None
         self.api_key = None
@@ -450,7 +431,15 @@
 
     @LazyProperty
     def permissions(self):
-        return self.__get_perms(user=self, cache=False)
+        """
+        Fills user permission attribute with permissions taken from database
+        works for permissions given for repositories, and for permissions that
+        are granted to groups
+
+        :param user: `AuthUser` instance
+        """
+        log.debug('Getting PERMISSION tree for %s', self)
+        return _cached_perms_data(self.user_id, self.is_admin)
 
     def has_repository_permission_level(self, repo_name, level, purpose=None):
         required_perms = {
@@ -492,22 +481,6 @@
     def api_keys(self):
         return self._get_api_keys()
 
-    def __get_perms(self, user, cache=False):
-        """
-        Fills user permission attribute with permissions taken from database
-        works for permissions given for repositories, and for permissions that
-        are granted to groups
-
-        :param user: `AuthUser` instance
-        """
-        user_id = user.user_id
-        user_is_admin = user.is_admin
-
-        log.debug('Getting PERMISSION tree')
-        compute = conditional_cache('short_term', 'cache_desc',
-                                    condition=cache, func=_cached_perms_data)
-        return compute(user_id, user_is_admin)
-
     def _get_api_keys(self):
         api_keys = [self.api_key]
         for api_key in UserApiKeys.query() \
@@ -566,14 +539,10 @@
         )
 
     @classmethod
-    def get_allowed_ips(cls, user_id, cache=False):
+    def get_allowed_ips(cls, user_id):
         _set = set()
 
-        default_ips = UserIpMap.query().filter(UserIpMap.user_id ==
-                                        User.get_default_user(cache=True).user_id)
-        if cache:
-            default_ips = default_ips.options(FromCache("sql_cache_short",
-                                              "get_user_ips_default"))
+        default_ips = UserIpMap.query().filter(UserIpMap.user_id == kallithea.DEFAULT_USER_ID)
         for ip in default_ips:
             try:
                 _set.add(ip.ip_addr)
@@ -583,9 +552,6 @@
                 pass
 
         user_ips = UserIpMap.query().filter(UserIpMap.user_id == user_id)
-        if cache:
-            user_ips = user_ips.options(FromCache("sql_cache_short",
-                                                  "get_user_ips_%s" % user_id))
         for ip in user_ips:
             try:
                 _set.add(ip.ip_addr)
--- a/kallithea/lib/auth_modules/__init__.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/auth_modules/__init__.py	Mon Apr 27 13:25:28 2020 +0200
@@ -20,7 +20,7 @@
 import traceback
 
 from kallithea.lib.auth import AuthUser, PasswordGenerator
-from kallithea.lib.compat import formatted_json, hybrid_property
+from kallithea.lib.compat import hybrid_property
 from kallithea.lib.utils2 import str2bool
 from kallithea.model.db import Setting, User
 from kallithea.model.meta import Session
@@ -136,9 +136,6 @@
                   username)
         if username:
             user = User.get_by_username_or_email(username)
-            if user is None:
-                log.debug('Fallback to fetch user in case insensitive mode')
-                user = User.get_by_username(username, case_insensitive=True)
         else:
             log.debug('provided username:`%s` is empty skipping...', username)
         return user
@@ -286,11 +283,11 @@
         ImportError -- if we couldn't import the plugin at all
     """
     log.debug("Importing %s", plugin)
-    if not plugin.startswith(u'kallithea.lib.auth_modules.auth_'):
-        parts = plugin.split(u'.lib.auth_modules.auth_', 1)
+    if not plugin.startswith('kallithea.lib.auth_modules.auth_'):
+        parts = plugin.split('.lib.auth_modules.auth_', 1)
         if len(parts) == 2:
             _module, pn = parts
-            plugin = u'kallithea.lib.auth_modules.auth_' + pn
+            plugin = 'kallithea.lib.auth_modules.auth_' + pn
     PLUGIN_CLASS_NAME = "KallitheaAuthPlugin"
     try:
         module = importlib.import_module(plugin)
@@ -351,7 +348,7 @@
             conf_key = "auth_%s_%s" % (plugin_name, v["name"])
             setting = Setting.get_by_name(conf_key)
             plugin_settings[v["name"]] = setting.app_settings_value if setting else None
-        log.debug('Settings for auth plugin %s:\n%s', plugin_name, formatted_json(plugin_settings))
+        log.debug('Settings for auth plugin %s: %s', plugin_name, plugin_settings)
 
         if not str2bool(plugin_settings["enabled"]):
             log.info("Authentication plugin %s is disabled, skipping for %s",
--- a/kallithea/lib/auth_modules/auth_internal.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/auth_modules/auth_internal.py	Mon Apr 27 13:25:28 2020 +0200
@@ -29,7 +29,7 @@
 import logging
 
 from kallithea.lib import auth_modules
-from kallithea.lib.compat import formatted_json, hybrid_property
+from kallithea.lib.compat import hybrid_property
 
 
 log = logging.getLogger(__name__)
@@ -76,7 +76,7 @@
             "admin": userobj.admin,
             "extern_name": userobj.user_id,
         }
-        log.debug(formatted_json(user_data))
+        log.debug('user data: %s', user_data)
 
         from kallithea.lib import auth
         password_match = auth.check_password(password, userobj.password)
--- a/kallithea/lib/auth_modules/auth_ldap.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/auth_modules/auth_ldap.py	Mon Apr 27 13:25:28 2020 +0200
@@ -31,6 +31,7 @@
 from kallithea.lib import auth_modules
 from kallithea.lib.compat import hybrid_property
 from kallithea.lib.exceptions import LdapConnectionError, LdapImportError, LdapPasswordError, LdapUsernameError
+from kallithea.lib.utils2 import safe_str
 
 
 log = logging.getLogger(__name__)
@@ -327,7 +328,8 @@
             (user_dn, ldap_attrs) = aldap.authenticate_ldap(username, password)
             log.debug('Got ldap DN response %s', user_dn)
 
-            get_ldap_attr = lambda k: ldap_attrs.get(settings.get(k), [''])[0]
+            def get_ldap_attr(k):
+                return safe_str(ldap_attrs.get(settings.get(k), [b''])[0])
 
             # old attrs fetched from Kallithea database
             admin = getattr(userobj, 'admin', False)
--- a/kallithea/lib/auth_modules/auth_pam.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/auth_modules/auth_pam.py	Mon Apr 27 13:25:28 2020 +0200
@@ -32,7 +32,7 @@
 import time
 
 from kallithea.lib import auth_modules
-from kallithea.lib.compat import formatted_json, hybrid_property
+from kallithea.lib.compat import hybrid_property
 
 
 try:
@@ -142,7 +142,7 @@
             log.warning("Cannot extract additional info for PAM user %s", username)
             pass
 
-        log.debug("pamuser: \n%s", formatted_json(user_data))
+        log.debug("pamuser: %s", user_data)
         log.info('user %s authenticated correctly', user_data['username'])
         return user_data
 
--- a/kallithea/lib/base.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/base.py	Mon Apr 27 13:25:28 2020 +0200
@@ -223,7 +223,7 @@
         Returns (None, wsgi_app) to send the wsgi_app response to the client.
         """
         # Use anonymous access if allowed for action on repo.
-        default_user = User.get_default_user(cache=True)
+        default_user = User.get_default_user()
         default_authuser = AuthUser.make(dbuser=default_user, ip_addr=ip_addr)
         if default_authuser is None:
             log.debug('No anonymous access at all') # move on to proper user auth
@@ -278,11 +278,8 @@
 
     def _check_permission(self, action, authuser, repo_name):
         """
-        Checks permissions using action (push/pull) user and repository
-        name
-
-        :param action: 'push' or 'pull' action
-        :param user: `User` instance
+        :param action: 'push' or 'pull'
+        :param user: `AuthUser` instance
         :param repo_name: repository name
         """
         if action == 'push':
@@ -291,7 +288,7 @@
                                                                   repo_name):
                 return False
 
-        else:
+        elif action == 'pull':
             #any other action need at least read permission
             if not HasPermissionAnyMiddleware('repository.read',
                                               'repository.write',
@@ -299,6 +296,9 @@
                                                                   repo_name):
                 return False
 
+        else:
+            assert False, action
+
         return True
 
     def _get_ip_addr(self, environ):
@@ -454,7 +454,7 @@
                     return log_in_user(user, remember=False, is_external_auth=True, ip_addr=ip_addr)
 
         # User is default user (if active) or anonymous
-        default_user = User.get_default_user(cache=True)
+        default_user = User.get_default_user()
         authuser = AuthUser.make(dbuser=default_user, ip_addr=ip_addr)
         if authuser is None: # fall back to anonymous
             authuser = AuthUser(dbuser=default_user) # TODO: somehow use .make?
@@ -529,7 +529,7 @@
             request.ip_addr = ip_addr
             request.needs_csrf_check = needs_csrf_check
 
-            log.info('IP: %s User: %s accessed %s',
+            log.info('IP: %s User: %s Request: %s',
                 request.ip_addr, request.authuser,
                 get_path_info(environ),
             )
@@ -552,7 +552,7 @@
 
     def _before(self, *args, **kwargs):
         super(BaseRepoController, self)._before(*args, **kwargs)
-        if c.repo_name:  # extracted from routes
+        if c.repo_name:  # extracted from request by base-base BaseController._before
             _dbr = Repository.get_by_repo_name(c.repo_name)
             if not _dbr:
                 return
--- a/kallithea/lib/caching_query.py	Mon Apr 13 21:40:33 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,239 +0,0 @@
-# apparently based on https://github.com/sqlalchemy/sqlalchemy/blob/rel_0_7/examples/beaker_caching/caching_query.py
-
-"""caching_query.py
-
-Represent persistence structures which allow the usage of
-Beaker caching with SQLAlchemy.
-
-The three new concepts introduced here are:
-
- * CachingQuery - a Query subclass that caches and
-   retrieves results in/from Beaker.
- * FromCache - a query option that establishes caching
-   parameters on a Query
- * _params_from_query - extracts value parameters from
-   a Query.
-
-The rest of what's here are standard SQLAlchemy and
-Beaker constructs.
-
-"""
-import beaker
-from beaker.exceptions import BeakerException
-from sqlalchemy.orm.interfaces import MapperOption
-from sqlalchemy.orm.query import Query
-from sqlalchemy.sql import visitors
-
-
-class CachingQuery(Query):
-    """A Query subclass which optionally loads full results from a Beaker
-    cache region.
-
-    The CachingQuery stores additional state that allows it to consult
-    a Beaker cache before accessing the database:
-
-    * A "region", which is a cache region argument passed to a
-      Beaker CacheManager, specifies a particular cache configuration
-      (including backend implementation, expiration times, etc.)
-    * A "namespace", which is a qualifying name that identifies a
-      group of keys within the cache.  A query that filters on a name
-      might use the name "by_name", a query that filters on a date range
-      to a joined table might use the name "related_date_range".
-
-    When the above state is present, a Beaker cache is retrieved.
-
-    The "namespace" name is first concatenated with
-    a string composed of the individual entities and columns the Query
-    requests, i.e. such as ``Query(User.id, User.name)``.
-
-    The Beaker cache is then loaded from the cache manager based
-    on the region and composed namespace.  The key within the cache
-    itself is then constructed against the bind parameters specified
-    by this query, which are usually literals defined in the
-    WHERE clause.
-
-    The FromCache mapper option below represent
-    the "public" method of configuring this state upon the CachingQuery.
-
-    """
-
-    def __init__(self, manager, *args, **kw):
-        self.cache_manager = manager
-        Query.__init__(self, *args, **kw)
-
-    def __iter__(self):
-        """override __iter__ to pull results from Beaker
-           if particular attributes have been configured.
-
-           Note that this approach does *not* detach the loaded objects from
-           the current session. If the cache backend is an in-process cache
-           (like "memory") and lives beyond the scope of the current session's
-           transaction, those objects may be expired. The method here can be
-           modified to first expunge() each loaded item from the current
-           session before returning the list of items, so that the items
-           in the cache are not the same ones in the current Session.
-
-        """
-        if hasattr(self, '_cache_parameters'):
-            return self.get_value(createfunc=lambda:
-                                  list(Query.__iter__(self)))
-        else:
-            return Query.__iter__(self)
-
-    def invalidate(self):
-        """Invalidate the value represented by this Query."""
-
-        cache, cache_key = _get_cache_parameters(self)
-        cache.remove(cache_key)
-
-    def get_value(self, merge=True, createfunc=None):
-        """Return the value from the cache for this query.
-
-        Raise KeyError if no value present and no
-        createfunc specified.
-
-        """
-        cache, cache_key = _get_cache_parameters(self)
-        ret = cache.get_value(cache_key, createfunc=createfunc)
-        if merge:
-            ret = self.merge_result(ret, load=False)
-        return ret
-
-    def set_value(self, value):
-        """Set the value in the cache for this query."""
-
-        cache, cache_key = _get_cache_parameters(self)
-        cache.put(cache_key, value)
-
-
-def query_callable(manager, query_cls=CachingQuery):
-    def query(*arg, **kw):
-        return query_cls(manager, *arg, **kw)
-    return query
-
-
-def get_cache_region(name, region):
-    if region not in beaker.cache.cache_regions:
-        raise BeakerException('Cache region `%s` not configured '
-            'Check if proper cache settings are in the .ini files' % region)
-    kw = beaker.cache.cache_regions[region]
-    return beaker.cache.Cache._get_cache(name, kw)
-
-
-def _get_cache_parameters(query):
-    """For a query with cache_region and cache_namespace configured,
-    return the corresponding Cache instance and cache key, based
-    on this query's current criterion and parameter values.
-
-    """
-    if not hasattr(query, '_cache_parameters'):
-        raise ValueError("This Query does not have caching "
-                         "parameters configured.")
-
-    region, namespace, cache_key = query._cache_parameters
-
-    namespace = _namespace_from_query(namespace, query)
-
-    if cache_key is None:
-        # cache key - the value arguments from this query's parameters.
-        args = _params_from_query(query)
-        args.append(query._limit)
-        args.append(query._offset)
-        cache_key = " ".join(str(x) for x in args)
-
-    if cache_key is None:
-        raise Exception('Cache key cannot be None')
-
-    # get cache
-    #cache = query.cache_manager.get_cache_region(namespace, region)
-    cache = get_cache_region(namespace, region)
-    # optional - hash the cache_key too for consistent length
-    # import uuid
-    # cache_key= str(uuid.uuid5(uuid.NAMESPACE_DNS, cache_key))
-
-    return cache, cache_key
-
-
-def _namespace_from_query(namespace, query):
-    # cache namespace - the token handed in by the
-    # option + class we're querying against
-    namespace = " ".join([namespace] + [str(x) for x in query._entities])
-
-    # memcached wants this
-    namespace = namespace.replace(' ', '_')
-
-    return namespace
-
-
-def _set_cache_parameters(query, region, namespace, cache_key):
-
-    if hasattr(query, '_cache_parameters'):
-        region, namespace, cache_key = query._cache_parameters
-        raise ValueError("This query is already configured "
-                        "for region %r namespace %r" %
-                        (region, namespace)
-                    )
-    query._cache_parameters = region, namespace, cache_key
-
-
-class FromCache(MapperOption):
-    """Specifies that a Query should load results from a cache."""
-
-    propagate_to_loaders = False
-
-    def __init__(self, region, namespace, cache_key=None):
-        """Construct a new FromCache.
-
-        :param region: the cache region.  Should be a
-        region configured in the Beaker CacheManager.
-
-        :param namespace: the cache namespace.  Should
-        be a name uniquely describing the target Query's
-        lexical structure.
-
-        :param cache_key: optional.  A string cache key
-        that will serve as the key to the query.   Use this
-        if your query has a huge amount of parameters (such
-        as when using in_()) which correspond more simply to
-        some other identifier.
-
-        """
-        self.region = region
-        self.namespace = namespace
-        self.cache_key = cache_key
-
-    def process_query(self, query):
-        """Process a Query during normal loading operation."""
-
-        _set_cache_parameters(query, self.region, self.namespace,
-                              self.cache_key)
-
-
-def _params_from_query(query):
-    """Pull the bind parameter values from a query.
-
-    This takes into account any scalar attribute bindparam set up.
-
-    E.g. params_from_query(query.filter(Cls.foo==5).filter(Cls.bar==7)))
-    would return [5, 7].
-
-    """
-    v = []
-
-    def visit_bindparam(bind):
-        if bind.key in query._params:
-            value = query._params[bind.key]
-        elif bind.callable:
-            # lazyloader may dig a callable in here, intended
-            # to late-evaluate params after autoflush is called.
-            # convert to a scalar value.
-            value = bind.callable()
-        else:
-            value = bind.value
-
-        v.append(value)
-    if query._criterion is not None:
-        visitors.traverse(query._criterion, {}, {'bindparam': visit_bindparam})
-    for f in query._from_obj:
-        visitors.traverse(f, {}, {'bindparam': visit_bindparam})
-    return v
--- a/kallithea/lib/celerylib/__init__.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/celerylib/__init__.py	Mon Apr 27 13:25:28 2020 +0200
@@ -33,7 +33,7 @@
 from decorator import decorator
 from tg import config
 
-from kallithea import CELERY_EAGER, CELERY_ON
+import kallithea
 from kallithea.lib.pidlock import DaemonLock, LockHeld
 from kallithea.lib.utils2 import safe_bytes
 from kallithea.model import meta
@@ -57,10 +57,10 @@
 
 
 def task(f_org):
-    """Wrapper of celery.task.task, running async if CELERY_ON
+    """Wrapper of celery.task.task, running async if CELERY_APP
     """
 
-    if CELERY_ON:
+    if kallithea.CELERY_APP:
         def f_async(*args, **kwargs):
             log.info('executing %s task', f_org.__name__)
             try:
@@ -68,8 +68,7 @@
             finally:
                 log.info('executed %s task', f_org.__name__)
         f_async.__name__ = f_org.__name__
-        from kallithea.lib import celerypylons
-        runner = celerypylons.task(ignore_result=True)(f_async)
+        runner = kallithea.CELERY_APP.task(ignore_result=True)(f_async)
 
         def f_wrapped(*args, **kwargs):
             t = runner.apply_async(args=args, kwargs=kwargs)
@@ -128,7 +127,7 @@
             ret = func(*fargs, **fkwargs)
             return ret
         finally:
-            if CELERY_ON and not CELERY_EAGER:
+            if kallithea.CELERY_APP and not kallithea.CELERY_EAGER:
                 meta.Session.remove()
 
     return decorator(__wrapper, func)
--- a/kallithea/lib/celerylib/tasks.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/celerylib/tasks.py	Mon Apr 27 13:25:28 2020 +0200
@@ -27,16 +27,16 @@
 """
 
 import email.utils
-import logging
 import os
 import traceback
 from collections import OrderedDict
 from operator import itemgetter
 from time import mktime
 
+import celery.utils.log
 from tg import config
 
-from kallithea import CELERY_ON
+import kallithea
 from kallithea.lib import celerylib, ext_json
 from kallithea.lib.helpers import person
 from kallithea.lib.hooks import log_create_repository
@@ -50,7 +50,7 @@
 __all__ = ['whoosh_index', 'get_commits_stats', 'send_email']
 
 
-log = logging.getLogger(__name__)
+log = celery.utils.log.get_task_logger(__name__)
 
 
 @celerylib.task
@@ -66,6 +66,11 @@
                          .run(full_index=full_index)
 
 
+# for js data compatibility cleans the key for person from '
+def akc(k):
+    return person(k).replace('"', '')
+
+
 @celerylib.task
 @celerylib.dbsession
 def get_commits_stats(repo_name, ts_min_y, ts_max_y, recurse_limit=100):
@@ -79,9 +84,6 @@
     try:
         lock = celerylib.DaemonLock(os.path.join(lockkey_path, lockkey))
 
-        # for js data compatibility cleans the key for person from '
-        akc = lambda k: person(k).replace('"', "")
-
         co_day_auth_aggr = {}
         commits_by_day_aggregate = {}
         repo = Repository.get_by_repo_name(repo_name)
@@ -218,7 +220,7 @@
         lock.release()
 
         # execute another task if celery is enabled
-        if len(repo.revisions) > 1 and CELERY_ON and recurse_limit > 0:
+        if len(repo.revisions) > 1 and kallithea.CELERY_APP and recurse_limit > 0:
             get_commits_stats(repo_name, ts_min_y, ts_max_y, recurse_limit - 1)
         elif recurse_limit <= 0:
             log.debug('Not recursing - limit has been reached')
@@ -231,7 +233,7 @@
 
 @celerylib.task
 @celerylib.dbsession
-def send_email(recipients, subject, body='', html_body='', headers=None, author=None):
+def send_email(recipients, subject, body='', html_body='', headers=None, from_name=None):
     """
     Sends an email with defined parameters from the .ini files.
 
@@ -241,7 +243,8 @@
     :param body: body of the mail
     :param html_body: html version of body
     :param headers: dictionary of prepopulated e-mail headers
-    :param author: User object of the author of this mail, if known and relevant
+    :param from_name: full name to be used as sender of this mail - often a
+    .full_name_or_username value
     """
     assert isinstance(recipients, list), recipients
     if headers is None:
@@ -273,13 +276,13 @@
     # SMTP sender
     envelope_from = email_config.get('app_email_from', 'Kallithea')
     # 'From' header
-    if author is not None:
-        # set From header based on author but with a generic e-mail address
+    if from_name is not None:
+        # set From header based on from_name but with a generic e-mail address
         # In case app_email_from is in "Some Name <e-mail>" format, we first
         # extract the e-mail address.
         envelope_addr = author_email(envelope_from)
         headers['From'] = '"%s" <%s>' % (
-            email.utils.quote('%s (no-reply)' % author.full_name_or_username),
+            email.utils.quote('%s (no-reply)' % from_name),
             envelope_addr)
 
     user = email_config.get('smtp_username')
@@ -411,7 +414,7 @@
 
     DBS = celerylib.get_session()
 
-    base_path = Repository.base_path()
+    base_path = kallithea.CONFIG['base_path']
     cur_user = User.guess_instance(cur_user)
 
     repo_name = form_data['repo_name']  # fork in this case
--- a/kallithea/lib/celerypylons/__init__.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/celerypylons/__init__.py	Mon Apr 27 13:25:28 2020 +0200
@@ -14,34 +14,64 @@
 mandatory settings.
 """
 
+import logging
+
 import celery
-import celery.result as result
 import tg
-from celery.bin import worker
-from celery.task import task
+
+import kallithea
 
 
-def celery_config(config):
-    """Return Celery config object populated from relevant settings in a config dict, such as tg.config"""
+class CeleryConfig(object):
+    imports = ['kallithea.lib.celerylib.tasks']
+    task_always_eager = False
 
-    # Verify .ini file configuration has been loaded
-    assert config['celery.imports'] == 'kallithea.lib.celerylib.tasks', 'Kallithea Celery configuration has not been loaded'
+# map from Kallithea .ini Celery 3 config names to Celery 4 config names
+celery3_compat = {
+    'broker.url': 'broker_url',
+    'celery.accept.content': 'accept_content',
+    'celery.always.eager': 'task_always_eager',
+    'celery.amqp.task.result.expires': 'result_expires',
+    'celeryd.concurrency': 'worker_concurrency',
+    'celeryd.max.tasks.per.child': 'worker_max_tasks_per_child',
+    #'celery.imports' ends up unchanged
+    'celery.result.backend': 'result_backend',
+    'celery.result.serializer': 'result_serializer',
+    'celery.task.serializer': 'task_serializer',
+}
 
-    class CeleryConfig(object):
-        pass
+list_config_names = """imports accept_content""".split()
+
+
+desupported = set([
+    'celery.result.dburi',
+    'celery.result.serialier',
+    'celery.send.task.error.emails',
+])
+
+
+log = logging.getLogger(__name__)
+
+
+def make_celery_config(config):
+    """Return Celery config object populated from relevant settings in a config dict, such as tg.config"""
 
     celery_config = CeleryConfig()
 
-    PREFIXES = """ADMINS BROKER CASSANDRA CELERYBEAT CELERYD CELERYMON CELERY EMAIL SERVER""".split()
-    LIST_PARAMS = """CELERY_IMPORTS ADMINS ROUTES CELERY_ACCEPT_CONTENT""".split()
-
     for config_key, config_value in sorted(config.items()):
-        celery_key = config_key.replace('.', '_').upper()
-        if celery_key.split('_', 1)[0] not in PREFIXES:
+        if config_key in desupported and config_value:
+            log.error('Celery configuration setting %r is no longer supported', config_key)
+        celery_key = celery3_compat.get(config_key)
+        parts = config_key.split('.', 1)
+        if celery_key:  # explicit Celery 3 backwards compatibility
+            pass
+        elif parts[0] == 'celery' and len(parts) == 2:  # Celery 4 config key
+            celery_key = parts[1]
+        else:
             continue
         if not isinstance(config_value, str):
             continue
-        if celery_key in LIST_PARAMS:
+        if celery_key in list_config_names:
             celery_value = config_value.split()
         elif config_value.isdigit():
             celery_value = int(config_value)
@@ -56,5 +86,7 @@
 def make_app():
     """Create celery app from the TurboGears configuration file"""
     app = celery.Celery()
-    app.config_from_object(celery_config(tg.config))
+    celery_config = make_celery_config(tg.config)
+    kallithea.CELERY_EAGER = celery_config.task_always_eager
+    app.config_from_object(celery_config)
     return app
--- a/kallithea/lib/compat.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/compat.py	Mon Apr 27 13:25:28 2020 +0200
@@ -62,3 +62,8 @@
 
 else:
     kill = os.kill
+
+
+# mute pyflakes "imported but unused"
+assert hybrid_property
+assert OrderedSet
--- a/kallithea/lib/db_manage.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/db_manage.py	Mon Apr 27 13:25:28 2020 +0200
@@ -26,8 +26,6 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
-from __future__ import print_function
-
 import logging
 import os
 import sys
@@ -56,7 +54,6 @@
         self.tests = tests
         self.root = root
         self.dburi = dbconf
-        self.db_exists = False
         self.cli_args = cli_args or {}
         self.init_db(SESSION=SESSION)
 
@@ -385,18 +382,18 @@
     def create_user(self, username, password, email='', admin=False):
         log.info('creating user %s', username)
         UserModel().create_or_update(username, password, email,
-                                     firstname=u'Kallithea', lastname=u'Admin',
+                                     firstname='Kallithea', lastname='Admin',
                                      active=True, admin=admin,
                                      extern_type=User.DEFAULT_AUTH_TYPE)
 
     def create_default_user(self):
         log.info('creating default user')
         # create default user for handling default permissions.
-        user = UserModel().create_or_update(username=User.DEFAULT_USER,
+        user = UserModel().create_or_update(username=User.DEFAULT_USER_NAME,
                                             password=str(uuid.uuid1())[:20],
                                             email='anonymous@kallithea-scm.org',
-                                            firstname=u'Anonymous',
-                                            lastname=u'User')
+                                            firstname='Anonymous',
+                                            lastname='User')
         # based on configuration options activate/deactivate this user which
         # controls anonymous access
         if self.cli_args.get('public_access') is False:
@@ -419,4 +416,4 @@
         permissions that are missing, and not alter already defined ones
         """
         log.info('creating default user permissions')
-        PermissionModel().create_default_permissions(user=User.DEFAULT_USER)
+        PermissionModel().create_default_permissions(user=User.DEFAULT_USER_NAME)
--- a/kallithea/lib/exceptions.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/exceptions.py	Mon Apr 27 13:25:28 2020 +0200
@@ -74,9 +74,8 @@
     pass
 
 
-class RepositoryCreationError(Exception):
+class HgsubversionImportError(Exception):
     pass
 
-
-class HgsubversionImportError(Exception):
+class InvalidCloneUriException(Exception):
     pass
--- a/kallithea/lib/feeds.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/feeds.py	Mon Apr 27 13:25:28 2020 +0200
@@ -59,7 +59,7 @@
     if date is not None:
         tag = re.sub('/', ',%s:/' % date.strftime('%Y-%m-%d'), tag, 1)
     tag = re.sub('#', '/', tag)
-    return u'tag:' + tag
+    return 'tag:' + tag
 
 
 class Attributes(object):
--- a/kallithea/lib/helpers.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/helpers.py	Mon Apr 27 13:25:28 2020 +0200
@@ -57,6 +57,25 @@
 from kallithea.lib.vcs.utils import author_email, author_name
 
 
+# mute pyflakes "imported but unused"
+assert Option
+assert checkbox
+assert end_form
+assert password
+assert radio
+assert submit
+assert text
+assert textarea
+assert format_byte_size
+assert chop_at
+assert wrap_paragraphs
+assert HasPermissionAny
+assert HasRepoGroupPermissionLevel
+assert HasRepoPermissionLevel
+assert time_to_datetime
+assert EmptyChangeset
+
+
 log = logging.getLogger(__name__)
 
 
@@ -483,11 +502,19 @@
     return [_Message(category, message) for category, message in _session_flash_messages(clear=True)]
 
 
-age = lambda x, y=False: _age(x, y)
-capitalize = lambda x: x.capitalize()
+def age(x, y=False):
+    return _age(x, y)
+
+def capitalize(x):
+    return x.capitalize()
+
 email = author_email
-short_id = lambda x: x[:12]
-hide_credentials = lambda x: ''.join(credentials_filter(x))
+
+def short_id(x):
+    return x[:12]
+
+def hide_credentials(x):
+    return ''.join(credentials_filter(x))
 
 
 def show_id(cs):
@@ -541,7 +568,7 @@
     email = author_email(author)
     if email:
         from kallithea.model.db import User
-        user = User.get_by_email(email, cache=True) # cache will only use sql_cache_short
+        user = User.get_by_email(email)
         if user is not None:
             return getattr(user, show_attr)
     return None
@@ -583,15 +610,12 @@
 
 def person_by_id(id_, show_attr="username"):
     from kallithea.model.db import User
-    # attr to return from fetched user
-    person_getter = lambda usr: getattr(usr, show_attr)
-
     # maybe it's an ID ?
     if str(id_).isdigit() or isinstance(id_, int):
         id_ = int(id_)
         user = User.get(id_)
         if user is not None:
-            return person_getter(user)
+            return getattr(user, show_attr)
     return id_
 
 
@@ -843,10 +867,7 @@
             .replace('[', '<b>') \
             .replace(']', '</b>')
 
-    action_params_func = lambda: ""
-
-    if callable(action_str[1]):
-        action_params_func = action_str[1]
+    action_params_func = action_str[1] if callable(action_str[1]) else (lambda: "")
 
     def action_parser_icon():
         action = user_log.action
@@ -1062,6 +1083,8 @@
     URLs links to what they say.
     Issues are linked to given issue-server.
     If link_ is provided, all text not already linking somewhere will link there.
+    >>> urlify_text("Urlify http://example.com/ and 'https://example.com' *and* <b>markup/b>")
+    literal('Urlify <a href="http://example.com/">http://example.com/</a> and &#39;<a href="https://example.com&apos">https://example.com&apos</a>; <b>*and*</b> &lt;b&gt;markup/b&gt;')
     """
 
     def _replace(match_obj):
@@ -1155,7 +1178,8 @@
         assert CONFIG['sqlalchemy.url'] # make sure config has been loaded
 
         # Build chain of urlify functions, starting with not doing any transformation
-        tmp_urlify_issues_f = lambda s: s
+        def tmp_urlify_issues_f(s):
+            return s
 
         issue_pat_re = re.compile(r'issue_pat(.*)')
         for k in CONFIG:
@@ -1207,9 +1231,9 @@
                      'url': issue_url,
                      'text': issue_text,
                     }
-            tmp_urlify_issues_f = (lambda s,
-                                          issue_re=issue_re, issues_replace=issues_replace, chain_f=tmp_urlify_issues_f:
-                                   issue_re.sub(issues_replace, chain_f(s)))
+
+            def tmp_urlify_issues_f(s, issue_re=issue_re, issues_replace=issues_replace, chain_f=tmp_urlify_issues_f):
+                return issue_re.sub(issues_replace, chain_f(s))
 
         # Set tmp function globally - atomically
         _urlify_issues_f = tmp_urlify_issues_f
--- a/kallithea/lib/indexers/__init__.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/indexers/__init__.py	Mon Apr 27 13:25:28 2020 +0200
@@ -203,7 +203,7 @@
         return res
 
     def get_short_content(self, res, chunks):
-        return u''.join([res['content'][chunk[0]:chunk[1]] for chunk in chunks])
+        return ''.join([res['content'][chunk[0]:chunk[1]] for chunk in chunks])
 
     def get_chunks(self):
         """
--- a/kallithea/lib/indexers/daemon.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/indexers/daemon.py	Mon Apr 27 13:25:28 2020 +0200
@@ -40,7 +40,7 @@
 from kallithea.config.conf import INDEX_EXTENSIONS, INDEX_FILENAMES
 from kallithea.lib.indexers import CHGSET_IDX_NAME, CHGSETS_SCHEMA, IDX_NAME, SCHEMA
 from kallithea.lib.utils2 import safe_str
-from kallithea.lib.vcs.exceptions import ChangesetError, NodeDoesNotExistError, RepositoryError
+from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError, ChangesetError, NodeDoesNotExistError, RepositoryError
 from kallithea.model.db import Repository
 from kallithea.model.scm import ScmModel
 
@@ -181,7 +181,7 @@
             bytes_content = node.content
             if b'\0' in bytes_content:
                 log.warning('    >> %s - no text content', path)
-                u_content = u''
+                u_content = ''
             else:
                 log.debug('    >> %s', path)
                 u_content = safe_str(bytes_content)
@@ -190,7 +190,7 @@
         else:
             log.debug('    >> %s - not indexable', path)
             # just index file name without it's content
-            u_content = u''
+            u_content = ''
             indexed += 1
 
         writer.add_document(
@@ -241,10 +241,10 @@
                 author=cs.author,
                 message=cs.message,
                 last=cs.last,
-                added=u' '.join(node.path for node in cs.added).lower(),
-                removed=u' '.join(node.path for node in cs.removed).lower(),
-                changed=u' '.join(node.path for node in cs.changed).lower(),
-                parents=u' '.join(cs.raw_id for cs in cs.parents),
+                added=' '.join(node.path for node in cs.added).lower(),
+                removed=' '.join(node.path for node in cs.removed).lower(),
+                changed=' '.join(node.path for node in cs.changed).lower(),
+                parents=' '.join(cs.raw_id for cs in cs.parents),
             )
 
         return indexed
@@ -287,7 +287,7 @@
                         continue
 
                     qp = QueryParser('repository', schema=CHGSETS_SCHEMA)
-                    q = qp.parse(u"last:t AND %s" % repo_name)
+                    q = qp.parse("last:t AND %s" % repo_name)
 
                     results = searcher.search(q)
 
@@ -299,14 +299,18 @@
                         # assuming that there is only one result, if not this
                         # may require a full re-index.
                         start_id = results[0]['raw_id']
-                        last_rev = repo.get_changeset(revision=start_id).revision
+                        try:
+                            last_rev = repo.get_changeset(revision=start_id).revision
+                        except ChangesetDoesNotExistError:
+                            log.error('previous last revision %s not found - indexing from scratch', start_id)
+                            start_id = None
 
                     # there are new changesets to index or a new repo to index
                     if last_rev == 0 or num_of_revs > last_rev + 1:
                         # delete the docs in the index for the previous
                         # last changeset(s)
                         for hit in results:
-                            q = qp.parse(u"last:t AND %s AND raw_id:%s" %
+                            q = qp.parse("last:t AND %s AND raw_id:%s" %
                                             (repo_name, hit['raw_id']))
                             writer.delete_by_query(q)
 
@@ -326,7 +330,7 @@
                     log.debug('>> NOTHING TO COMMIT TO CHANGESET INDEX<<')
 
     def update_file_index(self):
-        log.debug(u'STARTING INCREMENTAL INDEXING UPDATE FOR EXTENSIONS %s '
+        log.debug('STARTING INCREMENTAL INDEXING UPDATE FOR EXTENSIONS %s '
                   'AND REPOS %s', INDEX_EXTENSIONS, ' and '.join(self.repo_paths))
 
         idx = open_dir(self.index_location, indexname=self.indexname)
--- a/kallithea/lib/inifile.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/inifile.py	Mon Apr 27 13:25:28 2020 +0200
@@ -42,6 +42,10 @@
     'uuid': lambda: 'VERY-SECRET',
 }
 
+variable_options = {
+    'database_engine': ['sqlite', 'postgres', 'mysql'],
+    'http_server': ['waitress', 'gearbox', 'gevent', 'gunicorn', 'uwsgi'],
+}
 
 def expand(template, mako_variable_values, settings):
     """Expand mako template and tweak it.
@@ -63,16 +67,27 @@
     ... %elif conditional_options == 'option-b':
     ... some_variable = "never mind - option-b will not be used anyway ..."
     ... %endif
+    ...
+    ... [comment-section]
+    ... #variable3 = 3.0
+    ... #variable4 = 4.0
+    ... #variable5 = 5.0
+    ... variable5 = 5.1
+    ... #variable6 = 6.0
+    ... #variable6 = 6.1
+    ... #variable7 = 7.0
+    ... variable7 = 7.1
     ... '''
-    >>> selected_mako_conditionals = []
     >>> mako_variable_values = {'mako_variable': 'VALUE', 'mako_function': (lambda: 'FUNCTION RESULT'),
-    ...                         'conditional_options': 'option-a'}
+    ...                         'conditional_options': 'option-a', 'http_server': 'nc'}
     >>> settings = { # only partially used
     ...     '[first-section]': {'variable2': 'VAL2', 'first_extra': 'EXTRA'},
+    ...     '[comment-section]': {'variable3': '3.0', 'variable4': '4.1', 'variable5': '5.2', 'variable6': '6.2', 'variable7': '7.0'},
     ...     '[third-section]': {'third_extra': ' 3'},
     ...     '[fourth-section]': {'fourth_extra': '4', 'fourth': '"four"'},
     ... }
     >>> print(expand(template, mako_variable_values, settings))
+    ERROR: http_server is 'nc' - it should be one of 'waitress', 'gearbox', 'gevent', 'gunicorn', 'uwsgi'
     <BLANKLINE>
     [first-section]
     <BLANKLINE>
@@ -87,6 +102,19 @@
     [second-section]
     # option a was chosen
     <BLANKLINE>
+    [comment-section]
+    variable3 = 3.0
+    #variable4 = 4.0
+    variable4 = 4.1
+    #variable5 = 5.0
+    #variable5 = 5.1
+    variable5 = 5.2
+    #variable6 = 6.0
+    #variable6 = 6.1
+    variable6 = 6.2
+    variable7 = 7.0
+    #variable7 = 7.1
+    <BLANKLINE>
     [fourth-section]
     fourth = "four"
     fourth_extra = 4
@@ -99,6 +127,12 @@
     mako_variables.update(mako_variable_values or {})
     settings = dict((k, dict(v)) for k, v in settings.items()) # deep copy before mutating
 
+    for key, value in mako_variables.items():
+        if key in variable_options:
+            if value not in variable_options[key]:
+                print('ERROR: %s is %r - it should be one of %s' %
+                      (key, value, ', '.join(repr(x) for x in variable_options[key])))
+
     ini_lines = mako.template.Template(template).render(**mako_variables)
 
     def process_section(m):
@@ -106,20 +140,44 @@
         sectionname, lines = m.groups()
         if sectionname in settings:
             section_settings = settings.pop(sectionname)
+            add_after_key_value = {}  # map key to value it should be added after
 
-            def process_line(m):
-                """process a section line and update value if necessary"""
-                key, value = m.groups()
+            # 1st pass:
+            # comment out lines with keys that have new values
+            # find best line for keeping or un-commenting (because it has the right value) or adding after (because it is the last with other value)
+            def comment_out(m):
+                """process a section line if in section_settings and comment out and track in add_after_key_value"""
                 line = m.group(0)
-                if key in section_settings:
-                    new_line = '%s = %s' % (key, section_settings.pop(key))
-                    if new_line != line:
-                        # keep old entry as example - comments might refer to it
-                        line = '#%s\n%s' % (line, new_line)
-                return line.rstrip()
+                comment, key, line_value = m.groups()
+                if key not in section_settings:
+                    return line
+                new_value = section_settings[key]
+                if line_value == new_value or add_after_key_value.get(key) != new_value:
+                    add_after_key_value[key] = line_value
+                if comment:
+                    return line
+                return '#' + line
+
+            lines = re.sub(r'^(#)?([^#\n\s]*)[ \t]*=[ \t]*(.*)$', comment_out, lines, flags=re.MULTILINE)
 
-            # process lines that not are comments or empty and look like name=value
-            lines = re.sub(r'^([^#\n\s]*)[ \t]*=[ \t]*(.*)$', process_line, lines, flags=re.MULTILINE)
+            def add_after_comment(m):
+                """process a section comment line and add new value"""
+                line = m.group(0)
+                key, line_value = m.groups()
+                if key not in section_settings:
+                    return line
+                if line_value != add_after_key_value.get(key):
+                    return line
+                new_value = section_settings[key]
+                if new_value == line_value:
+                    line = line.lstrip('#')
+                else:
+                    line += '\n%s = %s' % (key, new_value)
+                section_settings.pop(key)
+                return line
+
+            lines = re.sub(r'^#([^#\n\s]*)[ \t]*=[ \t]*(.*)$', add_after_comment, lines, flags=re.MULTILINE)
+
             # add unused section settings
             if section_settings:
                 lines += '\n' + ''.join('%s = %s\n' % (key, value) for key, value in sorted(section_settings.items()))
--- a/kallithea/lib/locale.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/locale.py	Mon Apr 27 13:25:28 2020 +0200
@@ -24,7 +24,7 @@
     Note: UTF-8 is preferred, but for example ISO-8859-1 or mbcs should also
     work under the right circumstances."""
     try:
-        u'\xe9'.encode(sys.getfilesystemencoding()) # Test using é (&eacute;)
+        '\xe9'.encode(sys.getfilesystemencoding()) # Test using é (&eacute;)
     except UnicodeEncodeError:
         log.error("Cannot encode Unicode paths to file system encoding %r", sys.getfilesystemencoding())
         for var in ['LC_ALL', 'LC_CTYPE', 'LANG']:
--- a/kallithea/lib/markup_renderer.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/markup_renderer.py	Mon Apr 27 13:25:28 2020 +0200
@@ -150,6 +150,10 @@
 
     @classmethod
     def plain(cls, source, universal_newline=True):
+        """
+        >>> MarkupRenderer.plain('https://example.com/')
+        '<br /><a href="https://example.com/">https://example.com/</a>'
+        """
         source = safe_str(source)
         if universal_newline:
             newline = '\n'
--- a/kallithea/lib/middleware/pygrack.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/middleware/pygrack.py	Mon Apr 27 13:25:28 2020 +0200
@@ -165,7 +165,7 @@
             log.error(traceback.format_exc())
             raise exc.HTTPExpectationFailed()
 
-        if git_command in [u'git-receive-pack']:
+        if git_command in ['git-receive-pack']:
             # updating refs manually after each push.
             # Needed for pre-1.7.0.4 git clients using regular HTTP mode.
             from kallithea.lib.vcs import get_repo
--- a/kallithea/lib/middleware/sessionmiddleware.py	Mon Apr 13 21:40:33 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-# -*- coding: utf-8 -*-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# 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 General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-"""
-kallithea.lib.middleware.sessionmiddleware
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-session management middleware
-
-This file overrides Beaker's built-in SessionMiddleware
-class to automagically use secure cookies over HTTPS.
-
-Original Beaker SessionMiddleware class written by Ben Bangert
-"""
-
-from beaker.middleware import SessionMiddleware
-from beaker.session import SessionObject
-
-
-class SecureSessionMiddleware(SessionMiddleware):
-    def __call__(self, environ, start_response):
-        """
-        This function's implementation is taken directly from Beaker,
-        with HTTPS detection added. When accessed over HTTPS, force
-        setting cookie's secure flag.
-
-        The only difference from that original code is that we switch
-        the secure option on and off depending on the URL scheme (first
-        two lines). To avoid concurrency issues, we use a local options
-        variable.
-        """
-        options = dict(self.options)
-        options["secure"] = environ['wsgi.url_scheme'] == 'https'
-
-        session = SessionObject(environ, **options)
-        if environ.get('paste.registry'):
-            if environ['paste.registry'].reglist:
-                environ['paste.registry'].register(self.session, session)
-        environ[self.environ_key] = session
-        environ['beaker.get_session'] = self._get_session
-
-        if 'paste.testing_variables' in environ and 'webtest_varname' in options:
-            environ['paste.testing_variables'][options['webtest_varname']] = session
-
-        def session_start_response(status, headers, exc_info=None):
-            if session.accessed():
-                session.persist()
-                if session.__dict__['_headers']['set_cookie']:
-                    cookie = session.__dict__['_headers']['cookie_out']
-                    if cookie:
-                        headers.append(('Set-cookie', cookie))
-            return start_response(status, headers, exc_info)
-        return self.wrap_app(environ, session_start_response)
--- a/kallithea/lib/middleware/wrapper.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/middleware/wrapper.py	Mon Apr 27 13:25:28 2020 +0200
@@ -40,12 +40,14 @@
     def __init__(self, start_response):
         self._start_response = start_response
         self._start = time.time()
+        self.status = None
         self._size = 0
 
     def duration(self):
         return time.time() - self._start
 
     def start_response(self, status, response_headers, exc_info=None):
+        self.status = status
         write = self._start_response(status, response_headers, exc_info)
         def metered_write(s):
             self.measure(s)
@@ -77,7 +79,7 @@
 
     def close(self):
         self._result_close()
-        log.info("%s responded after %.3fs with %s bytes", self._description, self._meter.duration(), self._meter.size())
+        log.info("%s responded %r after %.3fs with %s bytes", self._description, self._meter.status, self._meter.duration(), self._meter.size())
 
 
 class RequestWrapper(object):
@@ -92,8 +94,9 @@
             _get_ip_addr(environ),
             get_path_info(environ),
         )
+        log.info("%s received", description)
         try:
             result = self.application(environ, meter.start_response)
         finally:
-            log.info("%s responding after %.3fs", description, meter.duration())
+            log.info("%s responding %r after %.3fs", description, meter.status, meter.duration())
         return ResultIter(result, meter, description)
--- a/kallithea/lib/paster_commands/template.ini.mako	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/paster_commands/template.ini.mako	Mon Apr 27 13:25:28 2020 +0200
@@ -1,11 +1,11 @@
 ## -*- coding: utf-8 -*-
-<%text>################################################################################</%text>
-<%text>################################################################################</%text>
-# Kallithea - config file generated with kallithea-config                      #
-#                                                                              #
-# The %(here)s variable will be replaced with the parent directory of this file#
-<%text>################################################################################</%text>
-<%text>################################################################################</%text>
+<%text>###################################################################################</%text>
+<%text>###################################################################################</%text>
+<%text>## Kallithea config file generated with kallithea-config                         ##</%text>
+<%text>##                                                                               ##</%text>
+<%text>## The %(here)s variable will be replaced with the parent directory of this file ##</%text>
+<%text>###################################################################################</%text>
+<%text>###################################################################################</%text>
 
 [DEFAULT]
 
@@ -55,11 +55,11 @@
 <%text>## For "SSL", use smtp_use_ssl = true and smtp_port = 465.</%text>
 <%text>## For "STARTTLS", use smtp_use_tls = true and smtp_port = 587.</%text>
 smtp_server =
-#smtp_username =
-#smtp_password =
+smtp_username =
+smtp_password =
 smtp_port =
-#smtp_use_ssl = false
-#smtp_use_tls = false
+smtp_use_ssl = false
+smtp_use_tls = false
 
 %if http_server != 'uwsgi':
 <%text>## Entry point for 'gearbox serve'</%text>
@@ -111,64 +111,33 @@
 %endif
 %else:
 <%text>## UWSGI ##</%text>
-<%text>## run with uwsgi --ini-paste-logged <inifile.ini></%text>
 [uwsgi]
-socket = /tmp/uwsgi.sock
-master = true
-http = ${host}:${port}
-
-<%text>## set as daemon and redirect all output to file</%text>
-#daemonize = ./uwsgi_kallithea.log
-
-<%text>## master process PID</%text>
-pidfile = ./uwsgi_kallithea.pid
+<%text>## Note: this section is parsed by the uWSGI .ini parser when run as:</%text>
+<%text>## uwsgi --venv /srv/kallithea/venv --ini-paste-logged my.ini</%text>
+<%text>## Note: in uWSGI 2.0.18 or older, pastescript needs to be installed to</%text>
+<%text>## get correct application logging. In later versions this is not necessary.</%text>
+<%text>## pip install pastescript</%text>
 
-<%text>## stats server with workers statistics, use uwsgitop</%text>
-<%text>## for monitoring, `uwsgitop 127.0.0.1:1717`</%text>
-stats = 127.0.0.1:1717
-memory-report = true
-
-<%text>## log 5XX errors</%text>
-log-5xx = true
-
-<%text>## Set the socket listen queue size.</%text>
-listen = 128
-
-<%text>## Gracefully Reload workers after the specified amount of managed requests</%text>
-<%text>## (avoid memory leaks).</%text>
-max-requests = 1000
+<%text>## HTTP Basics:</%text>
+http-socket = ${host}:${port}
+buffer-size = 65535                    ; Mercurial will use huge GET headers for discovery
 
-<%text>## enable large buffers</%text>
-buffer-size = 65535
-
-<%text>## socket and http timeouts ##</%text>
-http-timeout = 3600
-socket-timeout = 3600
-
-<%text>## Log requests slower than the specified number of milliseconds.</%text>
-log-slow = 10
-
-<%text>## Exit if no app can be loaded.</%text>
-need-app = true
-
-<%text>## Set lazy mode (load apps in workers instead of master).</%text>
-lazy = true
+<%text>## Scaling:</%text>
+master = true                          ; Use separate master and worker processes
+auto-procname = true                   ; Name worker processes accordingly
+lazy = true                            ; App *must* be loaded in workers - db connections can't be shared
+workers = 4                            ; On demand scaling up to this many worker processes
+cheaper = 1                            ; Initial and on demand scaling down to this many worker processes
+max-requests = 1000                    ; Graceful reload of worker processes to avoid leaks
 
-<%text>## scaling ##</%text>
-<%text>## set cheaper algorithm to use, if not set default will be used</%text>
-cheaper-algo = spare
-
-<%text>## minimum number of workers to keep at all times</%text>
-cheaper = 1
-
-<%text>## number of workers to spawn at startup</%text>
-cheaper-initial = 1
-
-<%text>## maximum number of workers that can be spawned</%text>
-workers = 4
-
-<%text>## how many workers should be spawned at a time</%text>
-cheaper-step = 1
+<%text>## Tweak defaults:</%text>
+strict = true                          ; Fail on unknown config directives
+enable-threads = true                  ; Enable Python threads (not threaded workers)
+vacuum = true                          ; Delete sockets during shutdown
+single-interpreter = true
+die-on-term = true                     ; Shutdown when receiving SIGTERM (default is respawn)
+need-app = true                        ; Exit early if no app can be loaded.
+reload-on-exception = true             ; Don't assume that the application worker can process more requests after a severe error
 
 %endif
 <%text>## middleware for hosting the WSGI application under a URL prefix</%text>
@@ -220,7 +189,7 @@
 <%text>## used, which is correct in many cases but for example not when using uwsgi.</%text>
 <%text>## If you change this setting, you should reinstall the Git hooks via</%text>
 <%text>## Admin > Settings > Remap and Rescan.</%text>
-# git_hook_interpreter = /srv/kallithea/venv/bin/python3
+#git_hook_interpreter = /srv/kallithea/venv/bin/python3
 %if git_hook_interpreter:
 git_hook_interpreter = ${git_hook_interpreter}
 %endif
@@ -295,7 +264,7 @@
 <%text>## issue_pat, issue_server_link and issue_sub can have suffixes to specify</%text>
 <%text>## multiple patterns, to other issues server, wiki or others</%text>
 <%text>## below an example how to create a wiki pattern</%text>
-# wiki-some-id -> https://wiki.example.com/some-id
+<%text>## wiki-some-id -> https://wiki.example.com/some-id</%text>
 
 #issue_pat_wiki = wiki-(\S+)
 #issue_server_link_wiki = https://wiki.example.com/\1
@@ -313,12 +282,12 @@
 allow_custom_hooks_settings = True
 
 <%text>## extra extensions for indexing, space separated and without the leading '.'.</%text>
-# index.extensions =
+#index.extensions =
 #    gemfile
 #    lock
 
 <%text>## extra filenames for indexing, space separated</%text>
-# index.filenames =
+#index.filenames =
 #    .dockerignore
 #    .editorconfig
 #    INSTALL
@@ -356,25 +325,23 @@
 <%text>###        CELERY CONFIG        ####</%text>
 <%text>####################################</%text>
 
+<%text>## Note: Celery doesn't support Windows.</%text>
 use_celery = false
 
-<%text>## Example: connect to the virtual host 'rabbitmqhost' on localhost as rabbitmq:</%text>
-broker.url = amqp://rabbitmq:qewqew@localhost:5672/rabbitmqhost
+<%text>## Celery config settings from https://docs.celeryproject.org/en/4.4.0/userguide/configuration.html prefixed with 'celery.'.</%text>
 
-celery.imports = kallithea.lib.celerylib.tasks
-celery.accept.content = pickle
-celery.result.backend = amqp
-celery.result.dburi = amqp://
-celery.result.serialier = json
+<%text>## Example: use the message queue on the local virtual host 'kallitheavhost' as the RabbitMQ user 'kallithea':</%text>
+celery.broker_url = amqp://kallithea:thepassword@localhost:5672/kallitheavhost
 
-#celery.send.task.error.emails = true
+celery.result.backend = db+sqlite:///celery-results.db
+
 #celery.amqp.task.result.expires = 18000
 
-celeryd.concurrency = 2
-celeryd.max.tasks.per.child = 1
+celery.worker_concurrency = 2
+celery.worker_max_tasks_per_child = 1
 
 <%text>## If true, tasks will never be sent to the queue, but executed locally instead.</%text>
-celery.always.eager = false
+celery.task_always_eager = false
 
 <%text>####################################</%text>
 <%text>###         BEAKER CACHE        ####</%text>
@@ -383,19 +350,15 @@
 beaker.cache.data_dir = %(here)s/data/cache/data
 beaker.cache.lock_dir = %(here)s/data/cache/lock
 
-beaker.cache.regions = short_term,long_term,sql_cache_short
-
-beaker.cache.short_term.type = memory
-beaker.cache.short_term.expire = 60
-beaker.cache.short_term.key_length = 256
+beaker.cache.regions = long_term,long_term_file
 
 beaker.cache.long_term.type = memory
 beaker.cache.long_term.expire = 36000
 beaker.cache.long_term.key_length = 256
 
-beaker.cache.sql_cache_short.type = memory
-beaker.cache.sql_cache_short.expire = 10
-beaker.cache.sql_cache_short.key_length = 256
+beaker.cache.long_term_file.type = file
+beaker.cache.long_term_file.expire = 604800
+beaker.cache.long_term_file.key_length = 256
 
 <%text>####################################</%text>
 <%text>###       BEAKER SESSION        ####</%text>
@@ -429,74 +392,33 @@
 #session.sa.url = postgresql://postgres:qwe@localhost/kallithea
 #session.table_name = db_session
 
-<%text>############################</%text>
-<%text>## ERROR HANDLING SYSTEMS ##</%text>
-<%text>############################</%text>
+<%text>####################################</%text>
+<%text>###       ERROR HANDLING        ####</%text>
+<%text>####################################</%text>
+
+<%text>## Show a nice error page for application HTTP errors and exceptions (default true)</%text>
+#errorpage.enabled = true
 
-# Propagate email settings to ErrorReporter of TurboGears2
-# You do not normally need to change these lines
-get trace_errors.error_email = email_to
+<%text>## Enable Backlash client-side interactive debugger (default false)</%text>
+<%text>## WARNING: *THIS MUST BE false IN PRODUCTION ENVIRONMENTS!!!*</%text>
+<%text>## This debug mode will allow all visitors to execute malicious code.</%text>
+#debug = false
+
+<%text>## Enable Backlash server-side error reporting (unless debug mode handles it client-side) (default true)</%text>
+#trace_errors.enable = true
+<%text>## Errors will be reported by mail if trace_errors.error_email is set.</%text>
+
+<%text>## Propagate email settings to ErrorReporter of TurboGears2</%text>
+<%text>## You do not normally need to change these lines</%text>
 get trace_errors.smtp_server = smtp_server
 get trace_errors.smtp_port = smtp_port
 get trace_errors.from_address = error_email_from
-
-%if error_aggregation_service == 'appenlight':
-<%text>####################</%text>
-<%text>### [appenlight] ###</%text>
-<%text>####################</%text>
-
-<%text>## AppEnlight is tailored to work with Kallithea, see</%text>
-<%text>## http://appenlight.com for details how to obtain an account</%text>
-<%text>## you must install python package `appenlight_client` to make it work</%text>
-
-<%text>## appenlight enabled</%text>
-appenlight = false
-
-appenlight.server_url = https://api.appenlight.com
-appenlight.api_key = YOUR_API_KEY
-
-<%text>## TWEAK AMOUNT OF INFO SENT HERE</%text>
-
-<%text>## enables 404 error logging (default False)</%text>
-appenlight.report_404 = false
-
-<%text>## time in seconds after request is considered being slow (default 1)</%text>
-appenlight.slow_request_time = 1
-
-<%text>## record slow requests in application</%text>
-<%text>## (needs to be enabled for slow datastore recording and time tracking)</%text>
-appenlight.slow_requests = true
+get trace_errors.error_email = email_to
+get trace_errors.smtp_username = smtp_username
+get trace_errors.smtp_password = smtp_password
+get trace_errors.smtp_use_tls = smtp_use_tls
 
-<%text>## enable hooking to application loggers</%text>
-#appenlight.logging = true
-
-<%text>## minimum log level for log capture</%text>
-#appenlight.logging.level = WARNING
-
-<%text>## send logs only from erroneous/slow requests</%text>
-<%text>## (saves API quota for intensive logging)</%text>
-appenlight.logging_on_error = false
-
-<%text>## list of additional keywords that should be grabbed from environ object</%text>
-<%text>## can be string with comma separated list of words in lowercase</%text>
-<%text>## (by default client will always send following info:</%text>
-<%text>## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that</%text>
-<%text>## start with HTTP* this list be extended with additional keywords here</%text>
-appenlight.environ_keys_whitelist =
-
-<%text>## list of keywords that should be blanked from request object</%text>
-<%text>## can be string with comma separated list of words in lowercase</%text>
-<%text>## (by default client will always blank keys that contain following words</%text>
-<%text>## 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'</%text>
-<%text>## this list be extended with additional keywords set here</%text>
-appenlight.request_keys_blacklist =
-
-<%text>## list of namespaces that should be ignores when gathering log entries</%text>
-<%text>## can be string with comma separated list of namespaces</%text>
-<%text>## (by default the client ignores own entries: appenlight_client.client)</%text>
-appenlight.log_namespace_blacklist =
-
-%elif error_aggregation_service == 'sentry':
+%if error_aggregation_service == 'sentry':
 <%text>################</%text>
 <%text>### [sentry] ###</%text>
 <%text>################</%text>
@@ -516,12 +438,6 @@
 sentry.exclude_paths =
 
 %endif
-<%text>################################################################################</%text>
-<%text>## WARNING: *DEBUG MODE MUST BE OFF IN A PRODUCTION ENVIRONMENT*              ##</%text>
-<%text>## Debug mode will enable the interactive debugging tool, allowing ANYONE to  ##</%text>
-<%text>## execute malicious code after an exception is raised.                       ##</%text>
-<%text>################################################################################</%text>
-debug = false
 
 <%text>##################################</%text>
 <%text>###       LOGVIEW CONFIG       ###</%text>
@@ -536,19 +452,19 @@
 <%text>#########################################################</%text>
 
 %if database_engine == 'sqlite':
-# SQLITE [default]
+<%text>## SQLITE [default]</%text>
 sqlalchemy.url = sqlite:///%(here)s/kallithea.db?timeout=60
 
 %elif database_engine == 'postgres':
-# POSTGRESQL
+<%text>## POSTGRESQL</%text>
 sqlalchemy.url = postgresql://user:pass@localhost/kallithea
 
 %elif database_engine == 'mysql':
-# MySQL
+<%text>## MySQL</%text>
 sqlalchemy.url = mysql://user:pass@localhost/kallithea?charset=utf8
 
 %endif
-# see sqlalchemy docs for others
+<%text>## see sqlalchemy docs for other backends</%text>
 
 sqlalchemy.pool_recycle = 3600
 
@@ -579,8 +495,8 @@
 [logger_root]
 level = NOTSET
 handlers = console
-# For coloring based on log level:
-# handlers = console_color
+<%text>## For coloring based on log level:</%text>
+#handlers = console_color
 
 [logger_routes]
 level = WARN
@@ -617,10 +533,10 @@
 level = WARN
 handlers =
 qualname = sqlalchemy.engine
-# For coloring based on log level and pretty printing of SQL:
-# level = INFO
-# handlers = console_color_sql
-# propagate = 0
+<%text>## For coloring based on log level and pretty printing of SQL:</%text>
+#level = INFO
+#handlers = console_color_sql
+#propagate = 0
 
 [logger_whoosh_indexer]
 level = WARN
@@ -647,13 +563,13 @@
 formatter = generic
 
 [handler_console_color]
-# ANSI color coding based on log level
+<%text>## ANSI color coding based on log level</%text>
 class = StreamHandler
 args = (sys.stderr,)
 formatter = color_formatter
 
 [handler_console_color_sql]
-# ANSI color coding and pretty printing of SQL statements
+<%text>## ANSI color coding and pretty printing of SQL statements</%text>
 class = StreamHandler
 args = (sys.stderr,)
 formatter = color_formatter_sql
@@ -684,16 +600,16 @@
 <%text>## SSH LOGGING ##</%text>
 <%text>#################</%text>
 
-# The default loggers use 'handler_console' that uses StreamHandler with
-# destination 'sys.stderr'. In the context of the SSH server process, these log
-# messages would be sent to the client, which is normally not what you want.
-# By default, when running ssh-serve, just use NullHandler and disable logging
-# completely. For other logging options, see:
-# https://docs.python.org/2/library/logging.handlers.html
+<%text>## The default loggers use 'handler_console' that uses StreamHandler with</%text>
+<%text>## destination 'sys.stderr'. In the context of the SSH server process, these log</%text>
+<%text>## messages would be sent to the client, which is normally not what you want.</%text>
+<%text>## By default, when running ssh-serve, just use NullHandler and disable logging</%text>
+<%text>## completely. For other logging options, see:</%text>
+<%text>## https://docs.python.org/2/library/logging.handlers.html</%text>
 
 [ssh_serve:logger_root]
 level = CRITICAL
 handlers = null
 
-# Note: If logging is configured with other handlers, they might need similar
-# muting for ssh-serve too.
+<%text>## Note: If logging is configured with other handlers, they might need similar</%text>
+<%text>## muting for ssh-serve too.</%text>
--- a/kallithea/lib/pidlock.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/pidlock.py	Mon Apr 27 13:25:28 2020 +0200
@@ -12,8 +12,6 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from __future__ import print_function
-
 import errno
 import os
 from multiprocessing.util import Finalize
--- a/kallithea/lib/rcmail/message.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/rcmail/message.py	Mon Apr 27 13:25:28 2020 +0200
@@ -2,35 +2,6 @@
 from kallithea.lib.rcmail.response import MailResponse
 
 
-class Attachment(object):
-    """
-    Encapsulates file attachment information.
-
-    :param filename: filename of attachment
-    :param content_type: file mimetype
-    :param data: the raw file data, either as string or file obj
-    :param disposition: content-disposition (if any)
-    """
-
-    def __init__(self,
-                 filename=None,
-                 content_type=None,
-                 data=None,
-                 disposition=None):
-
-        self.filename = filename
-        self.content_type = content_type
-        self.disposition = disposition or 'attachment'
-        self._data = data
-
-    @property
-    def data(self):
-        if isinstance(self._data, str):
-            return self._data
-        self._data = self._data.read()
-        return self._data
-
-
 class Message(object):
     """
     Encapsulates an email message.
--- a/kallithea/lib/rcmail/response.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/rcmail/response.py	Mon Apr 27 13:25:28 2020 +0200
@@ -44,7 +44,9 @@
 
 ADDRESS_HEADERS_WHITELIST = ['From', 'To', 'Delivered-To', 'Cc']
 DEFAULT_ENCODING = "utf-8"
-VALUE_IS_EMAIL_ADDRESS = lambda v: '@' in v
+
+def VALUE_IS_EMAIL_ADDRESS(v):
+    return '@' in v
 
 
 def normalize_header(header):
@@ -392,7 +394,7 @@
         if mail.body is None:
             return  # only None, '' is still ok
 
-        ctype, ctype_params = mail.content_encoding['Content-Type']
+        ctype, _ctype_params = mail.content_encoding['Content-Type']
         cdisp, cdisp_params = mail.content_encoding['Content-Disposition']
 
         assert ctype, ("Extract payload requires that mail.content_encoding "
--- a/kallithea/lib/utils.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/utils.py	Mon Apr 27 13:25:28 2020 +0200
@@ -31,15 +31,15 @@
 import re
 import sys
 import traceback
+import urllib.error
 from distutils.version import StrictVersion
 
-import beaker.cache
 import mercurial.config
+import mercurial.error
 import mercurial.ui
-from tg.i18n import ugettext as _
 
 import kallithea.config.conf
-from kallithea.lib.exceptions import HgsubversionImportError
+from kallithea.lib.exceptions import InvalidCloneUriException
 from kallithea.lib.utils2 import ascii_bytes, aslist, get_current_authuser, safe_bytes, safe_str
 from kallithea.lib.vcs.backends.git.repository import GitRepository
 from kallithea.lib.vcs.backends.hg.repository import MercurialRepository
@@ -47,7 +47,7 @@
 from kallithea.lib.vcs.exceptions import RepositoryError, VCSError
 from kallithea.lib.vcs.utils.fakemod import create_module
 from kallithea.lib.vcs.utils.helpers import get_scm
-from kallithea.model import meta
+from kallithea.model import db, meta
 from kallithea.model.db import RepoGroup, Repository, Setting, Ui, User, UserGroup, UserLog
 
 
@@ -145,7 +145,7 @@
         repo_obj = Repository.get_by_repo_name(repo_name)
     else:
         repo_obj = None
-        repo_name = u''
+        repo_name = ''
 
     user_log = UserLog()
     user_log.user_id = user_obj.user_id
@@ -225,35 +225,43 @@
 
 
 def is_valid_repo_uri(repo_type, url, ui):
-    """Check if the url seems like a valid remote repo location - raise an Exception if any problems"""
+    """Check if the url seems like a valid remote repo location
+    Raise InvalidCloneUriException if any problems"""
     if repo_type == 'hg':
         if url.startswith('http') or url.startswith('ssh'):
             # initially check if it's at least the proper URL
             # or does it pass basic auth
-            MercurialRepository._check_url(url, ui)
+            try:
+                MercurialRepository._check_url(url, ui)
+            except urllib.error.URLError as e:
+                raise InvalidCloneUriException('URI %s URLError: %s' % (url, e))
+            except mercurial.error.RepoError as e:
+                raise InvalidCloneUriException('Mercurial %s: %s' % (type(e).__name__, safe_str(bytes(e))))
         elif url.startswith('svn+http'):
             try:
                 from hgsubversion.svnrepo import svnremoterepo
             except ImportError:
-                raise HgsubversionImportError(_('Unable to activate hgsubversion support. '
-                                                'The "hgsubversion" library is missing'))
+                raise InvalidCloneUriException('URI type %s not supported - hgsubversion is not available' % (url,))
             svnremoterepo(ui, url).svn.uuid
         elif url.startswith('git+http'):
-            raise NotImplementedError()
+            raise InvalidCloneUriException('URI type %s not implemented' % (url,))
         else:
-            raise Exception('URI %s not allowed' % (url,))
+            raise InvalidCloneUriException('URI %s not allowed' % (url,))
 
     elif repo_type == 'git':
         if url.startswith('http') or url.startswith('git'):
             # initially check if it's at least the proper URL
             # or does it pass basic auth
-            GitRepository._check_url(url)
+            try:
+                GitRepository._check_url(url)
+            except urllib.error.URLError as e:
+                raise InvalidCloneUriException('URI %s URLError: %s' % (url, e))
         elif url.startswith('svn+http'):
-            raise NotImplementedError()
+            raise InvalidCloneUriException('URI type %s not implemented' % (url,))
         elif url.startswith('hg+http'):
-            raise NotImplementedError()
+            raise InvalidCloneUriException('URI type %s not implemented' % (url,))
         else:
-            raise Exception('URI %s not allowed' % (url))
+            raise InvalidCloneUriException('URI %s not allowed' % (url))
 
 
 def is_valid_repo(repo_name, base_path, scm=None):
@@ -309,19 +317,6 @@
     return False
 
 
-# propagated from mercurial documentation
-ui_sections = ['alias', 'auth',
-                'decode/encode', 'defaults',
-                'diff', 'email',
-                'extensions', 'format',
-                'merge-patterns', 'merge-tools',
-                'hooks', 'http_proxy',
-                'smtp', 'patch',
-                'paths', 'profiling',
-                'server', 'trusted',
-                'ui', 'web', ]
-
-
 def make_ui(repo_path=None):
     """
     Create an Mercurial 'ui' object based on database Ui settings, possibly
@@ -335,7 +330,7 @@
     baseui._tcfg = mercurial.config.config()
 
     sa = meta.Session()
-    for ui_ in sa.query(Ui).all():
+    for ui_ in sa.query(Ui).order_by(Ui.ui_section, Ui.ui_key):
         if ui_.ui_active:
             log.debug('config from db: [%s] %s=%r', ui_.ui_section,
                       ui_.ui_key, ui_.ui_value)
@@ -353,18 +348,10 @@
     baseui.setconfig(b'hooks', b'outgoing.kallithea_log_pull_action', b'python:kallithea.lib.hooks.log_pull_action')
 
     if repo_path is not None:
-        hgrc_path = os.path.join(repo_path, '.hg', 'hgrc')
-        if os.path.isfile(hgrc_path):
-            log.debug('reading hgrc from %s', hgrc_path)
-            cfg = mercurial.config.config()
-            cfg.read(safe_bytes(hgrc_path))
-            for section in ui_sections:
-                for k, v in cfg.items(section):
-                    log.debug('config from file: [%s] %s=%s', section, k, v)
-                    baseui.setconfig(ascii_bytes(section), ascii_bytes(k), safe_bytes(v))
-        else:
-            log.debug('hgrc file is not present at %s, skipping...', hgrc_path)
+        # Note: MercurialRepository / mercurial.localrepo.instance will do this too, so it will always be possible to override db settings or what is hardcoded above
+        baseui.readconfig(repo_path)
 
+    assert baseui.plain()  # set by hgcompat.monkey_do (invoked from import of vcs.backends.hg) to minimize potential impact of loading config files
     return baseui
 
 
@@ -377,6 +364,7 @@
     hgsettings = Setting.get_app_settings()
     for k, v in hgsettings.items():
         config[k] = v
+    config['base_path'] = Ui.get_repos_location()
 
 
 def set_vcs_config(config):
@@ -419,7 +407,7 @@
     """
     from kallithea.model.repo_group import RepoGroupModel
     sa = meta.Session()
-    groups = path.split(Repository.url_sep())
+    groups = path.split(db.URL_SEP)
     parent = None
     group = None
 
@@ -428,7 +416,7 @@
     rgm = RepoGroupModel()
     owner = User.get_first_admin()
     for lvl, group_name in enumerate(groups):
-        group_name = u'/'.join(groups[:lvl] + [group_name])
+        group_name = '/'.join(groups[:lvl] + [group_name])
         group = RepoGroup.get_by_group_name(group_name)
         desc = '%s group' % group_name
 
@@ -613,34 +601,3 @@
                     settings.GIT_EXECUTABLE_PATH, output)
 
     return ver
-
-
-#===============================================================================
-# CACHE RELATED METHODS
-#===============================================================================
-
-def conditional_cache(region, prefix, condition, func):
-    """
-
-    Conditional caching function use like::
-        def _c(arg):
-            #heavy computation function
-            return data
-
-        # depending from condition the compute is wrapped in cache or not
-        compute = conditional_cache('short_term', 'cache_desc', condition=True, func=func)
-        return compute(arg)
-
-    :param region: name of cache region
-    :param prefix: cache region prefix
-    :param condition: condition for cache to be triggered, and return data cached
-    :param func: wrapped heavy function to compute
-
-    """
-    wrapped = func
-    if condition:
-        log.debug('conditional_cache: True, wrapping call of '
-                  'func: %s into %s region cache' % (region, func))
-        wrapped = beaker.cache._cache_decorate((prefix,), None, None, region)(func)
-
-    return wrapped
--- a/kallithea/lib/utils2.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/utils2.py	Mon Apr 27 13:25:28 2020 +0200
@@ -27,13 +27,10 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
-from __future__ import print_function
-
 import binascii
 import datetime
 import json
 import os
-import pwd
 import re
 import time
 import urllib.parse
@@ -47,6 +44,20 @@
 from kallithea.lib.vcs.utils.lazy import LazyProperty
 
 
+try:
+    import pwd
+except ImportError:
+    pass
+
+
+# mute pyflakes "imported but unused"
+assert ascii_bytes
+assert ascii_str
+assert safe_bytes
+assert safe_str
+assert LazyProperty
+
+
 def str2bool(_str):
     """
     returns True/False value from given string, it tries to translate the
@@ -239,12 +250,12 @@
 
     # Format the result
     fmt_funcs = {
-        'year': lambda d: ungettext(u'%d year', '%d years', d) % d,
-        'month': lambda d: ungettext(u'%d month', '%d months', d) % d,
-        'day': lambda d: ungettext(u'%d day', '%d days', d) % d,
-        'hour': lambda d: ungettext(u'%d hour', '%d hours', d) % d,
-        'minute': lambda d: ungettext(u'%d minute', '%d minutes', d) % d,
-        'second': lambda d: ungettext(u'%d second', '%d seconds', d) % d,
+        'year': lambda d: ungettext('%d year', '%d years', d) % d,
+        'month': lambda d: ungettext('%d month', '%d months', d) % d,
+        'day': lambda d: ungettext('%d day', '%d days', d) % d,
+        'hour': lambda d: ungettext('%d hour', '%d hours', d) % d,
+        'minute': lambda d: ungettext('%d minute', '%d minutes', d) % d,
+        'second': lambda d: ungettext('%d second', '%d seconds', d) % d,
     }
 
     for i, part in enumerate(order):
@@ -325,7 +336,7 @@
     prefix = urllib.parse.unquote(parsed_url.path.rstrip('/'))
     try:
         system_user = pwd.getpwuid(os.getuid()).pw_name
-    except Exception: # TODO: support all systems - especially Windows
+    except NameError: # TODO: support all systems - especially Windows
         system_user = 'kallithea' # hardcoded default value ...
     args = {
         'scheme': parsed_url.scheme,
--- a/kallithea/lib/vcs/backends/base.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/vcs/backends/base.py	Mon Apr 27 13:25:28 2020 +0200
@@ -13,8 +13,8 @@
 import itertools
 
 from kallithea.lib.vcs.conf import settings
-from kallithea.lib.vcs.exceptions import (
-    ChangesetError, EmptyRepositoryError, NodeAlreadyAddedError, NodeAlreadyChangedError, NodeAlreadyExistsError, NodeAlreadyRemovedError, NodeDoesNotExistError, NodeNotChangedError, RepositoryError)
+from kallithea.lib.vcs.exceptions import (ChangesetError, EmptyRepositoryError, NodeAlreadyAddedError, NodeAlreadyChangedError, NodeAlreadyExistsError,
+                                          NodeAlreadyRemovedError, NodeDoesNotExistError, NodeNotChangedError, RepositoryError)
 from kallithea.lib.vcs.utils import author_email, author_name
 from kallithea.lib.vcs.utils.helpers import get_dict_for_attrs
 from kallithea.lib.vcs.utils.lazy import LazyProperty
@@ -258,8 +258,6 @@
         """
         Persists current changes made on this repository and returns newly
         created changeset.
-
-        :raises ``NothingChangedError``: if no changes has been made
         """
         raise NotImplementedError
 
@@ -1026,7 +1024,7 @@
         return self
 
     def get_file_content(self, path):
-        return u''
+        return b''
 
     def get_file_size(self, path):
         return 0
--- a/kallithea/lib/vcs/backends/git/changeset.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/vcs/backends/git/changeset.py	Mon Apr 27 13:25:28 2020 +0200
@@ -9,8 +9,8 @@
 from kallithea.lib.vcs.backends.base import BaseChangeset, EmptyChangeset
 from kallithea.lib.vcs.conf import settings
 from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError, ChangesetError, ImproperArchiveTypeError, NodeDoesNotExistError, RepositoryError, VCSError
-from kallithea.lib.vcs.nodes import (
-    AddedFileNodesGenerator, ChangedFileNodesGenerator, DirNode, FileNode, NodeKind, RemovedFileNodesGenerator, RootNode, SubModuleNode)
+from kallithea.lib.vcs.nodes import (AddedFileNodesGenerator, ChangedFileNodesGenerator, DirNode, FileNode, NodeKind, RemovedFileNodesGenerator, RootNode,
+                                     SubModuleNode)
 from kallithea.lib.vcs.utils import ascii_bytes, ascii_str, date_fromtimestamp, safe_int, safe_str
 from kallithea.lib.vcs.utils.lazy import LazyProperty
 
@@ -98,15 +98,6 @@
         heads = self.repository._heads(reverse=True)
         return [safe_str(b) for b in heads if heads[b] == self._commit.id] # FIXME: Inefficient ... and returning None!
 
-    def _fix_path(self, path):
-        """
-        Paths are stored without trailing slash so we need to get rid off it if
-        needed.
-        """
-        if path.endswith('/'):
-            path = path.rstrip('/')
-        return path
-
     def _get_id_for_path(self, path):
         # FIXME: Please, spare a couple of minutes and make those codes cleaner;
         if path not in self._paths:
@@ -167,7 +158,7 @@
             return NodeKind.DIR
 
     def _get_filectx(self, path):
-        path = self._fix_path(path)
+        path = path.rstrip('/')
         if self._get_kind(path) != NodeKind.FILE:
             raise ChangesetError("File does not exist for revision %s at "
                 " '%s'" % (self.raw_id, path))
@@ -396,7 +387,7 @@
         if self._get_kind(path) != NodeKind.DIR:
             raise ChangesetError("Directory does not exist for revision %s at "
                 " '%s'" % (self.revision, path))
-        path = self._fix_path(path)
+        path = path.rstrip('/')
         id = self._get_id_for_path(path)
         tree = self.repository._repo[id]
         dirnodes = []
@@ -436,7 +427,7 @@
         Returns ``Node`` object from the given ``path``. If there is no node at
         the given ``path``, ``ChangesetError`` would be raised.
         """
-        path = self._fix_path(path)
+        path = path.rstrip('/')
         if path not in self.nodes:
             try:
                 id_ = self._get_id_for_path(path)
@@ -444,8 +435,8 @@
                 raise NodeDoesNotExistError("Cannot find one of parents' "
                     "directories for a given path: %s" % path)
 
-            _GL = lambda m: m and objects.S_ISGITLINK(m)
-            if _GL(self._stat_modes.get(path)):
+            stat = self._stat_modes.get(path)
+            if stat and objects.S_ISGITLINK(stat):
                 tree = self.repository._repo[self._tree_id]
                 cf = ConfigFile.from_file(BytesIO(self.repository._repo.get_object(tree[b'.gitmodules'][1]).data))
                 url = ascii_str(cf.get(('submodule', path), 'url'))
--- a/kallithea/lib/vcs/backends/git/repository.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/vcs/backends/git/repository.py	Mon Apr 27 13:25:28 2020 +0200
@@ -28,8 +28,8 @@
 from kallithea.lib.vcs import subprocessio
 from kallithea.lib.vcs.backends.base import BaseRepository, CollectionGenerator
 from kallithea.lib.vcs.conf import settings
-from kallithea.lib.vcs.exceptions import (
-    BranchDoesNotExistError, ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError, TagAlreadyExistError, TagDoesNotExistError)
+from kallithea.lib.vcs.exceptions import (BranchDoesNotExistError, ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError, TagAlreadyExistError,
+                                          TagDoesNotExistError)
 from kallithea.lib.vcs.utils import ascii_str, date_fromtimestamp, makedate, safe_bytes, safe_str
 from kallithea.lib.vcs.utils.lazy import LazyProperty
 from kallithea.lib.vcs.utils.paths import abspath, get_user_home
@@ -171,8 +171,8 @@
         handlers = []
         url_obj = mercurial.util.url(safe_bytes(url))
         test_uri, authinfo = url_obj.authinfo()
-        if not test_uri.endswith('info/refs'):
-            test_uri = test_uri.rstrip('/') + '/info/refs'
+        if not test_uri.endswith(b'info/refs'):
+            test_uri = test_uri.rstrip(b'/') + b'/info/refs'
 
         url_obj.passwd = b'*****'
         cleaned_uri = str(url_obj)
@@ -190,7 +190,7 @@
 
         req = urllib.request.Request(
             "%s?%s" % (
-                test_uri,
+                safe_str(test_uri),
                 urllib.parse.urlencode({"service": 'git-upload-pack'})
             ))
 
@@ -204,7 +204,7 @@
 
         # now detect if it's proper git repo
         gitdata = resp.read()
-        if 'service=git-upload-pack' not in gitdata:
+        if b'service=git-upload-pack' not in gitdata:
             raise urllib.error.URLError(
                 "url [%s] does not look like an git" % cleaned_uri)
 
@@ -351,17 +351,16 @@
 
     @LazyProperty
     def contact(self):
-        undefined_contact = u'Unknown'
+        undefined_contact = 'Unknown'
         return undefined_contact
 
     @property
     def branches(self):
         if not self.revisions:
             return {}
-        sortkey = lambda ctx: ctx[0]
         _branches = [(safe_str(key), ascii_str(sha))
                      for key, (sha, type_) in self._parsed_refs.items() if type_ == b'H']
-        return OrderedDict(sorted(_branches, key=sortkey, reverse=False))
+        return OrderedDict(sorted(_branches, key=(lambda ctx: ctx[0]), reverse=False))
 
     @LazyProperty
     def closed_branches(self):
@@ -374,11 +373,9 @@
     def _get_tags(self):
         if not self.revisions:
             return {}
-
-        sortkey = lambda ctx: ctx[0]
         _tags = [(safe_str(key), ascii_str(sha))
                  for key, (sha, type_) in self._parsed_refs.items() if type_ == b'T']
-        return OrderedDict(sorted(_tags, key=sortkey, reverse=True))
+        return OrderedDict(sorted(_tags, key=(lambda ctx: ctx[0]), reverse=True))
 
     def tag(self, name, user, revision=None, message=None, date=None,
             **kwargs):
--- a/kallithea/lib/vcs/backends/hg/changeset.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/vcs/backends/hg/changeset.py	Mon Apr 27 13:25:28 2020 +0200
@@ -8,8 +8,8 @@
 from kallithea.lib.vcs.backends.base import BaseChangeset
 from kallithea.lib.vcs.conf import settings
 from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError, ChangesetError, ImproperArchiveTypeError, NodeDoesNotExistError, VCSError
-from kallithea.lib.vcs.nodes import (
-    AddedFileNodesGenerator, ChangedFileNodesGenerator, DirNode, FileNode, NodeKind, RemovedFileNodesGenerator, RootNode, SubModuleNode)
+from kallithea.lib.vcs.nodes import (AddedFileNodesGenerator, ChangedFileNodesGenerator, DirNode, FileNode, NodeKind, RemovedFileNodesGenerator, RootNode,
+                                     SubModuleNode)
 from kallithea.lib.vcs.utils import ascii_bytes, ascii_str, date_fromtimestamp, safe_bytes, safe_str
 from kallithea.lib.vcs.utils.lazy import LazyProperty
 from kallithea.lib.vcs.utils.paths import get_dirs_for_path
@@ -76,16 +76,13 @@
     @LazyProperty
     def successors(self):
         successors = mercurial.obsutil.successorssets(self._ctx._repo, self._ctx.node(), closest=True)
-        if successors:
-            # flatten the list here handles both divergent (len > 1)
-            # and the usual case (len = 1)
-            successors = [mercurial.node.hex(n)[:12] for sub in successors for n in sub if n != self._ctx.node()]
-
-        return successors
+        # flatten the list here handles both divergent (len > 1)
+        # and the usual case (len = 1)
+        return [safe_str(mercurial.node.hex(n)[:12]) for sub in successors for n in sub if n != self._ctx.node()]
 
     @LazyProperty
     def predecessors(self):
-        return [mercurial.node.hex(n)[:12] for n in mercurial.obsutil.closestpredecessors(self._ctx._repo, self._ctx.node())]
+        return [safe_str(mercurial.node.hex(n)[:12]) for n in mercurial.obsutil.closestpredecessors(self._ctx._repo, self._ctx.node())]
 
     @LazyProperty
     def bookmarks(self):
@@ -193,19 +190,8 @@
         # Only used to feed diffstat
         return b''.join(self._ctx.diff())
 
-    def _fix_path(self, path):
-        """
-        Paths are stored without trailing slash so we need to get rid off it if
-        needed. Also mercurial keeps filenodes as str so we need to decode
-        from unicode to str
-        """
-        if path.endswith('/'):
-            path = path.rstrip('/')
-
-        return path
-
     def _get_kind(self, path):
-        path = self._fix_path(path)
+        path = path.rstrip('/')
         if path in self._file_paths:
             return NodeKind.FILE
         elif path in self._dir_paths:
@@ -215,7 +201,7 @@
                 % (path))
 
     def _get_filectx(self, path):
-        path = self._fix_path(path)
+        path = path.rstrip('/')
         if self._get_kind(path) != NodeKind.FILE:
             raise ChangesetError("File does not exist for revision %s at "
                 " '%s'" % (self.raw_id, path))
@@ -330,8 +316,7 @@
         if self._get_kind(path) != NodeKind.DIR:
             raise ChangesetError("Directory does not exist for revision %s at "
                 " '%s'" % (self.revision, path))
-        path = self._fix_path(path)
-
+        path = path.rstrip('/')
         filenodes = [FileNode(f, changeset=self) for f in self._file_paths
             if os.path.dirname(f) == path]
         dirs = path == '' and '' or [d for d in self._dir_paths
@@ -357,7 +342,7 @@
         Returns ``Node`` object from the given ``path``. If there is no node at
         the given ``path``, ``ChangesetError`` would be raised.
         """
-        path = self._fix_path(path)
+        path = path.rstrip('/')
         if path not in self.nodes:
             if path in self._file_paths:
                 node = FileNode(path, changeset=self)
--- a/kallithea/lib/vcs/backends/hg/repository.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/vcs/backends/hg/repository.py	Mon Apr 27 13:25:28 2020 +0200
@@ -37,8 +37,8 @@
 import mercurial.util
 
 from kallithea.lib.vcs.backends.base import BaseRepository, CollectionGenerator
-from kallithea.lib.vcs.exceptions import (
-    BranchDoesNotExistError, ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError, TagAlreadyExistError, TagDoesNotExistError, VCSError)
+from kallithea.lib.vcs.exceptions import (BranchDoesNotExistError, ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError, TagAlreadyExistError,
+                                          TagDoesNotExistError, VCSError)
 from kallithea.lib.vcs.utils import ascii_str, author_email, author_name, date_fromtimestamp, makedate, safe_bytes, safe_str
 from kallithea.lib.vcs.utils.lazy import LazyProperty
 from kallithea.lib.vcs.utils.paths import abspath
@@ -294,6 +294,7 @@
         when the return code is non 200
         """
         # check first if it's not an local url
+        url = safe_bytes(url)
         if os.path.isdir(url) or url.startswith(b'file:'):
             return True
 
--- a/kallithea/lib/vcs/conf/settings.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/vcs/conf/settings.py	Mon Apr 27 13:25:28 2020 +0200
@@ -1,22 +1,5 @@
-import os
-import tempfile
-
 from kallithea.lib.vcs.utils import aslist
-from kallithea.lib.vcs.utils.paths import get_user_home
-
-
-abspath = lambda * p: os.path.abspath(os.path.join(*p))
 
-VCSRC_PATH = os.environ.get('VCSRC_PATH')
-
-if not VCSRC_PATH:
-    HOME_ = get_user_home()
-    if not HOME_:
-        HOME_ = tempfile.gettempdir()
-
-VCSRC_PATH = VCSRC_PATH or abspath(HOME_, '.vcsrc')
-if os.path.isdir(VCSRC_PATH):
-    VCSRC_PATH = os.path.join(VCSRC_PATH, '__init__.py')
 
 # list of default encoding used in safe_str/safe_bytes methods
 DEFAULT_ENCODINGS = aslist('utf-8')
--- a/kallithea/lib/vcs/exceptions.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/vcs/exceptions.py	Mon Apr 27 13:25:28 2020 +0200
@@ -30,10 +30,6 @@
     pass
 
 
-class BranchAlreadyExistError(RepositoryError):
-    pass
-
-
 class BranchDoesNotExistError(RepositoryError):
     pass
 
@@ -50,10 +46,6 @@
     pass
 
 
-class NothingChangedError(CommitError):
-    pass
-
-
 class NodeError(VCSError):
     pass
 
@@ -88,7 +80,3 @@
 
 class ImproperArchiveTypeError(VCSError):
     pass
-
-
-class CommandError(VCSError):
-    pass
--- a/kallithea/lib/vcs/nodes.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/vcs/nodes.py	Mon Apr 27 13:25:28 2020 +0200
@@ -27,10 +27,10 @@
 
 
 class NodeState:
-    ADDED = u'added'
-    CHANGED = u'changed'
-    NOT_CHANGED = u'not changed'
-    REMOVED = u'removed'
+    ADDED = 'added'
+    CHANGED = 'changed'
+    NOT_CHANGED = 'not changed'
+    REMOVED = 'removed'
 
 
 class NodeGeneratorBase(object):
@@ -128,51 +128,23 @@
         """
         return self.path.rstrip('/').split('/')[-1]
 
-    def _get_kind(self):
-        return self._kind
-
-    def _set_kind(self, kind):
-        if hasattr(self, '_kind'):
-            raise NodeError("Cannot change node's kind")
-        else:
-            self._kind = kind
-            # Post setter check (path's trailing slash)
-            if self.path.endswith('/'):
-                raise NodeError("Node's path cannot end with slash")
-
-    kind = property(_get_kind, _set_kind)
-
     def __eq__(self, other):
         if type(self) is not type(other):
             return False
-        if self._kind != other._kind:
+        if self.kind != other.kind:
             return False
         if self.path != other.path:
             return False
-        if self.is_file():
-            return self.content == other.content
-        else:
-            # For DirNode's check without entering each dir
-            self_nodes_paths = list(sorted(n.path for n in self.nodes))
-            other_nodes_paths = list(sorted(n.path for n in self.nodes))
-            return self_nodes_paths == other_nodes_paths
 
     def __lt__(self, other):
-        if self._kind < other._kind:
+        if self.kind < other.kind:
             return True
-        if self._kind > other._kind:
+        if self.kind > other.kind:
             return False
         if self.path < other.path:
             return True
         if self.path > other.path:
             return False
-        if self.is_file():
-            return self.content < other.content
-        else:
-            # For DirNode's check without entering each dir
-            self_nodes_paths = list(sorted(n.path for n in self.nodes))
-            other_nodes_paths = list(sorted(n.path for n in self.nodes))
-            return self_nodes_paths < other_nodes_paths
 
     def __repr__(self):
         return '<%s %r>' % (self.__class__.__name__, self.path)
@@ -261,6 +233,18 @@
         self._content = content
         self._mode = mode or 0o100644
 
+    def __eq__(self, other):
+        eq = super(FileNode, self).__eq__(other)
+        if eq is not None:
+            return eq
+        return self.content == other.content
+
+    def __lt__(self, other):
+        lt = super(FileNode, self).__lt__(other)
+        if lt is not None:
+            return lt
+        return self.content < other.content
+
     @LazyProperty
     def mode(self):
         """
@@ -479,10 +463,23 @@
         self.changeset = changeset
         self._nodes = nodes
 
-    @LazyProperty
-    def content(self):
-        raise NodeError("%s represents a dir and has no ``content`` attribute"
-            % self)
+    def __eq__(self, other):
+        eq = super(DirNode, self).__eq__(other)
+        if eq is not None:
+            return eq
+        # check without entering each dir
+        self_nodes_paths = list(sorted(n.path for n in self.nodes))
+        other_nodes_paths = list(sorted(n.path for n in self.nodes))
+        return self_nodes_paths == other_nodes_paths
+
+    def __lt__(self, other):
+        lt = super(DirNode, self).__lt__(other)
+        if lt is not None:
+            return lt
+        # check without entering each dir
+        self_nodes_paths = list(sorted(n.path for n in self.nodes))
+        other_nodes_paths = list(sorted(n.path for n in self.nodes))
+        return self_nodes_paths < other_nodes_paths
 
     @LazyProperty
     def nodes(self):
@@ -587,7 +584,7 @@
 
     def __init__(self, name, url, changeset=None, alias=None):
         # Note: Doesn't call Node.__init__!
-        self.path = name
+        self.path = name.rstrip('/')
         self.kind = NodeKind.SUBMODULE
         self.alias = alias
         # we have to use emptyChangeset here since this can point to svn/git/hg
@@ -606,4 +603,4 @@
         then only last part is returned.
         """
         org = self.path.rstrip('/').rsplit('/', 1)[-1]
-        return u'%s @ %s' % (org, self.changeset.short_id)
+        return '%s @ %s' % (org, self.changeset.short_id)
--- a/kallithea/lib/vcs/subprocessio.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/vcs/subprocessio.py	Mon Apr 27 13:25:28 2020 +0200
@@ -221,17 +221,6 @@
         return not self.worker.keep_reading.is_set()
 
     @property
-    def done_reading_event(self):
-        """
-        Done_reading does not mean that the iterator's buffer is empty.
-        Iterator might have done reading from underlying source, but the read
-        chunks might still be available for serving through .next() method.
-
-        :returns: An threading.Event class instance.
-        """
-        return self.worker.EOF
-
-    @property
     def done_reading(self):
         """
         Done_reading does not mean that the iterator's buffer is empty.
--- a/kallithea/lib/vcs/utils/helpers.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/vcs/utils/helpers.py	Mon Apr 27 13:25:28 2020 +0200
@@ -1,7 +1,6 @@
 """
 Utilities aimed to help achieve mostly basic tasks.
 """
-from __future__ import division
 
 import datetime
 import os
--- a/kallithea/lib/vcs/utils/hgcompat.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/vcs/utils/hgcompat.py	Mon Apr 27 13:25:28 2020 +0200
@@ -2,6 +2,7 @@
 Mercurial libs compatibility
 """
 
+import mercurial.encoding
 import mercurial.localrepo
 
 
@@ -11,3 +12,6 @@
     mercurial.localrepo.localrepository._lfstatuswriters = [lambda *msg, **opts: None]
     # 3.5 7699d3212994 added the invariant that repo.lfstatus must exist before hitting overridearchive
     mercurial.localrepo.localrepository.lfstatus = False
+
+    # Minimize potential impact from custom configuration
+    mercurial.encoding.environ[b'HGPLAIN'] = b'1'
--- a/kallithea/lib/vcs/utils/imports.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/vcs/utils/imports.py	Mon Apr 27 13:25:28 2020 +0200
@@ -1,6 +1,3 @@
-from kallithea.lib.vcs.exceptions import VCSError
-
-
 def import_class(class_path):
     """
     Returns class from the given path.
@@ -8,10 +5,7 @@
     For example, in order to get class located at
     ``vcs.backends.hg.MercurialRepository``:
 
-        try:
-            hgrepo = import_class('vcs.backends.hg.MercurialRepository')
-        except VCSError:
-            # handle error
+        hgrepo = import_class('vcs.backends.hg.MercurialRepository')
     """
     splitted = class_path.split('.')
     mod_path = '.'.join(splitted[:-1])
--- a/kallithea/lib/vcs/utils/lazy.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/vcs/utils/lazy.py	Mon Apr 27 13:25:28 2020 +0200
@@ -1,6 +1,3 @@
-import threading
-
-
 class _Missing(object):
 
     def __repr__(self):
@@ -44,21 +41,3 @@
             value = self._func(obj)
             obj.__dict__[self.__name__] = value
         return value
-
-
-class ThreadLocalLazyProperty(LazyProperty):
-    """
-    Same as above but uses thread local dict for cache storage.
-    """
-
-    def __get__(self, obj, klass=None):
-        if obj is None:
-            return self
-        if not hasattr(obj, '__tl_dict__'):
-            obj.__tl_dict__ = threading.local().__dict__
-
-        value = obj.__tl_dict__.get(self.__name__, _missing)
-        if value is _missing:
-            value = self._func(obj)
-            obj.__tl_dict__[self.__name__] = value
-        return value
--- a/kallithea/lib/vcs/utils/paths.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/vcs/utils/paths.py	Mon Apr 27 13:25:28 2020 +0200
@@ -1,7 +1,8 @@
 import os
 
 
-abspath = lambda * p: os.path.abspath(os.path.join(*p))
+def abspath(*p):
+    return os.path.abspath(os.path.join(*p))
 
 
 def get_dirs_for_path(*paths):
@@ -11,7 +12,7 @@
     for path in paths:
         head = path
         while head:
-            head, tail = os.path.split(head)
+            head, _tail = os.path.split(head)
             if head:
                 yield head
             else:
--- a/kallithea/lib/vcs/utils/progressbar.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/lib/vcs/utils/progressbar.py	Mon Apr 27 13:25:28 2020 +0200
@@ -1,7 +1,5 @@
 # encoding: UTF-8
 
-from __future__ import print_function
-
 import datetime
 import string
 import sys
--- a/kallithea/model/db.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/model/db.py	Mon Apr 27 13:25:28 2020 +0200
@@ -37,7 +37,6 @@
 
 import ipaddr
 import sqlalchemy
-from beaker.cache import cache_region, region_invalidate
 from sqlalchemy import Boolean, Column, DateTime, Float, ForeignKey, Index, Integer, LargeBinary, String, Unicode, UnicodeText, UniqueConstraint
 from sqlalchemy.ext.hybrid import hybrid_property
 from sqlalchemy.orm import class_mapper, joinedload, relationship, validates
@@ -46,14 +45,12 @@
 
 import kallithea
 from kallithea.lib import ext_json
-from kallithea.lib.caching_query import FromCache
 from kallithea.lib.exceptions import DefaultUserException
-from kallithea.lib.utils2 import (
-    Optional, ascii_bytes, aslist, get_changeset_safe, get_clone_url, remove_prefix, safe_bytes, safe_int, safe_str, str2bool, urlreadable)
+from kallithea.lib.utils2 import (Optional, ascii_bytes, aslist, get_changeset_safe, get_clone_url, remove_prefix, safe_bytes, safe_int, safe_str, str2bool,
+                                  urlreadable)
 from kallithea.lib.vcs import get_backend
 from kallithea.lib.vcs.backends.base import EmptyChangeset
 from kallithea.lib.vcs.utils.helpers import get_scm
-from kallithea.lib.vcs.utils.lazy import LazyProperty
 from kallithea.model.meta import Base, Session
 
 
@@ -279,13 +276,9 @@
         return res
 
     @classmethod
-    def get_app_settings(cls, cache=False):
+    def get_app_settings(cls):
 
         ret = cls.query()
-
-        if cache:
-            ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
-
         if ret is None:
             raise Exception('Could not get application settings !')
         settings = {}
@@ -296,7 +289,7 @@
         return settings
 
     @classmethod
-    def get_auth_settings(cls, cache=False):
+    def get_auth_settings(cls):
         ret = cls.query() \
                 .filter(cls.app_settings_name.startswith('auth_')).all()
         fd = {}
@@ -305,7 +298,7 @@
         return fd
 
     @classmethod
-    def get_default_repo_settings(cls, cache=False, strip_prefix=False):
+    def get_default_repo_settings(cls, strip_prefix=False):
         ret = cls.query() \
                 .filter(cls.app_settings_name.startswith('default_')).all()
         fd = {}
@@ -337,9 +330,7 @@
 class Ui(Base, BaseDbModel):
     __tablename__ = 'ui'
     __table_args__ = (
-        # FIXME: ui_key as key is wrong and should be removed when the corresponding
-        # Ui.get_by_key has been replaced by the composite key
-        UniqueConstraint('ui_key'),
+        Index('ui_ui_section_ui_key_idx', 'ui_section', 'ui_key'),
         UniqueConstraint('ui_section', 'ui_key'),
         _table_args_default_dict,
     )
@@ -372,6 +363,7 @@
         q = cls.query()
         q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE]))
         q = q.filter(cls.ui_section == 'hooks')
+        q = q.order_by(cls.ui_section, cls.ui_key)
         return q.all()
 
     @classmethod
@@ -379,6 +371,7 @@
         q = cls.query()
         q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE]))
         q = q.filter(cls.ui_section == 'hooks')
+        q = q.order_by(cls.ui_section, cls.ui_key)
         return q.all()
 
     @classmethod
@@ -405,7 +398,7 @@
         _table_args_default_dict,
     )
 
-    DEFAULT_USER = 'default'
+    DEFAULT_USER_NAME = 'default'
     DEFAULT_GRAVATAR_URL = 'https://secure.gravatar.com/avatar/{md5email}?d=identicon&s={size}'
     # The name of the default auth type in extern_type, 'internal' lives in auth_internal.py
     DEFAULT_AUTH_TYPE = 'internal'
@@ -511,7 +504,7 @@
 
     @hybrid_property
     def is_default_user(self):
-        return self.username == User.DEFAULT_USER
+        return self.username == User.DEFAULT_USER_NAME
 
     @hybrid_property
     def user_data(self):
@@ -531,7 +524,7 @@
             log.error(traceback.format_exc())
 
     def __repr__(self):
-        return "<%s %s: %r')>" % (self.__class__.__name__, self.user_id, self.username)
+        return "<%s %s: %r>" % (self.__class__.__name__, self.user_id, self.username)
 
     @classmethod
     def guess_instance(cls, value):
@@ -549,7 +542,7 @@
         return user
 
     @classmethod
-    def get_by_username_or_email(cls, username_or_email, case_insensitive=False, cache=False):
+    def get_by_username_or_email(cls, username_or_email, case_insensitive=True):
         """
         For anything that looks like an email address, look up by the email address (matching
         case insensitively).
@@ -558,35 +551,24 @@
         This assumes no normal username can have '@' symbol.
         """
         if '@' in username_or_email:
-            return User.get_by_email(username_or_email, cache=cache)
+            return User.get_by_email(username_or_email)
         else:
-            return User.get_by_username(username_or_email, case_insensitive=case_insensitive, cache=cache)
+            return User.get_by_username(username_or_email, case_insensitive=case_insensitive)
 
     @classmethod
-    def get_by_username(cls, username, case_insensitive=False, cache=False):
+    def get_by_username(cls, username, case_insensitive=False):
         if case_insensitive:
             q = cls.query().filter(sqlalchemy.func.lower(cls.username) == sqlalchemy.func.lower(username))
         else:
             q = cls.query().filter(cls.username == username)
-
-        if cache:
-            q = q.options(FromCache(
-                            "sql_cache_short",
-                            "get_user_%s" % _hash_key(username)
-                          )
-            )
         return q.scalar()
 
     @classmethod
-    def get_by_api_key(cls, api_key, cache=False, fallback=True):
+    def get_by_api_key(cls, api_key, fallback=True):
         if len(api_key) != 40 or not api_key.isalnum():
             return None
 
         q = cls.query().filter(cls.api_key == api_key)
-
-        if cache:
-            q = q.options(FromCache("sql_cache_short",
-                                    "get_api_key_%s" % api_key))
         res = q.scalar()
 
         if fallback and not res:
@@ -601,20 +583,12 @@
     @classmethod
     def get_by_email(cls, email, cache=False):
         q = cls.query().filter(sqlalchemy.func.lower(cls.email) == sqlalchemy.func.lower(email))
-
-        if cache:
-            q = q.options(FromCache("sql_cache_short",
-                                    "get_email_key_%s" % email))
-
         ret = q.scalar()
         if ret is None:
             q = UserEmailMap.query()
             # try fetching in alternate email map
             q = q.filter(sqlalchemy.func.lower(UserEmailMap.email) == sqlalchemy.func.lower(email))
             q = q.options(joinedload(UserEmailMap.user))
-            if cache:
-                q = q.options(FromCache("sql_cache_short",
-                                        "get_email_map_key_%s" % email))
             ret = getattr(q.scalar(), 'user', None)
 
         return ret
@@ -652,8 +626,8 @@
         return user
 
     @classmethod
-    def get_default_user(cls, cache=False):
-        user = User.get_by_username(User.DEFAULT_USER, cache=cache)
+    def get_default_user(cls):
+        user = User.get_by_username(User.DEFAULT_USER_NAME)
         if user is None:
             raise Exception('Missing default account!')
         return user
@@ -790,7 +764,7 @@
     action_date = Column(DateTime(timezone=False), nullable=False)
 
     def __repr__(self):
-        return "<%s %r: %r')>" % (self.__class__.__name__,
+        return "<%s %r: %r>" % (self.__class__.__name__,
                                   self.repository_name,
                                   self.action)
 
@@ -820,8 +794,8 @@
     users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
     users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
     users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
-    user_user_group_to_perm = relationship('UserUserGroupToPerm ', cascade='all')
-    user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
+    user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
+    user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
 
     owner = relationship('User')
 
@@ -843,7 +817,7 @@
             log.error(traceback.format_exc())
 
     def __repr__(self):
-        return "<%s %s: %r')>" % (self.__class__.__name__,
+        return "<%s %s: %r>" % (self.__class__.__name__,
                                   self.users_group_id,
                                   self.users_group_name)
 
@@ -852,26 +826,16 @@
         return super(UserGroup, cls).guess_instance(value, UserGroup.get_by_group_name)
 
     @classmethod
-    def get_by_group_name(cls, group_name, cache=False,
-                          case_insensitive=False):
+    def get_by_group_name(cls, group_name, case_insensitive=False):
         if case_insensitive:
             q = cls.query().filter(sqlalchemy.func.lower(cls.users_group_name) == sqlalchemy.func.lower(group_name))
         else:
             q = cls.query().filter(cls.users_group_name == group_name)
-        if cache:
-            q = q.options(FromCache(
-                            "sql_cache_short",
-                            "get_group_%s" % _hash_key(group_name)
-                          )
-            )
         return q.scalar()
 
     @classmethod
-    def get(cls, user_group_id, cache=False):
+    def get(cls, user_group_id):
         user_group = cls.query()
-        if cache:
-            user_group = user_group.options(FromCache("sql_cache_short",
-                                    "get_users_group_%s" % user_group_id))
         return user_group.get(user_group_id)
 
     def get_api_data(self, with_members=True):
@@ -959,9 +923,9 @@
     DEFAULT_CLONE_URI = '{scheme}://{user}@{netloc}/{repo}'
     DEFAULT_CLONE_SSH = 'ssh://{system_user}@{hostname}/{repo}'
 
-    STATE_CREATED = u'repo_state_created'
-    STATE_PENDING = u'repo_state_pending'
-    STATE_ERROR = u'repo_state_error'
+    STATE_CREATED = 'repo_state_created'
+    STATE_PENDING = 'repo_state_pending'
+    STATE_ERROR = 'repo_state_error'
 
     repo_id = Column(Integer(), primary_key=True)
     repo_name = Column(Unicode(255), nullable=False, unique=True)
@@ -1057,10 +1021,6 @@
         return q
 
     @classmethod
-    def url_sep(cls):
-        return URL_SEP
-
-    @classmethod
     def normalize_repo_name(cls, repo_name):
         """
         Normalizes os specific repo_name to the format internally stored inside
@@ -1069,7 +1029,7 @@
         :param cls:
         :param repo_name:
         """
-        return cls.url_sep().join(repo_name.split(os.sep))
+        return URL_SEP.join(repo_name.split(os.sep))
 
     @classmethod
     def guess_instance(cls, value):
@@ -1090,7 +1050,7 @@
 
     @classmethod
     def get_by_full_path(cls, repo_full_path):
-        base_full_path = os.path.realpath(cls.base_path())
+        base_full_path = os.path.realpath(kallithea.CONFIG['base_path'])
         repo_full_path = os.path.realpath(repo_full_path)
         assert repo_full_path.startswith(base_full_path + os.path.sep)
         repo_name = repo_full_path[len(base_full_path) + 1:]
@@ -1101,18 +1061,6 @@
     def get_repo_forks(cls, repo_id):
         return cls.query().filter(Repository.fork_id == repo_id)
 
-    @classmethod
-    def base_path(cls):
-        """
-        Returns base path where all repos are stored
-
-        :param cls:
-        """
-        q = Session().query(Ui) \
-            .filter(Ui.ui_key == cls.url_sep())
-        q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
-        return q.one().ui_value
-
     @property
     def forks(self):
         """
@@ -1129,7 +1077,7 @@
 
     @property
     def just_name(self):
-        return self.repo_name.split(Repository.url_sep())[-1]
+        return self.repo_name.split(URL_SEP)[-1]
 
     @property
     def groups_with_parents(self):
@@ -1142,36 +1090,19 @@
         groups.reverse()
         return groups
 
-    @LazyProperty
-    def repo_path(self):
-        """
-        Returns base full path for that repository means where it actually
-        exists on a filesystem
-        """
-        q = Session().query(Ui).filter(Ui.ui_key ==
-                                              Repository.url_sep())
-        q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
-        return q.one().ui_value
-
     @property
     def repo_full_path(self):
-        p = [self.repo_path]
+        """
+        Returns base full path for the repository - where it actually
+        exists on a filesystem.
+        """
+        p = [kallithea.CONFIG['base_path']]
         # we need to split the name by / since this is how we store the
         # names in the database, but that eventually needs to be converted
         # into a valid system path
-        p += self.repo_name.split(Repository.url_sep())
+        p += self.repo_name.split(URL_SEP)
         return os.path.join(*p)
 
-    @property
-    def cache_keys(self):
-        """
-        Returns associated cache keys for that repo
-        """
-        return CacheInvalidation.query() \
-            .filter(CacheInvalidation.cache_args == self.repo_name) \
-            .order_by(CacheInvalidation.cache_key) \
-            .all()
-
     def get_new_name(self, repo_name):
         """
         returns new full repository name based on assigned group and new new
@@ -1179,7 +1110,7 @@
         :param group_name:
         """
         path_prefix = self.group.full_path_splitted if self.group else []
-        return Repository.url_sep().join(path_prefix + [repo_name])
+        return URL_SEP.join(path_prefix + [repo_name])
 
     @property
     def _ui(self):
@@ -1199,7 +1130,7 @@
         """
         from kallithea.lib.utils import is_valid_repo
 
-        return is_valid_repo(repo_name, cls.base_path())
+        return is_valid_repo(repo_name, kallithea.CONFIG['base_path'])
 
     def get_api_data(self, with_revision_names=False,
                            with_pullrequests=False):
@@ -1394,33 +1325,21 @@
 
     def set_invalidate(self):
         """
-        Mark caches of this repo as invalid.
+        Flush SA session caches of instances of on disk repo.
         """
-        CacheInvalidation.set_invalidate(self.repo_name)
+        try:
+            del self._scm_instance
+        except AttributeError:
+            pass
 
-    _scm_instance = None
+    _scm_instance = None  # caching inside lifetime of SA session
 
     @property
     def scm_instance(self):
         if self._scm_instance is None:
-            self._scm_instance = self.scm_instance_cached()
+            return self.scm_instance_no_cache()  # will populate self._scm_instance
         return self._scm_instance
 
-    def scm_instance_cached(self, valid_cache_keys=None):
-        @cache_region('long_term', 'scm_instance_cached')
-        def _c(repo_name): # repo_name is just for the cache key
-            log.debug('Creating new %s scm_instance and populating cache', repo_name)
-            return self.scm_instance_no_cache()
-        rn = self.repo_name
-
-        valid = CacheInvalidation.test_and_set_valid(rn, None, valid_cache_keys=valid_cache_keys)
-        if not valid:
-            log.debug('Cache for %s invalidated, getting new object', rn)
-            region_invalidate(_c, None, 'scm_instance_cached', rn)
-        else:
-            log.debug('Trying to get scm_instance of %s from cache', rn)
-        return _c(rn)
-
     def scm_instance_no_cache(self):
         repo_full_path = self.repo_full_path
         alias = get_scm(repo_full_path)[0]
@@ -1429,12 +1348,11 @@
         backend = get_backend(alias)
 
         if alias == 'hg':
-            repo = backend(repo_full_path, create=False,
-                           baseui=self._ui)
+            self._scm_instance = backend(repo_full_path, create=False, baseui=self._ui)
         else:
-            repo = backend(repo_full_path, create=False)
+            self._scm_instance = backend(repo_full_path, create=False)
 
-        return repo
+        return self._scm_instance
 
     def __json__(self):
         return dict(
@@ -1490,7 +1408,7 @@
         """Return tuple with group_id and name as html literal"""
         from webhelpers2.html import literal
         if repo_group is None:
-            return (-1, u'-- %s --' % _('top level'))
+            return (-1, '-- %s --' % _('top level'))
         return repo_group.group_id, literal(cls.SEP.join(repo_group.full_path_splitted))
 
     @classmethod
@@ -1500,15 +1418,11 @@
                       key=lambda c: c[1].split(cls.SEP))
 
     @classmethod
-    def url_sep(cls):
-        return URL_SEP
-
-    @classmethod
     def guess_instance(cls, value):
         return super(RepoGroup, cls).guess_instance(value, RepoGroup.get_by_group_name)
 
     @classmethod
-    def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
+    def get_by_group_name(cls, group_name, case_insensitive=False):
         group_name = group_name.rstrip('/')
         if case_insensitive:
             gr = cls.query() \
@@ -1516,12 +1430,6 @@
         else:
             gr = cls.query() \
                 .filter(cls.group_name == group_name)
-        if cache:
-            gr = gr.options(FromCache(
-                            "sql_cache_short",
-                            "get_group_%s" % _hash_key(group_name)
-                            )
-            )
         return gr.scalar()
 
     @property
@@ -1541,7 +1449,7 @@
 
     @property
     def name(self):
-        return self.group_name.split(RepoGroup.url_sep())[-1]
+        return self.group_name.split(URL_SEP)[-1]
 
     @property
     def full_path(self):
@@ -1549,7 +1457,7 @@
 
     @property
     def full_path_splitted(self):
-        return self.group_name.split(RepoGroup.url_sep())
+        return self.group_name.split(URL_SEP)
 
     @property
     def repositories(self):
@@ -1604,7 +1512,7 @@
         """
         path_prefix = (self.parent_group.full_path_splitted if
                        self.parent_group else [])
-        return RepoGroup.url_sep().join(path_prefix + [group_name])
+        return URL_SEP.join(path_prefix + [group_name])
 
     def get_api_data(self):
         """
@@ -1743,27 +1651,27 @@
 
     @classmethod
     def get_default_perms(cls, default_user_id):
-        q = Session().query(UserRepoToPerm, Repository, cls) \
-         .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id)) \
-         .join((cls, UserRepoToPerm.permission_id == cls.permission_id)) \
+        q = Session().query(UserRepoToPerm) \
+         .options(joinedload(UserRepoToPerm.repository)) \
+         .options(joinedload(UserRepoToPerm.permission)) \
          .filter(UserRepoToPerm.user_id == default_user_id)
 
         return q.all()
 
     @classmethod
     def get_default_group_perms(cls, default_user_id):
-        q = Session().query(UserRepoGroupToPerm, RepoGroup, cls) \
-         .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id)) \
-         .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id)) \
+        q = Session().query(UserRepoGroupToPerm) \
+         .options(joinedload(UserRepoGroupToPerm.group)) \
+         .options(joinedload(UserRepoGroupToPerm.permission)) \
          .filter(UserRepoGroupToPerm.user_id == default_user_id)
 
         return q.all()
 
     @classmethod
     def get_default_user_group_perms(cls, default_user_id):
-        q = Session().query(UserUserGroupToPerm, UserGroup, cls) \
-         .join((UserGroup, UserUserGroupToPerm.user_group_id == UserGroup.users_group_id)) \
-         .join((cls, UserUserGroupToPerm.permission_id == cls.permission_id)) \
+        q = Session().query(UserUserGroupToPerm) \
+         .options(joinedload(UserUserGroupToPerm.user_group)) \
+         .options(joinedload(UserUserGroupToPerm.permission)) \
          .filter(UserUserGroupToPerm.user_id == default_user_id)
 
         return q.all()
@@ -2015,130 +1923,6 @@
         return cls.query().filter(cls.follows_repository_id == repo_id)
 
 
-class CacheInvalidation(Base, BaseDbModel):
-    __tablename__ = 'cache_invalidation'
-    __table_args__ = (
-        Index('key_idx', 'cache_key'),
-        _table_args_default_dict,
-    )
-
-    # cache_id, not used
-    cache_id = Column(Integer(), primary_key=True)
-    # cache_key as created by _get_cache_key
-    cache_key = Column(Unicode(255), nullable=False, unique=True)
-    # cache_args is a repo_name
-    cache_args = Column(Unicode(255), nullable=False)
-    # instance sets cache_active True when it is caching, other instances set
-    # cache_active to False to indicate that this cache is invalid
-    cache_active = Column(Boolean(), nullable=False, default=False)
-
-    def __init__(self, cache_key, repo_name=''):
-        self.cache_key = cache_key
-        self.cache_args = repo_name
-        self.cache_active = False
-
-    def __repr__(self):
-        return "<%s %s: %s=%s" % (
-            self.__class__.__name__,
-            self.cache_id, self.cache_key, self.cache_active)
-
-    def _cache_key_partition(self):
-        prefix, repo_name, suffix = self.cache_key.partition(self.cache_args)
-        return prefix, repo_name, suffix
-
-    def get_prefix(self):
-        """
-        get prefix that might have been used in _get_cache_key to
-        generate self.cache_key. Only used for informational purposes
-        in repo_edit.html.
-        """
-        # prefix, repo_name, suffix
-        return self._cache_key_partition()[0]
-
-    def get_suffix(self):
-        """
-        get suffix that might have been used in _get_cache_key to
-        generate self.cache_key. Only used for informational purposes
-        in repo_edit.html.
-        """
-        # prefix, repo_name, suffix
-        return self._cache_key_partition()[2]
-
-    @classmethod
-    def clear_cache(cls):
-        """
-        Delete all cache keys from database.
-        Should only be run when all instances are down and all entries thus stale.
-        """
-        cls.query().delete()
-        Session().commit()
-
-    @classmethod
-    def _get_cache_key(cls, key):
-        """
-        Wrapper for generating a unique cache key for this instance and "key".
-        key must / will start with a repo_name which will be stored in .cache_args .
-        """
-        prefix = kallithea.CONFIG.get('instance_id', '')
-        return "%s%s" % (prefix, key)
-
-    @classmethod
-    def set_invalidate(cls, repo_name):
-        """
-        Mark all caches of a repo as invalid in the database.
-        """
-        inv_objs = Session().query(cls).filter(cls.cache_args == repo_name).all()
-        log.debug('for repo %s got %s invalidation objects',
-                  repo_name, inv_objs)
-
-        for inv_obj in inv_objs:
-            log.debug('marking %s key for invalidation based on repo_name=%s',
-                      inv_obj, repo_name)
-            Session().delete(inv_obj)
-        Session().commit()
-
-    @classmethod
-    def test_and_set_valid(cls, repo_name, kind, valid_cache_keys=None):
-        """
-        Mark this cache key as active and currently cached.
-        Return True if the existing cache registration still was valid.
-        Return False to indicate that it had been invalidated and caches should be refreshed.
-        """
-
-        key = (repo_name + '_' + kind) if kind else repo_name
-        cache_key = cls._get_cache_key(key)
-
-        if valid_cache_keys and cache_key in valid_cache_keys:
-            return True
-
-        inv_obj = cls.query().filter(cls.cache_key == cache_key).scalar()
-        if inv_obj is None:
-            inv_obj = cls(cache_key, repo_name)
-            Session().add(inv_obj)
-        elif inv_obj.cache_active:
-            return True
-        inv_obj.cache_active = True
-        try:
-            Session().commit()
-        except sqlalchemy.exc.IntegrityError:
-            log.error('commit of CacheInvalidation failed - retrying')
-            Session().rollback()
-            inv_obj = cls.query().filter(cls.cache_key == cache_key).scalar()
-            if inv_obj is None:
-                log.error('failed to create CacheInvalidation entry')
-                # TODO: fail badly?
-            # else: TOCTOU - another thread added the key at the same time; no further action required
-        return False
-
-    @classmethod
-    def get_valid_cache_keys(cls):
-        """
-        Return opaque object with information of which caches still are valid
-        and can be used without checking for invalidation.
-        """
-        return set(inv_obj.cache_key for inv_obj in cls.query().filter(cls.cache_active).all())
-
-
 class ChangesetComment(Base, BaseDbModel):
     __tablename__ = 'changeset_comments'
     __table_args__ = (
@@ -2258,8 +2042,8 @@
     )
 
     # values for .status
-    STATUS_NEW = u'new'
-    STATUS_CLOSED = u'closed'
+    STATUS_NEW = 'new'
+    STATUS_CLOSED = 'closed'
 
     pull_request_id = Column(Integer(), primary_key=True)
     title = Column(Unicode(255), nullable=False)
@@ -2428,9 +2212,9 @@
         _table_args_default_dict,
     )
 
-    GIST_PUBLIC = u'public'
-    GIST_PRIVATE = u'private'
-    DEFAULT_FILENAME = u'gistfile1.txt'
+    GIST_PUBLIC = 'public'
+    GIST_PRIVATE = 'private'
+    DEFAULT_FILENAME = 'gistfile1.txt'
 
     gist_id = Column(Integer(), primary_key=True)
     gist_access_id = Column(Unicode(250), nullable=False)
@@ -2475,19 +2259,6 @@
         import kallithea.lib.helpers as h
         return h.canonical_url('gist', gist_id=self.gist_access_id)
 
-    @classmethod
-    def base_path(cls):
-        """
-        Returns base path where all gists are stored
-
-        :param cls:
-        """
-        from kallithea.model.gist import GIST_STORE_LOC
-        q = Session().query(Ui) \
-            .filter(Ui.ui_key == URL_SEP)
-        q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
-        return os.path.join(q.one().ui_value, GIST_STORE_LOC)
-
     def get_api_data(self):
         """
         Common function for generating gist related data for API
@@ -2509,13 +2280,15 @@
         )
         data.update(self.get_api_data())
         return data
+
     ## SCM functions
 
     @property
     def scm_instance(self):
         from kallithea.lib.vcs import get_repo
-        base_path = self.base_path()
-        return get_repo(os.path.join(base_path, self.gist_access_id))
+        from kallithea.model.gist import GIST_STORE_LOC
+        gist_base_path = os.path.join(kallithea.CONFIG['base_path'], GIST_STORE_LOC)
+        return get_repo(os.path.join(gist_base_path, self.gist_access_id))
 
 
 class UserSshKeys(Base, BaseDbModel):
--- a/kallithea/model/forms.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/model/forms.py	Mon Apr 27 13:25:28 2020 +0200
@@ -558,11 +558,11 @@
 
         filename = All(v.BasePath()(),
                        v.UnicodeString(strip=True, required=False))
-        description = v.UnicodeString(required=False, if_missing=u'')
+        description = v.UnicodeString(required=False, if_missing='')
         lifetime = v.OneOf(lifetime_options)
         mimetype = v.UnicodeString(required=False, if_missing=None)
         content = v.UnicodeString(required=True, not_empty=True)
-        public = v.UnicodeString(required=False, if_missing=u'')
-        private = v.UnicodeString(required=False, if_missing=u'')
+        public = v.UnicodeString(required=False, if_missing='')
+        private = v.UnicodeString(required=False, if_missing='')
 
     return _GistForm
--- a/kallithea/model/gist.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/model/gist.py	Mon Apr 27 13:25:28 2020 +0200
@@ -50,7 +50,7 @@
     rnd = random.SystemRandom() # use cryptographically secure system PRNG
     alphabet = '23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjklmnpqrstuvwxyz'
     length = 20
-    return u''.join(rnd.choice(alphabet) for _ in range(length))
+    return ''.join(rnd.choice(alphabet) for _ in range(length))
 
 
 class GistModel(object):
--- a/kallithea/model/meta.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/model/meta.py	Mon Apr 27 13:25:28 2020 +0200
@@ -18,8 +18,6 @@
 from sqlalchemy.ext.declarative import declarative_base
 from sqlalchemy.orm import scoped_session, sessionmaker
 
-from kallithea.lib import caching_query
-
 
 # Beaker CacheManager.  A home base for cache configurations.
 cache_manager = cache.CacheManager()
@@ -29,18 +27,13 @@
 #
 # SQLAlchemy session manager.
 #
-session_factory = sessionmaker(
-    query_cls=caching_query.query_callable(cache_manager),
-    expire_on_commit=True)
+session_factory = sessionmaker(expire_on_commit=True)
 Session = scoped_session(session_factory)
 
 # The base class for declarative schemas in db.py
 # Engine is injected when model.__init__.init_model() sets meta.Base.metadata.bind
 Base = declarative_base()
 
-# to use cache use this in query:
-#   .options(FromCache("sqlalchemy_cache_type", "cachekey"))
-
 
 # Define naming conventions for foreign keys, primary keys, indexes,
 # check constraints, and unique constraints, respectively.
--- a/kallithea/model/notification.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/model/notification.py	Mon Apr 27 13:25:28 2020 +0200
@@ -33,7 +33,6 @@
 from tg import tmpl_context as c
 from tg.i18n import ugettext as _
 
-import kallithea
 from kallithea.lib import helpers as h
 from kallithea.model.db import User
 
@@ -43,12 +42,12 @@
 
 class NotificationModel(object):
 
-    TYPE_CHANGESET_COMMENT = u'cs_comment'
-    TYPE_MESSAGE = u'message'
-    TYPE_MENTION = u'mention' # not used
-    TYPE_REGISTRATION = u'registration'
-    TYPE_PULL_REQUEST = u'pull_request'
-    TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
+    TYPE_CHANGESET_COMMENT = 'cs_comment'
+    TYPE_MESSAGE = 'message'
+    TYPE_MENTION = 'mention' # not used
+    TYPE_REGISTRATION = 'registration'
+    TYPE_PULL_REQUEST = 'pull_request'
+    TYPE_PULL_REQUEST_COMMENT = 'pull_request_comment'
 
     def create(self, created_by, subject, body, recipients=None,
                type_=TYPE_MESSAGE, with_email=True,
@@ -133,7 +132,8 @@
         # send email with notification to all other participants
         for rec in rec_objs:
             tasks.send_email([rec.email], email_subject, email_txt_body,
-                     email_html_body, headers, author=created_by_obj)
+                     email_html_body, headers,
+                     from_name=created_by_obj.full_name_or_username)
 
 
 class EmailNotificationModel(object):
@@ -149,7 +149,6 @@
 
     def __init__(self):
         super(EmailNotificationModel, self).__init__()
-        self._template_root = kallithea.CONFIG['paths']['templates'][0]
         self._tmpl_lookup = app_globals.mako_lookup
         self.email_types = {
             self.TYPE_CHANGESET_COMMENT: 'changeset_comment',
--- a/kallithea/model/permission.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/model/permission.py	Mon Apr 27 13:25:28 2020 +0200
@@ -75,7 +75,6 @@
         perms = UserToPerm.query().filter(UserToPerm.user == user).all()
         defined_perms_groups = set(_get_group(x.permission.permission_name) for x in perms)
         log.debug('GOT ALREADY DEFINED:%s', perms)
-        DEFAULT_PERMS = Permission.DEFAULT_USER_PERMISSIONS
 
         if force:
             for perm in perms:
@@ -84,7 +83,7 @@
             defined_perms_groups = []
         # For every default permission that needs to be created, we check if
         # its group is already defined. If it's not, we create default permission.
-        for perm_name in DEFAULT_PERMS:
+        for perm_name in Permission.DEFAULT_USER_PERMISSIONS:
             gr = _get_group(perm_name)
             if gr not in defined_perms_groups:
                 log.debug('GR:%s not found, creating permission %s',
--- a/kallithea/model/pull_request.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/model/pull_request.py	Mon Apr 27 13:25:28 2020 +0200
@@ -265,7 +265,7 @@
         from kallithea.model.changeset_status import ChangesetStatusModel
         from kallithea.model.comment import ChangesetCommentsModel
         comment = ChangesetCommentsModel().create(
-            text=u'',
+            text='',
             repo=self.org_repo,
             author=created_by,
             pull_request=pr,
--- a/kallithea/model/repo.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/model/repo.py	Mon Apr 27 13:25:28 2020 +0200
@@ -35,14 +35,13 @@
 import kallithea.lib.utils2
 from kallithea.lib import helpers as h
 from kallithea.lib.auth import HasRepoPermissionLevel, HasUserGroupPermissionLevel
-from kallithea.lib.caching_query import FromCache
 from kallithea.lib.exceptions import AttachedForksError
 from kallithea.lib.hooks import log_delete_repository
 from kallithea.lib.utils import is_valid_repo_uri, make_ui
 from kallithea.lib.utils2 import LazyProperty, get_current_authuser, obfuscate_url_pw, remove_prefix
 from kallithea.lib.vcs.backends import get_backend
-from kallithea.model.db import (
-    Permission, RepoGroup, Repository, RepositoryField, Session, Statistics, Ui, User, UserGroup, UserGroupRepoGroupToPerm, UserGroupRepoToPerm, UserRepoGroupToPerm, UserRepoToPerm)
+from kallithea.model.db import (URL_SEP, Permission, RepoGroup, Repository, RepositoryField, Session, Statistics, Ui, User, UserGroup, UserGroupRepoGroupToPerm,
+                                UserGroupRepoToPerm, UserRepoGroupToPerm, UserRepoToPerm)
 
 
 log = logging.getLogger(__name__)
@@ -50,7 +49,7 @@
 
 class RepoModel(object):
 
-    URL_SEPARATOR = Repository.url_sep()
+    URL_SEPARATOR = URL_SEP
 
     def _create_default_perms(self, repository, private):
         # create default permission
@@ -81,25 +80,17 @@
         q = Ui.query().filter(Ui.ui_key == '/').one()
         return q.ui_value
 
-    def get(self, repo_id, cache=False):
+    def get(self, repo_id):
         repo = Repository.query() \
             .filter(Repository.repo_id == repo_id)
-
-        if cache:
-            repo = repo.options(FromCache("sql_cache_short",
-                                          "get_repo_%s" % repo_id))
         return repo.scalar()
 
     def get_repo(self, repository):
         return Repository.guess_instance(repository)
 
-    def get_by_repo_name(self, repo_name, cache=False):
+    def get_by_repo_name(self, repo_name):
         repo = Repository.query() \
             .filter(Repository.repo_name == repo_name)
-
-        if cache:
-            repo = repo.options(FromCache("sql_cache_short",
-                                          "get_repo_%s" % repo_name))
         return repo.scalar()
 
     def get_all_user_repos(self, user):
@@ -109,12 +100,11 @@
         :param user:
         """
         from kallithea.lib.auth import AuthUser
-        user = User.guess_instance(user)
-        repos = AuthUser(dbuser=user).permissions['repositories']
-        access_check = lambda r: r[1] in ['repository.read',
-                                          'repository.write',
-                                          'repository.admin']
-        repos = [x[0] for x in filter(access_check, repos.items())]
+        auth_user = AuthUser(dbuser=User.guess_instance(user))
+        repos = [repo_name
+            for repo_name, perm in auth_user.permissions['repositories'].items()
+            if perm in ['repository.read', 'repository.write', 'repository.admin']
+            ]
         return Repository.query().filter(Repository.repo_name.in_(repos))
 
     @classmethod
@@ -138,12 +128,16 @@
         admin: return data for action column.
         """
         _render = self._render_datatable
-        from tg import tmpl_context as c
+        from tg import tmpl_context as c, request
+        from kallithea.model.scm import ScmModel
 
         def repo_lnk(name, rtype, rstate, private, fork_of):
             return _render('repo_name', name, rtype, rstate, private, fork_of,
                            short_name=short_name)
 
+        def following(repo_id, is_following):
+            return _render('following', repo_id, is_following)
+
         def last_change(last_change):
             return _render("last_change", last_change)
 
@@ -188,6 +182,10 @@
                 "just_name": repo.just_name,
                 "name": repo_lnk(repo.repo_name, repo.repo_type,
                                  repo.repo_state, repo.private, repo.fork),
+                "following": following(
+                    repo.repo_id,
+                    ScmModel().is_following_repo(repo.repo_name, request.authuser.user_id),
+                ),
                 "last_change_iso": repo.last_db_change.isoformat(),
                 "last_change": last_change(repo.last_db_change),
                 "last_changeset": last_rev(repo.repo_name, cs_cache),
@@ -272,7 +270,7 @@
                 cur_repo.owner = User.get_by_username(kwargs['owner'])
 
             if 'repo_group' in kwargs:
-                assert kwargs['repo_group'] != u'-1', kwargs # RepoForm should have converted to None
+                assert kwargs['repo_group'] != '-1', kwargs # RepoForm should have converted to None
                 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
                 cur_repo.repo_name = cur_repo.get_new_name(cur_repo.just_name)
             log.debug('Updating repo %s with params:%s', cur_repo, kwargs)
@@ -343,7 +341,7 @@
             # while repo_name_full is a full qualified name that is combined
             # with name and path of group
             repo_name_full = repo_name
-            repo_name = repo_name.split(self.URL_SEPARATOR)[-1]
+            repo_name = repo_name.split(URL_SEP)[-1]
             if kallithea.lib.utils2.repo_name_slug(repo_name) != repo_name:
                 raise Exception('invalid repo name %s' % repo_name)
 
--- a/kallithea/model/repo_group.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/model/repo_group.py	Mon Apr 27 13:25:28 2020 +0200
@@ -34,6 +34,7 @@
 
 import kallithea.lib.utils2
 from kallithea.lib.utils2 import LazyProperty
+from kallithea.model import db
 from kallithea.model.db import Permission, RepoGroup, Repository, Session, Ui, User, UserGroup, UserGroupRepoGroupToPerm, UserRepoGroupToPerm
 
 
@@ -115,7 +116,7 @@
         :param group: instance of group from database
         :param force_delete: use shutil rmtree to remove all objects
         """
-        paths = group.full_path.split(RepoGroup.url_sep())
+        paths = group.full_path.split(db.URL_SEP)
         paths = os.sep.join(paths)
 
         rm_path = os.path.join(self.repos_path, paths)
@@ -288,7 +289,7 @@
                 repo_group.parent_group_id = repo_group_args['parent_group_id']
 
             if 'parent_group_id' in repo_group_args:
-                assert repo_group_args['parent_group_id'] != u'-1', repo_group_args  # RepoGroupForm should have converted to None
+                assert repo_group_args['parent_group_id'] != '-1', repo_group_args  # RepoGroupForm should have converted to None
                 repo_group.parent_group = RepoGroup.get(repo_group_args['parent_group_id'])
             if 'group_name' in repo_group_args:
                 group_name = repo_group_args['group_name']
--- a/kallithea/model/repo_permission.py	Mon Apr 13 21:40:33 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-# -*- coding: utf-8 -*-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# 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 General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-"""
-kallithea.model.repo_permission
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-repository permission model for Kallithea
-
-This file was forked by the Kallithea project in July 2014.
-Original author and date, and relevant copyright and licensing information is below:
-:created_on: Oct 1, 2011
-:author: nvinot, marcink
-"""
-
-import logging
-
-from kallithea.model.db import Permission, Repository, Session, User, UserGroupRepoToPerm, UserRepoToPerm
-
-
-log = logging.getLogger(__name__)
-
-
-class RepositoryPermissionModel(object):
-
-    def get_user_permission(self, repository, user):
-        repository = Repository.guess_instance(repository)
-        user = User.guess_instance(user)
-
-        return UserRepoToPerm.query() \
-                .filter(UserRepoToPerm.user == user) \
-                .filter(UserRepoToPerm.repository == repository) \
-                .scalar()
-
-    def update_user_permission(self, repository, user, permission):
-        permission = Permission.get_by_key(permission)
-        current = self.get_user_permission(repository, user)
-        if current:
-            if current.permission is not permission:
-                current.permission = permission
-        else:
-            p = UserRepoToPerm()
-            p.user = user
-            p.repository = repository
-            p.permission = permission
-            Session().add(p)
-
-    def delete_user_permission(self, repository, user):
-        current = self.get_user_permission(repository, user)
-        if current:
-            Session().delete(current)
-
-    def get_users_group_permission(self, repository, users_group):
-        return UserGroupRepoToPerm.query() \
-                .filter(UserGroupRepoToPerm.users_group == users_group) \
-                .filter(UserGroupRepoToPerm.repository == repository) \
-                .scalar()
-
-    def update_users_group_permission(self, repository, users_group,
-                                      permission):
-        permission = Permission.get_by_key(permission)
-        current = self.get_users_group_permission(repository, users_group)
-        if current:
-            if current.permission is not permission:
-                current.permission = permission
-        else:
-            p = UserGroupRepoToPerm()
-            p.users_group = users_group
-            p.repository = repository
-            p.permission = permission
-            Session().add(p)
-
-    def delete_users_group_permission(self, repository, users_group):
-        current = self.get_users_group_permission(repository, users_group)
-        if current:
-            Session().delete(current)
-
-    def update_or_delete_user_permission(self, repository, user, permission):
-        if permission:
-            self.update_user_permission(repository, user, permission)
-        else:
-            self.delete_user_permission(repository, user)
-
-    def update_or_delete_users_group_permission(self, repository, user_group,
-                                              permission):
-        if permission:
-            self.update_users_group_permission(repository, user_group,
-                                               permission)
-        else:
-            self.delete_users_group_permission(repository, user_group)
--- a/kallithea/model/scm.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/model/scm.py	Mon Apr 27 13:25:28 2020 +0200
@@ -659,18 +659,18 @@
 
         repo = repo.scm_instance
 
-        branches_group = ([(u'branch:%s' % k, k) for k, v in
+        branches_group = ([('branch:%s' % k, k) for k, v in
                            repo.branches.items()], _("Branches"))
         hist_l.append(branches_group)
         choices.extend([x[0] for x in branches_group[0]])
 
         if repo.alias == 'hg':
-            bookmarks_group = ([(u'book:%s' % k, k) for k, v in
+            bookmarks_group = ([('book:%s' % k, k) for k, v in
                                 repo.bookmarks.items()], _("Bookmarks"))
             hist_l.append(bookmarks_group)
             choices.extend([x[0] for x in bookmarks_group[0]])
 
-        tags_group = ([(u'tag:%s' % k, k) for k, v in
+        tags_group = ([('tag:%s' % k, k) for k, v in
                        repo.tags.items()], _("Tags"))
         hist_l.append(tags_group)
         choices.extend([x[0] for x in tags_group[0]])
--- a/kallithea/model/ssh_key.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/model/ssh_key.py	Mon Apr 27 13:25:28 2020 +0200
@@ -52,7 +52,7 @@
         Will raise SshKeyModelException on errors
         """
         try:
-            keytype, pub, comment = ssh.parse_pub_key(public_key)
+            keytype, _pub, comment = ssh.parse_pub_key(public_key)
         except ssh.SshKeyParseError as e:
             raise SshKeyModelException(_('SSH key %r is invalid: %s') % (public_key, e.args[0]))
         if not description.strip():
@@ -134,8 +134,5 @@
             for key in UserSshKeys.query().join(UserSshKeys.user).filter(User.active == True):
                 f.write(ssh.authorized_keys_line(kallithea_cli_path, config['__file__'], key))
         os.chmod(tmp_authorized_keys, stat.S_IRUSR | stat.S_IWUSR)
-        # This preliminary remove is needed for Windows, not for Unix.
-        # TODO In Python 3, the remove+rename sequence below should become os.replace.
-        if os.path.exists(authorized_keys):
-            os.remove(authorized_keys)
-        os.rename(tmp_authorized_keys, authorized_keys)
+        # Note: simple overwrite / rename isn't enough to replace the file on Windows
+        os.replace(tmp_authorized_keys, authorized_keys)
--- a/kallithea/model/user.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/model/user.py	Mon Apr 27 13:25:28 2020 +0200
@@ -36,7 +36,6 @@
 from tg import config
 from tg.i18n import ugettext as _
 
-from kallithea.lib.caching_query import FromCache
 from kallithea.lib.exceptions import DefaultUserException, UserOwnsReposException
 from kallithea.lib.utils2 import generate_api_key, get_current_authuser
 from kallithea.model.db import Permission, User, UserEmailMap, UserIpMap, UserToPerm
@@ -49,11 +48,8 @@
 class UserModel(object):
     password_reset_token_lifetime = 86400 # 24 hours
 
-    def get(self, user_id, cache=False):
+    def get(self, user_id):
         user = User.query()
-        if cache:
-            user = user.options(FromCache("sql_cache_short",
-                                          "get_user_%s" % user_id))
         return user.get(user_id)
 
     def get_user(self, user):
@@ -94,8 +90,8 @@
         log_create_user(new_user.get_dict(), cur_user)
         return new_user
 
-    def create_or_update(self, username, password, email, firstname=u'',
-                         lastname=u'', active=True, admin=False,
+    def create_or_update(self, username, password, email, firstname='',
+                         lastname='', active=True, admin=False,
                          extern_type=None, extern_name=None, cur_user=None):
         """
         Creates a new instance if not found, or updates current one
@@ -183,7 +179,7 @@
         # notification to admins
         subject = _('New user registration')
         body = (
-            u'New user registration\n'
+            'New user registration\n'
             '---------------------\n'
             '- Username: {user.username}\n'
             '- Full Name: {user.full_name}\n'
@@ -203,7 +199,7 @@
     def update(self, user_id, form_data, skip_attrs=None):
         from kallithea.lib.auth import get_crypt_password
         skip_attrs = skip_attrs or []
-        user = self.get(user_id, cache=False)
+        user = self.get(user_id)
         if user.is_default_user:
             raise DefaultUserException(
                             _("You can't edit this user since it's "
@@ -308,8 +304,8 @@
         """
         app_secret = config.get('app_instance_uuid')
         return hmac.HMAC(
-            key=u'\0'.join([app_secret, user.password]).encode('utf-8'),
-            msg=u'\0'.join([session_id, str(user.user_id), user.email, str(timestamp)]).encode('utf-8'),
+            key='\0'.join([app_secret, user.password]).encode('utf-8'),
+            msg='\0'.join([session_id, str(user.user_id), user.email, str(timestamp)]).encode('utf-8'),
             digestmod=hashlib.sha1,
         ).hexdigest()
 
--- a/kallithea/model/user_group.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/model/user_group.py	Mon Apr 27 13:25:28 2020 +0200
@@ -28,8 +28,8 @@
 import traceback
 
 from kallithea.lib.exceptions import RepoGroupAssignmentError, UserGroupsAssignedException
-from kallithea.model.db import (
-    Permission, Session, User, UserGroup, UserGroupMember, UserGroupRepoToPerm, UserGroupToPerm, UserGroupUserGroupToPerm, UserUserGroupToPerm)
+from kallithea.model.db import (Permission, Session, User, UserGroup, UserGroupMember, UserGroupRepoToPerm, UserGroupToPerm, UserGroupUserGroupToPerm,
+                                UserUserGroupToPerm)
 
 
 log = logging.getLogger(__name__)
@@ -94,8 +94,8 @@
     def get_group(self, user_group):
         return UserGroup.guess_instance(user_group)
 
-    def get_by_name(self, name, cache=False, case_insensitive=False):
-        return UserGroup.get_by_group_name(name, cache=cache, case_insensitive=case_insensitive)
+    def get_by_name(self, name, case_insensitive=False):
+        return UserGroup.get_by_group_name(name, case_insensitive=case_insensitive)
 
     def create(self, name, description, owner, active=True, group_data=None):
         try:
@@ -367,7 +367,7 @@
         for gr in set(groups):
             existing_group = UserGroup.get_by_group_name(gr)
             if not existing_group:
-                desc = u'Automatically created from plugin:%s' % extern_type
+                desc = 'Automatically created from plugin:%s' % extern_type
                 # we use first admin account to set the owner of the group
                 existing_group = UserGroupModel().create(gr, desc, owner,
                                         group_data={'extern_type': extern_type})
--- a/kallithea/model/validators.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/model/validators.py	Mon Apr 27 13:25:28 2020 +0200
@@ -30,9 +30,10 @@
 from kallithea.config.routing import ADMIN_PREFIX
 from kallithea.lib.auth import HasPermissionAny, HasRepoGroupPermissionLevel
 from kallithea.lib.compat import OrderedSet
-from kallithea.lib.exceptions import LdapImportError
+from kallithea.lib.exceptions import InvalidCloneUriException, LdapImportError
 from kallithea.lib.utils import is_valid_repo_uri
 from kallithea.lib.utils2 import aslist, repo_name_slug, str2bool
+from kallithea.model import db
 from kallithea.model.db import RepoGroup, Repository, User, UserGroup
 
 
@@ -186,11 +187,7 @@
             slug = repo_name_slug(group_name)
 
             # check for parent of self
-            parent_of_self = lambda: (
-                old_data['group_id'] == parent_group_id
-                if parent_group_id else False
-            )
-            if edit and parent_of_self():
+            if edit and parent_group_id and old_data['group_id'] == parent_group_id:
                 msg = self.message('parent_group_id', state)
                 raise formencode.Invalid(msg, value, state,
                     error_dict=dict(parent_group_id=msg)
@@ -276,7 +273,7 @@
 def ValidAuth():
     class _validator(formencode.validators.FancyValidator):
         messages = {
-            'invalid_auth': _(u'Invalid username or password'),
+            'invalid_auth': _('Invalid username or password'),
         }
 
         def _validate_python(self, value, state):
@@ -329,7 +326,7 @@
                 # value needs to be aware of group name in order to check
                 # db key This is an actual just the name to store in the
                 # database
-                repo_name_full = group_path + RepoGroup.url_sep() + repo_name
+                repo_name_full = group_path + db.URL_SEP + repo_name
             else:
                 group_name = group_path = ''
                 repo_name_full = repo_name
@@ -413,8 +410,8 @@
             if url and url != value.get('clone_uri_hidden'):
                 try:
                     is_valid_repo_uri(repo_type, url, make_ui())
-                except Exception:
-                    log.exception('URL validation failed')
+                except InvalidCloneUriException as e:
+                    log.warning('validation of clone URL %r failed: %s', url, e)
                     msg = self.message('clone_uri', state)
                     raise formencode.Invalid(msg, value, state,
                         error_dict=dict(clone_uri=msg)
@@ -566,16 +563,16 @@
 
             for k, v in value.items():
                 if k.startswith('u_perm_') or k.startswith('g_perm_'):
-                    member = k[7:]
+                    member_name = k[7:]
                     t = {'u': 'user',
                          'g': 'users_group'
                     }[k[0]]
-                    if member == User.DEFAULT_USER:
+                    if member_name == User.DEFAULT_USER_NAME:
                         if str2bool(value.get('repo_private')):
                             # set none for default when updating to
                             # private repo protects against form manipulation
                             v = EMPTY_PERM
-                    perms_update.add((member, v, t))
+                    perms_update.add((member_name, v, t))
 
             value['perms_updates'] = list(perms_update)
             value['perms_new'] = list(perms_new)
@@ -584,16 +581,16 @@
             for k, v, t in perms_new:
                 try:
                     if t == 'user':
-                        self.user_db = User.query() \
+                        _user_db = User.query() \
                             .filter(User.active == True) \
                             .filter(User.username == k).one()
                     if t == 'users_group':
-                        self.user_db = UserGroup.query() \
+                        _user_db = UserGroup.query() \
                             .filter(UserGroup.users_group_active == True) \
                             .filter(UserGroup.users_group_name == k).one()
 
-                except Exception:
-                    log.exception('Updated permission failed')
+                except Exception as e:
+                    log.warning('Error validating %s permission %s', t, k)
                     msg = self.message('perm_new_member_type', state)
                     raise formencode.Invalid(msg, value, state,
                         error_dict=dict(perm_new_member_name=msg)
--- a/kallithea/public/fontello/demo.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/public/fontello/demo.html	Mon Apr 27 13:25:28 2020 +0200
@@ -276,7 +276,7 @@
     }
      </style>
     <link rel="stylesheet" href="css/animation.css"><!--[if IE 7]><link rel="stylesheet" href="css/kallithea-ie7.css"><![endif]-->
-    <script>
+    <script>'use strict';
       function toggleCodes(on) {
         var obj = document.getElementById('icons');
       
--- a/kallithea/public/js/base.js	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/public/js/base.js	Mon Apr 27 13:25:28 2020 +0200
@@ -171,12 +171,12 @@
             return output.join('');
         }
 
-        var str_format = function() {
+        function str_format() {
             if (!str_format.cache.hasOwnProperty(arguments[0])) {
                 str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
             }
             return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
-        };
+        }
 
         str_format.format = function(parse_tree, argv) {
             var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
@@ -239,7 +239,7 @@
                 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
                     parse_tree.push('%');
                 }
-                else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
+                else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
                     if (match[2]) {
                         arg_names |= 1;
                         var field_list = [], replacement_field = match[2], field_match = [];
@@ -281,10 +281,6 @@
         return str_format;
     })();
 
-    var vsprintf = function(fmt, argv) {
-        argv.unshift(fmt);
-        return sprintf.apply(null, argv);
-    };
     return {
         'url': function(route_name, params) {
             var result = route_name;
@@ -335,25 +331,10 @@
 })();
 
 
-/* Invoke all functions in callbacks */
-var _run_callbacks = function(callbacks){
-    if (callbacks !== undefined){
-        var _l = callbacks.length;
-        for (var i=0;i<_l;i++){
-            var func = callbacks[i];
-            if(typeof(func)=='function'){
-                try{
-                    func();
-                }catch (err){};
-            }
-        }
-    }
-}
-
 /**
  * turns objects into GET query string
  */
-var _toQueryString = function(o) {
+function _toQueryString(o) {
     if(typeof o !== 'object') {
         return false;
     }
@@ -362,7 +343,7 @@
         _qs.push(encodeURIComponent(_p) + '=' + encodeURIComponent(o[_p]));
     }
     return _qs.join('&');
-};
+}
 
 /**
  * Load HTML into DOM using Ajax
@@ -386,18 +367,18 @@
                     success();
                 }
             })
-        .fail(function(jqXHR, textStatus, errorThrown) {
+        .fail(function(jqXHR, textStatus) {
                 if (textStatus == "abort")
                     return;
                 $target.html('<span class="bg-danger">ERROR: {0}</span>'.format(textStatus));
                 $target.css('opacity','1.0');
             })
         ;
-};
+}
 
-var ajaxGET = function(url, success, failure) {
+function ajaxGET(url, success, failure) {
     if(failure === undefined) {
-        failure = function(jqXHR, textStatus, errorThrown) {
+        failure = function(jqXHR, textStatus) {
                 if (textStatus != "abort")
                     alert("Ajax GET error: " + textStatus);
             };
@@ -405,21 +386,20 @@
     return $.ajax({url: url, headers: {'X-PARTIAL-XHR': '1'}, cache: false})
         .done(success)
         .fail(failure);
-};
+}
 
-var ajaxPOST = function(url, postData, success, failure) {
+function ajaxPOST(url, postData, success, failure) {
     postData['_session_csrf_secret_token'] = _session_csrf_secret_token;
-    var postData = _toQueryString(postData);
     if(failure === undefined) {
-        failure = function(jqXHR, textStatus, errorThrown) {
+        failure = function(jqXHR, textStatus) {
                 if (textStatus != "abort")
                     alert("Error posting to server: " + textStatus);
             };
     }
-    return $.ajax({url: url, data: postData, type: 'POST', headers: {'X-PARTIAL-XHR': '1'}, cache: false})
+    return $.ajax({url: url, data: _toQueryString(postData), type: 'POST', headers: {'X-PARTIAL-XHR': '1'}, cache: false})
         .done(success)
         .fail(failure);
-};
+}
 
 
 /**
@@ -427,45 +407,47 @@
  * the .show_more must have an id that is the the id of an element to hide prefixed with _
  * the parentnode will be displayed
  */
-var show_more_event = function(){
+function show_more_event(){
     $('.show_more').click(function(e){
         var el = e.currentTarget;
         $('#' + el.id.substring(1)).hide();
         $(el.parentNode).show();
     });
-};
+}
 
 
-var _onSuccessFollow = function(target){
+function _onSuccessFollow(target){
     var $target = $(target);
     var $f_cnt = $('#current_followers_count');
     if ($target.hasClass('follow')) {
         $target.removeClass('follow').addClass('following');
         $target.prop('title', _TM['Stop following this repository']);
         if ($f_cnt.html()) {
-            var cnt = Number($f_cnt.html())+1;
+            const cnt = Number($f_cnt.html())+1;
             $f_cnt.html(cnt);
         }
     } else {
         $target.removeClass('following').addClass('follow');
         $target.prop('title', _TM['Start following this repository']);
         if ($f_cnt.html()) {
-            var cnt = Number($f_cnt.html())-1;
+            const cnt = Number($f_cnt.html())-1;
             $f_cnt.html(cnt);
         }
     }
 }
 
-var toggleFollowingRepo = function(target, follows_repository_id){
-    var args = 'follows_repository_id=' + follows_repository_id;
-    args += '&amp;_session_csrf_secret_token=' + _session_csrf_secret_token;
-    $.post(TOGGLE_FOLLOW_URL, args, function(data){
+function toggleFollowingRepo(target, follows_repository_id){
+    var args = {
+        'follows_repository_id': follows_repository_id,
+        '_session_csrf_secret_token': _session_csrf_secret_token
+    }
+    $.post(TOGGLE_FOLLOW_URL, args, function(){
             _onSuccessFollow(target);
         });
     return false;
-};
+}
 
-var showRepoSize = function(target, repo_name){
+function showRepoSize(target, repo_name){
     var args = '_session_csrf_secret_token=' + _session_csrf_secret_token;
 
     if(!$("#" + target).hasClass('loaded')){
@@ -477,12 +459,12 @@
         });
     }
     return false;
-};
+}
 
 /**
  * load tooltips dynamically based on data attributes, used for .lazy-cs changeset links
  */
-var get_changeset_tooltip = function() {
+function get_changeset_tooltip() {
     var $target = $(this);
     var tooltip = $target.data('tooltip');
     if (!tooltip) {
@@ -499,12 +481,12 @@
         $target.data('tooltip', tooltip);
     }
     return tooltip;
-};
+}
 
 /**
  * activate tooltips and popups
  */
-var tooltip_activate = function(){
+function tooltip_activate(){
     function placement(p, e){
         if(e.getBoundingClientRect().top > 2*$(window).height()/3){
             return 'top';
@@ -529,63 +511,7 @@
             placement: placement
         });
     });
-};
-
-
-/**
- * Quick filter widget
- *
- * @param target: filter input target
- * @param nodes: list of nodes in html we want to filter.
- * @param display_element function that takes current node from nodes and
- *    does hide or show based on the node
- */
-var q_filter = (function() {
-    var _namespace = {};
-    var namespace = function (target) {
-        if (!(target in _namespace)) {
-            _namespace[target] = {};
-        }
-        return _namespace[target];
-    };
-    return function (target, $nodes, display_element) {
-        var $nodes = $nodes;
-        var $q_filter_field = $('#' + target);
-        var F = namespace(target);
-
-        $q_filter_field.keyup(function (e) {
-            clearTimeout(F.filterTimeout);
-            F.filterTimeout = setTimeout(F.updateFilter, 600);
-        });
-
-        F.filterTimeout = null;
-
-        F.updateFilter = function () {
-            // Reset timeout
-            F.filterTimeout = null;
-
-            var obsolete = [];
-
-            var req = $q_filter_field.val().toLowerCase();
-
-            var showing = 0;
-            $nodes.each(function () {
-                var n = this;
-                var target_element = display_element(n);
-                if (req && n.innerHTML.toLowerCase().indexOf(req) == -1) {
-                    $(target_element).hide();
-                }
-                else {
-                    $(target_element).show();
-                    showing += 1;
-                }
-            });
-
-            $('#repo_count').html(showing);
-            /* FIXME: don't hardcode */
-        }
-    }
-})();
+}
 
 
 /**
@@ -661,12 +587,13 @@
     var addlabel = TRANSLATION_MAP['Add Another Comment'];
     var $add = $('<div class="add-button-row"><span class="btn btn-default btn-xs add-button">{0}</span></div>'.format(addlabel));
     $comment_div.append($add);
-    $add.children('.add-button').click(function(e) {
+    $add.children('.add-button').click(function() {
         comment_div_state($comment_div, f_path, line_no, true);
     });
 }
 
 // append a comment form to $comment_div
+// Note: var AJAX_COMMENT_URL must have been defined before invoking this function
 function _comment_div_append_form($comment_div, f_path, line_no) {
     var $form_div = $('#comment-inline-form-template').children()
         .clone()
@@ -725,7 +652,7 @@
             'save_close': pr_close,
             'save_delete': pr_delete
         };
-        var success = function(json_data) {
+        function success(json_data) {
             if (pr_delete) {
                 location = json_data['location'];
             } else {
@@ -738,8 +665,8 @@
                     location.reload(true);
                 }
             }
-        };
-        var failure = function(x, s, e) {
+        }
+        function failure(x, s, e) {
             $preview.removeClass('submitting').addClass('failed');
             var $status = $preview.find('.comment-submission-status');
             $('<span>', {
@@ -764,12 +691,12 @@
                     comment_div_state($comment_div, f_path, line_no);
                 })
             ).appendTo($status);
-        };
+        }
         ajaxPOST(AJAX_COMMENT_URL, postData, success, failure);
     });
 
     // add event handler for hide/cancel buttons
-    $form.find('.hide-inline-form').click(function(e) {
+    $form.find('.hide-inline-form').click(function() {
         comment_div_state($comment_div, f_path, line_no);
     });
 
@@ -783,10 +710,11 @@
 }
 
 
+// Note: var AJAX_COMMENT_URL must have been defined before invoking this function
 function deleteComment(comment_id) {
     var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__', comment_id);
     var postData = {};
-    var success = function(o) {
+    function success() {
         $('#comment-'+comment_id).remove();
         // Ignore that this might leave a stray Add button (or have a pending form with another comment) ...
     }
@@ -797,7 +725,7 @@
 /**
  * Double link comments
  */
-var linkInlineComments = function($firstlinks, $comments){
+function linkInlineComments($firstlinks, $comments){
     if ($comments.length > 0) {
         $firstlinks.html('<a href="#{0}">First comment</a>'.format($comments.prop('id')));
     }
@@ -805,7 +733,7 @@
         return;
     }
 
-    $comments.each(function(i, e){
+    $comments.each(function(i){
             var prev = '';
             if (i > 0){
                 var prev_anchor = $($comments.get(i-1)).prop('id');
@@ -823,13 +751,13 @@
 }
 
 /* activate files.html stuff */
-var fileBrowserListeners = function(node_list_url, url_base){
+function fileBrowserListeners(node_list_url, url_base){
     var $node_filter = $('#node_filter');
 
     var filterTimeout = null;
     var nodes = null;
 
-    var initFilter = function(){
+    function initFilter(){
         $('#node_filter_box_loading').show();
         $('#search_activate_id').hide();
         $('#add_node_id').hide();
@@ -850,7 +778,7 @@
         ;
     }
 
-    var updateFilter = function(e) {
+    function updateFilter(e) {
         return function(){
             // Reset timeout
             filterTimeout = null;
@@ -897,7 +825,7 @@
                 $('#tbody_filtered').hide();
             }
         }
-    };
+    }
 
     $('#filter_activate').click(function(){
             initFilter();
@@ -912,10 +840,10 @@
             clearTimeout(filterTimeout);
             filterTimeout = setTimeout(updateFilter(e),600);
         });
-};
+}
 
 
-var initCodeMirror = function(textarea_id, baseUrl, resetUrl){
+function initCodeMirror(textarea_id, baseUrl, resetUrl){
     var myCodeMirror = CodeMirror.fromTextArea($('#' + textarea_id)[0], {
             mode: "null",
             lineNumbers: true,
@@ -924,7 +852,7 @@
         });
     CodeMirror.modeURL = baseUrl + "/codemirror/mode/%N/%N.js";
 
-    $('#reset').click(function(e){
+    $('#reset').click(function(){
             window.location=resetUrl;
         });
 
@@ -941,14 +869,14 @@
         });
 
     return myCodeMirror
-};
+}
 
-var setCodeMirrorMode = function(codeMirrorInstance, mode) {
+function setCodeMirrorMode(codeMirrorInstance, mode) {
     CodeMirror.autoLoadMode(codeMirrorInstance, mode);
 }
 
 
-var _getIdentNode = function(n){
+function _getIdentNode(n){
     //iterate thrugh nodes until matching interesting node
 
     if (typeof n == 'undefined'){
@@ -961,11 +889,11 @@
     else{
         return _getIdentNode(n.parentNode);
     }
-};
+}
 
 /* generate links for multi line selects that can be shown by files.html page_highlights.
  * This is a mouseup handler for hlcode from CodeHtmlFormatter and pygmentize */
-var getSelectionLink = function(e) {
+function getSelectionLink() {
     //get selection from start/to nodes
     if (typeof window.getSelection != "undefined") {
         var s = window.getSelection();
@@ -973,8 +901,8 @@
         var from = _getIdentNode(s.anchorNode);
         var till = _getIdentNode(s.focusNode);
 
-        var f_int = parseInt(from.id.replace('L',''));
-        var t_int = parseInt(till.id.replace('L',''));
+        //var f_int = parseInt(from.id.replace('L',''));
+        //var t_int = parseInt(till.id.replace('L',''));
 
         var yoffset = 35;
         var ranges = [parseInt(from.id.replace('L','')), parseInt(till.id.replace('L',''))];
@@ -1002,53 +930,15 @@
             $hl_div.hide();
         }
     }
-};
+}
 
 /**
  * Autocomplete functionality
  */
 
-// Custom search function for the DataSource of users
-var autocompleteMatchUsers = function (sQuery, myUsers) {
-    // Case insensitive matching
-    var query = sQuery.toLowerCase();
-    var i = 0;
-    var l = myUsers.length;
-    var matches = [];
-
-    // Match against each name of each contact
-    for (; i < l; i++) {
-        var contact = myUsers[i];
-        if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
-             ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
-             ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
-            matches[matches.length] = contact;
-        }
-    }
-    return matches;
-};
-
-// Custom search function for the DataSource of userGroups
-var autocompleteMatchGroups = function (sQuery, myGroups) {
-    // Case insensitive matching
-    var query = sQuery.toLowerCase();
-    var i = 0;
-    var l = myGroups.length;
-    var matches = [];
-
-    // Match against each name of each group
-    for (; i < l; i++) {
-        var matched_group = myGroups[i];
-        if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
-            matches[matches.length] = matched_group;
-        }
-    }
-    return matches;
-};
-
 // Highlight the snippet if it is found in the full text, while escaping any existing markup.
 // Snippet must be lowercased already.
-var autocompleteHighlightMatch = function (full, snippet) {
+function autocompleteHighlightMatch(full, snippet) {
     var matchindex = full.toLowerCase().indexOf(snippet);
     if (matchindex <0)
         return full.html_escape();
@@ -1057,10 +947,10 @@
         + full.substr(matchindex, snippet.length).html_escape()
         + '</span>'
         + full.substring(matchindex + snippet.length).html_escape();
-};
+}
 
 // Return html snippet for showing the provided gravatar url
-var gravatar = function(gravatar_lnk, size, cssclass) {
+function gravatar(gravatar_lnk, size, cssclass) {
     if (!gravatar_lnk) {
         return '';
     }
@@ -1072,7 +962,7 @@
             '></i>').format(size, gravatar_lnk, cssclass);
 }
 
-var autocompleteGravatar = function(res, gravatar_lnk, size, group) {
+function autocompleteGravatar(res, gravatar_lnk, size, group) {
     var elem;
     if (group !== undefined) {
         elem = '<i class="perm-gravatar-ac icon-users"></i>';
@@ -1083,7 +973,7 @@
 }
 
 // Custom formatter to highlight the matching letters and do HTML escaping
-var autocompleteFormatter = function (oResultData, sQuery, sResultMatch) {
+function autocompleteFormatter(oResultData, sQuery, sResultMatch) {
     var query;
     if (sQuery && sQuery.toLowerCase) // YAHOO AutoComplete
         query = sQuery.toLowerCase();
@@ -1113,9 +1003,9 @@
     }
 
     return '';
-};
+}
 
-var SimpleUserAutoComplete = function ($inputElement) {
+function SimpleUserAutoComplete($inputElement) {
     $inputElement.select2({
         formatInputTooShort: $inputElement.attr('placeholder'),
         initSelection : function (element, callback) {
@@ -1134,12 +1024,12 @@
         ajax: {
             url: pyroutes.url('users_and_groups_data'),
             dataType: 'json',
-            data: function(term, page){
+            data: function(term){
               return {
                 query: term
               };
             },
-            results: function (data, page){
+            results: function (data){
               return data;
             },
             cache: true
@@ -1150,7 +1040,7 @@
     });
 }
 
-var MembersAutoComplete = function ($inputElement, $typeElement) {
+function MembersAutoComplete($inputElement, $typeElement) {
 
     $inputElement.select2({
         placeholder: $inputElement.attr('placeholder'),
@@ -1158,13 +1048,13 @@
         ajax: {
             url: pyroutes.url('users_and_groups_data'),
             dataType: 'json',
-            data: function(term, page){
+            data: function(term){
               return {
                 query: term,
                 types: 'users,groups'
               };
             },
-            results: function (data, page){
+            results: function (data){
               return data;
             },
             cache: true
@@ -1178,7 +1068,7 @@
     });
 }
 
-var MentionsAutoComplete = function ($inputElement) {
+function MentionsAutoComplete($inputElement) {
   $inputElement.atwho({
     at: "@",
     callbacks: {
@@ -1194,7 +1084,7 @@
           }
         );
       },
-      sorter: function(query, items, searchKey) {
+      sorter: function(query, items) {
         return items;
       }
     },
@@ -1207,28 +1097,10 @@
     },
     insertTpl: "${atwho-at}${nname}"
   });
-};
-
-
-// Set caret at the given position in the input element
-function _setCaretPosition($inputElement, caretPos) {
-    $inputElement.each(function(){
-        if(this.createTextRange) { // IE
-            var range = this.createTextRange();
-            range.move('character', caretPos);
-            range.select();
-        }
-        else if(this.selectionStart) { // other recent browsers
-            this.focus();
-            this.setSelectionRange(caretPos, caretPos);
-        }
-        else // last resort - very old browser
-            this.focus();
-    });
 }
 
 
-var addReviewMember = function(id,fname,lname,nname,gravatar_link,gravatar_size){
+function addReviewMember(id,fname,lname,nname,gravatar_link,gravatar_size){
     var displayname = nname;
     if ((fname != "") && (lname != "")) {
         displayname = "{0} {1} ({2})".format(fname, lname, nname);
@@ -1265,7 +1137,7 @@
     }
 }
 
-var removeReviewMember = function(reviewer_id, repo_name, pull_request_id){
+function removeReviewMember(reviewer_id){
     var $li = $('#reviewer_{0}'.format(reviewer_id));
     $li.find('div div').css("text-decoration", "line-through");
     $li.find('input').prop('name', 'review_members_removed');
@@ -1273,7 +1145,7 @@
 }
 
 /* activate auto completion of users as PR reviewers */
-var PullRequestAutoComplete = function ($inputElement) {
+function PullRequestAutoComplete($inputElement) {
     $inputElement.select2(
     {
         placeholder: $inputElement.attr('placeholder'),
@@ -1281,12 +1153,12 @@
         ajax: {
             url: pyroutes.url('users_and_groups_data'),
             dataType: 'json',
-            data: function(term, page){
+            data: function(term){
               return {
                 query: term
               };
             },
-            results: function (data, page){
+            results: function (data){
               return data;
             },
             cache: true
@@ -1320,12 +1192,12 @@
 }
 
 function ajaxActionRevokePermission(url, obj_id, obj_type, field_id, extra_data) {
-    var success = function (o) {
+    function success() {
             $('#' + field_id).remove();
-        };
-    var failure = function (o) {
+        }
+    function failure(o) {
             alert(_TM['Failed to revoke permission'] + ": " + o.status);
-        };
+        }
     var query_params = {};
     // put extra data into POST
     if (extra_data !== undefined && (typeof extra_data === 'object')){
@@ -1344,11 +1216,11 @@
     }
 
     ajaxPOST(url, query_params, success, failure);
-};
+}
 
 /* Multi selectors */
 
-var MultiSelectWidget = function(selected_id, available_id, form_id){
+function MultiSelectWidget(selected_id, available_id, form_id){
     var $availableselect = $('#' + available_id);
     var $selectedselect = $('#' + selected_id);
 
@@ -1363,10 +1235,10 @@
             return false;
         }).remove();
 
-    $('#add_element').click(function(e){
+    $('#add_element').click(function(){
             $selectedselect.append($availableselect.children('option:selected'));
         });
-    $('#remove_element').click(function(e){
+    $('#remove_element').click(function(){
             $availableselect.append($selectedselect.children('option:selected'));
         });
 
@@ -1382,7 +1254,7 @@
  Branch Sorting callback for select2, modifying the filtered result so prefix
  matches come before matches in the line.
  **/
-var branchSort = function(results, container, query) {
+function branchSort(results, container, query) {
     if (query.term) {
         return results.sort(function (a, b) {
             // Put closed branches after open ones (a bit of a hack ...)
@@ -1416,9 +1288,9 @@
         });
     }
     return results;
-};
+}
 
-var prefixFirstSort = function(results, container, query) {
+function prefixFirstSort(results, container, query) {
     if (query.term) {
         return results.sort(function (a, b) {
             // if parent node, no sorting
@@ -1447,23 +1319,23 @@
         });
     }
     return results;
-};
+}
 
 /* Helper for jQuery DataTables */
 
-var updateRowCountCallback = function updateRowCountCallback($elem, onlyDisplayed) {
+function updateRowCountCallback($elem, onlyDisplayed) {
     return function drawCallback() {
         var info = this.api().page.info(),
             count = onlyDisplayed === true ? info.recordsDisplay : info.recordsTotal;
         $elem.html(count);
     }
-};
+}
 
 
 /**
  * activate changeset parent/child navigation links
  */
-var activate_parent_child_links = function(){
+function activate_parent_child_links(){
 
     $('.parent-child-link').on('click', function(e){
         var $this = $(this);
--- a/kallithea/public/js/codemirror_loadmode.js	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/public/js/codemirror_loadmode.js	Mon Apr 27 13:25:28 2020 +0200
@@ -1,3 +1,5 @@
+'use strict';
+
 (function() {
   var loading = {};
   function splitCallback(cont, n) {
@@ -8,13 +10,13 @@
     var deps = CodeMirror.modes[mode].dependencies;
     if (!deps) return cont();
     var missing = [];
-    for (var i = 0; i < deps.length; ++i) {
+    for (let i = 0; i < deps.length; ++i) {
       if (!CodeMirror.modes.hasOwnProperty(deps[i]))
         missing.push(deps[i]);
     }
     if (!missing.length) return cont();
     var split = splitCallback(cont, missing.length);
-    for (var i = 0; i < missing.length; ++i)
+    for (let i = 0; i < missing.length; ++i)
       CodeMirror.requireMode(missing[i], split);
   }
 
@@ -60,10 +62,11 @@
 
   CodeMirror.getFilenameAndExt = function(filename){
     var parts = filename.split('.');
+    var ext;
 
     if (parts.length > 1){
-        var ext = parts.pop();
-        var filename = parts.join("");
+        ext = parts.pop();
+        filename = parts.join("");
     }
     return {"filename": filename, "ext": ext};
   };
--- a/kallithea/public/js/graph.js	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/public/js/graph.js	Mon Apr 27 13:25:28 2020 +0200
@@ -1,3 +1,5 @@
+'use strict';
+
 // branch_renderer.js - Rendering of branch DAGs on the client side
 //
 // Copyright 2010 Marcin Kuzminski <marcin AT python-works DOT com>
@@ -32,7 +34,7 @@
 	if (!document.createElement("canvas").getContext)
 		this.canvas = window.G_vmlCanvasManager.initElement(this.canvas);
 	if (!this.canvas) { // canvas creation did for some reason fail - fail silently
-		this.render = function(data) {};
+		this.render = function() {};
 		return;
 	}
 	this.ctx = this.canvas.getContext('2d');
@@ -80,7 +82,7 @@
 		}
 
 		var lineCount = 1;
-		for (var i=0;i<data.length;i++) {
+		for (let i=0;i<data.length;i++) {
 			var in_l = data[i][1];
 			for (var j in in_l) {
 				var m = in_l[j][0];
@@ -93,7 +95,7 @@
 		var box_size = Math.min(18, (canvasWidth - edge_pad * 2) / lineCount);
 		var base_x = canvasWidth - edge_pad;
 
-		for (var i=0; i < data.length; ++i) {
+		for (let i=0; i < data.length; ++i) {
 			var row = document.getElementById(row_id_prefix+idx);
 			if (row == null) {
 				console.log("error: row "+row_id_prefix+idx+" not found");
@@ -102,15 +104,15 @@
 			var next = document.getElementById(row_id_prefix+(idx+1));
 			var extra = 0;
 
-			cur = data[i];
-			node = cur[0];
-			in_l = cur[1];
-			closing = cur[2];
-			obsolete_node = cur[3];
-			bumped_node = cur[4];
-			divergent_node = cur[5];
-			extinct_node = cur[6];
-			unstable_node = cur[7];
+			const cur = data[i];
+			const node = cur[0];
+			const in_l = cur[1];
+			const closing = cur[2];
+			const obsolete_node = cur[3];
+			//const bumped_node = cur[4];
+			//const divergent_node = cur[5];
+			//const extinct_node = cur[6];
+			const unstable_node = cur[7];
 
 			// center dots on the first element in a td (not necessarily the first one, but there must be one)
 			var firstincell = $(row).find('td>*:visible')[0];
@@ -118,21 +120,21 @@
 			var rowY = Math.floor(row.offsetTop + firstincell.offsetTop + firstincell.offsetHeight/2);
 			var nextY = Math.floor((next == null) ? rowY + row.offsetHeight/2 : next.offsetTop + nextFirstincell.offsetTop + nextFirstincell.offsetHeight/2);
 
-			for (var j in in_l) {
-				line = in_l[j];
-				start = line[0];
-				end = line[1];
-				color = line[2];
-				obsolete_line = line[3];
+			for (let j in in_l) {
+				const line = in_l[j];
+				const start = line[0];
+				const end = line[1];
+				const color = line[2];
+				const obsolete_line = line[3];
 
-				x = Math.floor(base_x - box_size * start);
+				const x = Math.floor(base_x - box_size * start);
 
 				// figure out if this is a dead-end;
 				// we want to fade away this line
 				var dead_end = true;
 				if (next != null) {
-					nextdata = data[i+1];
-					next_l = nextdata[1];
+					const nextdata = data[i+1];
+					const next_l = nextdata[1];
 					for (var k=0; k < next_l.length; ++k) {
 						if (next_l[k][0] == end) {
 							dead_end = false;
@@ -144,7 +146,7 @@
 				}
 
 				if (dead_end) {
-					var gradient = this.ctx.createLinearGradient(x,rowY,x,nextY);
+					let gradient = this.ctx.createLinearGradient(x,rowY,x,nextY);
 					gradient.addColorStop(0,this.calcColor(color, 0.0, 0.65));
 					gradient.addColorStop(1,this.calcColor(color, 1.0, 0.0));
 					this.ctx.strokeStyle = gradient;
@@ -155,7 +157,7 @@
 				// the merged color
 				else if (color != node[1] && start == node[0])
 				{
-					var gradient = this.ctx.createLinearGradient(x,rowY,x,nextY);
+					let gradient = this.ctx.createLinearGradient(x,rowY,x,nextY);
 					gradient.addColorStop(0,this.calcColor(node[1], 0.0, 0.65));
 					gradient.addColorStop(1,this.calcColor(color, 0.0, 0.65));
 					this.ctx.strokeStyle = gradient;
@@ -192,10 +194,10 @@
 				this.ctx.setLineDash([]); // reset the dashed line, if any
 			}
 
-			column = node[0];
-			color = node[1];
+			const column = node[0];
+			const color = node[1];
 
-			x = Math.floor(base_x - box_size * column);
+			const x = Math.floor(base_x - box_size * column);
 
 			this.setColor(color, 0.25, 0.75);
 			if(unstable_node)
@@ -203,7 +205,7 @@
 				this.ctx.fillStyle = 'rgb(255, 0, 0)';
 			}
 
-			r = this.dot_radius
+			let r = this.dot_radius
 			if (obsolete_node)
 			{
 				this.ctx.beginPath();
--- a/kallithea/public/js/mergely.js	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/public/js/mergely.js	Mon Apr 27 13:25:28 2020 +0200
@@ -699,7 +699,7 @@
 		// resize
 		if (this.settings.autoresize) {
 			var sz_timeout1 = null;
-			var sz = function(init) {
+			function sz(init) {
 				//self.em_height = null; //recalculate
 				if (self.settings.resize) self.settings.resize(init);
 				self.editor[self.id + '-lhs'].refresh();
@@ -854,7 +854,7 @@
 	_clear: function() {
 		var self = this, name, editor, fns, timer, i, change, l;
 
-		var clear_changes = function() {
+		function clear_changes() {
 			timer = new Mgly.Timer();
 			for (i = 0, l = editor.lineCount(); i < l; ++i) {
 				editor.removeLineClass(i, 'background');
--- a/kallithea/templates/admin/admin.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/admin.html	Mon Apr 27 13:25:28 2020 +0200
@@ -27,7 +27,7 @@
     </div>
 </div>
 
-<script>
+<script>'use strict';
 $(document).ready(function() {
   $('#j_filter').click(function(){
     var $jfilter = $('#j_filter');
@@ -35,9 +35,9 @@
         $jfilter.val('');
     }
   });
-  var fix_j_filter_width = function(len){
+  function fix_j_filter_width(len){
       $('#j_filter').css('width', Math.max(80, len*6.50)+'px');
-  };
+  }
   $('#j_filter').keyup(function () {
     fix_j_filter_width($('#j_filter').val().length);
   });
--- a/kallithea/templates/admin/admin_log.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/admin_log.html	Mon Apr 27 13:25:28 2020 +0200
@@ -37,7 +37,7 @@
     %endfor
 </table>
 
-<script type="text/javascript">
+<script>'use strict';
   $(document).ready(function(){
     var $user_log = $('#user_log');
     $user_log.on('click','.pager_link',function(e){
--- a/kallithea/templates/admin/auth/auth_settings.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/auth/auth_settings.html	Mon Apr 27 13:25:28 2020 +0200
@@ -105,10 +105,10 @@
     </div>
 </div>
 
-<script>
+<script>'use strict';
     $('.toggle-plugin').click(function(e){
         var $auth_plugins_input = $('#auth_plugins');
-        var notEmpty = function(element, index, array) {
+        function notEmpty(element) {
             return (element != "");
         }
         var elems = $auth_plugins_input.val().split(',').filter(notEmpty);
--- a/kallithea/templates/admin/gists/edit.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/gists/edit.html	Mon Apr 27 13:25:28 2020 +0200
@@ -6,9 +6,9 @@
 </%block>
 
 <%block name="js_extra">
-  <script type="text/javascript" src="${h.url('/codemirror/lib/codemirror.js')}"></script>
-  <script type="text/javascript" src="${h.url('/js/codemirror_loadmode.js')}"></script>
-  <script type="text/javascript" src="${h.url('/codemirror/mode/meta.js')}"></script>
+  <script src="${h.url('/codemirror/lib/codemirror.js')}"></script>
+  <script src="${h.url('/js/codemirror_loadmode.js')}"></script>
+  <script src="${h.url('/codemirror/mode/meta.js')}"></script>
 </%block>
 <%block name="css_extra">
   <link rel="stylesheet" type="text/css" href="${h.url('/codemirror/lib/codemirror.css')}"/>
@@ -35,7 +35,7 @@
               ${(h.HTML(_('Gist was updated since you started editing. Copy your changes and click %(here)s to reload new version.'))
                              % {'here': h.link_to(_('here'),h.url('edit_gist', gist_id=c.gist.gist_access_id))})}
             </div>
-            <script>
+            <script>'use strict';
             if (typeof jQuery != 'undefined') {
                 $(".alert").alert();
             }
@@ -79,7 +79,7 @@
                 </div>
 
                 ## dynamic edit box.
-                <script type="text/javascript">
+                <script>'use strict';
                     $(document).ready(function(){
                         var myCodeMirror = initCodeMirror(${h.js('editor_' + h.FID('f',file.path))}, ${h.jshtml(request.script_name)}, '');
 
@@ -117,7 +117,7 @@
                         });
 
                         // on type the new filename set mode
-                        $filename_input.keyup(function(e){
+                        $filename_input.keyup(function(){
                             var file_data = CodeMirror.getFilenameAndExt(this.value);
                             if(file_data['ext'] != null){
                                 var detected_mode = CodeMirror.findModeByExtension(file_data['ext']) || CodeMirror.findModeByMIME('text/plain');
@@ -146,7 +146,7 @@
             <a class="btn btn-default" href="${h.url('gist', gist_id=c.gist.gist_access_id)}">${_('Cancel')}</a>
             </div>
           ${h.end_form()}
-          <script>
+          <script>'use strict';
               $('#update').on('click', function(e){
                   e.preventDefault();
 
--- a/kallithea/templates/admin/gists/new.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/gists/new.html	Mon Apr 27 13:25:28 2020 +0200
@@ -6,9 +6,9 @@
 </%block>
 
 <%block name="js_extra">
-  <script type="text/javascript" src="${h.url('/codemirror/lib/codemirror.js')}"></script>
-  <script type="text/javascript" src="${h.url('/js/codemirror_loadmode.js')}"></script>
-  <script type="text/javascript" src="${h.url('/codemirror/mode/meta.js')}"></script>
+  <script src="${h.url('/codemirror/lib/codemirror.js')}"></script>
+  <script src="${h.url('/js/codemirror_loadmode.js')}"></script>
+  <script src="${h.url('/codemirror/mode/meta.js')}"></script>
 </%block>
 <%block name="css_extra">
   <link rel="stylesheet" type="text/css" href="${h.url('/codemirror/lib/codemirror.css')}"/>
@@ -55,7 +55,7 @@
             ${h.reset('reset',_('Reset'),class_="btn btn-default btn-xs")}
             </div>
           ${h.end_form()}
-          <script type="text/javascript">
+          <script>'use strict';
             $(document).ready(function(){
                 var myCodeMirror = initCodeMirror('editor', ${h.jshtml(request.script_name)}, '');
 
@@ -93,7 +93,7 @@
                 });
 
                 // on type the new filename set mode
-                $filename_input.keyup(function(e){
+                $filename_input.keyup(function(){
                     var file_data = CodeMirror.getFilenameAndExt(this.value);
                     if(file_data['ext'] != null){
                         var detected_mode = CodeMirror.findModeByExtension(file_data['ext']) || CodeMirror.findModeByMIME('text/plain');
--- a/kallithea/templates/admin/my_account/my_account_api_keys.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/my_account/my_account_api_keys.html	Mon Apr 27 13:25:28 2020 +0200
@@ -90,7 +90,7 @@
 ''')}</p>
 </div>
 
-<script>
+<script>'use strict';
     $(document).ready(function(){
         $("#lifetime").select2({
             'dropdownAutoWidth': true
--- a/kallithea/templates/admin/my_account/my_account_repos.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/my_account/my_account_repos.html	Mon Apr 27 13:25:28 2020 +0200
@@ -4,9 +4,9 @@
     <table class="table" id="datatable_list_wrap" width="100%"></table>
 </div>
 
-<script>
+<script>'use strict';
   var data = ${h.js(c.data)};
-  var myDataTable = $("#datatable_list_wrap").DataTable({
+  $("#datatable_list_wrap").DataTable({
         data: data.records,
         columns: [
             {data: "raw_name", "visible": false, searchable: false},
--- a/kallithea/templates/admin/my_account/my_account_watched.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/my_account/my_account_watched.html	Mon Apr 27 13:25:28 2020 +0200
@@ -4,9 +4,9 @@
     <table class="table" id="datatable_list_wrap" width="100%"></table>
 </div>
 
-<script>
+<script>'use strict';
   var data = ${h.js(c.data)};
-  var myDataTable = $("#datatable_list_wrap").DataTable({
+  $("#datatable_list_wrap").DataTable({
         data: data.records,
         columns: [
             {data: "raw_name", "visible": false, searchable: false},
--- a/kallithea/templates/admin/repo_groups/repo_group_add.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/repo_groups/repo_group_add.html	Mon Apr 27 13:25:28 2020 +0200
@@ -61,9 +61,9 @@
     </div>
     ${h.end_form()}
 </div>
-<script>
+<script>'use strict';
     $(document).ready(function(){
-        var setCopyPermsOption = function(group_val){
+        function setCopyPermsOption(group_val){
             if(group_val != "-1"){
                 $('#copy_perms').show();
             }
--- a/kallithea/templates/admin/repo_groups/repo_group_edit_perms.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/repo_groups/repo_group_edit_perms.html	Mon Apr 27 13:25:28 2020 +0200
@@ -102,15 +102,15 @@
 </div>
 ${h.end_form()}
 
-<script type="text/javascript">
+<script>'use strict';
     function ajaxActionRevoke(obj_id, obj_type, field_id, obj_name) {
-        url = ${h.jshtml(h.url('edit_repo_group_perms_delete', group_name=c.repo_group.group_name))};
+        let url = ${h.jshtml(h.url('edit_repo_group_perms_delete', group_name=c.repo_group.group_name))};
         var revoke_msg = _TM['Confirm to revoke permission for {0}: {1} ?'].format(obj_type.replace('_', ' '), obj_name);
         if (confirm(revoke_msg)){
             var recursive = $('input[name=recursive]:checked').val();
             ajaxActionRevokePermission(url, obj_id, obj_type, field_id, {recursive:recursive});
         }
-    };
+    }
 
     $(document).ready(function () {
         if (!$('#perm_new_member_name').hasClass('error')) {
--- a/kallithea/templates/admin/repo_groups/repo_group_edit_settings.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/repo_groups/repo_group_edit_settings.html	Mon Apr 27 13:25:28 2020 +0200
@@ -41,7 +41,7 @@
 </div>
 ${h.end_form()}
 
-<script>
+<script>'use strict';
     $(document).ready(function(){
         $("#parent_group_id").select2({
             'dropdownAutoWidth': true
--- a/kallithea/templates/admin/repo_groups/repo_groups.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/repo_groups/repo_groups.html	Mon Apr 27 13:25:28 2020 +0200
@@ -30,9 +30,9 @@
         <table class="table" id="datatable_list_wrap" width="100%"></table>
     </div>
 </div>
-<script>
+<script>'use strict';
   var data = ${h.js(c.data)};
-  var myDataTable = $("#datatable_list_wrap").DataTable({
+  $("#datatable_list_wrap").DataTable({
         data: data.records,
         columns: [
             {data: "raw_name", visible: false, searchable: false},
--- a/kallithea/templates/admin/repos/repo_add_base.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/repos/repo_add_base.html	Mon Apr 27 13:25:28 2020 +0200
@@ -65,9 +65,9 @@
             </div>
         </div>
 </div>
-<script>
+<script>'use strict';
     $(document).ready(function(){
-        var setCopyPermsOption = function(group_val){
+        function setCopyPermsOption(group_val){
             if(group_val != "-1"){
                 $('#copy_perms').show();
             }
--- a/kallithea/templates/admin/repos/repo_creating.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/repos/repo_creating.html	Mon Apr 27 13:25:28 2020 +0200
@@ -42,7 +42,7 @@
     </div>
 </div>
 
-<script>
+<script>'use strict';
 (function worker() {
   $.ajax({
     url: ${h.js(h.url('repo_check_home', repo_name=c.repo_name, repo=c.repo, task_id=c.task_id))},
@@ -52,7 +52,7 @@
           window.location = ${h.js(h.url('summary_home', repo_name = c.repo))};
       }
     },
-    complete: function(resp, status) {
+    complete: function(resp) {
       if (resp.status == 200){
           // Schedule the next request when the current one's complete
           setTimeout(worker, 1000);
--- a/kallithea/templates/admin/repos/repo_edit.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/repos/repo_edit.html	Mon Apr 27 13:25:28 2020 +0200
@@ -33,9 +33,6 @@
           <li class="${'active' if c.active=='fields' else ''}">
               <a href="${h.url('edit_repo_fields', repo_name=c.repo_name)}">${_('Extra Fields')}</a>
           </li>
-          <li class="${'active' if c.active=='caches' else ''}">
-              <a href="${h.url('edit_repo_caches', repo_name=c.repo_name)}">${_('Caches')}</a>
-          </li>
           <li class="${'active' if c.active=='remote' else ''}">
               <a href="${h.url('edit_repo_remote', repo_name=c.repo_name)}">${_('Remote')}</a>
           </li>
--- a/kallithea/templates/admin/repos/repo_edit_advanced.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/repos/repo_edit_advanced.html	Mon Apr 27 13:25:28 2020 +0200
@@ -9,7 +9,7 @@
 </div>
 ${h.end_form()}
 
-<script>
+<script>'use strict';
     $(document).ready(function(){
         $("#id_fork_of").select2({
             'dropdownAutoWidth': true
--- a/kallithea/templates/admin/repos/repo_edit_caches.html	Mon Apr 13 21:40:33 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-${h.form(url('update_repo_caches', repo_name=c.repo_name))}
-<div class="form">
-   <div>
-       ${h.submit('reset_cache_%s' % c.repo_info.repo_name,_('Invalidate Repository Cache'),class_="btn btn-default btn-sm")}
-      <div class="text-muted">
-        ${_('Manually invalidate cache for this repository. On first access, the repository will be cached again.')}
-      </div>
-      <div>
-        <h5>${_('List of Cached Values')}</h5>
-        <table class="table">
-          <tr>
-            <th>${_('Prefix')}</th>
-            <th>${_('Key')}</th>
-            <th>${_('Active')}</th>
-          </tr>
-          %for cache in c.repo_info.cache_keys:
-              <tr>
-                <td>${cache.get_prefix() or '-'}</td>
-                <td>${cache.cache_key}</td>
-                <td>${h.boolicon(cache.cache_active)}</td>
-              </tr>
-          %endfor
-        </table>
-      </div>
-   </div>
-</div>
-${h.end_form()}
--- a/kallithea/templates/admin/repos/repo_edit_permissions.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/repos/repo_edit_permissions.html	Mon Apr 27 13:25:28 2020 +0200
@@ -12,7 +12,7 @@
                     <td></td>
                 </tr>
                 ## USERS
-                %for r2p in sorted(c.repo_info.repo_to_perm, key=lambda x: x.user.username != 'default' and x.user.username):
+                %for r2p in sorted(c.repo_info.repo_to_perm, key=lambda x: '' if x.user.username == 'default' else x.user.username):
                     %if r2p.user.username =='default' and c.repo_info.private:
                         <tr>
                             <td colspan="4">
@@ -87,14 +87,14 @@
 </div>
 ${h.end_form()}
 
-<script type="text/javascript">
+<script>'use strict';
     function ajaxActionRevoke(obj_id, obj_type, field_id, obj_name) {
-        url = ${h.js(h.url('edit_repo_perms_revoke',repo_name=c.repo_name))};
+        let url = ${h.js(h.url('edit_repo_perms_revoke',repo_name=c.repo_name))};
         var revoke_msg = _TM['Confirm to revoke permission for {0}: {1} ?'].format(obj_type.replace('_', ' '), obj_name);
         if (confirm(revoke_msg)){
             ajaxActionRevokePermission(url, obj_id, obj_type, field_id);
         }
-    };
+    }
 
     $(document).ready(function () {
         if (!$('#perm_new_member_name').hasClass('error')) {
--- a/kallithea/templates/admin/repos/repo_edit_settings.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/repos/repo_edit_settings.html	Mon Apr 27 13:25:28 2020 +0200
@@ -103,7 +103,7 @@
     </div>
     ${h.end_form()}
 
-<script>
+<script>'use strict';
     $(document).ready(function(){
         $('#repo_landing_rev').select2({
             'dropdownAutoWidth': true
--- a/kallithea/templates/admin/repos/repos.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/repos/repos.html	Mon Apr 27 13:25:28 2020 +0200
@@ -29,9 +29,9 @@
     </div>
 
 </div>
-<script>
+<script>'use strict';
   var data = ${h.js(c.data)};
-  var myDataTable = $("#datatable_list_wrap").DataTable({
+  $("#datatable_list_wrap").DataTable({
         data: data.records,
         columns: [
             {data: "raw_name", visible: false, searchable: false},
--- a/kallithea/templates/admin/settings/settings_hooks.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/settings/settings_hooks.html	Mon Apr 27 13:25:28 2020 +0200
@@ -50,16 +50,16 @@
 ${h.end_form()}
 % endif
 
-<script type="text/javascript">
+<script>'use strict';
 function delete_hook(hook_id, field_id) {
     var sUrl = ${h.js(h.url('admin_settings_hooks_delete'))};
-    var success = function (o) {
+    function success() {
             $('#' + field_id).remove();
-        };
-    var failure = function (o) {
+        }
+    function failure() {
             alert(${h.js(_('Failed to remove hook'))});
-        };
+        }
     var postData = {'hook_id': hook_id};
     ajaxPOST(sUrl, postData, success, failure);
-};
+}
 </script>
--- a/kallithea/templates/admin/settings/settings_vcs.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/settings/settings_vcs.html	Mon Apr 27 13:25:28 2020 +0200
@@ -69,9 +69,9 @@
     </div>
     ${h.end_form()}
 
-    <script type="text/javascript">
+    <script>'use strict';
         $(document).ready(function(){
-            $('#path_unlock').on('click', function(e){
+            $('#path_unlock').on('click', function(){
                 $('#path_unlock_icon').removeClass('icon-lock');
                 $('#path_unlock_icon').addClass('icon-lock-open-alt');
                 $('#paths_root_path').removeAttr('readonly');
--- a/kallithea/templates/admin/user_groups/user_group_add.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/user_groups/user_group_add.html	Mon Apr 27 13:25:28 2020 +0200
@@ -52,7 +52,7 @@
     ${h.end_form()}
 </div>
 
-<script>
+<script>'use strict';
     $(document).ready(function(){
         $('#users_group_name').focus();
     });
--- a/kallithea/templates/admin/user_groups/user_group_edit_perms.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/user_groups/user_group_edit_perms.html	Mon Apr 27 13:25:28 2020 +0200
@@ -92,14 +92,14 @@
 </div>
 ${h.end_form()}
 
-<script type="text/javascript">
+<script>'use strict';
     function ajaxActionRevoke(obj_id, obj_type, field_id, obj_name) {
-        url = ${h.js(h.url('edit_user_group_perms_delete', id=c.user_group.users_group_id))};
+        let url = ${h.js(h.url('edit_user_group_perms_delete', id=c.user_group.users_group_id))};
         var revoke_msg = _TM['Confirm to revoke permission for {0}: {1} ?'].format(obj_type.replace('_', ' '), obj_name);
         if (confirm(revoke_msg)){
             ajaxActionRevokePermission(url, obj_id, obj_type, field_id);
         }
-    };
+    }
 
     $(document).ready(function () {
         if (!$('#perm_new_member_name').hasClass('error')) {
--- a/kallithea/templates/admin/user_groups/user_group_edit_settings.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/user_groups/user_group_edit_settings.html	Mon Apr 27 13:25:28 2020 +0200
@@ -48,6 +48,6 @@
                 </div>
     </div>
 ${h.end_form()}
-<script type="text/javascript">
+<script>'use strict';
   MultiSelectWidget('users_group_members','available_members','edit_users_group');
 </script>
--- a/kallithea/templates/admin/user_groups/user_groups.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/user_groups/user_groups.html	Mon Apr 27 13:25:28 2020 +0200
@@ -29,9 +29,9 @@
         <table class="table" id="datatable_list_wrap" width="100%"></table>
     </div>
 </div>
-<script>
+<script>'use strict';
     var data = ${h.js(c.data)};
-    var $dataTable = $("#datatable_list_wrap").DataTable({
+    $("#datatable_list_wrap").DataTable({
         data: data.records,
         columns: [
             {data: "raw_name", visible: false, searchable: false},
--- a/kallithea/templates/admin/users/user_add.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/users/user_add.html	Mon Apr 27 13:25:28 2020 +0200
@@ -84,7 +84,7 @@
     ${h.end_form()}
 </div>
 
-<script>
+<script>'use strict';
     $(document).ready(function(){
         $('#username').focus();
     });
--- a/kallithea/templates/admin/users/user_edit_api_keys.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/users/user_edit_api_keys.html	Mon Apr 27 13:25:28 2020 +0200
@@ -77,7 +77,7 @@
     ${h.end_form()}
 </div>
 
-<script>
+<script>'use strict';
     $(document).ready(function(){
         $("#lifetime").select2({
             'dropdownAutoWidth': true
--- a/kallithea/templates/admin/users/users.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/admin/users/users.html	Mon Apr 27 13:25:28 2020 +0200
@@ -28,9 +28,9 @@
     </div>
 </div>
 
-<script>
+<script>'use strict';
     var data = ${h.js(c.data)};
-    var $dataTable = $("#datatable_list_wrap").DataTable({
+    $("#datatable_list_wrap").DataTable({
         data: data.records,
         columns: [
             {data: "gravatar", sortable: false, searchable: false},
--- a/kallithea/templates/base/base.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/base/base.html	Mon Apr 27 13:25:28 2020 +0200
@@ -163,12 +163,12 @@
               ## also it feels like a job for the controller
               %if request.authuser.username != 'default':
                   <li>
-                   <a href="#" class="${'following' if c.repository_following else 'follow'}" onclick="toggleFollowingRepo(this, ${c.db_repo.repo_id});">
+                   <a href="#" class="${'following' if c.repository_following else 'follow'}" onclick="return toggleFollowingRepo(this, ${c.db_repo.repo_id});">
                     <span class="show-follow"><i class="icon-heart-empty"></i>${_('Follow')}</span>
                     <span class="show-following"><i class="icon-heart"></i>${_('Unfollow')}</span>
                    </a>
                   </li>
-                  <li><a href="${h.url('repo_fork_home',repo_name=c.repo_name)}"><i class="icon-git-pull-request"></i>${_('Fork')}</a></li>
+                  <li><a href="${h.url('repo_fork_home',repo_name=c.repo_name)}"><i class="icon-fork"></i>${_('Fork')}</a></li>
                   <li><a href="${h.url('pullrequest_home',repo_name=c.repo_name)}"><i class="icon-git-pull-request"></i>${_('Create Pull Request')}</a></li>
               %endif
              </ul>
@@ -177,7 +177,7 @@
     </div>
     </div>
   </nav>
-  <script type="text/javascript">
+  <script>'use strict';
     $(document).ready(function() {
       var bcache = {};
 
@@ -192,7 +192,7 @@
           formatSelection: function(obj) {
               return obj.text.html_escape();
           },
-          formatNoMatches: function(term) {
+          formatNoMatches: function() {
               return ${h.jshtml(_('No matches found'))};
           },
           escapeMarkup: function(m) {
@@ -399,12 +399,12 @@
     </li>
   </ul>
 
-    <script type="text/javascript">
+    <script>'use strict';
         $(document).ready(function(){
             var visual_show_public_icon = ${h.js(c.visual.show_public_icon)};
             var cache = {}
             /*format the look of items in the list*/
-            var format = function(state){
+            function format(state){
                 if (!state.id){
                   return state.text.html_escape(); // optgroup
                 }
@@ -441,7 +441,7 @@
                 sortResults: prefixFirstSort,
                 formatResult: format,
                 formatSelection: format,
-                formatNoMatches: function(term){
+                formatNoMatches: function(){
                     return ${h.jshtml(_('No matches found'))};
                 },
                 containerCssClass: "repo-switcher",
@@ -527,7 +527,7 @@
         </div>
     </div>
 
-    <script type="text/javascript">
+    <script>'use strict';
       $(document).ready(function(){
           activate_parent_child_links();
       });
--- a/kallithea/templates/base/flash_msg.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/base/flash_msg.html	Mon Apr 27 13:25:28 2020 +0200
@@ -9,7 +9,7 @@
             </div>
         % endfor
     % endif
-    <script>
+    <script>'use strict';
     if (typeof jQuery != 'undefined') {
         $(".alert").alert();
     }
--- a/kallithea/templates/base/perms_summary.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/base/perms_summary.html	Mon Apr 27 13:25:28 2020 +0200
@@ -97,9 +97,9 @@
         %endif
      %endfor
 </div>
-<script>
+<script>'use strict';
     $(document).ready(function(){
-        var show_empty = function(section){
+        function show_empty(section){
             var visible = $('.section_{0} tr.perm_row:visible'.format(section)).length;
             if(visible == 0){
                 $('#empty_{0}'.format(section)).show();
@@ -108,10 +108,10 @@
                 $('#empty_{0}'.format(section)).hide();
             }
         }
-        var update_show = function($checkbox){
+        function update_show($checkbox){
             var section = $checkbox.data('section');
 
-            var elems = $('.filter_' + section).each(function(el){
+            $('.filter_' + section).each(function(){
                 var perm_type = $checkbox.data('perm_type');
                 var checked = $checkbox.prop('checked');
                 if(checked){
--- a/kallithea/templates/base/root.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/base/root.html	Mon Apr 27 13:25:28 2020 +0200
@@ -21,7 +21,7 @@
         <%block name="css_extra"/>
 
         ## JAVASCRIPT ##
-        <script type="text/javascript">
+        <script>'use strict';
             ## JS translations map
             var TRANSLATION_MAP = {
                 'Cancel': ${h.jshtml(_("Cancel"))},
@@ -58,7 +58,7 @@
             };
             var _TM = TRANSLATION_MAP;
 
-            var TOGGLE_FOLLOW_URL  = ${h.js(h.url('toggle_following'))};
+            var TOGGLE_FOLLOW_URL = ${h.js(h.url('toggle_following'))};
 
             var REPO_NAME = "";
             %if hasattr(c, 'repo_name'):
@@ -67,17 +67,17 @@
 
             var _session_csrf_secret_token = ${h.js(h.session_csrf_secret_token())};
         </script>
-        <script type="text/javascript" src="${h.url('/js/jquery.min.js', ver=c.kallithea_version)}"></script>
-        <script type="text/javascript" src="${h.url('/js/jquery.dataTables.js', ver=c.kallithea_version)}"></script>
-        <script type="text/javascript" src="${h.url('/js/dataTables.bootstrap.js', ver=c.kallithea_version)}"></script>
-        <script type="text/javascript" src="${h.url('/js/bootstrap.js', ver=c.kallithea_version)}"></script>
-        <script type="text/javascript" src="${h.url('/js/select2.js', ver=c.kallithea_version)}"></script>
-        <script type="text/javascript" src="${h.url('/js/jquery.caret.min.js', ver=c.kallithea_version)}"></script>
-        <script type="text/javascript" src="${h.url('/js/jquery.atwho.min.js', ver=c.kallithea_version)}"></script>
-        <script type="text/javascript" src="${h.url('/js/base.js', ver=c.kallithea_version)}"></script>
+        <script src="${h.url('/js/jquery.min.js', ver=c.kallithea_version)}"></script>
+        <script src="${h.url('/js/jquery.dataTables.js', ver=c.kallithea_version)}"></script>
+        <script src="${h.url('/js/dataTables.bootstrap.js', ver=c.kallithea_version)}"></script>
+        <script src="${h.url('/js/bootstrap.js', ver=c.kallithea_version)}"></script>
+        <script src="${h.url('/js/select2.js', ver=c.kallithea_version)}"></script>
+        <script src="${h.url('/js/jquery.caret.min.js', ver=c.kallithea_version)}"></script>
+        <script src="${h.url('/js/jquery.atwho.min.js', ver=c.kallithea_version)}"></script>
+        <script src="${h.url('/js/base.js', ver=c.kallithea_version)}"></script>
         ## EXTRA FOR JS
         <%block name="js_extra"/>
-        <script type="text/javascript">
+        <script>'use strict';
             $(document).ready(function(){
               tooltip_activate();
               show_more_event();
--- a/kallithea/templates/changelog/changelog.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/changelog/changelog.html	Mon Apr 27 13:25:28 2020 +0200
@@ -80,8 +80,8 @@
 
                 ${c.cs_pagination.pager()}
 
-        <script type="text/javascript" src="${h.url('/js/graph.js', ver=c.kallithea_version)}"></script>
-        <script type="text/javascript">
+        <script src="${h.url('/js/graph.js', ver=c.kallithea_version)}"></script>
+        <script>'use strict';
             var jsdata = ${h.js(c.jsdata)};
             var graph = new BranchRenderer('graph_canvas', 'graph_content', 'chg_');
 
@@ -90,7 +90,7 @@
 
                 pyroutes.register('changeset_home', ${h.js(h.url('changeset_home', repo_name='%(repo_name)s', revision='%(revision)s'))}, ['repo_name', 'revision']);
 
-                var checkbox_checker = function(e) {
+                function checkbox_checker() {
                     var $checked_checkboxes = $checkboxes.filter(':checked');
                     var $singlerange = $('#singlerange');
 
@@ -163,7 +163,7 @@
                         $('#compare_fork').show();
                         $checkboxes.closest('tr').removeClass('out-of-range');
                     }
-                };
+                }
                 checkbox_checker();
                 $checkboxes.click(function() {
                     checkbox_checker();
@@ -171,7 +171,7 @@
                 });
                 $('#singlerange').click(checkbox_checker);
 
-                $('#rev_range_clear').click(function(e){
+                $('#rev_range_clear').click(function(){
                     $checkboxes.prop('checked', false);
                     checkbox_checker();
                     graph.render(jsdata);
--- a/kallithea/templates/changelog/changelog_table.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/changelog/changelog_table.html	Mon Apr 27 13:25:28 2020 +0200
@@ -110,9 +110,9 @@
     </tbody>
     </table>
 
-<script type="text/javascript">
+<script>'use strict';
   $(document).ready(function() {
-    $('#changesets .expand_commit').on('click',function(e){
+    $('#changesets .expand_commit').on('click',function(){
       $(this).next('.mid').find('.message > div').toggleClass('hidden');
       ${resize_js};
     });
--- a/kallithea/templates/changeset/changeset.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/changeset/changeset.html	Mon Apr 27 13:25:28 2020 +0200
@@ -22,9 +22,9 @@
   <div class="panel-heading clearfix">
     ${self.breadcrumbs()}
   </div>
-  <script>
-    AJAX_COMMENT_URL = ${h.js(url('changeset_comment',repo_name=c.repo_name,revision=c.changeset.raw_id))};
-    AJAX_COMMENT_DELETE_URL = ${h.js(url('changeset_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__'))};
+  <script>'use strict';
+    var AJAX_COMMENT_URL = ${h.js(url('changeset_comment',repo_name=c.repo_name,revision=c.changeset.raw_id))};
+    var AJAX_COMMENT_DELETE_URL = ${h.js(url('changeset_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__'))};
   </script>
   <div class="panel-body">
     <div class="panel panel-default">
@@ -184,9 +184,9 @@
     </div>
 
     ## FORM FOR MAKING JS ACTION AS CHANGESET COMMENTS
-    <script type="text/javascript">
+    <script>'use strict';
       $(document).ready(function(){
-          $('.code-difftable').on('click', '.add-bubble', function(e){
+          $('.code-difftable').on('click', '.add-bubble', function(){
               show_comment_form($(this));
           });
 
--- a/kallithea/templates/changeset/changeset_file_comment.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/changeset/changeset_file_comment.html	Mon Apr 27 13:25:28 2020 +0200
@@ -192,7 +192,7 @@
   </div>
 </div>
 
-<script>
+<script>'use strict';
 
 $(document).ready(function () {
 
--- a/kallithea/templates/changeset/diff_block.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/changeset/diff_block.html	Mon Apr 27 13:25:28 2020 +0200
@@ -96,9 +96,9 @@
 </%def>
 
 <%def name="diff_block_js()">
-<script type="text/javascript">
+<script>'use strict';
 $(document).ready(function(){
-    $('.btn-image-diff-show').click(function(e){
+    $('.btn-image-diff-show').click(function(){
         $('.btn-image-diff-show').hide();
         $('.btn-image-diff-swap').show();
         $('.img-diff-swapable')
@@ -112,10 +112,10 @@
         $('#'+e.currentTarget.id+'-img-a.img-diff-swapable')
           .before($('#'+e.currentTarget.id+'-img-b.img-diff-swapable'));
     });
-    var reset = function(e){
+    function reset(e){
         $('#'+e.currentTarget.id+'-img-a.img-diff-swapable')
           .after($('#'+e.currentTarget.id+'-img-b.img-diff-swapable'));
-    };
+    }
     $('.btn-image-diff-swap').mouseup(reset);
     $('.btn-image-diff-swap').mouseleave(reset);
 
--- a/kallithea/templates/compare/compare_cs.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/compare/compare_cs.html	Mon Apr 27 13:25:28 2020 +0200
@@ -63,17 +63,17 @@
 %if c.is_ajax_preview:
 <div id="jsdata" style="display:none">${h.js(c.jsdata)}</div>
 %else:
-<script type="text/javascript" src="${h.url('/js/graph.js', ver=c.kallithea_version)}"></script>
+<script src="${h.url('/js/graph.js', ver=c.kallithea_version)}"></script>
 %endif
 
-<script type="text/javascript">
+<script>'use strict';
     var jsdata = ${h.js(c.jsdata)};
     var graph = new BranchRenderer('graph_canvas', 'graph_content_pr', 'chg_');
 
     $(document).ready(function(){
         graph.render(jsdata);
 
-        $('.expand_commit').click(function(e){
+        $('.expand_commit').click(function(){
             $(this).next('.mid').find('.message').toggleClass('expanded');
             graph.render(jsdata);
         });
--- a/kallithea/templates/compare/compare_diff.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/compare/compare_diff.html	Mon Apr 27 13:25:28 2020 +0200
@@ -98,7 +98,7 @@
     </div>
 
 </div>
-    <script type="text/javascript">
+    <script>'use strict';
 
    $(document).ready(function(){
     var cache = {};
@@ -154,7 +154,7 @@
     make_revision_dropdown("#compare_org",   ${h.js(c.a_repo.repo_name)},  ${h.js(c.a_ref_name)},  'cache');
     make_revision_dropdown("#compare_other", ${h.js(c.cs_repo.repo_name)}, ${h.js(c.cs_ref_name)}, 'cache2');
 
-    var values_changed = function() {
+    function values_changed() {
         var values = $('#compare_org').select2('data') && $('#compare_other').select2('data');
         if (values) {
              $('#compare_revs').removeClass("disabled");
@@ -167,7 +167,7 @@
     values_changed();
     $('#compare_org').change(values_changed);
     $('#compare_other').change(values_changed);
-    $('#compare_revs').on('click', function(e){
+    $('#compare_revs').on('click', function(){
         var org = $('#compare_org').select2('data');
         var other = $('#compare_other').select2('data');
         if (!org || !other) {
--- a/kallithea/templates/data_table/_dt_elements.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/data_table/_dt_elements.html	Mon Apr 27 13:25:28 2020 +0200
@@ -31,6 +31,12 @@
   </div>
 </%def>
 
+<%def name="following(repo_id, repo_following)">
+  %if request.authuser.username != 'default':
+    <a href="#" class="${'following' if repo_following else 'follow'}" onclick="return toggleFollowingRepo(this, ${repo_id});"><i class="list-extra icon-heart-empty show-follow" title="${_('Follow')}"></i><i class="list-extra icon-heart show-following" title="${_('Unfollow')}"></i></a>
+  %endif
+</%def>
+
 <%def name="last_change(last_change)">
   <span data-toggle="tooltip" title="${h.fmt_date(last_change)}" date="${last_change}">${h.age(last_change)}</span>
 </%def>
--- a/kallithea/templates/email_templates/changeset_comment.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/email_templates/changeset_comment.html	Mon Apr 27 13:25:28 2020 +0200
@@ -33,7 +33,8 @@
     </tr>
     <tr>
         <td>
-<%include file="button.html" args="url=cs_comment_url,title=_('View Comment'),padding_bottom=False"/>\
+<% title = _('View Comment') %>\
+<%include file="button.html" args="url=cs_comment_url,title=title,padding_bottom=False"/>\
         </td>
     </tr>
 </table>
--- a/kallithea/templates/email_templates/changeset_comment.txt	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/email_templates/changeset_comment.txt	Mon Apr 27 13:25:28 2020 +0200
@@ -13,4 +13,5 @@
 ${_('by')|n,unicode} \
 ${cs_author.full_name_and_username|n,unicode}.
 
-<%include file="button.txt" args="url=cs_comment_url,title=_('View Comment')"/>\
+<% title = _('View Comment') %>\
+<%include file="button.txt" args="url=cs_comment_url,title=title"/>\
--- a/kallithea/templates/email_templates/default.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/email_templates/default.html	Mon Apr 27 13:25:28 2020 +0200
@@ -1,7 +1,8 @@
 <%inherit file="main.html"/>\
 \
 <%block name="header">\
-<%include file="header.html" args="title=_('Message'),link=None"/>\
+<% title = _('Message') %>\
+<%include file="header.html" args="title=title,link=None"/>\
 </%block>\
 \
 <table cellpadding="0" cellspacing="0" border="0" width="100%">
--- a/kallithea/templates/email_templates/password_reset.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/email_templates/password_reset.html	Mon Apr 27 13:25:28 2020 +0200
@@ -1,7 +1,8 @@
 <%inherit file="main.html"/>\
 \
 <%block name="header">\
-<%include file="header.html" args="title=_('Password Reset Request'),link=None"/>\
+<% title = _('Password Reset Request') %>\
+<%include file="header.html" args="title=title,link=None"/>\
 </%block>\
 \
 <table cellpadding="0" cellspacing="0" border="0" width="100%" style="table-layout:fixed;word-wrap:break-word;">
--- a/kallithea/templates/email_templates/password_reset.txt	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/email_templates/password_reset.txt	Mon Apr 27 13:25:28 2020 +0200
@@ -1,5 +1,6 @@
 <%block name="header">\
-<%include file="header.txt" args="title=_('Password Reset Request'),link=None"/>\
+<% title = _('Password Reset Request') %>\
+<%include file="header.txt" args="title=title,link=None"/>\
 </%block>\
 \
 ${_('Hello %s') % user|n,unicode},
--- a/kallithea/templates/email_templates/pull_request.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/email_templates/pull_request.html	Mon Apr 27 13:25:28 2020 +0200
@@ -82,7 +82,8 @@
     </tr>
     <tr>
         <td>
-<%include file="button.html" args="url=pr_url,title=_('View Pull Request'),padding_bottom=False"/>\
+<% title = _('View Pull Request') %>\
+<%include file="button.html" args="url=pr_url,title=title,padding_bottom=False"/>\
         </td>
     </tr>
 </table>
--- a/kallithea/templates/email_templates/pull_request.txt	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/email_templates/pull_request.txt	Mon Apr 27 13:25:28 2020 +0200
@@ -29,4 +29,5 @@
 ${h.shorter(desc, 80, firstline=True)|n,unicode}
 %endfor
 
-<%include file="button.txt" args="url=pr_url,title='View Pull Request'"/>\
+<% title = _('View Pull Request') %>\
+<%include file="button.txt" args="url=pr_url,title=title"/>\
--- a/kallithea/templates/email_templates/pull_request_comment.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/email_templates/pull_request_comment.html	Mon Apr 27 13:25:28 2020 +0200
@@ -40,7 +40,8 @@
     </tr>
     <tr>
         <td>
-<%include file="button.html" args="url=pr_comment_url,title=_('View Comment'),padding_bottom=False"/>\
+<% title = _('View Comment') %>\
+<%include file="button.html" args="url=pr_comment_url,title=title,padding_bottom=False"/>\
         </td>
     </tr>
 </table>
--- a/kallithea/templates/email_templates/pull_request_comment.txt	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/email_templates/pull_request_comment.txt	Mon Apr 27 13:25:28 2020 +0200
@@ -19,4 +19,5 @@
 ${_('branch')|n,unicode} \
 ${pr_target_branch|n,unicode}
 
-<%include file="button.txt" args="url=pr_comment_url,title=_('View Comment')"/>\
+<% title = _('View Comment') %>\
+<%include file="button.txt" args="url=pr_comment_url,title=title"/>\
--- a/kallithea/templates/email_templates/registration.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/email_templates/registration.html	Mon Apr 27 13:25:28 2020 +0200
@@ -2,7 +2,8 @@
 <%inherit file="main.html"/>\
 \
 <%block name="header">\
-<%include file="header.html" args="title=_('New User Registration'),link=registered_user_url"/>\
+<% title = _('New User Registration') %>\
+<%include file="header.html" args="title=title,link=registered_user_url"/>\
 </%block>\
 \
 <table cellpadding="0" cellspacing="0" border="0" width="100%">
@@ -38,7 +39,8 @@
     </tr>
     <tr>
         <td colspan="2">
-<%include file="button.html" args="url=registered_user_url,title=_('View User Profile'),padding_bottom=False"/>\
+<% title = _('View User Profile') %>\
+<%include file="button.html" args="url=registered_user_url,title=title,padding_bottom=False"/>\
         </td>
     </tr>
 </table>
--- a/kallithea/templates/email_templates/registration.txt	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/email_templates/registration.txt	Mon Apr 27 13:25:28 2020 +0200
@@ -1,5 +1,6 @@
 <%block name="header">\
-<%include file="header.txt" args="title=_('New User Registration'),link=registered_user_url"/>\
+<% title = _('New User Registration') %>\
+<%include file="header.txt" args="title=title,link=registered_user_url"/>\
 </%block>\
 
 ${_('Username')|n,unicode}: ${new_username|n,unicode}
@@ -8,4 +9,5 @@
 
 ${_('Email')|n,unicode}: ${new_email|n,unicode}
 
-<%include file="button.txt" args="url=registered_user_url,title='View User Profile'"/>\
+<% title = _('View User Profile') %>\
+<%include file="button.txt" args="url=registered_user_url,title=title"/>\
--- a/kallithea/templates/files/diff_2way.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/files/diff_2way.html	Mon Apr 27 13:25:28 2020 +0200
@@ -3,8 +3,8 @@
 <%inherit file="/base/base.html"/>
 
 <%block name="js_extra">
-  <script type="text/javascript" src="${h.url('/codemirror/lib/codemirror.js')}"></script>
-  <script type="text/javascript" src="${h.url('/js/mergely.js')}"></script>
+  <script src="${h.url('/codemirror/lib/codemirror.js')}"></script>
+  <script src="${h.url('/js/mergely.js')}"></script>
 </%block>
 <%block name="css_extra">
   <link rel="stylesheet" type="text/css" href="${h.url('/codemirror/lib/codemirror.css')}"/>
@@ -60,7 +60,7 @@
         </div>
     </div>
 
-<script>
+<script>'use strict';
 var orig1_url = ${h.jshtml(h.url('files_raw_home',repo_name=c.repo_name,f_path=c.node1.path,revision=c.cs1.raw_id))};
 var orig2_url = ${h.jshtml(h.url('files_raw_home',repo_name=c.repo_name,f_path=c.node2.path,revision=c.cs2.raw_id))};
 
--- a/kallithea/templates/files/files.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/files/files.html	Mon Apr 27 13:25:28 2020 +0200
@@ -36,7 +36,7 @@
     </div>
 </div>
 
-<script type="text/javascript">
+<script>'use strict';
 var CACHE = {};
 var CACHE_EXPIRE = 5*60*1000; //cache for 5*60s
 //used to construct links from the search list
@@ -50,7 +50,7 @@
 pyroutes.register('files_history_home', ${h.js(h.url('files_history_home', repo_name=c.repo_name,revision='%(revision)s',f_path='%(f_path)s'))}, ['revision', 'f_path']);
 pyroutes.register('files_authors_home', ${h.js(h.url('files_authors_home', repo_name=c.repo_name,revision='%(revision)s',f_path='%(f_path)s'))}, ['revision', 'f_path']);
 
-var ypjax_links = function(){
+function ypjax_links(){
     $('.ypjax-link').click(function(e){
 
         //don't do ypjax on middle click
@@ -88,7 +88,7 @@
     });
 }
 
-var load_state = function(state) {
+function load_state(state) {
     var $files_data = $('#files_data');
     var cache_key = state.url;
     var _cache_obj = CACHE[cache_key];
@@ -106,7 +106,7 @@
     }
 }
 
-var post_load_state = function(state) {
+function post_load_state(state) {
     ypjax_links();
     tooltip_activate();
 
@@ -125,16 +125,16 @@
     }
 
     function highlight_lines(lines){
-        for(pos in lines){
+        for(let pos in lines){
           $('#L'+lines[pos]).css('background-color','#FFFFBE');
         }
     }
-    page_highlights = location.href.substring(location.href.indexOf('#')+1).split('L');
+    let page_highlights = location.href.substring(location.href.indexOf('#')+1).split('L');
     if (page_highlights.length == 2){
-       highlight_ranges  = page_highlights[1].split(",");
+       let highlight_ranges  = page_highlights[1].split(",");
 
        var h_lines = [];
-       for (pos in highlight_ranges){
+       for (let pos in highlight_ranges){
             var _range = highlight_ranges[pos].split('-');
             if(_range.length == 2){
                 var start = parseInt(_range[0]);
--- a/kallithea/templates/files/files_add.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/files/files_add.html	Mon Apr 27 13:25:28 2020 +0200
@@ -5,9 +5,9 @@
 </%block>
 
 <%block name="js_extra">
-  <script type="text/javascript" src="${h.url('/codemirror/lib/codemirror.js')}"></script>
-  <script type="text/javascript" src="${h.url('/js/codemirror_loadmode.js')}"></script>
-  <script type="text/javascript" src="${h.url('/codemirror/mode/meta.js')}"></script>
+  <script src="${h.url('/codemirror/lib/codemirror.js')}"></script>
+  <script src="${h.url('/js/codemirror_loadmode.js')}"></script>
+  <script src="${h.url('/codemirror/mode/meta.js')}"></script>
 </%block>
 <%block name="css_extra">
   <link rel="stylesheet" type="text/css" href="${h.url('/codemirror/lib/codemirror.css')}"/>
@@ -70,7 +70,7 @@
               </div>
             </div>
             ${h.end_form()}
-            <script type="text/javascript">
+            <script>'use strict';
                 $(document).ready(function(){
                     var reset_url = ${h.jshtml(h.url('files_home',repo_name=c.repo_name,revision=c.cs.raw_id,f_path=c.f_path))};
                     var myCodeMirror = initCodeMirror('editor', ${h.jshtml(request.script_name)}, reset_url);
@@ -107,7 +107,7 @@
                     });
 
                     // on type the new filename set mode
-                    $filename_input.keyup(function(e){
+                    $filename_input.keyup(function(){
                         var file_data = CodeMirror.getFilenameAndExt(this.value);
                         if(file_data['ext'] != null){
                             var detected_mode = CodeMirror.findModeByExtension(file_data['ext']) || CodeMirror.findModeByMIME('text/plain');
--- a/kallithea/templates/files/files_browser.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/files/files_browser.html	Mon Apr 27 13:25:28 2020 +0200
@@ -109,7 +109,7 @@
     </div>
 </div>
 
-<script>
+<script>'use strict';
     $(document).ready(function(){
         // init node filter if we pass GET param ?search=1
         var search_GET = ${h.js(request.GET.get('search',''))};
--- a/kallithea/templates/files/files_edit.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/files/files_edit.html	Mon Apr 27 13:25:28 2020 +0200
@@ -5,9 +5,9 @@
 </%block>
 
 <%block name="js_extra">
-  <script type="text/javascript" src="${h.url('/codemirror/lib/codemirror.js')}"></script>
-  <script type="text/javascript" src="${h.url('/js/codemirror_loadmode.js')}"></script>
-  <script type="text/javascript" src="${h.url('/codemirror/mode/meta.js')}"></script>
+  <script src="${h.url('/codemirror/lib/codemirror.js')}"></script>
+  <script src="${h.url('/js/codemirror_loadmode.js')}"></script>
+  <script src="${h.url('/codemirror/mode/meta.js')}"></script>
 </%block>
 <%block name="css_extra">
   <link rel="stylesheet" type="text/css" href="${h.url('/codemirror/lib/codemirror.css')}"/>
@@ -77,7 +77,7 @@
     </div>
 </div>
 
-<script type="text/javascript">
+<script>'use strict';
     $(document).ready(function(){
         var reset_url = ${h.jshtml(h.url('files_home',repo_name=c.repo_name,revision=c.cs.raw_id,f_path=c.file.path))};
         var myCodeMirror = initCodeMirror('editor', ${h.jshtml(request.script_name)}, reset_url);
--- a/kallithea/templates/followers/followers.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/followers/followers.html	Mon Apr 27 13:25:28 2020 +0200
@@ -25,7 +25,7 @@
         </div>
     </div>
 </div>
-<script type="text/javascript">
+<script>'use strict';
   $(document).ready(function(){
     var $followers = $('#followers');
     $followers.on('click','.pager_link',function(e){
--- a/kallithea/templates/forks/fork.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/forks/fork.html	Mon Apr 27 13:25:28 2020 +0200
@@ -88,7 +88,7 @@
     </div>
     ${h.end_form()}
 </div>
-<script>
+<script>'use strict';
     $(document).ready(function(){
         $("#repo_group").select2({
             'dropdownAutoWidth': true
--- a/kallithea/templates/forks/forks.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/forks/forks.html	Mon Apr 27 13:25:28 2020 +0200
@@ -25,7 +25,7 @@
         </div>
     </div>
 </div>
-<script type="text/javascript">
+<script>'use strict';
   $(document).ready(function(){
       var $forks = $('#forks');
       $forks.on('click','.pager_link',function(e){
--- a/kallithea/templates/index_base.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/index_base.html	Mon Apr 27 13:25:28 2020 +0200
@@ -44,22 +44,23 @@
         </div>
     </div>
 
-      <script>
-        var data = ${h.js(c.data)},
-            $dataTable = $("#repos_list_wrap").DataTable({
+      <script>'use strict';
+        var data = ${h.js(c.data)};
+        $("#repos_list_wrap").DataTable({
                 data: data.records,
                 columns: [
                     {data: "raw_name", visible: false, searchable: false},
                     {title: ${h.jshtml(_('Repository'))}, data: "name", orderData: [0,], render: {
-                        filter: function(data, type, row, meta) {
+                        filter: function(data, type, row) {
                             return row.just_name;
                         }
                     }},
+                    {data: "following", defaultContent: '', sortable: false},
                     {data: "desc", title: ${h.jshtml(_('Description'))}, searchable: false},
                     {data: "last_change_iso", defaultContent: '', visible: false, searchable: false},
-                    {data: "last_change", defaultContent: '', title: ${h.jshtml(_('Last Change'))}, orderData: [3,], searchable: false},
+                    {data: "last_change", defaultContent: '', title: ${h.jshtml(_('Last Change'))}, orderData: [4,], searchable: false},
                     {data: "last_rev_raw", defaultContent: '', visible: false, searchable: false},
-                    {data: "last_changeset", defaultContent: '', title: ${h.jshtml(_('Tip'))}, orderData: [5,], searchable: false},
+                    {data: "last_changeset", defaultContent: '', title: ${h.jshtml(_('Tip'))}, orderData: [6,], searchable: false},
                     {data: "owner", defaultContent: '', title: ${h.jshtml(_('Owner'))}, searchable: false},
                     {data: "atom", defaultContent: '', sortable: false}
                 ],
--- a/kallithea/templates/journal/journal.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/journal/journal.html	Mon Apr 27 13:25:28 2020 +0200
@@ -41,7 +41,7 @@
         </div>
     </div>
 
-<script type="text/javascript">
+<script>'use strict';
 
     $('#j_filter').click(function(){
         var $jfilter = $('#j_filter');
@@ -49,9 +49,9 @@
             $jfilter.val('');
         }
     });
-    var fix_j_filter_width = function(len){
+    function fix_j_filter_width(len){
         $('#j_filter').css('width', Math.max(80, len*6.50)+'px');
-    };
+    }
     $('#j_filter').keyup(function(){
         fix_j_filter_width($('#j_filter').val().length);
     });
@@ -72,7 +72,7 @@
 
 </script>
 
-<script type="text/javascript">
+<script>'use strict';
     $(document).ready(function(){
         var $journal = $('#journal');
         $journal.on('click','.pager_link',function(e){
--- a/kallithea/templates/login.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/login.html	Mon Apr 27 13:25:28 2020 +0200
@@ -64,7 +64,7 @@
             </div>
         </div>
         ${h.end_form()}
-        <script type="text/javascript">
+        <script>'use strict';
         $(document).ready(function(){
             $('#username').focus();
         });
--- a/kallithea/templates/password_reset.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/password_reset.html	Mon Apr 27 13:25:28 2020 +0200
@@ -7,7 +7,7 @@
 
 <%block name="js_extra">
     %if c.captcha_active:
-        <script type="text/javascript" src="https://www.google.com/recaptcha/api.js"></script>
+        <script src="https://www.google.com/recaptcha/api.js"></script>
     %endif
 </%block>
 
@@ -53,7 +53,7 @@
                 </div>
         </div>
         ${h.end_form()}
-        <script type="text/javascript">
+        <script>'use strict';
          $(document).ready(function(){
             $('#email').focus();
          });
--- a/kallithea/templates/pullrequests/pullrequest.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/pullrequests/pullrequest.html	Mon Apr 27 13:25:28 2020 +0200
@@ -91,12 +91,12 @@
 
 </div>
 
-<script type="text/javascript" src="${h.url('/js/graph.js', ver=c.kallithea_version)}"></script>
-<script type="text/javascript">
+<script src="${h.url('/js/graph.js', ver=c.kallithea_version)}"></script>
+<script>'use strict';
   pyroutes.register('pullrequest_repo_info', ${h.js(url('pullrequest_repo_info',repo_name='%(repo_name)s'))}, ['repo_name']);
 
   var pendingajax = undefined;
-  var otherrepoChanged = function(){
+  function otherrepoChanged(){
       var $other_ref = $('#other_ref');
       $other_ref.prop('disabled', true);
       var repo_name = $('#other_repo').val();
@@ -132,9 +132,9 @@
               $other_ref.prop('disabled', false);
               loadPreview();
           });
-  };
+  }
 
-  var loadPreview = function(){
+  function loadPreview(){
       //url template
       var url = ${h.js(h.url('compare_url',
                          repo_name='__other_repo__',
@@ -162,7 +162,7 @@
           '__other_ref_name__': other_ref[2]
       }; // gather the org/other ref and repo here
 
-      for (k in rev_data){
+      for (let k in rev_data){
           url = url.replace(k,rev_data[k]);
       }
 
@@ -170,7 +170,7 @@
           pendingajax.abort();
           pendingajax = undefined;
       }
-      pendingajax = asynchtml(url, $('#pull_request_overview'), function(o){
+      pendingajax = asynchtml(url, $('#pull_request_overview'), function(){
           pendingajax = undefined;
       });
   }
@@ -186,14 +186,14 @@
           maxResults: 50,
           sortResults: branchSort
       });
-      $("#org_ref").on("change", function(e){
+      $("#org_ref").on("change", function(){
           loadPreview();
       });
 
       $("#other_repo").select2({
           dropdownAutoWidth: true
       });
-      $("#other_repo").on("change", function(e){
+      $("#other_repo").on("change", function(){
           otherrepoChanged();
       });
 
@@ -202,7 +202,7 @@
           maxResults: 50,
           sortResults: branchSort
       });
-      $("#other_ref").on("change", function(e){
+      $("#other_ref").on("change", function(){
           loadPreview();
       });
 
--- a/kallithea/templates/pullrequests/pullrequest_show.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/pullrequests/pullrequest_show.html	Mon Apr 27 13:25:28 2020 +0200
@@ -312,10 +312,10 @@
             </div>
         </div>
     </div>
-    <script>
+    <script>'use strict';
     // TODO: switch this to pyroutes
-    AJAX_COMMENT_URL = ${h.js(url('pullrequest_comment',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id))};
-    AJAX_COMMENT_DELETE_URL = ${h.js(url('pullrequest_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__'))};
+    var AJAX_COMMENT_URL = ${h.js(url('pullrequest_comment',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id))};
+    var AJAX_COMMENT_DELETE_URL = ${h.js(url('pullrequest_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__'))};
 
     pyroutes.register('pullrequest_comment', ${h.js(url('pullrequest_comment',repo_name='%(repo_name)s',pull_request_id='%(pull_request_id)s'))}, ['repo_name', 'pull_request_id']);
     pyroutes.register('pullrequest_comment_delete', ${h.js(url('pullrequest_comment_delete',repo_name='%(repo_name)s',comment_id='%(comment_id)s'))}, ['repo_name', 'comment_id']);
@@ -343,12 +343,12 @@
     ## main comment form and it status
     ${comment.comments(change_status=c.allowed_to_change_status)}
 
-    <script type="text/javascript">
+    <script>'use strict';
       $(document).ready(function(){
           PullRequestAutoComplete($('#user'));
           SimpleUserAutoComplete($('#owner'));
 
-          $('.code-difftable').on('click', '.add-bubble', function(e){
+          $('.code-difftable').on('click', '.add-bubble', function(){
               show_comment_form($(this));
           });
 
@@ -368,7 +368,7 @@
               $('#pr-form-clone').prop('disabled',!update);
           });
           var $org_review_members = $('#review_members').clone();
-          $('#pr-form-reset').click(function(e){
+          $('#pr-form-reset').click(function(){
               $('.pr-do-edit').hide();
               $('.pr-not-edit').show();
               $('#pr-form-save').prop('disabled',false);
--- a/kallithea/templates/register.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/register.html	Mon Apr 27 13:25:28 2020 +0200
@@ -7,7 +7,7 @@
 
 <%block name="js_extra">
     %if c.captcha_active:
-        <script type="text/javascript" src="https://www.google.com/recaptcha/api.js"></script>
+        <script src="https://www.google.com/recaptcha/api.js"></script>
     %endif
 </%block>
 
@@ -90,7 +90,7 @@
                 </div>
         </div>
         ${h.end_form()}
-        <script type="text/javascript">
+        <script>'use strict';
         $(document).ready(function(){
             $('#username').focus();
         });
--- a/kallithea/templates/summary/statistics.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/summary/statistics.html	Mon Apr 27 13:25:28 2020 +0200
@@ -15,9 +15,9 @@
 <%block name="head_extra">
   <link href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name,api_key=request.authuser.api_key)}" rel="alternate" title="${_('%s ATOM feed') % c.repo_name}" type="application/atom+xml" />
   <link href="${h.url('rss_feed_home',repo_name=c.db_repo.repo_name,api_key=request.authuser.api_key)}" rel="alternate" title="${_('%s RSS feed') % c.repo_name}" type="application/rss+xml" />
-  <script type="text/javascript" src="${h.url('/js/jquery.flot.js', ver=c.kallithea_version)}"></script>
-  <script type="text/javascript" src="${h.url('/js/jquery.flot.selection.js', ver=c.kallithea_version)}"></script>
-  <script type="text/javascript" src="${h.url('/js/jquery.flot.time.js', ver=c.kallithea_version)}"></script>
+  <script src="${h.url('/js/jquery.flot.js', ver=c.kallithea_version)}"></script>
+  <script src="${h.url('/js/jquery.flot.selection.js', ver=c.kallithea_version)}"></script>
+  <script src="${h.url('/js/jquery.flot.time.js', ver=c.kallithea_version)}"></script>
 </%block>
 
 <%def name="main()">
@@ -51,16 +51,16 @@
     </div>
 </div>
 
-<script type="text/javascript">
+<script>'use strict';
 var data = ${h.js(c.trending_languages)};
 var total = 0;
 var tbl = document.createElement('table');
 tbl.setAttribute('class','trending_language_tbl');
 var cnt = 0;
-for (var i=0;i<data.length;i++){
+for (let i=0;i<data.length;i++){
     total+= data[i][1].count;
 }
-for (var i=0;i<data.length;i++){
+for (let i=0;i<data.length;i++){
     cnt += 1;
 
     var hide = cnt>2;
@@ -103,7 +103,7 @@
     if(cnt == 3){
         var show_more = document.createElement('tr');
         var td = document.createElement('td');
-        lnk = document.createElement('a');
+        let lnk = document.createElement('a');
 
         lnk.href='#';
         lnk.innerHTML = ${h.jshtml(_('Show more'))};
@@ -118,7 +118,7 @@
 }
 
 </script>
-<script type="text/javascript">
+<script>'use strict';
 
 /**
  * Plots summary graph
@@ -136,17 +136,15 @@
             "to":to
         }
     };
-    for(var key in dataset){
-      var data = dataset[key].data;
+    for(let key in dataset){
+      let data = dataset[key].data;
       for(var d in data){
         data[d].time *= 1000;
       }
     }
-    for(var key in overview_dataset){
+    for(let key in overview_dataset){
       overview_dataset[key][0] *= 1000;
     }
-    var dataset = dataset;
-    var overview_dataset = [overview_dataset];
     var choiceContainer = $("#legend_choices")[0];
     var choiceContainerTable = $("#legend_choices_tables")[0];
     var $plotContainer = $('#commit_history');
@@ -158,8 +156,7 @@
         bars: {show:true, align: 'center', lineWidth: 4},
         legend: {show:true,
                 container: "#legend_container",
-                labelFormatter: function(label, series) {
-                        // series is the series object for the label
+                labelFormatter: function(label) {
                         return '<a href="javascript:void(0)"> ' + label + '</a>';
                     }
         },
@@ -207,8 +204,6 @@
 
     /**
      * generate checkboxes accordingly to data
-     * @param keys
-     * @returns
      */
     function generateCheckboxes(data) {
         //append checkboxes
@@ -257,12 +252,9 @@
 
         var data = [];
         var new_dataset = {};
-        var keys = [];
-        var max_commits = 0;
         for(var key in dataset){
-
             for(var ds in dataset[key].data){
-                commit_data = dataset[key].data[ds];
+                let commit_data = dataset[key].data[ds];
                 if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
                     if(new_dataset[key] === undefined){
                         new_dataset[key] = {data:[],label:key};
@@ -290,7 +282,7 @@
     * redraw using new checkbox data
     */
     function plotchoiced(e){
-        args = e.data;
+        let args = e.data;
         var cur_data = args[0];
         var cur_ranges = args[1];
 
@@ -382,7 +374,7 @@
             if (previousPoint != item.datapoint) {
                 previousPoint = item.datapoint;
 
-                var tooltip = $("#tooltip")[0];
+                let tooltip = $("#tooltip")[0];
                 if(tooltip) {
                       tooltip.parentNode.removeChild(tooltip);
                 }
@@ -419,7 +411,7 @@
             }
         }
         else {
-              var tooltip = $("#tooltip")[0];
+              let tooltip = $("#tooltip")[0];
 
               if(tooltip) {
                     tooltip.parentNode.removeChild(tooltip);
@@ -432,14 +424,14 @@
      * MAIN EXECUTION
      */
 
-    var data = getDataAccordingToRanges(initial_ranges);
+    let data = getDataAccordingToRanges(initial_ranges);
     generateCheckboxes(data);
 
     //main plot
     var plot = $.plot(plotContainer,data,plot_options);
 
     //overview
-    var overview = $.plot(overviewContainer, overview_dataset, overview_options);
+    var overview = $.plot(overviewContainer, [overview_dataset], overview_options);
 
     //show initial selection on overview
     overview.setSelection(initial_ranges);
--- a/kallithea/templates/summary/summary.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/templates/summary/summary.html	Mon Apr 27 13:25:28 2020 +0200
@@ -27,8 +27,8 @@
   <link href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name,api_key=request.authuser.api_key)}" rel="alternate" title="${_('%s ATOM feed') % c.repo_name}" type="application/atom+xml" />
   <link href="${h.url('rss_feed_home',repo_name=c.db_repo.repo_name,api_key=request.authuser.api_key)}" rel="alternate" title="${_('%s RSS feed') % c.repo_name}" type="application/rss+xml" />
 
-  <script>
-  redirect_hash_branch = function(){
+  <script>'use strict';
+  function redirect_hash_branch(){
     var branch = window.location.hash.replace(/^#(.*)/, '$1');
     if (branch){
       window.location = ${h.js(h.url('changelog_home',repo_name=c.repo_name,branch='__BRANCH__'))}
@@ -238,9 +238,9 @@
 </div>
 %endif
 
-<script type="text/javascript">
+<script>'use strict';
 $(document).ready(function(){
-    $('#clone-url input').click(function(e){
+    $('#clone-url input').click(function(){
         if($(this).hasClass('selected')){
             $(this).removeClass('selected');
             return ;
@@ -254,17 +254,17 @@
     var $clone_by_name = $('#clone_by_name');
     var $clone_by_id = $('#clone_by_id');
     var $clone_ssh = $('#clone_ssh');
-    $clone_url.on('click', '.btn.use-name', function(e){
+    $clone_url.on('click', '.btn.use-name', function(){
         $clone_by_name.show();
         $clone_by_id.hide();
         $clone_ssh.hide();
     });
-    $clone_url.on('click', '.btn.use-id', function(e){
+    $clone_url.on('click', '.btn.use-id', function(){
         $clone_by_id.show();
         $clone_by_name.hide();
         $clone_ssh.hide();
     });
-    $clone_url.on('click', '.btn.use-ssh', function(e){
+    $clone_url.on('click', '.btn.use-ssh', function(){
         $clone_by_id.hide();
         $clone_by_name.hide();
         $clone_ssh.show();
@@ -309,7 +309,7 @@
     $('#download_options').change(function(e){
        var new_cs = e.added
 
-       for(k in tmpl_links){
+       for(let k in tmpl_links){
            var s = $('#'+k+'_link');
            if(s){
              var title_tmpl = ${h.jshtml(_('Download %s as %s') % ('__CS_NAME__','__CS_EXT__'))};
@@ -334,17 +334,17 @@
 </script>
 
 %if c.show_stats:
-<script type="text/javascript">
+<script>'use strict';
 $(document).ready(function(){
     var data = ${h.js(c.trending_languages)};
     var total = 0;
     var tbl = document.createElement('table');
     tbl.setAttribute('class','table');
     var cnt = 0;
-    for (var i=0;i<data.length;i++){
+    for (let i=0;i<data.length;i++){
         total+= data[i][1].count;
     }
-    for (var i=0;i<data.length;i++){
+    for (let i=0;i<data.length;i++){
         cnt += 1;
 
         var hide = cnt>2;
@@ -393,7 +393,7 @@
         if(cnt == 3){
             var show_more = document.createElement('tr');
             var td = document.createElement('td');
-            lnk = document.createElement('a');
+            let lnk = document.createElement('a');
 
             lnk.href='#';
             lnk.innerHTML = ${h.jshtml(_('Show more'))};
--- a/kallithea/tests/api/api_base.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/api/api_base.py	Mon Apr 27 13:25:28 2020 +0200
@@ -40,8 +40,8 @@
 
 
 API_URL = '/_admin/api'
-TEST_USER_GROUP = u'test_user_group'
-TEST_REPO_GROUP = u'test_repo_group'
+TEST_USER_GROUP = 'test_user_group'
+TEST_REPO_GROUP = 'test_repo_group'
 
 fixture = Fixture()
 
@@ -100,13 +100,12 @@
             username='test-api',
             password='test',
             email='test@example.com',
-            firstname=u'first',
-            lastname=u'last'
+            firstname='first',
+            lastname='last'
         )
         Session().commit()
         cls.TEST_USER_LOGIN = cls.test_user.username
         cls.apikey_regular = cls.test_user.api_key
-        cls.default_user_username = User.get_default_user().username
 
     @classmethod
     def teardown_class(cls):
@@ -281,7 +280,7 @@
     def test_api_pull_remote(self):
         # Note: pulling from local repos is a mis-feature - it will bypass access control
         # ... but ok, if the path already has been set in the database
-        repo_name = u'test_pull'
+        repo_name = 'test_pull'
         r = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
         # hack around that clone_uri can't be set to to a local path
         # (as shown by test_api_create_repo_clone_uri_local)
@@ -305,7 +304,7 @@
         assert pre_cached_tip != post_cached_tip
 
     def test_api_pull_fork(self):
-        fork_name = u'fork'
+        fork_name = 'fork'
         fixture.create_fork(self.REPO, fork_name)
         id_, params = _build_data(self.apikey, 'pull',
                                   repoid=fork_name,)
@@ -327,7 +326,7 @@
         self._compare_error(id_, expected, given=response.body)
 
     def test_api_pull_custom_remote(self):
-        repo_name = u'test_pull_custom_remote'
+        repo_name = 'test_pull_custom_remote'
         fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
 
         custom_remote_path = os.path.join(Ui.get_by_key('paths', '/').ui_value, self.REPO)
@@ -358,40 +357,6 @@
         expected = 'Error occurred during rescan repositories action'
         self._compare_error(id_, expected, given=response.body)
 
-    def test_api_invalidate_cache(self):
-        repo = RepoModel().get_by_repo_name(self.REPO)
-        repo.scm_instance_cached()  # seed cache
-
-        id_, params = _build_data(self.apikey, 'invalidate_cache',
-                                  repoid=self.REPO)
-        response = api_call(self, params)
-
-        expected = {
-            'msg': "Cache for repository `%s` was invalidated" % (self.REPO,),
-            'repository': self.REPO
-        }
-        self._compare_ok(id_, expected, given=response.body)
-
-    @mock.patch.object(ScmModel, 'mark_for_invalidation', crash)
-    def test_api_invalidate_cache_error(self):
-        id_, params = _build_data(self.apikey, 'invalidate_cache',
-                                  repoid=self.REPO)
-        response = api_call(self, params)
-
-        expected = 'Error occurred during cache invalidation action'
-        self._compare_error(id_, expected, given=response.body)
-
-    def test_api_invalidate_cache_regular_user_no_permission(self):
-        repo = RepoModel().get_by_repo_name(self.REPO)
-        repo.scm_instance_cached() # seed cache
-
-        id_, params = _build_data(self.apikey_regular, 'invalidate_cache',
-                                  repoid=self.REPO)
-        response = api_call(self, params)
-
-        expected = "repository `%s` does not exist" % (self.REPO,)
-        self._compare_error(id_, expected, given=response.body)
-
     def test_api_create_existing_user(self):
         id_, params = _build_data(self.apikey, 'create_user',
                                   username=base.TEST_USER_ADMIN_LOGIN,
@@ -489,10 +454,10 @@
         self._compare_error(id_, expected, given=response.body)
 
     def test_api_delete_user(self):
-        usr = UserModel().create_or_update(username=u'test_user',
-                                           password=u'qweqwe',
-                                           email=u'u232@example.com',
-                                           firstname=u'u1', lastname=u'u1')
+        usr = UserModel().create_or_update(username='test_user',
+                                           password='qweqwe',
+                                           email='u232@example.com',
+                                           firstname='u1', lastname='u1')
         Session().commit()
         username = usr.username
         email = usr.email
@@ -510,10 +475,10 @@
 
     @mock.patch.object(UserModel, 'delete', crash)
     def test_api_delete_user_when_exception_happened(self):
-        usr = UserModel().create_or_update(username=u'test_user',
-                                           password=u'qweqwe',
-                                           email=u'u232@example.com',
-                                           firstname=u'u1', lastname=u'u1')
+        usr = UserModel().create_or_update(username='test_user',
+                                           password='qweqwe',
+                                           email='u232@example.com',
+                                           firstname='u1', lastname='u1')
         Session().commit()
         username = usr.username
 
@@ -610,7 +575,7 @@
         self._compare_error(id_, expected, given=response.body)
 
     def test_api_get_repo(self):
-        new_group = u'some_new_group'
+        new_group = 'some_new_group'
         make_user_group(new_group)
         RepoModel().grant_user_group_permission(repo=self.REPO,
                                                 group_name=new_group,
@@ -619,8 +584,8 @@
         id_, params = _build_data(self.apikey, 'get_repo',
                                   repoid=self.REPO)
         response = api_call(self, params)
-        assert u"tags" not in response.json[u'result']
-        assert u'pull_requests' not in response.json[u'result']
+        assert "tags" not in response.json['result']
+        assert 'pull_requests' not in response.json['result']
 
         repo = RepoModel().get_by_repo_name(self.REPO)
         ret = repo.get_api_data()
@@ -655,8 +620,8 @@
                                   with_revision_names=True,
                                   with_pullrequests=True)
         response = api_call(self, params)
-        assert u"v0.2.0" in response.json[u'result'][u'tags']
-        assert u'pull_requests' in response.json[u'result']
+        assert "v0.2.0" in response.json['result']['tags']
+        assert 'pull_requests' in response.json['result']
 
     @base.parametrize('grant_perm', [
         ('repository.admin'),
@@ -706,7 +671,7 @@
 
     def test_api_get_repo_by_non_admin_no_permission_to_repo(self):
         RepoModel().grant_user_permission(repo=self.REPO,
-                                          user=self.default_user_username,
+                                          user=User.DEFAULT_USER_NAME,
                                           perm='repository.none')
         try:
             RepoModel().grant_user_permission(repo=self.REPO,
@@ -721,7 +686,7 @@
             self._compare_error(id_, expected, given=response.body)
         finally:
             RepoModel().grant_user_permission(repo=self.REPO,
-                                              user=self.default_user_username,
+                                              user=User.DEFAULT_USER_NAME,
                                               perm='repository.read')
 
     def test_api_get_repo_that_doesn_not_exist(self):
@@ -838,7 +803,7 @@
             RepoModel().revoke_user_permission(self.REPO, self.TEST_USER_LOGIN)
 
     def test_api_create_repo(self):
-        repo_name = u'api-repo'
+        repo_name = 'api-repo'
         id_, params = _build_data(self.apikey, 'create_repo',
                                   repo_name=repo_name,
                                   owner=base.TEST_USER_ADMIN_LOGIN,
@@ -858,12 +823,12 @@
         fixture.destroy_repo(repo_name)
 
     @base.parametrize('repo_name', [
-        u'',
-        u'.',
-        u'..',
-        u':',
-        u'/',
-        u'<test>',
+        '',
+        '.',
+        '..',
+        ':',
+        '/',
+        '<test>',
     ])
     def test_api_create_repo_bad_names(self, repo_name):
         id_, params = _build_data(self.apikey, 'create_repo',
@@ -884,7 +849,7 @@
         # cloning from local repos was a mis-feature - it would bypass access control
         # TODO: introduce other test coverage of actual remote cloning
         clone_uri = os.path.join(base.TESTS_TMP_PATH, self.REPO)
-        repo_name = u'api-repo'
+        repo_name = 'api-repo'
         id_, params = _build_data(self.apikey, 'create_repo',
                                   repo_name=repo_name,
                                   owner=base.TEST_USER_ADMIN_LOGIN,
@@ -897,8 +862,8 @@
         fixture.destroy_repo(repo_name)
 
     def test_api_create_repo_and_repo_group(self):
-        repo_group_name = u'my_gr'
-        repo_name = u'%s/api-repo' % repo_group_name
+        repo_group_name = 'my_gr'
+        repo_name = '%s/api-repo' % repo_group_name
 
         # repo creation can no longer also create repo group
         id_, params = _build_data(self.apikey, 'create_repo',
@@ -906,7 +871,7 @@
                                   owner=base.TEST_USER_ADMIN_LOGIN,
                                   repo_type=self.REPO_TYPE,)
         response = api_call(self, params)
-        expected = u'repo group `%s` not found' % repo_group_name
+        expected = 'repo group `%s` not found' % repo_group_name
         self._compare_error(id_, expected, given=response.body)
         assert RepoModel().get_by_repo_name(repo_name) is None
 
@@ -932,9 +897,9 @@
         fixture.destroy_repo_group(repo_group_name)
 
     def test_api_create_repo_in_repo_group_without_permission(self):
-        repo_group_basename = u'api-repo-repo'
-        repo_group_name = u'%s/%s' % (TEST_REPO_GROUP, repo_group_basename)
-        repo_name = u'%s/api-repo' % repo_group_name
+        repo_group_basename = 'api-repo-repo'
+        repo_group_name = '%s/%s' % (TEST_REPO_GROUP, repo_group_basename)
+        repo_name = '%s/api-repo' % repo_group_name
 
         top_group = RepoGroup.get_by_group_name(TEST_REPO_GROUP)
         assert top_group
@@ -968,7 +933,7 @@
         fixture.destroy_repo_group(repo_group_name)
 
     def test_api_create_repo_unknown_owner(self):
-        repo_name = u'api-repo'
+        repo_name = 'api-repo'
         owner = 'i-dont-exist'
         id_, params = _build_data(self.apikey, 'create_repo',
                                   repo_name=repo_name,
@@ -980,7 +945,7 @@
         self._compare_error(id_, expected, given=response.body)
 
     def test_api_create_repo_dont_specify_owner(self):
-        repo_name = u'api-repo'
+        repo_name = 'api-repo'
         owner = 'i-dont-exist'
         id_, params = _build_data(self.apikey, 'create_repo',
                                   repo_name=repo_name,
@@ -1000,7 +965,7 @@
         fixture.destroy_repo(repo_name)
 
     def test_api_create_repo_by_non_admin(self):
-        repo_name = u'api-repo'
+        repo_name = 'api-repo'
         owner = 'i-dont-exist'
         id_, params = _build_data(self.apikey_regular, 'create_repo',
                                   repo_name=repo_name,
@@ -1020,7 +985,7 @@
         fixture.destroy_repo(repo_name)
 
     def test_api_create_repo_by_non_admin_specify_owner(self):
-        repo_name = u'api-repo'
+        repo_name = 'api-repo'
         owner = 'i-dont-exist'
         id_, params = _build_data(self.apikey_regular, 'create_repo',
                                   repo_name=repo_name,
@@ -1051,13 +1016,13 @@
                                   owner=base.TEST_USER_ADMIN_LOGIN,
                                   repo_type=self.REPO_TYPE,)
         response = api_call(self, params)
-        expected = u'repo group `%s` not found' % group_name
+        expected = 'repo group `%s` not found' % group_name
         self._compare_error(id_, expected, given=response.body)
         fixture.destroy_repo(repo_name)
 
     @mock.patch.object(RepoModel, 'create', crash)
     def test_api_create_repo_exception_occurred(self):
-        repo_name = u'api-repo'
+        repo_name = 'api-repo'
         id_, params = _build_data(self.apikey, 'create_repo',
                                   repo_name=repo_name,
                                   owner=base.TEST_USER_ADMIN_LOGIN,
@@ -1068,18 +1033,18 @@
 
     @base.parametrize('changing_attr,updates', [
         ('owner', {'owner': base.TEST_USER_REGULAR_LOGIN}),
-        ('description', {'description': u'new description'}),
+        ('description', {'description': 'new description'}),
         ('clone_uri', {'clone_uri': 'http://example.com/repo'}), # will fail - pulling from non-existing repo should fail
         ('clone_uri', {'clone_uri': '/repo'}), # will fail - pulling from local repo was a mis-feature - it would bypass access control
         ('clone_uri', {'clone_uri': None}),
         ('landing_rev', {'landing_rev': 'branch:master'}),
         ('enable_statistics', {'enable_statistics': True}),
         ('enable_downloads', {'enable_downloads': True}),
-        ('name', {'name': u'new_repo_name'}),
-        ('repo_group', {'group': u'test_group_for_update'}),
+        ('name', {'name': 'new_repo_name'}),
+        ('repo_group', {'group': 'test_group_for_update'}),
     ])
     def test_api_update_repo(self, changing_attr, updates):
-        repo_name = u'api_update_me'
+        repo_name = 'api_update_me'
         repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
         if changing_attr == 'repo_group':
             fixture.create_repo_group(updates['group'])
@@ -1090,10 +1055,10 @@
         if changing_attr == 'name':
             repo_name = updates['name']
         if changing_attr == 'repo_group':
-            repo_name = u'/'.join([updates['group'], repo_name])
+            repo_name = '/'.join([updates['group'], repo_name])
         try:
             if changing_attr == 'clone_uri' and updates['clone_uri']:
-                expected = u'failed to update repo `%s`' % repo_name
+                expected = 'failed to update repo `%s`' % repo_name
                 self._compare_error(id_, expected, given=response.body)
             else:
                 expected = {
@@ -1108,20 +1073,20 @@
 
     @base.parametrize('changing_attr,updates', [
         ('owner', {'owner': base.TEST_USER_REGULAR_LOGIN}),
-        ('description', {'description': u'new description'}),
+        ('description', {'description': 'new description'}),
         ('clone_uri', {'clone_uri': 'http://example.com/repo'}), # will fail - pulling from non-existing repo should fail
         ('clone_uri', {'clone_uri': '/repo'}), # will fail - pulling from local repo was a mis-feature - it would bypass access control
         ('clone_uri', {'clone_uri': None}),
         ('landing_rev', {'landing_rev': 'branch:master'}),
         ('enable_statistics', {'enable_statistics': True}),
         ('enable_downloads', {'enable_downloads': True}),
-        ('name', {'name': u'new_repo_name'}),
-        ('repo_group', {'group': u'test_group_for_update'}),
+        ('name', {'name': 'new_repo_name'}),
+        ('repo_group', {'group': 'test_group_for_update'}),
     ])
     def test_api_update_group_repo(self, changing_attr, updates):
-        group_name = u'lololo'
+        group_name = 'lololo'
         fixture.create_repo_group(group_name)
-        repo_name = u'%s/api_update_me' % group_name
+        repo_name = '%s/api_update_me' % group_name
         repo = fixture.create_repo(repo_name, repo_group=group_name, repo_type=self.REPO_TYPE)
         if changing_attr == 'repo_group':
             fixture.create_repo_group(updates['group'])
@@ -1130,12 +1095,12 @@
                                   repoid=repo_name, **updates)
         response = api_call(self, params)
         if changing_attr == 'name':
-            repo_name = u'%s/%s' % (group_name, updates['name'])
+            repo_name = '%s/%s' % (group_name, updates['name'])
         if changing_attr == 'repo_group':
-            repo_name = u'/'.join([updates['group'], repo_name.rsplit('/', 1)[-1]])
+            repo_name = '/'.join([updates['group'], repo_name.rsplit('/', 1)[-1]])
         try:
             if changing_attr == 'clone_uri' and updates['clone_uri']:
-                expected = u'failed to update repo `%s`' % repo_name
+                expected = 'failed to update repo `%s`' % repo_name
                 self._compare_error(id_, expected, given=response.body)
             else:
                 expected = {
@@ -1150,7 +1115,7 @@
         fixture.destroy_repo_group(group_name)
 
     def test_api_update_repo_repo_group_does_not_exist(self):
-        repo_name = u'admin_owned'
+        repo_name = 'admin_owned'
         fixture.create_repo(repo_name)
         updates = {'group': 'test_group_for_update'}
         id_, params = _build_data(self.apikey, 'update_repo',
@@ -1163,7 +1128,7 @@
             fixture.destroy_repo(repo_name)
 
     def test_api_update_repo_regular_user_not_allowed(self):
-        repo_name = u'admin_owned'
+        repo_name = 'admin_owned'
         fixture.create_repo(repo_name)
         updates = {'description': 'something else'}
         id_, params = _build_data(self.apikey_regular, 'update_repo',
@@ -1177,7 +1142,7 @@
 
     @mock.patch.object(RepoModel, 'update', crash)
     def test_api_update_repo_exception_occurred(self):
-        repo_name = u'api_update_me'
+        repo_name = 'api_update_me'
         fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
         id_, params = _build_data(self.apikey, 'update_repo',
                                   repoid=repo_name, owner=base.TEST_USER_ADMIN_LOGIN,)
@@ -1189,8 +1154,8 @@
             fixture.destroy_repo(repo_name)
 
     def test_api_update_repo_regular_user_change_repo_name(self):
-        repo_name = u'admin_owned'
-        new_repo_name = u'new_repo_name'
+        repo_name = 'admin_owned'
+        new_repo_name = 'new_repo_name'
         fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
         RepoModel().grant_user_permission(repo=repo_name,
                                           user=self.TEST_USER_LOGIN,
@@ -1209,8 +1174,8 @@
             fixture.destroy_repo(new_repo_name)
 
     def test_api_update_repo_regular_user_change_repo_name_allowed(self):
-        repo_name = u'admin_owned'
-        new_repo_name = u'new_repo_name'
+        repo_name = 'admin_owned'
+        new_repo_name = 'new_repo_name'
         repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
         RepoModel().grant_user_permission(repo=repo_name,
                                           user=self.TEST_USER_LOGIN,
@@ -1232,7 +1197,7 @@
             fixture.destroy_repo(new_repo_name)
 
     def test_api_update_repo_regular_user_change_owner(self):
-        repo_name = u'admin_owned'
+        repo_name = 'admin_owned'
         fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
         RepoModel().grant_user_permission(repo=repo_name,
                                           user=self.TEST_USER_LOGIN,
@@ -1248,7 +1213,7 @@
             fixture.destroy_repo(repo_name)
 
     def test_api_delete_repo(self):
-        repo_name = u'api_delete_me'
+        repo_name = 'api_delete_me'
         fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
 
         id_, params = _build_data(self.apikey, 'delete_repo',
@@ -1266,7 +1231,7 @@
             fixture.destroy_repo(repo_name)
 
     def test_api_delete_repo_by_non_admin(self):
-        repo_name = u'api_delete_me'
+        repo_name = 'api_delete_me'
         fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
                             cur_user=self.TEST_USER_LOGIN)
         id_, params = _build_data(self.apikey_regular, 'delete_repo',
@@ -1284,7 +1249,7 @@
             fixture.destroy_repo(repo_name)
 
     def test_api_delete_repo_by_non_admin_no_permission(self):
-        repo_name = u'api_delete_me'
+        repo_name = 'api_delete_me'
         fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
         try:
             id_, params = _build_data(self.apikey_regular, 'delete_repo',
@@ -1296,7 +1261,7 @@
             fixture.destroy_repo(repo_name)
 
     def test_api_delete_repo_exception_occurred(self):
-        repo_name = u'api_delete_me'
+        repo_name = 'api_delete_me'
         fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
         try:
             with mock.patch.object(RepoModel, 'delete', crash):
@@ -1310,7 +1275,7 @@
             fixture.destroy_repo(repo_name)
 
     def test_api_fork_repo(self):
-        fork_name = u'api-repo-fork'
+        fork_name = 'api-repo-fork'
         id_, params = _build_data(self.apikey, 'fork_repo',
                                   repoid=self.REPO,
                                   fork_name=fork_name,
@@ -1329,8 +1294,8 @@
         fixture.destroy_repo(fork_name)
 
     @base.parametrize('fork_name', [
-        u'api-repo-fork',
-        u'%s/api-repo-fork' % TEST_REPO_GROUP,
+        'api-repo-fork',
+        '%s/api-repo-fork' % TEST_REPO_GROUP,
     ])
     def test_api_fork_repo_non_admin(self, fork_name):
         id_, params = _build_data(self.apikey_regular, 'fork_repo',
@@ -1350,7 +1315,7 @@
         fixture.destroy_repo(fork_name)
 
     def test_api_fork_repo_non_admin_specify_owner(self):
-        fork_name = u'api-repo-fork'
+        fork_name = 'api-repo-fork'
         id_, params = _build_data(self.apikey_regular, 'fork_repo',
                                   repoid=self.REPO,
                                   fork_name=fork_name,
@@ -1363,10 +1328,10 @@
 
     def test_api_fork_repo_non_admin_no_permission_to_fork(self):
         RepoModel().grant_user_permission(repo=self.REPO,
-                                          user=self.default_user_username,
+                                          user=User.DEFAULT_USER_NAME,
                                           perm='repository.none')
         try:
-            fork_name = u'api-repo-fork'
+            fork_name = 'api-repo-fork'
             id_, params = _build_data(self.apikey_regular, 'fork_repo',
                                       repoid=self.REPO,
                                       fork_name=fork_name,
@@ -1376,7 +1341,7 @@
             self._compare_error(id_, expected, given=response.body)
         finally:
             RepoModel().grant_user_permission(repo=self.REPO,
-                                              user=self.default_user_username,
+                                              user=User.DEFAULT_USER_NAME,
                                               perm='repository.read')
             fixture.destroy_repo(fork_name)
 
@@ -1386,7 +1351,7 @@
         ('admin', 'repository.admin'),
     ])
     def test_api_fork_repo_non_admin_no_create_repo_permission(self, name, perm):
-        fork_name = u'api-repo-fork'
+        fork_name = 'api-repo-fork'
         # regardless of base repository permission, forking is disallowed
         # when repository creation is disabled
         RepoModel().grant_user_permission(repo=self.REPO,
@@ -1404,7 +1369,7 @@
         fixture.destroy_repo(fork_name)
 
     def test_api_fork_repo_unknown_owner(self):
-        fork_name = u'api-repo-fork'
+        fork_name = 'api-repo-fork'
         owner = 'i-dont-exist'
         id_, params = _build_data(self.apikey, 'fork_repo',
                                   repoid=self.REPO,
@@ -1416,11 +1381,11 @@
         self._compare_error(id_, expected, given=response.body)
 
     def test_api_fork_repo_fork_exists(self):
-        fork_name = u'api-repo-fork'
+        fork_name = 'api-repo-fork'
         fixture.create_fork(self.REPO, fork_name)
 
         try:
-            fork_name = u'api-repo-fork'
+            fork_name = 'api-repo-fork'
 
             id_, params = _build_data(self.apikey, 'fork_repo',
                                       repoid=self.REPO,
@@ -1449,7 +1414,7 @@
 
     @mock.patch.object(RepoModel, 'create_fork', crash)
     def test_api_fork_repo_exception_occurred(self):
-        fork_name = u'api-repo-fork'
+        fork_name = 'api-repo-fork'
         id_, params = _build_data(self.apikey, 'fork_repo',
                                   repoid=self.REPO,
                                   fork_name=fork_name,
@@ -1478,7 +1443,7 @@
         self._compare_ok(id_, expected, given=response.body)
 
     def test_api_get_user_groups(self):
-        gr_name = u'test_user_group2'
+        gr_name = 'test_user_group2'
         make_user_group(gr_name)
 
         try:
@@ -1486,7 +1451,7 @@
             response = api_call(self, params)
 
             expected = []
-            for gr_name in [TEST_USER_GROUP, u'test_user_group2']:
+            for gr_name in [TEST_USER_GROUP, 'test_user_group2']:
                 user_group = UserGroupModel().get_group(gr_name)
                 ret = user_group.get_api_data()
                 expected.append(ret)
@@ -1495,7 +1460,7 @@
             fixture.destroy_user_group(gr_name)
 
     def test_api_create_user_group(self):
-        group_name = u'some_new_group'
+        group_name = 'some_new_group'
         id_, params = _build_data(self.apikey, 'create_user_group',
                                   group_name=group_name)
         response = api_call(self, params)
@@ -1521,7 +1486,7 @@
 
     @mock.patch.object(UserGroupModel, 'create', crash)
     def test_api_get_user_group_exception_occurred(self):
-        group_name = u'exception_happens'
+        group_name = 'exception_happens'
         id_, params = _build_data(self.apikey, 'create_user_group',
                                   group_name=group_name)
         response = api_call(self, params)
@@ -1530,14 +1495,14 @@
         self._compare_error(id_, expected, given=response.body)
 
     @base.parametrize('changing_attr,updates', [
-        ('group_name', {'group_name': u'new_group_name'}),
-        ('group_name', {'group_name': u'test_group_for_update'}),
+        ('group_name', {'group_name': 'new_group_name'}),
+        ('group_name', {'group_name': 'test_group_for_update'}),
         ('owner', {'owner': base.TEST_USER_REGULAR_LOGIN}),
         ('active', {'active': False}),
         ('active', {'active': True}),
     ])
     def test_api_update_user_group(self, changing_attr, updates):
-        gr_name = u'test_group_for_update'
+        gr_name = 'test_group_for_update'
         user_group = fixture.create_user_group(gr_name)
         try:
             id_, params = _build_data(self.apikey, 'update_user_group',
@@ -1557,7 +1522,7 @@
 
     @mock.patch.object(UserGroupModel, 'update', crash)
     def test_api_update_user_group_exception_occurred(self):
-        gr_name = u'test_group'
+        gr_name = 'test_group'
         fixture.create_user_group(gr_name)
         try:
             id_, params = _build_data(self.apikey, 'update_user_group',
@@ -1569,7 +1534,7 @@
             fixture.destroy_user_group(gr_name)
 
     def test_api_add_user_to_user_group(self):
-        gr_name = u'test_group'
+        gr_name = 'test_group'
         fixture.create_user_group(gr_name)
         try:
             id_, params = _build_data(self.apikey, 'add_user_to_user_group',
@@ -1596,7 +1561,7 @@
 
     @mock.patch.object(UserGroupModel, 'add_user_to_group', crash)
     def test_api_add_user_to_user_group_exception_occurred(self):
-        gr_name = u'test_group'
+        gr_name = 'test_group'
         fixture.create_user_group(gr_name)
         try:
             id_, params = _build_data(self.apikey, 'add_user_to_user_group',
@@ -1609,7 +1574,7 @@
             fixture.destroy_user_group(gr_name)
 
     def test_api_remove_user_from_user_group(self):
-        gr_name = u'test_group_3'
+        gr_name = 'test_group_3'
         gr = fixture.create_user_group(gr_name)
         UserGroupModel().add_user_to_group(gr, user=base.TEST_USER_ADMIN_LOGIN)
         Session().commit()
@@ -1629,7 +1594,7 @@
 
     @mock.patch.object(UserGroupModel, 'remove_user_from_group', crash)
     def test_api_remove_user_from_user_group_exception_occurred(self):
-        gr_name = u'test_group_3'
+        gr_name = 'test_group_3'
         gr = fixture.create_user_group(gr_name)
         UserGroupModel().add_user_to_group(gr, user=base.TEST_USER_ADMIN_LOGIN)
         Session().commit()
@@ -1644,7 +1609,7 @@
             fixture.destroy_user_group(gr_name)
 
     def test_api_delete_user_group(self):
-        gr_name = u'test_group'
+        gr_name = 'test_group'
         ugroup = fixture.create_user_group(gr_name)
         gr_id = ugroup.users_group_id
         try:
@@ -1661,7 +1626,7 @@
                 fixture.destroy_user_group(gr_name)
 
     def test_api_delete_user_group_that_is_assigned(self):
-        gr_name = u'test_group'
+        gr_name = 'test_group'
         ugroup = fixture.create_user_group(gr_name)
         gr_id = ugroup.users_group_id
 
@@ -1679,7 +1644,7 @@
                 fixture.destroy_user_group(gr_name)
 
     def test_api_delete_user_group_exception_occurred(self):
-        gr_name = u'test_group'
+        gr_name = 'test_group'
         ugroup = fixture.create_user_group(gr_name)
         gr_id = ugroup.users_group_id
         id_, params = _build_data(self.apikey, 'delete_user_group',
@@ -2467,7 +2432,7 @@
         id_, params = _build_data(self.apikey, 'get_changeset',
                                   repoid=self.REPO, raw_id = '7ab37bc680b4aa72c34d07b230c866c28e9fcfff')
         response = api_call(self, params)
-        expected = u'Changeset %s does not exist' % ('7ab37bc680b4aa72c34d07b230c866c28e9fcfff',)
+        expected = 'Changeset %s does not exist' % ('7ab37bc680b4aa72c34d07b230c866c28e9fcfff',)
         self._compare_error(id_, expected, given=response.body)
 
     def test_api_get_changeset_without_permission(self):
@@ -2477,11 +2442,11 @@
         id_, params = _build_data(self.apikey_regular, 'get_changeset',
                                   repoid=self.REPO, raw_id=self.TEST_REVISION)
         response = api_call(self, params)
-        expected = u'Access denied to repo %s' % self.REPO
+        expected = 'Access denied to repo %s' % self.REPO
         self._compare_error(id_, expected, given=response.body)
 
     def test_api_get_pullrequest(self):
-        pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, u'get test')
+        pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'get test')
         random_id = random.randrange(1, 9999)
         params = ascii_bytes(ext_json.dumps({
             "id": random_id,
@@ -2512,7 +2477,7 @@
                                       b"2000-01-01T00:00:00", response.body))
 
     def test_api_close_pullrequest(self):
-        pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, u'close test')
+        pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, 'close test')
         random_id = random.randrange(1, 9999)
         params = ascii_bytes(ext_json.dumps({
             "id": random_id,
@@ -2528,7 +2493,7 @@
         assert pullrequest.is_closed() == True
 
     def test_api_status_pullrequest(self):
-        pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, u"status test")
+        pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, "status test")
 
         random_id = random.randrange(1, 9999)
         params = ascii_bytes(ext_json.dumps({
@@ -2553,7 +2518,7 @@
         assert ChangesetStatus.STATUS_APPROVED == ChangesetStatusModel().calculate_pull_request_result(pullrequest)[2]
 
     def test_api_comment_pullrequest(self):
-        pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, u"comment test")
+        pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, "comment test")
         random_id = random.randrange(1, 9999)
         params = ascii_bytes(ext_json.dumps({
             "id": random_id,
@@ -2564,4 +2529,4 @@
         response = api_call(self, params)
         self._compare_ok(random_id, True, given=response.body)
         pullrequest = PullRequest().get(pull_request_id)
-        assert pullrequest.comments[-1].text == u'Looks good to me'
+        assert pullrequest.comments[-1].text == 'Looks good to me'
--- a/kallithea/tests/api/test_api_git.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/api/test_api_git.py	Mon Apr 27 13:25:28 2020 +0200
@@ -20,9 +20,9 @@
     REPO = GIT_REPO
     REPO_TYPE = 'git'
     TEST_REVISION = GIT_TEST_REVISION
-    TEST_PR_SRC = u'c60f01b77c42dce653d6b1d3b04689862c261929'
-    TEST_PR_DST = u'10cddef6b794696066fb346434014f0a56810218'
-    TEST_PR_REVISIONS = [u'1bead5880d2dbe831762bf7fb439ba2919b75fdd',
-                         u'9bcd3ecfc8832a8cd881c1c1bbe2d13ffa9d94c7',
-                         u'283de4dfca8479875a1befb8d4059f3bbb725145',
-                         u'c60f01b77c42dce653d6b1d3b04689862c261929']
+    TEST_PR_SRC = 'c60f01b77c42dce653d6b1d3b04689862c261929'
+    TEST_PR_DST = '10cddef6b794696066fb346434014f0a56810218'
+    TEST_PR_REVISIONS = ['1bead5880d2dbe831762bf7fb439ba2919b75fdd',
+                         '9bcd3ecfc8832a8cd881c1c1bbe2d13ffa9d94c7',
+                         '283de4dfca8479875a1befb8d4059f3bbb725145',
+                         'c60f01b77c42dce653d6b1d3b04689862c261929']
--- a/kallithea/tests/api/test_api_hg.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/api/test_api_hg.py	Mon Apr 27 13:25:28 2020 +0200
@@ -20,10 +20,10 @@
     REPO = HG_REPO
     REPO_TYPE = 'hg'
     TEST_REVISION = HG_TEST_REVISION
-    TEST_PR_SRC = u'4f7e2131323e0749a740c0a56ab68ae9269c562a'
-    TEST_PR_DST = u'92831aebf2f8dd4879e897024b89d09af214df1c'
-    TEST_PR_REVISIONS = [u'720bbdb27665d6262b313e8a541b654d0cbd5b27',
-                         u'f41649565a9e89919a588a163e717b4084f8a3b1',
-                         u'94f45ed825a113e61af7e141f44ca578374abef0',
-                         u'fef5bfe1dc17611d5fb59a7f6f95c55c3606f933',
-                         u'4f7e2131323e0749a740c0a56ab68ae9269c562a']
+    TEST_PR_SRC = '4f7e2131323e0749a740c0a56ab68ae9269c562a'
+    TEST_PR_DST = '92831aebf2f8dd4879e897024b89d09af214df1c'
+    TEST_PR_REVISIONS = ['720bbdb27665d6262b313e8a541b654d0cbd5b27',
+                         'f41649565a9e89919a588a163e717b4084f8a3b1',
+                         '94f45ed825a113e61af7e141f44ca578374abef0',
+                         'fef5bfe1dc17611d5fb59a7f6f95c55c3606f933',
+                         '4f7e2131323e0749a740c0a56ab68ae9269c562a']
--- a/kallithea/tests/base.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/base.py	Mon Apr 27 13:25:28 2020 +0200
@@ -66,17 +66,17 @@
 
 IP_ADDR = '127.0.0.127'
 
-HG_REPO = u'vcs_test_hg'
-GIT_REPO = u'vcs_test_git'
+HG_REPO = 'vcs_test_hg'
+GIT_REPO = 'vcs_test_git'
 
-NEW_HG_REPO = u'vcs_test_hg_new'
-NEW_GIT_REPO = u'vcs_test_git_new'
+NEW_HG_REPO = 'vcs_test_hg_new'
+NEW_GIT_REPO = 'vcs_test_git_new'
 
-HG_FORK = u'vcs_test_hg_fork'
-GIT_FORK = u'vcs_test_git_fork'
+HG_FORK = 'vcs_test_hg_fork'
+GIT_FORK = 'vcs_test_git_fork'
 
-HG_TEST_REVISION = u"a53d9201d4bc278910d416d94941b7ea007ecd52"
-GIT_TEST_REVISION = u"7ab37bc680b4aa72c34d07b230c866c28e9fc204"
+HG_TEST_REVISION = "a53d9201d4bc278910d416d94941b7ea007ecd52"
+GIT_TEST_REVISION = "7ab37bc680b4aa72c34d07b230c866c28e9fc204"
 
 
 ## VCS
@@ -180,14 +180,14 @@
 
     def checkSessionFlash(self, response, msg=None, skip=0, _matcher=lambda msg, m: msg in m):
         if 'flash' not in response.session:
-            pytest.fail(u'msg `%s` not found - session has no flash:\n%s' % (msg, response))
+            pytest.fail('msg `%s` not found - session has no flash:\n%s' % (msg, response))
         try:
             level, m = response.session['flash'][-1 - skip]
             if _matcher(msg, m):
                 return
         except IndexError:
             pass
-        pytest.fail(u'msg `%s` not found in session flash (skipping %s): %s' %
+        pytest.fail('msg `%s` not found in session flash (skipping %s): %s' %
                     (msg, skip, ', '.join('`%s`' % m for level, m in response.session['flash'])))
 
     def checkSessionFlashRegex(self, response, regex, skip=0):
--- a/kallithea/tests/conftest.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/conftest.py	Mon Apr 27 13:25:28 2020 +0200
@@ -45,7 +45,6 @@
             #'ssh_locale': 'C',
             'app_instance_uuid': 'test',
             'show_revision_number': 'true',
-            'beaker.cache.sql_cache_short.expire': '1',
             'session.secret': '{74e0cd75-b339-478b-b129-07dd221def1f}',
             #'i18n.lang': '',
         },
@@ -146,7 +145,7 @@
     user_model = UserModel()
 
     user_ids = []
-    user_ids.append(User.get_default_user().user_id)
+    user_ids.append(kallithea.DEFAULT_USER_ID)
     user_ids.append(User.get_by_username(TEST_USER_REGULAR_LOGIN).user_id)
 
     for user_id in user_ids:
--- a/kallithea/tests/fixture.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/fixture.py	Mon Apr 27 13:25:28 2020 +0200
@@ -41,8 +41,8 @@
 from kallithea.model.scm import ScmModel
 from kallithea.model.user import UserModel
 from kallithea.model.user_group import UserGroupModel
-from kallithea.tests.base import (
-    GIT_REPO, HG_REPO, IP_ADDR, TEST_USER_ADMIN_EMAIL, TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN, TESTS_TMP_PATH, invalidate_all_caches)
+from kallithea.tests.base import (GIT_REPO, HG_REPO, IP_ADDR, TEST_USER_ADMIN_EMAIL, TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN, TESTS_TMP_PATH,
+                                  invalidate_all_caches)
 
 
 log = logging.getLogger(__name__)
@@ -92,8 +92,8 @@
             repo_name=None,
             repo_type='hg',
             clone_uri='',
-            repo_group=u'-1',
-            repo_description=u'DESC',
+            repo_group='-1',
+            repo_description='DESC',
             repo_private=False,
             repo_landing_rev='rev:tip',
             repo_copy_permissions=False,
@@ -113,8 +113,8 @@
         """Return form values to be validated through RepoGroupForm"""
         defs = dict(
             group_name=None,
-            group_description=u'DESC',
-            parent_group_id=u'-1',
+            group_description='DESC',
+            parent_group_id='-1',
             perms_updates=[],
             perms_new=[],
             recursive=False
@@ -128,8 +128,8 @@
             username=name,
             password='qweqwe',
             email='%s+test@example.com' % name,
-            firstname=u'TestUser',
-            lastname=u'Test',
+            firstname='TestUser',
+            lastname='Test',
             active=True,
             admin=False,
             extern_type='internal',
@@ -142,7 +142,7 @@
     def _get_user_group_create_params(self, name, **custom):
         defs = dict(
             users_group_name=name,
-            user_group_description=u'DESC',
+            user_group_description='DESC',
             users_group_active=True,
             user_group_data={},
         )
@@ -253,7 +253,7 @@
 
     def create_gist(self, **kwargs):
         form_data = {
-            'description': u'new-gist',
+            'description': 'new-gist',
             'owner': TEST_USER_ADMIN_LOGIN,
             'gist_type': Gist.GIST_PUBLIC,
             'lifetime': -1,
@@ -324,12 +324,12 @@
         return cs
 
     def review_changeset(self, repo, revision, status, author=TEST_USER_ADMIN_LOGIN):
-        comment = ChangesetCommentsModel().create(u"review comment", repo, author, revision=revision, send_email=False)
+        comment = ChangesetCommentsModel().create("review comment", repo, author, revision=revision, send_email=False)
         csm = ChangesetStatusModel().set_status(repo, ChangesetStatus.STATUS_APPROVED, author, comment, revision=revision)
         Session().commit()
         return csm
 
-    def create_pullrequest(self, testcontroller, repo_name, pr_src_rev, pr_dst_rev, title=u'title'):
+    def create_pullrequest(self, testcontroller, repo_name, pr_src_rev, pr_dst_rev, title='title'):
         org_ref = 'branch:stable:%s' % pr_src_rev
         other_ref = 'branch:default:%s' % pr_dst_rev
         with test_context(testcontroller.app): # needed to be able to mock request user
@@ -339,7 +339,7 @@
             request.authuser = AuthUser(dbuser=owner_user)
             # creating a PR sends a message with an absolute URL - without routing that requires mocking
             with mock.patch.object(helpers, 'url', (lambda arg, qualified=False, **kwargs: ('https://localhost' if qualified else '') + '/fake/' + arg)):
-                cmd = CreatePullRequestAction(org_repo, other_repo, org_ref, other_ref, title, u'No description', owner_user, reviewers)
+                cmd = CreatePullRequestAction(org_repo, other_repo, org_ref, other_ref, title, 'No description', owner_user, reviewers)
                 pull_request = cmd.execute()
             Session().commit()
         return pull_request.pull_request_id
--- a/kallithea/tests/functional/test_admin_auth_settings.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_admin_auth_settings.py	Mon Apr 27 13:25:28 2020 +0200
@@ -26,7 +26,7 @@
         self.log_user()
 
         params = self._enable_plugins('kallithea.lib.auth_modules.auth_internal,kallithea.lib.auth_modules.auth_ldap')
-        params.update({'auth_ldap_host': u'dc.example.com',
+        params.update({'auth_ldap_host': 'dc.example.com',
                        'auth_ldap_port': '999',
                        'auth_ldap_tls_kind': 'PLAIN',
                        'auth_ldap_tls_reqcert': 'NEVER',
@@ -48,7 +48,7 @@
         self.checkSessionFlash(response, 'Auth settings updated successfully')
 
         new_settings = Setting.get_auth_settings()
-        assert new_settings['auth_ldap_host'] == u'dc.example.com', 'fail db write compare'
+        assert new_settings['auth_ldap_host'] == 'dc.example.com', 'fail db write compare'
 
     @base.skipif(not base.ldap_lib_installed, reason='skipping due to missing ldap lib')
     def test_ldap_error_form_wrong_port_number(self):
@@ -239,7 +239,7 @@
         self.checkSessionFlash(response, 'Auth settings updated successfully')
 
         new_settings = Setting.get_auth_settings()
-        assert new_settings['auth_crowd_host'] == u'hostname', 'fail db write compare'
+        assert new_settings['auth_crowd_host'] == 'hostname', 'fail db write compare'
 
     @base.skipif(not base.pam_lib_installed, reason='skipping due to missing pam lib')
     def test_pam_save_settings(self):
@@ -256,4 +256,4 @@
         self.checkSessionFlash(response, 'Auth settings updated successfully')
 
         new_settings = Setting.get_auth_settings()
-        assert new_settings['auth_pam_service'] == u'kallithea', 'fail db write compare'
+        assert new_settings['auth_pam_service'] == 'kallithea', 'fail db write compare'
--- a/kallithea/tests/functional/test_admin_gists.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_admin_gists.py	Mon Apr 27 13:25:28 2020 +0200
@@ -5,7 +5,7 @@
 
 
 def _create_gist(f_name, content='some gist', lifetime=-1,
-                 description=u'gist-desc', gist_type='public',
+                 description='gist-desc', gist_type='public',
                  owner=base.TEST_USER_ADMIN_LOGIN):
     gist_mapping = {
         f_name: {'content': content}
@@ -33,7 +33,7 @@
 
         g1 = _create_gist('gist1').gist_access_id
         g2 = _create_gist('gist2', lifetime=1400).gist_access_id
-        g3 = _create_gist('gist3', description=u'gist3-desc').gist_access_id
+        g3 = _create_gist('gist3', description='gist3-desc').gist_access_id
         g4 = _create_gist('gist4', gist_type='private').gist_access_id
         response = self.app.get(base.url('gists'))
         # Test response...
--- a/kallithea/tests/functional/test_admin_permissions.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_admin_permissions.py	Mon Apr 27 13:25:28 2020 +0200
@@ -1,3 +1,4 @@
+import kallithea
 from kallithea.model.db import User, UserIpMap
 from kallithea.tests import base
 
@@ -17,7 +18,7 @@
 
     def test_add_delete_ips(self, auto_clear_ip_permissions):
         self.log_user()
-        default_user_id = User.get_default_user().user_id
+        default_user_id = kallithea.DEFAULT_USER_ID
 
         # Add IP and verify it is shown in UI and both gives access and rejects
 
--- a/kallithea/tests/functional/test_admin_repo_groups.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_admin_repo_groups.py	Mon Apr 27 13:25:28 2020 +0200
@@ -11,7 +11,7 @@
 
     def test_case_insensitivity(self):
         self.log_user()
-        group_name = u'newgroup'
+        group_name = 'newgroup'
         response = self.app.post(url('repos_groups'),
                                  fixture._get_repo_group_create_params(group_name=group_name,
                                                                  _session_csrf_secret_token=self.session_csrf_secret_token()))
--- a/kallithea/tests/functional/test_admin_repos.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_admin_repos.py	Mon Apr 27 13:25:28 2020 +0200
@@ -7,7 +7,8 @@
 import pytest
 
 from kallithea.lib import vcs
-from kallithea.model.db import Permission, RepoGroup, Repository, Ui, User, UserRepoToPerm
+from kallithea.model import db
+from kallithea.model.db import Permission, Repository, Ui, User, UserRepoToPerm
 from kallithea.model.meta import Session
 from kallithea.model.repo import RepoModel
 from kallithea.model.repo_group import RepoGroupModel
@@ -45,7 +46,7 @@
     def test_create(self):
         self.log_user()
         repo_name = self.NEW_REPO
-        description = u'description for newly created repo'
+        description = 'description for newly created repo'
         response = self.app.post(base.url('repos'),
                         fixture._get_repo_create_params(repo_private=False,
                                                 repo_name=repo_name,
@@ -54,7 +55,7 @@
                                                 _session_csrf_secret_token=self.session_csrf_secret_token()))
         ## run the check page that triggers the flash message
         response = self.app.get(base.url('repo_check_home', repo_name=repo_name))
-        assert response.json == {u'result': True}
+        assert response.json == {'result': True}
         self.checkSessionFlash(response,
                                'Created repository <a href="/%s">%s</a>'
                                % (repo_name, repo_name))
@@ -83,7 +84,7 @@
     def test_case_insensitivity(self):
         self.log_user()
         repo_name = self.NEW_REPO
-        description = u'description for newly created repo'
+        description = 'description for newly created repo'
         response = self.app.post(base.url('repos'),
                                  fixture._get_repo_create_params(repo_private=False,
                                                                  repo_name=repo_name,
@@ -107,15 +108,15 @@
         self.log_user()
 
         ## create GROUP
-        group_name = u'sometest_%s' % self.REPO_TYPE
+        group_name = 'sometest_%s' % self.REPO_TYPE
         gr = RepoGroupModel().create(group_name=group_name,
-                                     group_description=u'test',
+                                     group_description='test',
                                      owner=base.TEST_USER_ADMIN_LOGIN)
         Session().commit()
 
-        repo_name = u'ingroup'
-        repo_name_full = RepoGroup.url_sep().join([group_name, repo_name])
-        description = u'description for newly created repo'
+        repo_name = 'ingroup'
+        repo_name_full = db.URL_SEP.join([group_name, repo_name])
+        description = 'description for newly created repo'
         response = self.app.post(base.url('repos'),
                         fixture._get_repo_create_params(repo_private=False,
                                                 repo_name=repo_name,
@@ -125,7 +126,7 @@
                                                 _session_csrf_secret_token=self.session_csrf_secret_token()))
         ## run the check page that triggers the flash message
         response = self.app.get(base.url('repo_check_home', repo_name=repo_name_full))
-        assert response.json == {u'result': True}
+        assert response.json == {'result': True}
         self.checkSessionFlash(response,
                                'Created repository <a href="/%s">%s</a>'
                                % (repo_name_full, repo_name_full))
@@ -165,10 +166,10 @@
         # revoke
         user_model = UserModel()
         # disable fork and create on default user
-        user_model.revoke_perm(User.DEFAULT_USER, 'hg.create.repository')
-        user_model.grant_perm(User.DEFAULT_USER, 'hg.create.none')
-        user_model.revoke_perm(User.DEFAULT_USER, 'hg.fork.repository')
-        user_model.grant_perm(User.DEFAULT_USER, 'hg.fork.none')
+        user_model.revoke_perm(User.DEFAULT_USER_NAME, 'hg.create.repository')
+        user_model.grant_perm(User.DEFAULT_USER_NAME, 'hg.create.none')
+        user_model.revoke_perm(User.DEFAULT_USER_NAME, 'hg.fork.repository')
+        user_model.grant_perm(User.DEFAULT_USER_NAME, 'hg.fork.none')
 
         # disable on regular user
         user_model.revoke_perm(base.TEST_USER_REGULAR_LOGIN, 'hg.create.repository')
@@ -178,21 +179,21 @@
         Session().commit()
 
         ## create GROUP
-        group_name = u'reg_sometest_%s' % self.REPO_TYPE
+        group_name = 'reg_sometest_%s' % self.REPO_TYPE
         gr = RepoGroupModel().create(group_name=group_name,
-                                     group_description=u'test',
+                                     group_description='test',
                                      owner=base.TEST_USER_ADMIN_LOGIN)
         Session().commit()
 
-        group_name_allowed = u'reg_sometest_allowed_%s' % self.REPO_TYPE
+        group_name_allowed = 'reg_sometest_allowed_%s' % self.REPO_TYPE
         gr_allowed = RepoGroupModel().create(group_name=group_name_allowed,
-                                     group_description=u'test',
+                                     group_description='test',
                                      owner=base.TEST_USER_REGULAR_LOGIN)
         Session().commit()
 
-        repo_name = u'ingroup'
-        repo_name_full = RepoGroup.url_sep().join([group_name, repo_name])
-        description = u'description for newly created repo'
+        repo_name = 'ingroup'
+        repo_name_full = db.URL_SEP.join([group_name, repo_name])
+        description = 'description for newly created repo'
         response = self.app.post(base.url('repos'),
                         fixture._get_repo_create_params(repo_private=False,
                                                 repo_name=repo_name,
@@ -204,9 +205,9 @@
         response.mustcontain('Invalid value')
 
         # user is allowed to create in this group
-        repo_name = u'ingroup'
-        repo_name_full = RepoGroup.url_sep().join([group_name_allowed, repo_name])
-        description = u'description for newly created repo'
+        repo_name = 'ingroup'
+        repo_name_full = db.URL_SEP.join([group_name_allowed, repo_name])
+        description = 'description for newly created repo'
         response = self.app.post(base.url('repos'),
                         fixture._get_repo_create_params(repo_private=False,
                                                 repo_name=repo_name,
@@ -217,7 +218,7 @@
 
         ## run the check page that triggers the flash message
         response = self.app.get(base.url('repo_check_home', repo_name=repo_name_full))
-        assert response.json == {u'result': True}
+        assert response.json == {'result': True}
         self.checkSessionFlash(response,
                                'Created repository <a href="/%s">%s</a>'
                                % (repo_name_full, repo_name_full))
@@ -255,9 +256,9 @@
         self.log_user()
 
         ## create GROUP
-        group_name = u'sometest_%s' % self.REPO_TYPE
+        group_name = 'sometest_%s' % self.REPO_TYPE
         gr = RepoGroupModel().create(group_name=group_name,
-                                     group_description=u'test',
+                                     group_description='test',
                                      owner=base.TEST_USER_ADMIN_LOGIN)
         perm = Permission.get_by_key('repository.write')
         RepoGroupModel().grant_user_permission(gr, base.TEST_USER_REGULAR_LOGIN, perm)
@@ -265,9 +266,9 @@
         ## add repo permissions
         Session().commit()
 
-        repo_name = u'ingroup_inherited_%s' % self.REPO_TYPE
-        repo_name_full = RepoGroup.url_sep().join([group_name, repo_name])
-        description = u'description for newly created repo'
+        repo_name = 'ingroup_inherited_%s' % self.REPO_TYPE
+        repo_name_full = db.URL_SEP.join([group_name, repo_name])
+        description = 'description for newly created repo'
         response = self.app.post(base.url('repos'),
                         fixture._get_repo_create_params(repo_private=False,
                                                 repo_name=repo_name,
@@ -320,7 +321,7 @@
     def test_create_remote_repo_wrong_clone_uri(self):
         self.log_user()
         repo_name = self.NEW_REPO
-        description = u'description for newly created repo'
+        description = 'description for newly created repo'
         response = self.app.post(base.url('repos'),
                         fixture._get_repo_create_params(repo_private=False,
                                                 repo_name=repo_name,
@@ -333,7 +334,7 @@
     def test_create_remote_repo_wrong_clone_uri_hg_svn(self):
         self.log_user()
         repo_name = self.NEW_REPO
-        description = u'description for newly created repo'
+        description = 'description for newly created repo'
         response = self.app.post(base.url('repos'),
                         fixture._get_repo_create_params(repo_private=False,
                                                 repo_name=repo_name,
@@ -345,8 +346,8 @@
 
     def test_delete(self):
         self.log_user()
-        repo_name = u'vcs_test_new_to_delete_%s' % self.REPO_TYPE
-        description = u'description for newly created repo'
+        repo_name = 'vcs_test_new_to_delete_%s' % self.REPO_TYPE
+        description = 'description for newly created repo'
         response = self.app.post(base.url('repos'),
                         fixture._get_repo_create_params(repo_private=False,
                                                 repo_type=self.REPO_TYPE,
@@ -404,9 +405,9 @@
                                                 _session_csrf_secret_token=self.session_csrf_secret_token()))
         ## run the check page that triggers the flash message
         response = self.app.get(base.url('repo_check_home', repo_name=repo_name))
-        assert response.json == {u'result': True}
+        assert response.json == {'result': True}
         self.checkSessionFlash(response,
-                               u'Created repository <a href="/%s">%s</a>'
+                               'Created repository <a href="/%s">%s</a>'
                                % (urllib.parse.quote(repo_name), repo_name))
         # test if the repo was created in the database
         new_repo = Session().query(Repository) \
@@ -505,7 +506,7 @@
 
     def test_set_fork_of_other_repo(self):
         self.log_user()
-        other_repo = u'other_%s' % self.REPO_TYPE
+        other_repo = 'other_%s' % self.REPO_TYPE
         fixture.create_repo(other_repo, repo_type=self.REPO_TYPE)
         repo = Repository.get_by_repo_name(self.REPO)
         repo2 = Repository.get_by_repo_name(other_repo)
@@ -562,10 +563,10 @@
         # revoke
         user_model = UserModel()
         # disable fork and create on default user
-        user_model.revoke_perm(User.DEFAULT_USER, 'hg.create.repository')
-        user_model.grant_perm(User.DEFAULT_USER, 'hg.create.none')
-        user_model.revoke_perm(User.DEFAULT_USER, 'hg.fork.repository')
-        user_model.grant_perm(User.DEFAULT_USER, 'hg.fork.none')
+        user_model.revoke_perm(User.DEFAULT_USER_NAME, 'hg.create.repository')
+        user_model.grant_perm(User.DEFAULT_USER_NAME, 'hg.create.none')
+        user_model.revoke_perm(User.DEFAULT_USER_NAME, 'hg.fork.repository')
+        user_model.grant_perm(User.DEFAULT_USER_NAME, 'hg.fork.none')
 
         # disable on regular user
         user_model.revoke_perm(base.TEST_USER_REGULAR_LOGIN, 'hg.create.repository')
@@ -577,7 +578,7 @@
 
         user = User.get(usr['user_id'])
 
-        repo_name = self.NEW_REPO + u'no_perms'
+        repo_name = self.NEW_REPO + 'no_perms'
         description = 'description for newly created repo'
         response = self.app.post(base.url('repos'),
                         fixture._get_repo_create_params(repo_private=False,
--- a/kallithea/tests/functional/test_admin_user_groups.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_admin_user_groups.py	Mon Apr 27 13:25:28 2020 +0200
@@ -4,7 +4,7 @@
 from kallithea.tests import base
 
 
-TEST_USER_GROUP = u'admins_test'
+TEST_USER_GROUP = 'admins_test'
 
 
 class TestAdminUsersGroupsController(base.TestController):
@@ -19,7 +19,7 @@
         users_group_name = TEST_USER_GROUP
         response = self.app.post(base.url('users_groups'),
                                  {'users_group_name': users_group_name,
-                                  'user_group_description': u'DESC',
+                                  'user_group_description': 'DESC',
                                   'active': True,
                                   '_session_csrf_secret_token': self.session_csrf_secret_token()})
         response.follow()
@@ -44,7 +44,7 @@
         users_group_name = TEST_USER_GROUP + 'another'
         response = self.app.post(base.url('users_groups'),
                                  {'users_group_name': users_group_name,
-                                  'user_group_description': u'DESC',
+                                  'user_group_description': 'DESC',
                                   'active': True,
                                   '_session_csrf_secret_token': self.session_csrf_secret_token()})
         response.follow()
@@ -68,7 +68,7 @@
         users_group_name = TEST_USER_GROUP + 'another2'
         response = self.app.post(base.url('users_groups'),
                                  {'users_group_name': users_group_name,
-                                  'user_group_description': u'DESC',
+                                  'user_group_description': 'DESC',
                                   'active': True,
                                   '_session_csrf_secret_token': self.session_csrf_secret_token()})
         response.follow()
@@ -137,7 +137,7 @@
         users_group_name = TEST_USER_GROUP + 'another2'
         response = self.app.post(base.url('users_groups'),
                                  {'users_group_name': users_group_name,
-                                  'user_group_description': u'DESC',
+                                  'user_group_description': 'DESC',
                                   'active': True,
                                   '_session_csrf_secret_token': self.session_csrf_secret_token()})
         response.follow()
--- a/kallithea/tests/functional/test_admin_users.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_admin_users.py	Mon Apr 27 13:25:28 2020 +0200
@@ -17,6 +17,7 @@
 from tg.util.webtest import test_context
 from webob.exc import HTTPNotFound
 
+import kallithea
 from kallithea.controllers.admin.users import UsersController
 from kallithea.lib import helpers as h
 from kallithea.lib.auth import check_password
@@ -34,7 +35,7 @@
 @pytest.fixture
 def user_and_repo_group_fail():
     username = 'repogrouperr'
-    groupname = u'repogroup_fail'
+    groupname = 'repogroup_fail'
     user = fixture.create_user(name=username)
     repo_group = fixture.create_repo_group(name=groupname, cur_user=username)
     yield user, repo_group
@@ -62,8 +63,8 @@
         username = 'newtestuser'
         password = 'test12'
         password_confirmation = password
-        name = u'name'
-        lastname = u'lastname'
+        name = 'name'
+        lastname = 'lastname'
         email = 'mail@example.com'
 
         response = self.app.post(base.url('new_user'),
@@ -98,8 +99,8 @@
         self.log_user()
         username = 'new_user'
         password = ''
-        name = u'name'
-        lastname = u'lastname'
+        name = 'name'
+        lastname = 'lastname'
         email = 'errmail.example.com'
 
         response = self.app.post(base.url('new_user'),
@@ -194,7 +195,7 @@
     def test_delete_repo_err(self):
         self.log_user()
         username = 'repoerr'
-        reponame = u'repoerr_fail'
+        reponame = 'repoerr_fail'
 
         fixture.create_user(name=username)
         fixture.create_repo(name=reponame, cur_user=username)
@@ -245,7 +246,7 @@
     def test_delete_user_group_err(self):
         self.log_user()
         username = 'usergrouperr'
-        groupname = u'usergroup_fail'
+        groupname = 'usergroup_fail'
 
         fixture.create_user(name=username)
         ug = fixture.create_user_group(name=groupname, cur_user=username)
@@ -280,8 +281,8 @@
         perm_create = Permission.get_by_key('hg.create.repository')
 
         user = UserModel().create_or_update(username='dummy', password='qwe',
-                                            email='dummy', firstname=u'a',
-                                            lastname=u'b')
+                                            email='dummy', firstname='a',
+                                            lastname='b')
         Session().commit()
         uid = user.user_id
 
@@ -310,8 +311,8 @@
         perm_create = Permission.get_by_key('hg.create.repository')
 
         user = UserModel().create_or_update(username='dummy', password='qwe',
-                                            email='dummy', firstname=u'a',
-                                            lastname=u'b')
+                                            email='dummy', firstname='a',
+                                            lastname='b')
         Session().commit()
         uid = user.user_id
 
@@ -339,8 +340,8 @@
         perm_fork = Permission.get_by_key('hg.fork.repository')
 
         user = UserModel().create_or_update(username='dummy', password='qwe',
-                                            email='dummy', firstname=u'a',
-                                            lastname=u'b')
+                                            email='dummy', firstname='a',
+                                            lastname='b')
         Session().commit()
         uid = user.user_id
 
@@ -369,8 +370,8 @@
         perm_fork = Permission.get_by_key('hg.fork.repository')
 
         user = UserModel().create_or_update(username='dummy', password='qwe',
-                                            email='dummy', firstname=u'a',
-                                            lastname=u'b')
+                                            email='dummy', firstname='a',
+                                            lastname='b')
         Session().commit()
         uid = user.user_id
 
@@ -515,9 +516,9 @@
         response.mustcontain(no=[api_key])
 
     def test_add_ssh_key(self):
-        description = u'something'
-        public_key = u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== me@localhost'
-        fingerprint = u'Ke3oUCNJM87P0jJTb3D+e3shjceP2CqMpQKVd75E9I8'
+        description = 'something'
+        public_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== me@localhost'
+        fingerprint = 'Ke3oUCNJM87P0jJTb3D+e3shjceP2CqMpQKVd75E9I8'
 
         self.log_user()
         user = User.get_by_username(base.TEST_USER_REGULAR_LOGIN)
@@ -538,9 +539,9 @@
         Session().commit()
 
     def test_remove_ssh_key(self):
-        description = u''
-        public_key = u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== me@localhost'
-        fingerprint = u'Ke3oUCNJM87P0jJTb3D+e3shjceP2CqMpQKVd75E9I8'
+        description = ''
+        public_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== me@localhost'
+        fingerprint = 'Ke3oUCNJM87P0jJTb3D+e3shjceP2CqMpQKVd75E9I8'
 
         self.log_user()
         user = User.get_by_username(base.TEST_USER_REGULAR_LOGIN)
@@ -553,7 +554,7 @@
         self.checkSessionFlash(response, 'SSH key %s successfully added' % fingerprint)
         response.follow()
         ssh_key = UserSshKeys.query().filter(UserSshKeys.user_id == user_id).one()
-        assert ssh_key.description == u'me@localhost'
+        assert ssh_key.description == 'me@localhost'
 
         response = self.app.post(base.url('edit_user_ssh_keys_delete', id=user_id),
                                  {'del_public_key_fingerprint': ssh_key.fingerprint,
@@ -578,7 +579,7 @@
         assert u._get_user_or_raise_if_default(user.user_id) == user
         # the default user should raise
         with pytest.raises(HTTPNotFound):
-            u._get_user_or_raise_if_default(User.get_default_user().user_id)
+            u._get_user_or_raise_if_default(kallithea.DEFAULT_USER_ID)
 
 
 class TestAdminUsersControllerForDefaultUser(base.TestController):
--- a/kallithea/tests/functional/test_changeset_pullrequests_comments.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_changeset_pullrequests_comments.py	Mon Apr 27 13:25:28 2020 +0200
@@ -16,7 +16,7 @@
     def test_create(self):
         self.log_user()
         rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
-        text = u'general comment on changeset'
+        text = 'general comment on changeset'
 
         params = {'text': text, '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(base.url(controller='changeset', action='comment',
@@ -39,7 +39,7 @@
     def test_create_inline(self):
         self.log_user()
         rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
-        text = u'inline comment on changeset'
+        text = 'inline comment on changeset'
         f_path = 'vcs/web/simplevcs/views/repository.py'
         line = 'n1'
 
@@ -70,7 +70,7 @@
         self.log_user()
 
         rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
-        text = u'@%s check CommentOnRevision' % base.TEST_USER_REGULAR_LOGIN
+        text = '@%s check CommentOnRevision' % base.TEST_USER_REGULAR_LOGIN
 
         params = {'text': text, '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(base.url(controller='changeset', action='comment',
@@ -93,7 +93,7 @@
     def test_create_status_change(self):
         self.log_user()
         rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
-        text = u'general comment on changeset'
+        text = 'general comment on changeset'
 
         params = {'text': text, 'changeset_status': 'rejected',
                 '_session_csrf_secret_token': self.session_csrf_secret_token()}
@@ -121,7 +121,7 @@
     def test_delete(self):
         self.log_user()
         rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
-        text = u'general comment on changeset to be deleted'
+        text = 'general comment on changeset to be deleted'
 
         params = {'text': text, '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(base.url(controller='changeset', action='comment',
@@ -175,7 +175,7 @@
         self.log_user()
         pr_id = self._create_pr()
 
-        text = u'general comment on pullrequest'
+        text = 'general comment on pullrequest'
         params = {'text': text, '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(base.url(controller='pullrequests', action='comment',
                                      repo_name=base.HG_REPO, pull_request_id=pr_id),
@@ -201,7 +201,7 @@
         self.log_user()
         pr_id = self._create_pr()
 
-        text = u'inline comment on changeset'
+        text = 'inline comment on changeset'
         f_path = 'vcs/web/simplevcs/views/repository.py'
         line = 'n1'
         params = {'text': text, 'f_path': f_path, 'line': line, '_session_csrf_secret_token': self.session_csrf_secret_token()}
@@ -231,7 +231,7 @@
         self.log_user()
         pr_id = self._create_pr()
 
-        text = u'@%s check CommentOnRevision' % base.TEST_USER_REGULAR_LOGIN
+        text = '@%s check CommentOnRevision' % base.TEST_USER_REGULAR_LOGIN
         params = {'text': text, '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(base.url(controller='pullrequests', action='comment',
                                      repo_name=base.HG_REPO, pull_request_id=pr_id),
@@ -254,7 +254,7 @@
         self.log_user()
         pr_id = self._create_pr()
 
-        text = u'general comment on pullrequest'
+        text = 'general comment on pullrequest'
         params = {'text': text, 'changeset_status': 'rejected',
                 '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(base.url(controller='pullrequests', action='comment',
@@ -285,7 +285,7 @@
         self.log_user()
         pr_id = self._create_pr()
 
-        text = u'general comment on changeset to be deleted'
+        text = 'general comment on changeset to be deleted'
         params = {'text': text, '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(base.url(controller='pullrequests', action='comment',
                                      repo_name=base.HG_REPO, pull_request_id=pr_id),
@@ -315,7 +315,7 @@
         self.log_user()
         pr_id = self._create_pr()
 
-        text = u'general comment on pullrequest'
+        text = 'general comment on pullrequest'
         params = {'text': text, 'save_close': 'close',
                 '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(base.url(controller='pullrequests', action='comment',
@@ -338,7 +338,7 @@
         self.log_user()
         pr_id = self._create_pr()
 
-        text = u'general comment on pullrequest'
+        text = 'general comment on pullrequest'
         params = {'text': text, 'save_delete': 'delete',
                 '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(base.url(controller='pullrequests', action='comment',
@@ -358,7 +358,7 @@
         pr_id = self._create_pr()
 
         # first close
-        text = u'general comment on pullrequest'
+        text = 'general comment on pullrequest'
         params = {'text': text, 'save_close': 'close',
                 '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(base.url(controller='pullrequests', action='comment',
--- a/kallithea/tests/functional/test_compare.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_compare.py	Mon Apr 27 13:25:28 2020 +0200
@@ -28,7 +28,7 @@
 
     def test_compare_forks_on_branch_extra_commits_hg(self):
         self.log_user()
-        repo1 = fixture.create_repo(u'one', repo_type='hg',
+        repo1 = fixture.create_repo('one', repo_type='hg',
                                     repo_description='diff-test',
                                     cur_user=base.TEST_USER_ADMIN_LOGIN)
         self.r1_id = repo1.repo_id
@@ -38,7 +38,7 @@
                 parent=None, newfile=True)
 
         # fork this repo
-        repo2 = fixture.create_fork(u'one', u'one-fork')
+        repo2 = fixture.create_fork('one', 'one-fork')
         self.r2_id = repo2.repo_id
 
         # add two extra commit into fork
@@ -79,7 +79,7 @@
 
     def test_compare_forks_on_branch_extra_commits_git(self):
         self.log_user()
-        repo1 = fixture.create_repo(u'one-git', repo_type='git',
+        repo1 = fixture.create_repo('one-git', repo_type='git',
                                     repo_description='diff-test',
                                     cur_user=base.TEST_USER_ADMIN_LOGIN)
         self.r1_id = repo1.repo_id
@@ -89,7 +89,7 @@
                 parent=None, newfile=True)
 
         # fork this repo
-        repo2 = fixture.create_fork(u'one-git', u'one-git-fork')
+        repo2 = fixture.create_fork('one-git', 'one-git-fork')
         self.r2_id = repo2.repo_id
 
         # add two extra commit into fork
@@ -131,7 +131,7 @@
     def test_compare_forks_on_branch_extra_commits_origin_has_incoming_hg(self):
         self.log_user()
 
-        repo1 = fixture.create_repo(u'one', repo_type='hg',
+        repo1 = fixture.create_repo('one', repo_type='hg',
                                     repo_description='diff-test',
                                     cur_user=base.TEST_USER_ADMIN_LOGIN)
 
@@ -143,7 +143,7 @@
                 parent=None, newfile=True)
 
         # fork this repo
-        repo2 = fixture.create_fork(u'one', u'one-fork')
+        repo2 = fixture.create_fork('one', 'one-fork')
         self.r2_id = repo2.repo_id
 
         # now commit something to origin repo
@@ -190,7 +190,7 @@
     def test_compare_forks_on_branch_extra_commits_origin_has_incoming_git(self):
         self.log_user()
 
-        repo1 = fixture.create_repo(u'one-git', repo_type='git',
+        repo1 = fixture.create_repo('one-git', repo_type='git',
                                     repo_description='diff-test',
                                     cur_user=base.TEST_USER_ADMIN_LOGIN)
 
@@ -202,7 +202,7 @@
                 parent=None, newfile=True)
 
         # fork this repo
-        repo2 = fixture.create_fork(u'one-git', u'one-git-fork')
+        repo2 = fixture.create_fork('one-git', 'one-git-fork')
         self.r2_id = repo2.repo_id
 
         # now commit something to origin repo
@@ -261,7 +261,7 @@
         # make repo1, and cs1+cs2
         self.log_user()
 
-        repo1 = fixture.create_repo(u'repo1', repo_type='hg',
+        repo1 = fixture.create_repo('repo1', repo_type='hg',
                                     repo_description='diff-test',
                                     cur_user=base.TEST_USER_ADMIN_LOGIN)
         self.r1_id = repo1.repo_id
@@ -274,7 +274,7 @@
                 content='line1\nline2\n', message='commit2', vcs_type='hg',
                 parent=cs0)
         # fork this repo
-        repo2 = fixture.create_fork(u'repo1', u'repo1-fork')
+        repo2 = fixture.create_fork('repo1', 'repo1-fork')
         self.r2_id = repo2.repo_id
         # now make cs3-6
         cs2 = fixture.commit_change(repo1.repo_name, filename='file1',
@@ -329,7 +329,7 @@
 #
         # make repo1, and cs1+cs2
         self.log_user()
-        repo1 = fixture.create_repo(u'repo1', repo_type='hg',
+        repo1 = fixture.create_repo('repo1', repo_type='hg',
                                     repo_description='diff-test',
                                     cur_user=base.TEST_USER_ADMIN_LOGIN)
         self.r1_id = repo1.repo_id
@@ -342,7 +342,7 @@
                 content='line1\nline2\n', message='commit2', vcs_type='hg',
                 parent=cs0)
         # fork this repo
-        repo2 = fixture.create_fork(u'repo1', u'repo1-fork')
+        repo2 = fixture.create_fork('repo1', 'repo1-fork')
         self.r2_id = repo2.repo_id
         # now make cs3-6
         cs2 = fixture.commit_change(repo1.repo_name, filename='file1',
@@ -448,7 +448,7 @@
     def test_org_repo_new_commits_after_forking_simple_diff_hg(self):
         self.log_user()
 
-        repo1 = fixture.create_repo(u'one', repo_type='hg',
+        repo1 = fixture.create_repo('one', repo_type='hg',
                                     repo_description='diff-test',
                                     cur_user=base.TEST_USER_ADMIN_LOGIN)
 
@@ -460,7 +460,7 @@
         Session().commit()
         assert repo1.scm_instance.revisions == [cs0.raw_id]
         # fork the repo1
-        repo2 = fixture.create_fork(r1_name, u'one-fork',
+        repo2 = fixture.create_fork(r1_name, 'one-fork',
                                     cur_user=base.TEST_USER_ADMIN_LOGIN)
         Session().commit()
         assert repo2.scm_instance.revisions == [cs0.raw_id]
@@ -520,7 +520,7 @@
     def test_org_repo_new_commits_after_forking_simple_diff_git(self):
         self.log_user()
 
-        repo1 = fixture.create_repo(u'one-git', repo_type='git',
+        repo1 = fixture.create_repo('one-git', repo_type='git',
                                     repo_description='diff-test',
                                     cur_user=base.TEST_USER_ADMIN_LOGIN)
 
@@ -533,7 +533,7 @@
         Session().commit()
         assert repo1.scm_instance.revisions == [cs0.raw_id]
         # fork the repo1
-        repo2 = fixture.create_fork(r1_name, u'one-git-fork',
+        repo2 = fixture.create_fork(r1_name, 'one-git-fork',
                                     cur_user=base.TEST_USER_ADMIN_LOGIN)
         Session().commit()
         assert repo2.scm_instance.revisions == [cs0.raw_id]
--- a/kallithea/tests/functional/test_files.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_files.py	Mon Apr 27 13:25:28 2020 +0200
@@ -252,7 +252,7 @@
 
     def test_raw_file_wrong_cs(self):
         self.log_user()
-        rev = u'ERRORce30c96924232dffcd24178a07ffeb5dfc'
+        rev = 'ERRORce30c96924232dffcd24178a07ffeb5dfc'
         f_path = 'vcs/nodes.py'
 
         response = self.app.get(base.url(controller='files', action='rawfile',
@@ -289,7 +289,7 @@
 
     def test_raw_wrong_cs(self):
         self.log_user()
-        rev = u'ERRORcce30c96924232dffcd24178a07ffeb5dfc'
+        rev = 'ERRORcce30c96924232dffcd24178a07ffeb5dfc'
         f_path = 'vcs/nodes.py'
 
         response = self.app.get(base.url(controller='files', action='raw',
@@ -381,7 +381,7 @@
     ])
     def test_add_file_into_hg(self, cnt, location, filename):
         self.log_user()
-        repo = fixture.create_repo(u'commit-test-%s' % cnt, repo_type='hg')
+        repo = fixture.create_repo('commit-test-%s' % cnt, repo_type='hg')
         response = self.app.post(base.url('files_add_home',
                                       repo_name=repo.repo_name,
                                       revision='tip', f_path='/'),
@@ -457,7 +457,7 @@
     ])
     def test_add_file_into_git(self, cnt, location, filename):
         self.log_user()
-        repo = fixture.create_repo(u'commit-test-%s' % cnt, repo_type='git')
+        repo = fixture.create_repo('commit-test-%s' % cnt, repo_type='git')
         response = self.app.post(base.url('files_add_home',
                                       repo_name=repo.repo_name,
                                       revision='tip', f_path='/'),
@@ -492,7 +492,7 @@
 
     def test_edit_file_view_not_on_branch_hg(self):
         self.log_user()
-        repo = fixture.create_repo(u'test-edit-repo', repo_type='hg')
+        repo = fixture.create_repo('test-edit-repo', repo_type='hg')
 
         ## add file
         location = 'vcs'
@@ -522,7 +522,7 @@
 
     def test_edit_file_view_commit_changes_hg(self):
         self.log_user()
-        repo = fixture.create_repo(u'test-edit-repo', repo_type='hg')
+        repo = fixture.create_repo('test-edit-repo', repo_type='hg')
 
         ## add file
         location = 'vcs'
@@ -566,7 +566,7 @@
 
     def test_edit_file_view_not_on_branch_git(self):
         self.log_user()
-        repo = fixture.create_repo(u'test-edit-repo', repo_type='git')
+        repo = fixture.create_repo('test-edit-repo', repo_type='git')
 
         ## add file
         location = 'vcs'
@@ -596,7 +596,7 @@
 
     def test_edit_file_view_commit_changes_git(self):
         self.log_user()
-        repo = fixture.create_repo(u'test-edit-repo', repo_type='git')
+        repo = fixture.create_repo('test-edit-repo', repo_type='git')
 
         ## add file
         location = 'vcs'
@@ -640,7 +640,7 @@
 
     def test_delete_file_view_not_on_branch_hg(self):
         self.log_user()
-        repo = fixture.create_repo(u'test-delete-repo', repo_type='hg')
+        repo = fixture.create_repo('test-delete-repo', repo_type='hg')
 
         ## add file
         location = 'vcs'
@@ -670,7 +670,7 @@
 
     def test_delete_file_view_commit_changes_hg(self):
         self.log_user()
-        repo = fixture.create_repo(u'test-delete-repo', repo_type='hg')
+        repo = fixture.create_repo('test-delete-repo', repo_type='hg')
 
         ## add file
         location = 'vcs'
@@ -713,7 +713,7 @@
 
     def test_delete_file_view_not_on_branch_git(self):
         self.log_user()
-        repo = fixture.create_repo(u'test-delete-repo', repo_type='git')
+        repo = fixture.create_repo('test-delete-repo', repo_type='git')
 
         ## add file
         location = 'vcs'
@@ -743,7 +743,7 @@
 
     def test_delete_file_view_commit_changes_git(self):
         self.log_user()
-        repo = fixture.create_repo(u'test-delete-repo', repo_type='git')
+        repo = fixture.create_repo('test-delete-repo', repo_type='git')
 
         ## add file
         location = 'vcs'
--- a/kallithea/tests/functional/test_forks.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_forks.py	Mon Apr 27 13:25:28 2020 +0200
@@ -23,9 +23,9 @@
     REPO_FORK = None
 
     def setup_method(self, method):
-        self.username = u'forkuser'
-        self.password = u'qweqwe'
-        u1 = fixture.create_user(self.username, password=self.password, email=u'fork_king@example.com')
+        self.username = 'forkuser'
+        self.password = 'qweqwe'
+        u1 = fixture.create_user(self.username, password=self.password, email='fork_king@example.com')
         self.u1_id = u1.user_id
         Session().commit()
 
@@ -69,7 +69,7 @@
         org_repo = Repository.get_by_repo_name(repo_name)
         creation_args = {
             'repo_name': fork_name,
-            'repo_group': u'-1',
+            'repo_group': '-1',
             'fork_parent_id': org_repo.repo_id,
             'repo_type': self.REPO_TYPE,
             'description': description,
@@ -93,7 +93,7 @@
 
     def test_fork_create_into_group(self):
         self.log_user()
-        group = fixture.create_repo_group(u'vc')
+        group = fixture.create_repo_group('vc')
         group_id = group.group_id
         fork_name = self.REPO_FORK
         fork_name_full = 'vc/%s' % fork_name
@@ -143,10 +143,10 @@
         # create a fork
         repo_name = self.REPO
         org_repo = Repository.get_by_repo_name(repo_name)
-        fork_name = self.REPO_FORK + u'-rødgrød'
+        fork_name = self.REPO_FORK + '-rødgrød'
         creation_args = {
             'repo_name': fork_name,
-            'repo_group': u'-1',
+            'repo_group': '-1',
             'fork_parent_id': org_repo.repo_id,
             'repo_type': self.REPO_TYPE,
             'description': 'unicode repo 1',
@@ -164,10 +164,10 @@
         assert fork_repo
 
         # fork the fork
-        fork_name_2 = self.REPO_FORK + u'-blåbærgrød'
+        fork_name_2 = self.REPO_FORK + '-blåbærgrød'
         creation_args = {
             'repo_name': fork_name_2,
-            'repo_group': u'-1',
+            'repo_group': '-1',
             'fork_parent_id': fork_repo.repo_id,
             'repo_type': self.REPO_TYPE,
             'description': 'unicode repo 2',
@@ -196,7 +196,7 @@
         org_repo = Repository.get_by_repo_name(repo_name)
         creation_args = {
             'repo_name': fork_name,
-            'repo_group': u'-1',
+            'repo_group': '-1',
             'fork_parent_id': org_repo.repo_id,
             'repo_type': self.REPO_TYPE,
             'description': description,
--- a/kallithea/tests/functional/test_home.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_home.py	Mon Apr 27 13:25:28 2020 +0200
@@ -53,35 +53,35 @@
 
     def test_index_page_on_groups(self):
         self.log_user()
-        gr = fixture.create_repo_group(u'gr1')
-        fixture.create_repo(name=u'gr1/repo_in_group', repo_group=gr)
-        response = self.app.get(base.url('repos_group_home', group_name=u'gr1'))
+        gr = fixture.create_repo_group('gr1')
+        fixture.create_repo(name='gr1/repo_in_group', repo_group=gr)
+        response = self.app.get(base.url('repos_group_home', group_name='gr1'))
 
         try:
-            response.mustcontain(u"gr1/repo_in_group")
+            response.mustcontain("gr1/repo_in_group")
         finally:
-            RepoModel().delete(u'gr1/repo_in_group')
-            RepoGroupModel().delete(repo_group=u'gr1', force_delete=True)
+            RepoModel().delete('gr1/repo_in_group')
+            RepoGroupModel().delete(repo_group='gr1', force_delete=True)
             Session().commit()
 
     def test_users_and_groups_data(self):
-        fixture.create_user('evil', firstname=u'D\'o\'ct"o"r', lastname=u'Évíl')
-        fixture.create_user_group(u'grrrr', user_group_description=u"Groüp")
-        response = self.app.get(base.url('users_and_groups_data', query=u'evi'))
+        fixture.create_user('evil', firstname='D\'o\'ct"o"r', lastname='Évíl')
+        fixture.create_user_group('grrrr', user_group_description="Groüp")
+        response = self.app.get(base.url('users_and_groups_data', query='evi'))
         assert response.status_code == 302
         assert base.url('login_home') in response.location
         self.log_user(base.TEST_USER_REGULAR_LOGIN, base.TEST_USER_REGULAR_PASS)
-        response = self.app.get(base.url('users_and_groups_data', query=u'evi'))
+        response = self.app.get(base.url('users_and_groups_data', query='evi'))
         result = json.loads(response.body)['results']
-        assert result[0].get('fname') == u'D\'o\'ct"o"r'
-        assert result[0].get('lname') == u'Évíl'
-        response = self.app.get(base.url('users_and_groups_data', key=u'evil'))
+        assert result[0].get('fname') == 'D\'o\'ct"o"r'
+        assert result[0].get('lname') == 'Évíl'
+        response = self.app.get(base.url('users_and_groups_data', key='evil'))
         result = json.loads(response.body)['results']
-        assert result[0].get('fname') == u'D\'o\'ct"o"r'
-        assert result[0].get('lname') == u'Évíl'
-        response = self.app.get(base.url('users_and_groups_data', query=u'rrrr'))
+        assert result[0].get('fname') == 'D\'o\'ct"o"r'
+        assert result[0].get('lname') == 'Évíl'
+        response = self.app.get(base.url('users_and_groups_data', query='rrrr'))
         result = json.loads(response.body)['results']
         assert not result
-        response = self.app.get(base.url('users_and_groups_data', types='users,groups', query=u'rrrr'))
+        response = self.app.get(base.url('users_and_groups_data', types='users,groups', query='rrrr'))
         result = json.loads(response.body)['results']
-        assert result[0].get('grname') == u'grrrr'
+        assert result[0].get('grname') == 'grrrr'
--- a/kallithea/tests/functional/test_login.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_login.py	Mon Apr 27 13:25:28 2020 +0200
@@ -164,7 +164,7 @@
 
     @base.parametrize('args', [
         {'foo':'one', 'bar':'two'},
-        {'blue': u'blå', 'green': u'grøn'},
+        {'blue': 'blå', 'green': 'grøn'},
     ])
     def test_redirection_to_login_form_preserves_get_args(self, args):
         with fixture.anon_access(False):
@@ -178,7 +178,7 @@
 
     @base.parametrize('args,args_encoded', [
         ({'foo':'one', 'bar':'two'}, ('foo=one', 'bar=two')),
-        ({'blue': u'blå', 'green':u'grøn'},
+        ({'blue': 'blå', 'green':'grøn'},
              ('blue=bl%C3%A5', 'green=gr%C3%B8n')),
     ])
     def test_login_form_preserves_get_args(self, args, args_encoded):
@@ -190,7 +190,7 @@
 
     @base.parametrize('args,args_encoded', [
         ({'foo':'one', 'bar':'two'}, ('foo=one', 'bar=two')),
-        ({'blue': u'blå', 'green':u'grøn'},
+        ({'blue': 'blå', 'green':'grøn'},
              ('blue=bl%C3%A5', 'green=gr%C3%B8n')),
     ])
     def test_redirection_after_successful_login_preserves_get_args(self, args, args_encoded):
@@ -205,7 +205,7 @@
 
     @base.parametrize('args,args_encoded', [
         ({'foo':'one', 'bar':'two'}, ('foo=one', 'bar=two')),
-        ({'blue': u'blå', 'green':u'grøn'},
+        ({'blue': 'blå', 'green':'grøn'},
              ('blue=bl%C3%A5', 'green=gr%C3%B8n')),
     ])
     def test_login_form_after_incorrect_login_preserves_get_args(self, args, args_encoded):
@@ -392,8 +392,8 @@
         username = 'test_password_reset_1'
         password = 'qweqwe'
         email = 'username@example.com'
-        name = u'passwd'
-        lastname = u'reset'
+        name = 'passwd'
+        lastname = 'reset'
         timestamp = int(time.time())
 
         new = User()
@@ -410,7 +410,7 @@
             User.get_by_username(username), timestamp, self.session_csrf_secret_token())
 
         collected = []
-        def mock_send_email(recipients, subject, body='', html_body='', headers=None, author=None):
+        def mock_send_email(recipients, subject, body='', html_body='', headers=None, from_name=None):
             collected.append((recipients, subject, body, html_body))
 
         with mock.patch.object(kallithea.lib.celerylib.tasks, 'send_email', mock_send_email), \
@@ -521,12 +521,12 @@
         self._api_key_test(api_key, code)
 
     def test_access_page_via_extra_api_key(self):
-        new_api_key = ApiKeyModel().create(base.TEST_USER_ADMIN_LOGIN, u'test')
+        new_api_key = ApiKeyModel().create(base.TEST_USER_ADMIN_LOGIN, 'test')
         Session().commit()
         self._api_key_test(new_api_key.api_key, status=200)
 
     def test_access_page_via_expired_api_key(self):
-        new_api_key = ApiKeyModel().create(base.TEST_USER_ADMIN_LOGIN, u'test')
+        new_api_key = ApiKeyModel().create(base.TEST_USER_ADMIN_LOGIN, 'test')
         Session().commit()
         # patch the API key and make it expired
         new_api_key.expires = 0
--- a/kallithea/tests/functional/test_my_account.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_my_account.py	Mon Apr 27 13:25:28 2020 +0200
@@ -161,8 +161,8 @@
                                     username=base.TEST_USER_ADMIN_LOGIN,
                                     new_password=base.TEST_USER_ADMIN_PASS,
                                     password_confirmation='test122',
-                                    firstname=u'NewName',
-                                    lastname=u'NewLastname',
+                                    firstname='NewName',
+                                    lastname='NewLastname',
                                     email=new_email,
                                     _session_csrf_secret_token=self.session_csrf_secret_token())
                                 )
@@ -178,8 +178,8 @@
                                             username=base.TEST_USER_ADMIN_LOGIN,
                                             new_password=base.TEST_USER_ADMIN_PASS,
                                             password_confirmation='test122',
-                                            firstname=u'NewName',
-                                            lastname=u'NewLastname',
+                                            firstname='NewName',
+                                            lastname='NewLastname',
                                             email=new_email,
                                             _session_csrf_secret_token=self.session_csrf_secret_token()))
 
@@ -252,9 +252,9 @@
         response.mustcontain(no=[api_key])
 
     def test_my_account_add_ssh_key(self):
-        description = u'something'
-        public_key = u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== me@localhost'
-        fingerprint = u'Ke3oUCNJM87P0jJTb3D+e3shjceP2CqMpQKVd75E9I8'
+        description = 'something'
+        public_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== me@localhost'
+        fingerprint = 'Ke3oUCNJM87P0jJTb3D+e3shjceP2CqMpQKVd75E9I8'
 
         self.log_user(base.TEST_USER_REGULAR2_LOGIN, base.TEST_USER_REGULAR2_PASS)
         response = self.app.post(base.url('my_account_ssh_keys'),
@@ -273,9 +273,9 @@
         Session().commit()
 
     def test_my_account_remove_ssh_key(self):
-        description = u''
-        public_key = u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== me@localhost'
-        fingerprint = u'Ke3oUCNJM87P0jJTb3D+e3shjceP2CqMpQKVd75E9I8'
+        description = ''
+        public_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== me@localhost'
+        fingerprint = 'Ke3oUCNJM87P0jJTb3D+e3shjceP2CqMpQKVd75E9I8'
 
         self.log_user(base.TEST_USER_REGULAR2_LOGIN, base.TEST_USER_REGULAR2_PASS)
         response = self.app.post(base.url('my_account_ssh_keys'),
@@ -286,7 +286,7 @@
         response.follow()
         user_id = response.session['authuser']['user_id']
         ssh_key = UserSshKeys.query().filter(UserSshKeys.user_id == user_id).one()
-        assert ssh_key.description == u'me@localhost'
+        assert ssh_key.description == 'me@localhost'
 
         response = self.app.post(base.url('my_account_ssh_keys_delete'),
                                  {'del_public_key_fingerprint': ssh_key.fingerprint,
--- a/kallithea/tests/functional/test_pullrequests.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_pullrequests.py	Mon Apr 27 13:25:28 2020 +0200
@@ -292,14 +292,14 @@
 class TestPullrequestsGetRepoRefs(base.TestController):
 
     def setup_method(self, method):
-        self.repo_name = u'main'
+        self.repo_name = 'main'
         repo = fixture.create_repo(self.repo_name, repo_type='hg')
         self.repo_scm_instance = repo.scm_instance
         Session().commit()
         self.c = PullrequestsController()
 
     def teardown_method(self, method):
-        fixture.destroy_repo(u'main')
+        fixture.destroy_repo('main')
         Session().commit()
         Session.remove()
 
--- a/kallithea/tests/functional/test_search_indexing.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_search_indexing.py	Mon Apr 27 13:25:28 2020 +0200
@@ -39,12 +39,12 @@
 
 repos = [
     # reponame,              init func or fork base, groupname
-    (u'indexing_test',       init_indexing_test,     None),
-    (u'indexing_test-fork',  u'indexing_test',       None),
-    (u'group/indexing_test', u'indexing_test',       u'group'),
-    (u'this-is-it',          u'indexing_test',       None),
-    (u'indexing_test-foo',   u'indexing_test',       None),
-    (u'stopword_test',       init_stopword_test,     None),
+    ('indexing_test',       init_indexing_test,     None),
+    ('indexing_test-fork',  'indexing_test',       None),
+    ('group/indexing_test', 'indexing_test',       'group'),
+    ('this-is-it',          'indexing_test',       None),
+    ('indexing_test-foo',   'indexing_test',       None),
+    ('stopword_test',       init_stopword_test,     None),
 ]
 
 
@@ -109,12 +109,12 @@
         rebuild_index(full_index=True) # rebuild fully for subsequent tests
 
     @base.parametrize('reponame', [
-        (u'indexing_test'),
-        (u'indexing_test-fork'),
-        (u'group/indexing_test'),
-        (u'this-is-it'),
-        (u'*-fork'),
-        (u'group/*'),
+        ('indexing_test'),
+        ('indexing_test-fork'),
+        ('group/indexing_test'),
+        ('this-is-it'),
+        ('*-fork'),
+        ('group/*'),
     ])
     @base.parametrize('searchtype,query,hit', [
         ('content', 'this_should_be_unique_content', 1),
@@ -130,10 +130,10 @@
         response.mustcontain('>%d results' % hit)
 
     @base.parametrize('reponame', [
-        (u'indexing_test'),
-        (u'indexing_test-fork'),
-        (u'group/indexing_test'),
-        (u'this-is-it'),
+        ('indexing_test'),
+        ('indexing_test-fork'),
+        ('group/indexing_test'),
+        ('this-is-it'),
     ])
     @base.parametrize('searchtype,query,hit', [
         ('content', 'this_should_be_unique_content', 1),
--- a/kallithea/tests/functional/test_summary.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/functional/test_summary.py	Mon Apr 27 13:25:28 2020 +0200
@@ -111,7 +111,7 @@
 
     def test_index_by_repo_having_id_path_in_name_hg(self):
         self.log_user()
-        fixture.create_repo(name=u'repo_1')
+        fixture.create_repo(name='repo_1')
         response = self.app.get(base.url(controller='summary',
                                     action='index',
                                     repo_name='repo_1'))
@@ -119,7 +119,7 @@
         try:
             response.mustcontain("repo_1")
         finally:
-            RepoModel().delete(Repository.get_by_repo_name(u'repo_1'))
+            RepoModel().delete(Repository.get_by_repo_name('repo_1'))
             Session().commit()
 
     def test_index_by_id_git(self):
--- a/kallithea/tests/models/common.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/models/common.py	Mon Apr 27 13:25:28 2020 +0200
@@ -12,7 +12,7 @@
 
 def _destroy_project_tree(test_u1_id):
     Session.remove()
-    repo_group = RepoGroup.get_by_group_name(group_name=u'g0')
+    repo_group = RepoGroup.get_by_group_name(group_name='g0')
     for el in reversed(repo_group.recursive_groups_and_repos()):
         if isinstance(el, Repository):
             RepoModel().delete(el)
@@ -50,21 +50,21 @@
 
     """
     test_u1 = UserModel().create_or_update(
-        username=u'test_u1', password=u'qweqwe',
-        email=u'test_u1@example.com', firstname=u'test_u1', lastname=u'test_u1'
+        username='test_u1', password='qweqwe',
+        email='test_u1@example.com', firstname='test_u1', lastname='test_u1'
     )
-    g0 = fixture.create_repo_group(u'g0')
-    g0_1 = fixture.create_repo_group(u'g0_1', parent_group_id=g0)
-    g0_1_1 = fixture.create_repo_group(u'g0_1_1', parent_group_id=g0_1)
-    g0_1_1_r1 = fixture.create_repo(u'g0/g0_1/g0_1_1/g0_1_1_r1', repo_group=g0_1_1)
-    g0_1_1_r2 = fixture.create_repo(u'g0/g0_1/g0_1_1/g0_1_1_r2', repo_group=g0_1_1)
-    g0_1_r1 = fixture.create_repo(u'g0/g0_1/g0_1_r1', repo_group=g0_1)
-    g0_2 = fixture.create_repo_group(u'g0_2', parent_group_id=g0)
-    g0_2_r1 = fixture.create_repo(u'g0/g0_2/g0_2_r1', repo_group=g0_2)
-    g0_2_r2 = fixture.create_repo(u'g0/g0_2/g0_2_r2', repo_group=g0_2)
-    g0_3 = fixture.create_repo_group(u'g0_3', parent_group_id=g0)
-    g0_3_r1 = fixture.create_repo(u'g0/g0_3/g0_3_r1', repo_group=g0_3)
-    g0_3_r2_private = fixture.create_repo(u'g0/g0_3/g0_3_r1_private',
+    g0 = fixture.create_repo_group('g0')
+    g0_1 = fixture.create_repo_group('g0_1', parent_group_id=g0)
+    g0_1_1 = fixture.create_repo_group('g0_1_1', parent_group_id=g0_1)
+    g0_1_1_r1 = fixture.create_repo('g0/g0_1/g0_1_1/g0_1_1_r1', repo_group=g0_1_1)
+    g0_1_1_r2 = fixture.create_repo('g0/g0_1/g0_1_1/g0_1_1_r2', repo_group=g0_1_1)
+    g0_1_r1 = fixture.create_repo('g0/g0_1/g0_1_r1', repo_group=g0_1)
+    g0_2 = fixture.create_repo_group('g0_2', parent_group_id=g0)
+    g0_2_r1 = fixture.create_repo('g0/g0_2/g0_2_r1', repo_group=g0_2)
+    g0_2_r2 = fixture.create_repo('g0/g0_2/g0_2_r2', repo_group=g0_2)
+    g0_3 = fixture.create_repo_group('g0_3', parent_group_id=g0)
+    g0_3_r1 = fixture.create_repo('g0/g0_3/g0_3_r1', repo_group=g0_3)
+    g0_3_r2_private = fixture.create_repo('g0/g0_3/g0_3_r1_private',
                                           repo_group=g0_3, repo_private=True)
     return test_u1
 
--- a/kallithea/tests/models/test_comments.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/models/test_comments.py	Mon Apr 27 13:25:28 2020 +0200
@@ -29,7 +29,7 @@
             self._check_comment_count(repo_id, revision,
                     expected_len_comments=0, expected_len_inline_comments=0)
 
-            text = u'a comment'
+            text = 'a comment'
             new_comment = ChangesetCommentsModel().create(
                     text=text,
                     repo=base.HG_REPO,
@@ -53,9 +53,9 @@
             self._check_comment_count(repo_id, revision,
                     expected_len_comments=0, expected_len_inline_comments=0)
 
-            text = u'an inline comment'
-            f_path = u'vcs/tests/base.py'
-            line_no = u'n50'
+            text = 'an inline comment'
+            f_path = 'vcs/tests/base.py'
+            line_no = 'n50'
             new_comment = ChangesetCommentsModel().create(
                     text=text,
                     repo=base.HG_REPO,
@@ -87,9 +87,9 @@
             self._check_comment_count(repo_id, revision,
                     expected_len_comments=0, expected_len_inline_comments=0)
 
-            text = u'an inline comment'
-            f_path = u'vcs/tests/base.py'
-            line_no = u'n50'
+            text = 'an inline comment'
+            f_path = 'vcs/tests/base.py'
+            line_no = 'n50'
             new_comment = ChangesetCommentsModel().create(
                     text=text,
                     repo=base.HG_REPO,
@@ -99,8 +99,8 @@
                     line_no=line_no,
                     send_email=False)
 
-            text2 = u'another inline comment, same file'
-            line_no2 = u'o41'
+            text2 = 'another inline comment, same file'
+            line_no2 = 'o41'
             new_comment2 = ChangesetCommentsModel().create(
                     text=text2,
                     repo=base.HG_REPO,
@@ -110,9 +110,9 @@
                     line_no=line_no2,
                     send_email=False)
 
-            text3 = u'another inline comment, same file'
-            f_path3 = u'vcs/tests/test_hg.py'
-            line_no3 = u'n159'
+            text3 = 'another inline comment, same file'
+            f_path3 = 'vcs/tests/test_hg.py'
+            line_no3 = 'n159'
             new_comment3 = ChangesetCommentsModel().create(
                     text=text3,
                     repo=base.HG_REPO,
@@ -167,9 +167,9 @@
             self._check_comment_count(repo_id, revision,
                     expected_len_comments=0, expected_len_inline_comments=0)
 
-            text = u'an inline comment'
-            f_path = u'vcs/tests/base.py'
-            line_no = u'n50'
+            text = 'an inline comment'
+            f_path = 'vcs/tests/base.py'
+            line_no = 'n50'
             new_comment = ChangesetCommentsModel().create(
                     text=text,
                     repo=base.HG_REPO,
@@ -179,8 +179,8 @@
                     line_no=line_no,
                     send_email=False)
 
-            text2 = u'another inline comment, same file'
-            line_no2 = u'o41'
+            text2 = 'another inline comment, same file'
+            line_no2 = 'o41'
             new_comment2 = ChangesetCommentsModel().create(
                     text=text2,
                     repo=base.HG_REPO,
@@ -190,9 +190,9 @@
                     line_no=line_no2,
                     send_email=False)
 
-            text3 = u'another inline comment, same file'
-            f_path3 = u'vcs/tests/test_hg.py'
-            line_no3 = u'n159'
+            text3 = 'another inline comment, same file'
+            f_path3 = 'vcs/tests/test_hg.py'
+            line_no3 = 'n159'
             new_comment3 = ChangesetCommentsModel().create(
                     text=text3,
                     repo=base.HG_REPO,
--- a/kallithea/tests/models/test_dump_html_mails.ref.html	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/models/test_dump_html_mails.ref.html	Mon Apr 27 13:25:28 2020 +0200
@@ -5,7 +5,7 @@
 <hr/>
 <h1>cs_comment, is_mention=False, status_change=None</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: u2@example.com
 Subject: [Comment] repo/name changeset cafe1234 "This changeset did something cl..." on brunch
 </pre>
@@ -164,7 +164,7 @@
 <hr/>
 <h1>cs_comment, is_mention=True, status_change=None</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: u2@example.com
 Subject: [Comment] repo/name changeset cafe1234 "This changeset did something cl..." on brunch
 </pre>
@@ -323,7 +323,7 @@
 <hr/>
 <h1>cs_comment, is_mention=False, status_change='Approved'</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: u2@example.com
 Subject: [Approved: Comment] repo/name changeset cafe1234 "This changeset did something cl..." on brunch
 </pre>
@@ -500,7 +500,7 @@
 <hr/>
 <h1>cs_comment, is_mention=True, status_change='Approved'</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: u2@example.com
 Subject: [Approved: Comment] repo/name changeset cafe1234 "This changeset did something cl..." on brunch
 </pre>
@@ -677,7 +677,7 @@
 <hr/>
 <h1>message</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: u2@example.com
 Subject: Test Message
 </pre>
@@ -748,7 +748,7 @@
 <hr/>
 <h1>registration</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: u2@example.com
 Subject: New user newbie registered
 </pre>
@@ -881,7 +881,7 @@
 <hr/>
 <h1>pull_request, is_mention=False</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: u2@example.com
 Subject: [Review] repo/name PR #7 "The Title" from devbranch by u2
 </pre>
@@ -1072,7 +1072,7 @@
 <hr/>
 <h1>pull_request, is_mention=True</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: u2@example.com
 Subject: [Review] repo/name PR #7 "The Title" from devbranch by u2
 </pre>
@@ -1263,7 +1263,7 @@
 <hr/>
 <h1>pull_request_comment, is_mention=False, status_change=None, closing_pr=False</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: u2@example.com
 Subject: [Comment] repo/name PR #7 "The Title" from devbranch by u2
 </pre>
@@ -1430,7 +1430,7 @@
 <hr/>
 <h1>pull_request_comment, is_mention=True, status_change=None, closing_pr=False</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: u2@example.com
 Subject: [Comment] repo/name PR #7 "The Title" from devbranch by u2
 </pre>
@@ -1597,7 +1597,7 @@
 <hr/>
 <h1>pull_request_comment, is_mention=False, status_change='Under Review', closing_pr=False</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: u2@example.com
 Subject: [Under Review: Comment] repo/name PR #7 "The Title" from devbranch by u2
 </pre>
@@ -1782,7 +1782,7 @@
 <hr/>
 <h1>pull_request_comment, is_mention=True, status_change='Under Review', closing_pr=False</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: u2@example.com
 Subject: [Under Review: Comment] repo/name PR #7 "The Title" from devbranch by u2
 </pre>
@@ -1967,7 +1967,7 @@
 <hr/>
 <h1>pull_request_comment, is_mention=False, status_change=None, closing_pr=True</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: u2@example.com
 Subject: [Closing: Comment] repo/name PR #7 "The Title" from devbranch by u2
 </pre>
@@ -2151,7 +2151,7 @@
 <hr/>
 <h1>pull_request_comment, is_mention=True, status_change=None, closing_pr=True</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: u2@example.com
 Subject: [Closing: Comment] repo/name PR #7 "The Title" from devbranch by u2
 </pre>
@@ -2335,7 +2335,7 @@
 <hr/>
 <h1>pull_request_comment, is_mention=False, status_change='Under Review', closing_pr=True</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: u2@example.com
 Subject: [Under Review, Closing: Comment] repo/name PR #7 "The Title" from devbranch by u2
 </pre>
@@ -2525,7 +2525,7 @@
 <hr/>
 <h1>pull_request_comment, is_mention=True, status_change='Under Review', closing_pr=True</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: u2@example.com
 Subject: [Under Review, Closing: Comment] repo/name PR #7 "The Title" from devbranch by u2
 </pre>
@@ -2715,7 +2715,7 @@
 <hr/>
 <h1>TYPE_PASSWORD_RESET</h1>
 <pre>
-From: u1
+From: u1 u1 <name@example.com>
 To: john@doe.com
 Subject: Password reset link
 </pre>
--- a/kallithea/tests/models/test_notifications.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/models/test_notifications.py	Mon Apr 27 13:25:28 2020 +0200
@@ -18,24 +18,24 @@
 
     def setup_method(self, method):
         Session.remove()
-        u1 = UserModel().create_or_update(username=u'u1',
-                                        password=u'qweqwe',
-                                        email=u'u1@example.com',
-                                        firstname=u'u1', lastname=u'u1')
+        u1 = UserModel().create_or_update(username='u1',
+                                        password='qweqwe',
+                                        email='u1@example.com',
+                                        firstname='u1', lastname='u1')
         Session().commit()
         self.u1 = u1.user_id
 
-        u2 = UserModel().create_or_update(username=u'u2',
-                                        password=u'qweqwe',
-                                        email=u'u2@example.com',
-                                        firstname=u'u2', lastname=u'u3')
+        u2 = UserModel().create_or_update(username='u2',
+                                        password='qweqwe',
+                                        email='u2@example.com',
+                                        firstname='u2', lastname='u3')
         Session().commit()
         self.u2 = u2.user_id
 
-        u3 = UserModel().create_or_update(username=u'u3',
-                                        password=u'qweqwe',
-                                        email=u'u3@example.com',
-                                        firstname=u'u3', lastname=u'u3')
+        u3 = UserModel().create_or_update(username='u3',
+                                        password='qweqwe',
+                                        email='u3@example.com',
+                                        firstname='u3', lastname='u3')
         Session().commit()
         self.u3 = u3.user_id
 
@@ -43,15 +43,15 @@
         with test_context(self.app):
             usrs = [self.u1, self.u2]
 
-            def send_email(recipients, subject, body='', html_body='', headers=None, author=None):
+            def send_email(recipients, subject, body='', html_body='', headers=None, from_name=None):
                 assert recipients == ['u2@example.com']
                 assert subject == 'Test Message'
-                assert body == u"hi there"
+                assert body == "hi there"
                 assert '>hi there<' in html_body
-                assert author.username == 'u1'
+                assert from_name == 'u1 u1'
             with mock.patch.object(kallithea.lib.celerylib.tasks, 'send_email', send_email):
                 NotificationModel().create(created_by=self.u1,
-                                                   subject=u'subj', body=u'hi there',
+                                                   subject='subj', body='hi there',
                                                    recipients=usrs)
 
     @mock.patch.object(h, 'canonical_url', (lambda arg, **kwargs: 'http://%s/?%s' % (arg, '&'.join('%s=%s' % (k, v) for (k, v) in sorted(kwargs.items())))))
@@ -59,11 +59,11 @@
         # Exercise all notification types and dump them to one big html file
         l = []
 
-        def send_email(recipients, subject, body='', html_body='', headers=None, author=None):
+        def send_email(recipients, subject, body='', html_body='', headers=None, from_name=None):
             l.append('<hr/>\n')
             l.append('<h1>%s</h1>\n' % desc) # desc is from outer scope
             l.append('<pre>\n')
-            l.append('From: %s\n' % author.username)
+            l.append('From: %s <name@example.com>\n' % from_name)
             l.append('To: %s\n' % ' '.join(recipients))
             l.append('Subject: %s\n' % subject)
             l.append('</pre>\n')
@@ -90,7 +90,7 @@
 
                 for type_, body, kwargs in [
                         (NotificationModel.TYPE_CHANGESET_COMMENT,
-                         u'This is the new \'comment\'.\n\n - and here it ends indented.',
+                         'This is the new \'comment\'.\n\n - and here it ends indented.',
                          dict(
                             short_id='cafe1234',
                             raw_id='cafe1234c0ffeecafe',
@@ -105,18 +105,18 @@
                             cs_url='http://changeset.com',
                             cs_author=User.get(self.u2))),
                         (NotificationModel.TYPE_MESSAGE,
-                         u'This is the \'body\' of the "test" message\n - nothing interesting here except indentation.',
+                         'This is the \'body\' of the "test" message\n - nothing interesting here except indentation.',
                          dict()),
                         #(NotificationModel.TYPE_MENTION, '$body', None), # not used
                         (NotificationModel.TYPE_REGISTRATION,
-                         u'Registration body',
+                         'Registration body',
                          dict(
                             new_username='newbie',
                             registered_user_url='http://newbie.org',
                             new_email='new@email.com',
                             new_full_name='New Full Name')),
                         (NotificationModel.TYPE_PULL_REQUEST,
-                         u'This PR is \'awesome\' because it does <stuff>\n - please approve indented!',
+                         'This PR is \'awesome\' because it does <stuff>\n - please approve indented!',
                          dict(
                             pr_user_created='Requesting User (root)', # pr_owner should perhaps be used for @mention in description ...
                             is_mention=[False, True],
@@ -124,7 +124,7 @@
                             org_repo_name='repo_org',
                             **pr_kwargs)),
                         (NotificationModel.TYPE_PULL_REQUEST_COMMENT,
-                         u'Me too!\n\n - and indented on second line',
+                         'Me too!\n\n - and indented on second line',
                          dict(
                             closing_pr=[False, True],
                             is_mention=[False, True],
@@ -133,7 +133,7 @@
                             status_change=[None, 'Under Review'],
                             **pr_kwargs)),
                         ]:
-                    kwargs['repo_name'] = u'repo/name'
+                    kwargs['repo_name'] = 'repo/name'
                     params = [(type_, type_, body, kwargs)]
                     for param_name in ['is_mention', 'status_change', 'closing_pr']: # TODO: inline/general
                         if not isinstance(kwargs.get(param_name), list):
@@ -149,7 +149,7 @@
                     for desc, type_, body, kwargs in params:
                         # desc is used as "global" variable
                         NotificationModel().create(created_by=self.u1,
-                                                           subject=u'unused', body=body, email_kwargs=kwargs,
+                                                           subject='unused', body=body, email_kwargs=kwargs,
                                                            recipients=[self.u2], type_=type_)
 
                 # Email type TYPE_PASSWORD_RESET has no corresponding notification type - test it directly:
@@ -159,7 +159,7 @@
                     "Password reset link",
                     EmailNotificationModel().get_email_tmpl(EmailNotificationModel.TYPE_PASSWORD_RESET, 'txt', **kwargs),
                     EmailNotificationModel().get_email_tmpl(EmailNotificationModel.TYPE_PASSWORD_RESET, 'html', **kwargs),
-                    author=User.get(self.u1))
+                    from_name=User.get(self.u1).full_name_or_username)
 
         out = '<!doctype html>\n<html lang="en">\n<head><title>Notifications</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head>\n<body>\n%s\n</body>\n</html>\n' % \
             re.sub(r'<(/?(?:!doctype|html|head|title|meta|body)\b[^>]*)>', r'<!--\1-->', ''.join(l))
--- a/kallithea/tests/models/test_permissions.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/models/test_permissions.py	Mon Apr 27 13:25:28 2020 +0200
@@ -1,5 +1,6 @@
 from kallithea.lib.auth import AuthUser
-from kallithea.model.db import Permission, RepoGroup, User, UserGroupRepoGroupToPerm, UserToPerm
+from kallithea.model import db
+from kallithea.model.db import Permission, User, UserGroupRepoGroupToPerm, UserToPerm
 from kallithea.model.meta import Session
 from kallithea.model.permission import PermissionModel
 from kallithea.model.repo import RepoModel
@@ -18,27 +19,27 @@
     @classmethod
     def setup_class(cls):
         # recreate default user to get a clean start
-        PermissionModel().create_default_permissions(user=User.DEFAULT_USER,
+        PermissionModel().create_default_permissions(user=User.DEFAULT_USER_NAME,
                                                      force=True)
         Session().commit()
 
     def setup_method(self, method):
         self.u1 = UserModel().create_or_update(
-            username=u'u1', password=u'qweqwe',
-            email=u'u1@example.com', firstname=u'u1', lastname=u'u1'
+            username='u1', password='qweqwe',
+            email='u1@example.com', firstname='u1', lastname='u1'
         )
         self.u2 = UserModel().create_or_update(
-            username=u'u2', password=u'qweqwe',
-            email=u'u2@example.com', firstname=u'u2', lastname=u'u2'
+            username='u2', password='qweqwe',
+            email='u2@example.com', firstname='u2', lastname='u2'
         )
         self.u3 = UserModel().create_or_update(
-            username=u'u3', password=u'qweqwe',
-            email=u'u3@example.com', firstname=u'u3', lastname=u'u3'
+            username='u3', password='qweqwe',
+            email='u3@example.com', firstname='u3', lastname='u3'
         )
         self.anon = User.get_default_user()
         self.a1 = UserModel().create_or_update(
-            username=u'a1', password=u'qweqwe',
-            email=u'a1@example.com', firstname=u'a1', lastname=u'a1', admin=True
+            username='a1', password='qweqwe',
+            email='a1@example.com', firstname='a1', lastname='a1', admin=True
         )
         Session().commit()
 
@@ -100,11 +101,11 @@
         assert u1_auth.permissions['repositories'][base.HG_REPO] == perms['repositories'][base.HG_REPO]
 
     def test_default_group_perms(self):
-        self.g1 = fixture.create_repo_group(u'test1', skip_if_exists=True)
-        self.g2 = fixture.create_repo_group(u'test2', skip_if_exists=True)
+        self.g1 = fixture.create_repo_group('test1', skip_if_exists=True)
+        self.g2 = fixture.create_repo_group('test2', skip_if_exists=True)
         u1_auth = AuthUser(user_id=self.u1.user_id)
         perms = {
-            'repositories_groups': {u'test1': 'group.read', u'test2': 'group.read'},
+            'repositories_groups': {'test1': 'group.read', 'test2': 'group.read'},
             'global': set(Permission.DEFAULT_USER_PERMISSIONS),
             'repositories': {base.HG_REPO: 'repository.read'}
         }
@@ -113,11 +114,11 @@
         assert u1_auth.permissions['global'] == perms['global']
 
     def test_default_admin_group_perms(self):
-        self.g1 = fixture.create_repo_group(u'test1', skip_if_exists=True)
-        self.g2 = fixture.create_repo_group(u'test2', skip_if_exists=True)
+        self.g1 = fixture.create_repo_group('test1', skip_if_exists=True)
+        self.g2 = fixture.create_repo_group('test2', skip_if_exists=True)
         a1_auth = AuthUser(user_id=self.a1.user_id)
         perms = {
-            'repositories_groups': {u'test1': 'group.admin', u'test2': 'group.admin'},
+            'repositories_groups': {'test1': 'group.admin', 'test2': 'group.admin'},
             'global': set(['hg.admin', 'hg.create.write_on_repogroup.true']),
             'repositories': {base.HG_REPO: 'repository.admin'}
         }
@@ -127,7 +128,7 @@
 
     def test_propagated_permission_from_users_group_by_explicit_perms_exist(self):
         # make group
-        self.ug1 = fixture.create_user_group(u'G1')
+        self.ug1 = fixture.create_user_group('G1')
         UserGroupModel().add_user_to_group(self.ug1, self.u1)
 
         # set user permission none
@@ -147,7 +148,7 @@
 
     def test_propagated_permission_from_users_group(self):
         # make group
-        self.ug1 = fixture.create_user_group(u'G1')
+        self.ug1 = fixture.create_user_group('G1')
         UserGroupModel().add_user_to_group(self.ug1, self.u3)
 
         # grant perm for group this should override default permission from user
@@ -168,7 +169,7 @@
 
     def test_propagated_permission_from_users_group_lower_weight(self):
         # make group
-        self.ug1 = fixture.create_user_group(u'G1')
+        self.ug1 = fixture.create_user_group('G1')
         # add user to group
         UserGroupModel().add_user_to_group(self.ug1, self.u1)
 
@@ -198,14 +199,14 @@
         assert u1_auth.permissions['repositories_groups'] == perms['repositories_groups']
 
     def test_repo_in_group_permissions(self):
-        self.g1 = fixture.create_repo_group(u'group1', skip_if_exists=True)
-        self.g2 = fixture.create_repo_group(u'group2', skip_if_exists=True)
+        self.g1 = fixture.create_repo_group('group1', skip_if_exists=True)
+        self.g2 = fixture.create_repo_group('group2', skip_if_exists=True)
         # both perms should be read !
         u1_auth = AuthUser(user_id=self.u1.user_id)
-        assert u1_auth.permissions['repositories_groups'] == {u'group1': u'group.read', u'group2': u'group.read'}
+        assert u1_auth.permissions['repositories_groups'] == {'group1': 'group.read', 'group2': 'group.read'}
 
         a1_auth = AuthUser(user_id=self.anon.user_id)
-        assert a1_auth.permissions['repositories_groups'] == {u'group1': u'group.read', u'group2': u'group.read'}
+        assert a1_auth.permissions['repositories_groups'] == {'group1': 'group.read', 'group2': 'group.read'}
 
         # Change perms to none for both groups
         RepoGroupModel().grant_user_permission(repo_group=self.g1,
@@ -216,23 +217,23 @@
                                                perm='group.none')
 
         u1_auth = AuthUser(user_id=self.u1.user_id)
-        assert u1_auth.permissions['repositories_groups'] == {u'group1': u'group.none', u'group2': u'group.none'}
+        assert u1_auth.permissions['repositories_groups'] == {'group1': 'group.none', 'group2': 'group.none'}
 
         a1_auth = AuthUser(user_id=self.anon.user_id)
-        assert a1_auth.permissions['repositories_groups'] == {u'group1': u'group.none', u'group2': u'group.none'}
+        assert a1_auth.permissions['repositories_groups'] == {'group1': 'group.none', 'group2': 'group.none'}
 
         # add repo to group
-        name = RepoGroup.url_sep().join([self.g1.group_name, 'test_perm'])
+        name = db.URL_SEP.join([self.g1.group_name, 'test_perm'])
         self.test_repo = fixture.create_repo(name=name,
                                              repo_type='hg',
                                              repo_group=self.g1,
                                              cur_user=self.u1,)
 
         u1_auth = AuthUser(user_id=self.u1.user_id)
-        assert u1_auth.permissions['repositories_groups'] == {u'group1': u'group.none', u'group2': u'group.none'}
+        assert u1_auth.permissions['repositories_groups'] == {'group1': 'group.none', 'group2': 'group.none'}
 
         a1_auth = AuthUser(user_id=self.anon.user_id)
-        assert a1_auth.permissions['repositories_groups'] == {u'group1': u'group.none', u'group2': u'group.none'}
+        assert a1_auth.permissions['repositories_groups'] == {'group1': 'group.none', 'group2': 'group.none'}
 
         # grant permission for u2 !
         RepoGroupModel().grant_user_permission(repo_group=self.g1, user=self.u2,
@@ -243,27 +244,27 @@
         assert self.u1 != self.u2
         # u1 and anon should have not change perms while u2 should !
         u1_auth = AuthUser(user_id=self.u1.user_id)
-        assert u1_auth.permissions['repositories_groups'] == {u'group1': u'group.none', u'group2': u'group.none'}
+        assert u1_auth.permissions['repositories_groups'] == {'group1': 'group.none', 'group2': 'group.none'}
 
         u2_auth = AuthUser(user_id=self.u2.user_id)
-        assert u2_auth.permissions['repositories_groups'] == {u'group1': u'group.read', u'group2': u'group.read'}
+        assert u2_auth.permissions['repositories_groups'] == {'group1': 'group.read', 'group2': 'group.read'}
 
         a1_auth = AuthUser(user_id=self.anon.user_id)
-        assert a1_auth.permissions['repositories_groups'] == {u'group1': u'group.none', u'group2': u'group.none'}
+        assert a1_auth.permissions['repositories_groups'] == {'group1': 'group.none', 'group2': 'group.none'}
 
     def test_repo_group_user_as_user_group_member(self):
         # create Group1
-        self.g1 = fixture.create_repo_group(u'group1', skip_if_exists=True)
+        self.g1 = fixture.create_repo_group('group1', skip_if_exists=True)
         a1_auth = AuthUser(user_id=self.anon.user_id)
 
-        assert a1_auth.permissions['repositories_groups'] == {u'group1': u'group.read'}
+        assert a1_auth.permissions['repositories_groups'] == {'group1': 'group.read'}
 
         # set default permission to none
         RepoGroupModel().grant_user_permission(repo_group=self.g1,
                                                user=self.anon,
                                                perm='group.none')
         # make group
-        self.ug1 = fixture.create_user_group(u'G1')
+        self.ug1 = fixture.create_user_group('G1')
         # add user to group
         UserGroupModel().add_user_to_group(self.ug1, self.u1)
         Session().commit()
@@ -275,10 +276,10 @@
 
         # check his permissions
         a1_auth = AuthUser(user_id=self.anon.user_id)
-        assert a1_auth.permissions['repositories_groups'] == {u'group1': u'group.none'}
+        assert a1_auth.permissions['repositories_groups'] == {'group1': 'group.none'}
 
         u1_auth = AuthUser(user_id=self.u1.user_id)
-        assert u1_auth.permissions['repositories_groups'] == {u'group1': u'group.none'}
+        assert u1_auth.permissions['repositories_groups'] == {'group1': 'group.none'}
 
         # grant ug1 read permissions for
         RepoGroupModel().grant_user_group_permission(repo_group=self.g1,
@@ -294,10 +295,10 @@
 
         a1_auth = AuthUser(user_id=self.anon.user_id)
 
-        assert a1_auth.permissions['repositories_groups'] == {u'group1': u'group.none'}
+        assert a1_auth.permissions['repositories_groups'] == {'group1': 'group.none'}
 
         u1_auth = AuthUser(user_id=self.u1.user_id)
-        assert u1_auth.permissions['repositories_groups'] == {u'group1': u'group.read'}
+        assert u1_auth.permissions['repositories_groups'] == {'group1': 'group.read'}
 
     def test_inherit_nice_permissions_from_default_user(self):
         user_model = UserModel()
@@ -388,7 +389,7 @@
     def test_inactive_user_group_does_not_affect_global_permissions(self):
         # Add user to inactive user group, set specific permissions on user
         # group and and verify it really is inactive.
-        self.ug1 = fixture.create_user_group(u'G1')
+        self.ug1 = fixture.create_user_group('G1')
         user_group_model = UserGroupModel()
         user_group_model.add_user_to_group(self.ug1, self.u1)
         user_group_model.update(self.ug1, {'users_group_active': False})
@@ -420,7 +421,7 @@
     def test_inactive_user_group_does_not_affect_global_permissions_inverse(self):
         # Add user to inactive user group, set specific permissions on user
         # group and and verify it really is inactive.
-        self.ug1 = fixture.create_user_group(u'G1')
+        self.ug1 = fixture.create_user_group('G1')
         user_group_model = UserGroupModel()
         user_group_model.add_user_to_group(self.ug1, self.u1)
         user_group_model.update(self.ug1, {'users_group_active': False})
@@ -450,14 +451,14 @@
                               'hg.create.write_on_repogroup.true'])
 
     def test_inactive_user_group_does_not_affect_repo_permissions(self):
-        self.ug1 = fixture.create_user_group(u'G1')
+        self.ug1 = fixture.create_user_group('G1')
         user_group_model = UserGroupModel()
         user_group_model.add_user_to_group(self.ug1, self.u1)
         user_group_model.update(self.ug1, {'users_group_active': False})
 
         # note: make u2 repo owner rather than u1, because the owner always has
         # admin permissions
-        self.test_repo = fixture.create_repo(name=u'myownrepo',
+        self.test_repo = fixture.create_repo(name='myownrepo',
                                              repo_type='hg',
                                              cur_user=self.u2)
 
@@ -474,14 +475,14 @@
         assert u1_auth.permissions['repositories']['myownrepo'] == 'repository.write'
 
     def test_inactive_user_group_does_not_affect_repo_permissions_inverse(self):
-        self.ug1 = fixture.create_user_group(u'G1')
+        self.ug1 = fixture.create_user_group('G1')
         user_group_model = UserGroupModel()
         user_group_model.add_user_to_group(self.ug1, self.u1)
         user_group_model.update(self.ug1, {'users_group_active': False})
 
         # note: make u2 repo owner rather than u1, because the owner always has
         # admin permissions
-        self.test_repo = fixture.create_repo(name=u'myownrepo',
+        self.test_repo = fixture.create_repo(name='myownrepo',
                                              repo_type='hg',
                                              cur_user=self.u2)
 
@@ -498,12 +499,12 @@
         assert u1_auth.permissions['repositories']['myownrepo'] == 'repository.admin'
 
     def test_inactive_user_group_does_not_affect_repo_group_permissions(self):
-        self.ug1 = fixture.create_user_group(u'G1')
+        self.ug1 = fixture.create_user_group('G1')
         user_group_model = UserGroupModel()
         user_group_model.add_user_to_group(self.ug1, self.u1)
         user_group_model.update(self.ug1, {'users_group_active': False})
 
-        self.g1 = fixture.create_repo_group(u'group1', skip_if_exists=True)
+        self.g1 = fixture.create_repo_group('group1', skip_if_exists=True)
 
         # enable admin access for user group on repo group
         RepoGroupModel().grant_user_group_permission(self.g1,
@@ -515,15 +516,15 @@
                                                perm='group.write')
         Session().commit()
         u1_auth = AuthUser(user_id=self.u1.user_id)
-        assert u1_auth.permissions['repositories_groups'] == {u'group1': u'group.write'}
+        assert u1_auth.permissions['repositories_groups'] == {'group1': 'group.write'}
 
     def test_inactive_user_group_does_not_affect_repo_group_permissions_inverse(self):
-        self.ug1 = fixture.create_user_group(u'G1')
+        self.ug1 = fixture.create_user_group('G1')
         user_group_model = UserGroupModel()
         user_group_model.add_user_to_group(self.ug1, self.u1)
         user_group_model.update(self.ug1, {'users_group_active': False})
 
-        self.g1 = fixture.create_repo_group(u'group1', skip_if_exists=True)
+        self.g1 = fixture.create_repo_group('group1', skip_if_exists=True)
 
         # enable only write access for user group on repo group
         RepoGroupModel().grant_user_group_permission(self.g1,
@@ -535,15 +536,15 @@
                                                perm='group.admin')
         Session().commit()
         u1_auth = AuthUser(user_id=self.u1.user_id)
-        assert u1_auth.permissions['repositories_groups'] == {u'group1': u'group.admin'}
+        assert u1_auth.permissions['repositories_groups'] == {'group1': 'group.admin'}
 
     def test_inactive_user_group_does_not_affect_user_group_permissions(self):
-        self.ug1 = fixture.create_user_group(u'G1')
+        self.ug1 = fixture.create_user_group('G1')
         user_group_model = UserGroupModel()
         user_group_model.add_user_to_group(self.ug1, self.u1)
         user_group_model.update(self.ug1, {'users_group_active': False})
 
-        self.ug2 = fixture.create_user_group(u'G2')
+        self.ug2 = fixture.create_user_group('G2')
 
         # enable admin access for user group on user group
         UserGroupModel().grant_user_group_permission(self.ug2,
@@ -555,16 +556,16 @@
                                                perm='usergroup.write')
         Session().commit()
         u1_auth = AuthUser(user_id=self.u1.user_id)
-        assert u1_auth.permissions['user_groups'][u'G1'] == u'usergroup.read'
-        assert u1_auth.permissions['user_groups'][u'G2'] == u'usergroup.write'
+        assert u1_auth.permissions['user_groups']['G1'] == 'usergroup.read'
+        assert u1_auth.permissions['user_groups']['G2'] == 'usergroup.write'
 
     def test_inactive_user_group_does_not_affect_user_group_permissions_inverse(self):
-        self.ug1 = fixture.create_user_group(u'G1')
+        self.ug1 = fixture.create_user_group('G1')
         user_group_model = UserGroupModel()
         user_group_model.add_user_to_group(self.ug1, self.u1)
         user_group_model.update(self.ug1, {'users_group_active': False})
 
-        self.ug2 = fixture.create_user_group(u'G2')
+        self.ug2 = fixture.create_user_group('G2')
 
         # enable only write access for user group on user group
         UserGroupModel().grant_user_group_permission(self.ug2,
@@ -576,12 +577,12 @@
                                                perm='usergroup.admin')
         Session().commit()
         u1_auth = AuthUser(user_id=self.u1.user_id)
-        assert u1_auth.permissions['user_groups'][u'G1'] == u'usergroup.read'
-        assert u1_auth.permissions['user_groups'][u'G2'] == u'usergroup.admin'
+        assert u1_auth.permissions['user_groups']['G1'] == 'usergroup.read'
+        assert u1_auth.permissions['user_groups']['G2'] == 'usergroup.admin'
 
     def test_owner_permissions_doesnot_get_overwritten_by_group(self):
         # create repo as USER,
-        self.test_repo = fixture.create_repo(name=u'myownrepo',
+        self.test_repo = fixture.create_repo(name='myownrepo',
                                              repo_type='hg',
                                              cur_user=self.u1)
 
@@ -589,7 +590,7 @@
         u1_auth = AuthUser(user_id=self.u1.user_id)
         assert u1_auth.permissions['repositories']['myownrepo'] == 'repository.admin'
         # set his permission as user group, he should still be admin
-        self.ug1 = fixture.create_user_group(u'G1')
+        self.ug1 = fixture.create_user_group('G1')
         UserGroupModel().add_user_to_group(self.ug1, self.u1)
         RepoModel().grant_user_group_permission(self.test_repo,
                                                  group_name=self.ug1,
@@ -601,7 +602,7 @@
 
     def test_owner_permissions_doesnot_get_overwritten_by_others(self):
         # create repo as USER,
-        self.test_repo = fixture.create_repo(name=u'myownrepo',
+        self.test_repo = fixture.create_repo(name='myownrepo',
                                              repo_type='hg',
                                              cur_user=self.u1)
 
--- a/kallithea/tests/models/test_repo_groups.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/models/test_repo_groups.py	Mon Apr 27 13:25:28 2020 +0200
@@ -3,6 +3,7 @@
 import pytest
 from sqlalchemy.exc import IntegrityError
 
+from kallithea.model import db
 from kallithea.model.db import RepoGroup
 from kallithea.model.meta import Session
 from kallithea.model.repo import RepoModel
@@ -14,7 +15,7 @@
 fixture = Fixture()
 
 
-def _update_repo_group(id_, group_name, desc=u'desc', parent_id=None):
+def _update_repo_group(id_, group_name, desc='desc', parent_id=None):
     form_data = dict(
         group_name=group_name,
         group_description=desc,
@@ -37,9 +38,9 @@
 class TestRepoGroups(base.TestController):
 
     def setup_method(self, method):
-        self.g1 = fixture.create_repo_group(u'test1', skip_if_exists=True)
-        self.g2 = fixture.create_repo_group(u'test2', skip_if_exists=True)
-        self.g3 = fixture.create_repo_group(u'test3', skip_if_exists=True)
+        self.g1 = fixture.create_repo_group('test1', skip_if_exists=True)
+        self.g2 = fixture.create_repo_group('test2', skip_if_exists=True)
+        self.g3 = fixture.create_repo_group('test3', skip_if_exists=True)
 
     def teardown_method(self, method):
         Session.remove()
@@ -56,7 +57,7 @@
         RepoGroupModel().delete(id_)
 
     def test_create_group(self):
-        g = fixture.create_repo_group(u'newGroup')
+        g = fixture.create_repo_group('newGroup')
         Session().commit()
         assert g.full_path == 'newGroup'
 
@@ -64,85 +65,84 @@
 
     def test_create_same_name_group(self):
         with pytest.raises(IntegrityError):
-            fixture.create_repo_group(u'newGroup')
+            fixture.create_repo_group('newGroup')
         Session().rollback()
 
     def test_same_subgroup(self):
-        sg1 = fixture.create_repo_group(u'sub1', parent_group_id=self.g1.group_id)
+        sg1 = fixture.create_repo_group('sub1', parent_group_id=self.g1.group_id)
         assert sg1.parent_group == self.g1
         assert sg1.full_path == 'test1/sub1'
         assert self.__check_path('test1', 'sub1')
 
-        ssg1 = fixture.create_repo_group(u'subsub1', parent_group_id=sg1.group_id)
+        ssg1 = fixture.create_repo_group('subsub1', parent_group_id=sg1.group_id)
         assert ssg1.parent_group == sg1
         assert ssg1.full_path == 'test1/sub1/subsub1'
         assert self.__check_path('test1', 'sub1', 'subsub1')
 
     def test_remove_group(self):
-        sg1 = fixture.create_repo_group(u'deleteme')
+        sg1 = fixture.create_repo_group('deleteme')
         self.__delete_group(sg1.group_id)
 
         assert RepoGroup.get(sg1.group_id) is None
         assert not self.__check_path('deteteme')
 
-        sg1 = fixture.create_repo_group(u'deleteme', parent_group_id=self.g1.group_id)
+        sg1 = fixture.create_repo_group('deleteme', parent_group_id=self.g1.group_id)
         self.__delete_group(sg1.group_id)
 
         assert RepoGroup.get(sg1.group_id) is None
         assert not self.__check_path('test1', 'deteteme')
 
     def test_rename_single_group(self):
-        sg1 = fixture.create_repo_group(u'initial')
+        sg1 = fixture.create_repo_group('initial')
 
-        new_sg1 = _update_repo_group(sg1.group_id, u'after')
+        new_sg1 = _update_repo_group(sg1.group_id, 'after')
         assert self.__check_path('after')
-        assert RepoGroup.get_by_group_name(u'initial') is None
+        assert RepoGroup.get_by_group_name('initial') is None
 
     def test_update_group_parent(self):
 
-        sg1 = fixture.create_repo_group(u'initial', parent_group_id=self.g1.group_id)
+        sg1 = fixture.create_repo_group('initial', parent_group_id=self.g1.group_id)
 
-        new_sg1 = _update_repo_group(sg1.group_id, u'after', parent_id=self.g1.group_id)
+        new_sg1 = _update_repo_group(sg1.group_id, 'after', parent_id=self.g1.group_id)
         assert self.__check_path('test1', 'after')
-        assert RepoGroup.get_by_group_name(u'test1/initial') is None
+        assert RepoGroup.get_by_group_name('test1/initial') is None
 
-        new_sg1 = _update_repo_group(sg1.group_id, u'after', parent_id=self.g3.group_id)
+        new_sg1 = _update_repo_group(sg1.group_id, 'after', parent_id=self.g3.group_id)
         assert self.__check_path('test3', 'after')
-        assert RepoGroup.get_by_group_name(u'test3/initial') == None
+        assert RepoGroup.get_by_group_name('test3/initial') == None
 
-        new_sg1 = _update_repo_group(sg1.group_id, u'hello')
+        new_sg1 = _update_repo_group(sg1.group_id, 'hello')
         assert self.__check_path('hello')
 
-        assert RepoGroup.get_by_group_name(u'hello') == new_sg1
+        assert RepoGroup.get_by_group_name('hello') == new_sg1
 
     def test_subgrouping_with_repo(self):
 
-        g1 = fixture.create_repo_group(u'g1')
-        g2 = fixture.create_repo_group(u'g2')
+        g1 = fixture.create_repo_group('g1')
+        g2 = fixture.create_repo_group('g2')
         # create new repo
-        r = fixture.create_repo(u'john')
+        r = fixture.create_repo('john')
 
         assert r.repo_name == 'john'
         # put repo into group
-        r = _update_repo(u'john', repo_group=g1.group_id)
+        r = _update_repo('john', repo_group=g1.group_id)
         Session().commit()
         assert r.repo_name == 'g1/john'
 
-        _update_repo_group(g1.group_id, u'g1', parent_id=g2.group_id)
+        _update_repo_group(g1.group_id, 'g1', parent_id=g2.group_id)
         assert self.__check_path('g2', 'g1')
 
         # test repo
-        assert r.repo_name == RepoGroup.url_sep().join(['g2', 'g1',
-                                                                r.just_name])
+        assert r.repo_name == db.URL_SEP.join(['g2', 'g1', r.just_name])
 
     def test_move_to_root(self):
-        g1 = fixture.create_repo_group(u't11')
-        g2 = fixture.create_repo_group(u't22', parent_group_id=g1.group_id)
+        g1 = fixture.create_repo_group('t11')
+        g2 = fixture.create_repo_group('t22', parent_group_id=g1.group_id)
 
         assert g2.full_path == 't11/t22'
         assert self.__check_path('t11', 't22')
 
-        g2 = _update_repo_group(g2.group_id, u'g22', parent_id=None)
+        g2 = _update_repo_group(g2.group_id, 'g22', parent_id=None)
         Session().commit()
 
         assert g2.group_name == 'g22'
@@ -152,14 +152,14 @@
         assert self.__check_path('g22')
 
     def test_rename_top_level_group_in_nested_setup(self):
-        g1 = fixture.create_repo_group(u'L1')
-        g2 = fixture.create_repo_group(u'L2', parent_group_id=g1.group_id)
-        g3 = fixture.create_repo_group(u'L3', parent_group_id=g2.group_id)
+        g1 = fixture.create_repo_group('L1')
+        g2 = fixture.create_repo_group('L2', parent_group_id=g1.group_id)
+        g3 = fixture.create_repo_group('L3', parent_group_id=g2.group_id)
 
-        r = fixture.create_repo(u'L1/L2/L3/L3_REPO', repo_group=g3.group_id)
+        r = fixture.create_repo('L1/L2/L3/L3_REPO', repo_group=g3.group_id)
 
         ## rename L1 all groups should be now changed
-        _update_repo_group(g1.group_id, u'L1_NEW')
+        _update_repo_group(g1.group_id, 'L1_NEW')
         Session().commit()
         assert g1.full_path == 'L1_NEW'
         assert g2.full_path == 'L1_NEW/L2'
@@ -167,14 +167,14 @@
         assert r.repo_name == 'L1_NEW/L2/L3/L3_REPO'
 
     def test_change_parent_of_top_level_group_in_nested_setup(self):
-        g1 = fixture.create_repo_group(u'R1')
-        g2 = fixture.create_repo_group(u'R2', parent_group_id=g1.group_id)
-        g3 = fixture.create_repo_group(u'R3', parent_group_id=g2.group_id)
-        g4 = fixture.create_repo_group(u'R1_NEW')
+        g1 = fixture.create_repo_group('R1')
+        g2 = fixture.create_repo_group('R2', parent_group_id=g1.group_id)
+        g3 = fixture.create_repo_group('R3', parent_group_id=g2.group_id)
+        g4 = fixture.create_repo_group('R1_NEW')
 
-        r = fixture.create_repo(u'R1/R2/R3/R3_REPO', repo_group=g3.group_id)
+        r = fixture.create_repo('R1/R2/R3/R3_REPO', repo_group=g3.group_id)
         ## rename L1 all groups should be now changed
-        _update_repo_group(g1.group_id, u'R1', parent_id=g4.group_id)
+        _update_repo_group(g1.group_id, 'R1', parent_id=g4.group_id)
         Session().commit()
         assert g1.full_path == 'R1_NEW/R1'
         assert g2.full_path == 'R1_NEW/R1/R2'
@@ -182,15 +182,15 @@
         assert r.repo_name == 'R1_NEW/R1/R2/R3/R3_REPO'
 
     def test_change_parent_of_top_level_group_in_nested_setup_with_rename(self):
-        g1 = fixture.create_repo_group(u'X1')
-        g2 = fixture.create_repo_group(u'X2', parent_group_id=g1.group_id)
-        g3 = fixture.create_repo_group(u'X3', parent_group_id=g2.group_id)
-        g4 = fixture.create_repo_group(u'X1_NEW')
+        g1 = fixture.create_repo_group('X1')
+        g2 = fixture.create_repo_group('X2', parent_group_id=g1.group_id)
+        g3 = fixture.create_repo_group('X3', parent_group_id=g2.group_id)
+        g4 = fixture.create_repo_group('X1_NEW')
 
-        r = fixture.create_repo(u'X1/X2/X3/X3_REPO', repo_group=g3.group_id)
+        r = fixture.create_repo('X1/X2/X3/X3_REPO', repo_group=g3.group_id)
 
         ## rename L1 all groups should be now changed
-        _update_repo_group(g1.group_id, u'X1_PRIM', parent_id=g4.group_id)
+        _update_repo_group(g1.group_id, 'X1_PRIM', parent_id=g4.group_id)
         Session().commit()
         assert g1.full_path == 'X1_NEW/X1_PRIM'
         assert g2.full_path == 'X1_NEW/X1_PRIM/X2'
--- a/kallithea/tests/models/test_repos.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/models/test_repos.py	Mon Apr 27 13:25:28 2020 +0200
@@ -17,65 +17,65 @@
         Session.remove()
 
     def test_remove_repo(self):
-        repo = fixture.create_repo(name=u'test-repo-1')
+        repo = fixture.create_repo(name='test-repo-1')
         Session().commit()
 
         RepoModel().delete(repo=repo)
         Session().commit()
 
-        assert Repository.get_by_repo_name(repo_name=u'test-repo-1') is None
+        assert Repository.get_by_repo_name(repo_name='test-repo-1') is None
 
     def test_remove_repo_repo_raises_exc_when_attached_forks(self):
-        repo = fixture.create_repo(name=u'test-repo-1')
+        repo = fixture.create_repo(name='test-repo-1')
         Session().commit()
 
-        fixture.create_fork(repo.repo_name, u'test-repo-fork-1')
+        fixture.create_fork(repo.repo_name, 'test-repo-fork-1')
         Session().commit()
 
         with pytest.raises(AttachedForksError):
             RepoModel().delete(repo=repo)
         # cleanup
-        RepoModel().delete(repo=u'test-repo-fork-1')
-        RepoModel().delete(repo=u'test-repo-1')
+        RepoModel().delete(repo='test-repo-fork-1')
+        RepoModel().delete(repo='test-repo-1')
         Session().commit()
 
     def test_remove_repo_delete_forks(self):
-        repo = fixture.create_repo(name=u'test-repo-1')
+        repo = fixture.create_repo(name='test-repo-1')
         Session().commit()
 
-        fork = fixture.create_fork(repo.repo_name, u'test-repo-fork-1')
+        fork = fixture.create_fork(repo.repo_name, 'test-repo-fork-1')
         Session().commit()
 
         # fork of fork
-        fixture.create_fork(fork.repo_name, u'test-repo-fork-fork-1')
+        fixture.create_fork(fork.repo_name, 'test-repo-fork-fork-1')
         Session().commit()
 
         RepoModel().delete(repo=repo, forks='delete')
         Session().commit()
 
-        assert Repository.get_by_repo_name(repo_name=u'test-repo-1') is None
-        assert Repository.get_by_repo_name(repo_name=u'test-repo-fork-1') is None
-        assert Repository.get_by_repo_name(repo_name=u'test-repo-fork-fork-1') is None
+        assert Repository.get_by_repo_name(repo_name='test-repo-1') is None
+        assert Repository.get_by_repo_name(repo_name='test-repo-fork-1') is None
+        assert Repository.get_by_repo_name(repo_name='test-repo-fork-fork-1') is None
 
     def test_remove_repo_detach_forks(self):
-        repo = fixture.create_repo(name=u'test-repo-1')
+        repo = fixture.create_repo(name='test-repo-1')
         Session().commit()
 
-        fork = fixture.create_fork(repo.repo_name, u'test-repo-fork-1')
+        fork = fixture.create_fork(repo.repo_name, 'test-repo-fork-1')
         Session().commit()
 
         # fork of fork
-        fixture.create_fork(fork.repo_name, u'test-repo-fork-fork-1')
+        fixture.create_fork(fork.repo_name, 'test-repo-fork-fork-1')
         Session().commit()
 
         RepoModel().delete(repo=repo, forks='detach')
         Session().commit()
 
         try:
-            assert Repository.get_by_repo_name(repo_name=u'test-repo-1') is None
-            assert Repository.get_by_repo_name(repo_name=u'test-repo-fork-1') is not None
-            assert Repository.get_by_repo_name(repo_name=u'test-repo-fork-fork-1') is not None
+            assert Repository.get_by_repo_name(repo_name='test-repo-1') is None
+            assert Repository.get_by_repo_name(repo_name='test-repo-fork-1') is not None
+            assert Repository.get_by_repo_name(repo_name='test-repo-fork-fork-1') is not None
         finally:
-            RepoModel().delete(repo=u'test-repo-fork-fork-1')
-            RepoModel().delete(repo=u'test-repo-fork-1')
+            RepoModel().delete(repo='test-repo-fork-fork-1')
+            RepoModel().delete(repo='test-repo-fork-1')
             Session().commit()
--- a/kallithea/tests/models/test_settings.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/models/test_settings.py	Mon Apr 27 13:25:28 2020 +0200
@@ -35,7 +35,7 @@
     setting = Setting.create_or_update(name, 'spam', type='list')
     Session().flush() # must flush so we can delete it below
     try:
-        assert setting.app_settings_value == [u'spam']
+        assert setting.app_settings_value == ['spam']
         # Assign back setting value.
         setting.app_settings_value = setting.app_settings_value
         # Quirk: value is stringified on write and listified on read.
--- a/kallithea/tests/models/test_user_group_permissions_on_repo_groups.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/models/test_user_group_permissions_on_repo_groups.py	Mon Apr 27 13:25:28 2020 +0200
@@ -16,7 +16,7 @@
 _get_group_perms = None
 
 
-def permissions_setup_func(group_name=u'g0', perm='group.read', recursive='all'):
+def permissions_setup_func(group_name='g0', perm='group.read', recursive='all'):
     """
     Resets all permissions to perm attribute
     """
@@ -43,7 +43,7 @@
     Session().commit()
     test_u2_id = test_u2.user_id
 
-    gr1 = fixture.create_user_group(u'perms_group_1')
+    gr1 = fixture.create_user_group('perms_group_1')
     Session().commit()
     test_u2_gr_id = gr1.users_group_id
     UserGroupModel().add_user_to_group(gr1, user=test_u2_id)
@@ -57,13 +57,13 @@
 
 def teardown_module():
     _destroy_project_tree(test_u2_id)
-    fixture.destroy_user_group(u'perms_group_1')
+    fixture.destroy_user_group('perms_group_1')
 
 
 def test_user_permissions_on_group_without_recursive_mode():
     # set permission to g0 non-recursive mode
     recursive = 'none'
-    group = u'g0'
+    group = 'g0'
     permissions_setup_func(group, 'group.write', recursive=recursive)
 
     items = [x for x in _get_repo_perms(group, recursive)]
@@ -82,7 +82,7 @@
 def test_user_permissions_on_group_without_recursive_mode_subgroup():
     # set permission to g0 non-recursive mode
     recursive = 'none'
-    group = u'g0/g0_1'
+    group = 'g0/g0_1'
     permissions_setup_func(group, 'group.write', recursive=recursive)
 
     items = [x for x in _get_repo_perms(group, recursive)]
@@ -103,7 +103,7 @@
     # set permission to g0 recursive mode, all children including
     # other repos and groups should have this permission now set !
     recursive = 'all'
-    group = u'g0'
+    group = 'g0'
     permissions_setup_func(group, 'group.write', recursive=recursive)
 
     repo_items = [x for x in _get_repo_perms(group, recursive)]
@@ -120,7 +120,7 @@
 def test_user_permissions_on_group_with_recursive_mode_inner_group():
     ## set permission to g0_3 group to none
     recursive = 'all'
-    group = u'g0/g0_3'
+    group = 'g0/g0_3'
     permissions_setup_func(group, 'group.none', recursive=recursive)
 
     repo_items = [x for x in _get_repo_perms(group, recursive)]
@@ -137,7 +137,7 @@
 def test_user_permissions_on_group_with_recursive_mode_deepest():
     ## set permission to g0/g0_1/g0_1_1 group to write
     recursive = 'all'
-    group = u'g0/g0_1/g0_1_1'
+    group = 'g0/g0_1/g0_1_1'
     permissions_setup_func(group, 'group.write', recursive=recursive)
 
     repo_items = [x for x in _get_repo_perms(group, recursive)]
@@ -154,7 +154,7 @@
 def test_user_permissions_on_group_with_recursive_mode_only_with_repos():
     ## set permission to g0/g0_2 group to admin
     recursive = 'all'
-    group = u'g0/g0_2'
+    group = 'g0/g0_2'
     permissions_setup_func(group, 'group.admin', recursive=recursive)
 
     repo_items = [x for x in _get_repo_perms(group, recursive)]
@@ -171,7 +171,7 @@
 def test_user_permissions_on_group_with_recursive_mode_on_repos():
     # set permission to g0/g0_1 with recursive mode on just repositories
     recursive = 'repos'
-    group = u'g0/g0_1'
+    group = 'g0/g0_1'
     perm = 'group.write'
     permissions_setup_func(group, perm, recursive=recursive)
 
@@ -195,7 +195,7 @@
 def test_user_permissions_on_group_with_recursive_mode_on_repo_groups():
     # set permission to g0/g0_1 with recursive mode on just repository groups
     recursive = 'groups'
-    group = u'g0/g0_1'
+    group = 'g0/g0_1'
     perm = 'group.none'
     permissions_setup_func(group, perm, recursive=recursive)
 
--- a/kallithea/tests/models/test_user_groups.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/models/test_user_groups.py	Mon Apr 27 13:25:28 2020 +0200
@@ -18,12 +18,12 @@
 
     @base.parametrize('pre_existing,regular_should_be,external_should_be,groups,expected', [
         ([], [], [], [], []),
-        ([], [u'regular'], [], [], [u'regular']),  # no changes of regular
-        ([u'some_other'], [], [], [u'some_other'], []),   # not added to regular group
-        ([], [u'regular'], [u'container'], [u'container'], [u'regular', u'container']),
-        ([], [u'regular'], [], [u'container', u'container2'], [u'regular', u'container', u'container2']),
-        ([], [u'regular'], [u'other'], [], [u'regular']),  # remove not used
-        ([u'some_other'], [u'regular'], [u'other', u'container'], [u'container', u'container2'], [u'regular', u'container', u'container2']),
+        ([], ['regular'], [], [], ['regular']),  # no changes of regular
+        (['some_other'], [], [], ['some_other'], []),   # not added to regular group
+        ([], ['regular'], ['container'], ['container'], ['regular', 'container']),
+        ([], ['regular'], [], ['container', 'container2'], ['regular', 'container', 'container2']),
+        ([], ['regular'], ['other'], [], ['regular']),  # remove not used
+        (['some_other'], ['regular'], ['other', 'container'], ['container', 'container2'], ['regular', 'container', 'container2']),
     ])
     def test_enforce_groups(self, pre_existing, regular_should_be,
                             external_should_be, groups, expected):
--- a/kallithea/tests/models/test_user_permissions_on_repo_groups.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/models/test_user_permissions_on_repo_groups.py	Mon Apr 27 13:25:28 2020 +0200
@@ -1,6 +1,7 @@
 import functools
 
-from kallithea.model.db import RepoGroup, Repository, User
+import kallithea
+from kallithea.model.db import RepoGroup, Repository
 from kallithea.model.meta import Session
 from kallithea.model.repo_group import RepoGroupModel
 from kallithea.tests.models.common import _check_expected_count, _create_project_tree, _destroy_project_tree, _get_perms, check_tree_perms, expected_count
@@ -11,7 +12,7 @@
 _get_group_perms = None
 
 
-def permissions_setup_func(group_name=u'g0', perm='group.read', recursive='all',
+def permissions_setup_func(group_name='g0', perm='group.read', recursive='all',
                            user_id=None):
     """
     Resets all permissions to perm attribute
@@ -19,7 +20,7 @@
     if not user_id:
         user_id = test_u1_id
         permissions_setup_func(group_name, perm, recursive,
-                               user_id=User.get_default_user().user_id)
+                               user_id=kallithea.DEFAULT_USER_ID)
 
     repo_group = RepoGroup.get_by_group_name(group_name=group_name)
     if not repo_group:
@@ -56,7 +57,7 @@
 def test_user_permissions_on_group_without_recursive_mode():
     # set permission to g0 non-recursive mode
     recursive = 'none'
-    group = u'g0'
+    group = 'g0'
     permissions_setup_func(group, 'group.write', recursive=recursive)
 
     items = [x for x in _get_repo_perms(group, recursive)]
@@ -75,7 +76,7 @@
 def test_user_permissions_on_group_without_recursive_mode_subgroup():
     # set permission to g0 non-recursive mode
     recursive = 'none'
-    group = u'g0/g0_1'
+    group = 'g0/g0_1'
     permissions_setup_func(group, 'group.write', recursive=recursive)
 
     items = [x for x in _get_repo_perms(group, recursive)]
@@ -96,7 +97,7 @@
     # set permission to g0 recursive mode, all children including
     # other repos and groups should have this permission now set !
     recursive = 'all'
-    group = u'g0'
+    group = 'g0'
     permissions_setup_func(group, 'group.write', recursive=recursive)
 
     repo_items = [x for x in _get_repo_perms(group, recursive)]
@@ -115,8 +116,8 @@
     # set permission to g0 recursive mode, all children including
     # other repos and groups should have this permission now set !
     recursive = 'all'
-    group = u'g0'
-    default_user_id = User.get_default_user().user_id
+    group = 'g0'
+    default_user_id = kallithea.DEFAULT_USER_ID
     permissions_setup_func(group, 'group.write', recursive=recursive,
                            user_id=default_user_id)
 
@@ -142,7 +143,7 @@
 def test_user_permissions_on_group_with_recursive_mode_inner_group():
     ## set permission to g0_3 group to none
     recursive = 'all'
-    group = u'g0/g0_3'
+    group = 'g0/g0_3'
     permissions_setup_func(group, 'group.none', recursive=recursive)
 
     repo_items = [x for x in _get_repo_perms(group, recursive)]
@@ -159,7 +160,7 @@
 def test_user_permissions_on_group_with_recursive_mode_deepest():
     ## set permission to g0_3 group to none
     recursive = 'all'
-    group = u'g0/g0_1/g0_1_1'
+    group = 'g0/g0_1/g0_1_1'
     permissions_setup_func(group, 'group.write', recursive=recursive)
 
     repo_items = [x for x in _get_repo_perms(group, recursive)]
@@ -176,7 +177,7 @@
 def test_user_permissions_on_group_with_recursive_mode_only_with_repos():
     ## set permission to g0_3 group to none
     recursive = 'all'
-    group = u'g0/g0_2'
+    group = 'g0/g0_2'
     permissions_setup_func(group, 'group.admin', recursive=recursive)
 
     repo_items = [x for x in _get_repo_perms(group, recursive)]
@@ -194,9 +195,9 @@
     # set permission to g0/g0_1 recursive repos only mode, all children including
     # other repos should have this permission now set, inner groups are excluded!
     recursive = 'repos'
-    group = u'g0/g0_1'
+    group = 'g0/g0_1'
     perm = 'group.none'
-    default_user_id = User.get_default_user().user_id
+    default_user_id = kallithea.DEFAULT_USER_ID
 
     permissions_setup_func(group, perm, recursive=recursive,
                            user_id=default_user_id)
@@ -227,7 +228,7 @@
 def test_user_permissions_on_group_with_recursive_repo_mode_inner_group():
     ## set permission to g0_3 group to none, with recursive repos only
     recursive = 'repos'
-    group = u'g0/g0_3'
+    group = 'g0/g0_3'
     perm = 'group.none'
     permissions_setup_func(group, perm, recursive=recursive)
 
@@ -253,8 +254,8 @@
     # other groups should have this permission now set. repositories should
     # remain intact as we use groups only mode !
     recursive = 'groups'
-    group = u'g0/g0_1'
-    default_user_id = User.get_default_user().user_id
+    group = 'g0/g0_1'
+    default_user_id = kallithea.DEFAULT_USER_ID
     permissions_setup_func(group, 'group.write', recursive=recursive,
                            user_id=default_user_id)
 
@@ -278,7 +279,7 @@
 def test_user_permissions_on_group_with_recursive_group_mode_inner_group():
     ## set permission to g0_3 group to none, with recursive mode for groups only
     recursive = 'groups'
-    group = u'g0/g0_3'
+    group = 'g0/g0_3'
     permissions_setup_func(group, 'group.none', recursive=recursive)
 
     repo_items = [x for x in _get_repo_perms(group, recursive)]
--- a/kallithea/tests/models/test_users.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/models/test_users.py	Mon Apr 27 13:25:28 2020 +0200
@@ -21,21 +21,21 @@
         Session.remove()
 
     def test_create_and_remove(self):
-        usr = UserModel().create_or_update(username=u'test_user',
-                                           password=u'qweqwe',
-                                           email=u'u232@example.com',
-                                           firstname=u'u1', lastname=u'u1')
+        usr = UserModel().create_or_update(username='test_user',
+                                           password='qweqwe',
+                                           email='u232@example.com',
+                                           firstname='u1', lastname='u1')
         Session().commit()
-        assert User.get_by_username(u'test_user') == usr
-        assert User.get_by_username(u'test_USER', case_insensitive=True) == usr
+        assert User.get_by_username('test_user') == usr
+        assert User.get_by_username('test_USER', case_insensitive=True) == usr
         # User.get_by_username without explicit request for case insensitivty
         # will use database case sensitivity. The following will thus return
         # None on for example PostgreSQL but find test_user on MySQL - we are
         # fine with leaving that as undefined as long as it doesn't crash.
-        User.get_by_username(u'test_USER', case_insensitive=False)
+        User.get_by_username('test_USER', case_insensitive=False)
 
         # make user group
-        user_group = fixture.create_user_group(u'some_example_group')
+        user_group = fixture.create_user_group('some_example_group')
         Session().commit()
 
         UserGroupModel().add_user_to_group(user_group, usr)
@@ -49,15 +49,15 @@
         assert UserGroupMember.query().all() == []
 
     def test_additional_email_as_main(self):
-        usr = UserModel().create_or_update(username=u'test_user',
-                                           password=u'qweqwe',
-                                     email=u'main_email@example.com',
-                                     firstname=u'u1', lastname=u'u1')
+        usr = UserModel().create_or_update(username='test_user',
+                                           password='qweqwe',
+                                     email='main_email@example.com',
+                                     firstname='u1', lastname='u1')
         Session().commit()
 
         with pytest.raises(AttributeError):
             m = UserEmailMap()
-            m.email = u'main_email@example.com'
+            m.email = 'main_email@example.com'
             m.user = usr
             Session().add(m)
             Session().commit()
@@ -66,14 +66,14 @@
         Session().commit()
 
     def test_extra_email_map(self):
-        usr = UserModel().create_or_update(username=u'test_user',
-                                           password=u'qweqwe',
-                                     email=u'main_email@example.com',
-                                     firstname=u'u1', lastname=u'u1')
+        usr = UserModel().create_or_update(username='test_user',
+                                           password='qweqwe',
+                                     email='main_email@example.com',
+                                     firstname='u1', lastname='u1')
         Session().commit()
 
         m = UserEmailMap()
-        m.email = u'main_email2@example.com'
+        m.email = 'main_email2@example.com'
         m.user = usr
         Session().add(m)
         Session().commit()
@@ -104,10 +104,10 @@
 class TestUsers(base.TestController):
 
     def setup_method(self, method):
-        self.u1 = UserModel().create_or_update(username=u'u1',
-                                        password=u'qweqwe',
-                                        email=u'u1@example.com',
-                                        firstname=u'u1', lastname=u'u1')
+        self.u1 = UserModel().create_or_update(username='u1',
+                                        password='qweqwe',
+                                        email='u1@example.com',
+                                        firstname='u1', lastname='u1')
 
     def teardown_method(self, method):
         perm = Permission.query().all()
--- a/kallithea/tests/other/test_auth_ldap.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/other/test_auth_ldap.py	Mon Apr 27 13:25:28 2020 +0200
@@ -22,8 +22,8 @@
         pass
 
     def authenticate_ldap(self, username, password):
-        return 'spam dn', dict(test_ldap_firstname=[u'spam ldap first name'],
-                               test_ldap_lastname=[u'spam ldap last name'],
+        return 'spam dn', dict(test_ldap_firstname=['spam ldap first name'],
+                               test_ldap_lastname=['spam ldap last name'],
                                test_ldap_email=['spam ldap email'])
 
 
@@ -39,8 +39,8 @@
     user_input = dict(username='test-user-{0}'.format(uniqifier),
                       password='spam password',
                       email='spam-email-{0}'.format(uniqifier),
-                      firstname=u'spam first name',
-                      lastname=u'spam last name',
+                      firstname='spam first name',
+                      lastname='spam last name',
                       active=True,
                       admin=False)
     user = create_test_user(user_input)
@@ -54,14 +54,14 @@
     # Verify that authenication succeeded and retrieved correct attributes
     # from LDAP.
     assert user_data is not None
-    assert user_data.get('firstname') == u'spam ldap first name'
-    assert user_data.get('lastname') == u'spam ldap last name'
+    assert user_data.get('firstname') == 'spam ldap first name'
+    assert user_data.get('lastname') == 'spam ldap last name'
     assert user_data.get('email') == 'spam ldap email'
 
     # Verify that authentication overwrote user attributes with the ones
     # retrieved from LDAP.
-    assert user.firstname == u'spam ldap first name'
-    assert user.lastname == u'spam ldap last name'
+    assert user.firstname == 'spam ldap first name'
+    assert user.lastname == 'spam ldap last name'
     assert user.email == 'spam ldap email'
 
 
@@ -83,16 +83,16 @@
     # Verify that authenication succeeded and retrieved correct attributes
     # from LDAP.
     assert user_data is not None
-    assert user_data.get('firstname') == u'spam ldap first name'
-    assert user_data.get('lastname') == u'spam ldap last name'
+    assert user_data.get('firstname') == 'spam ldap first name'
+    assert user_data.get('lastname') == 'spam ldap last name'
     assert user_data.get('email') == 'spam ldap email'
 
     # Verify that authentication created new user with attributes
     # retrieved from LDAP.
     new_user = User.get_by_username(username)
     assert new_user is not None
-    assert new_user.firstname == u'spam ldap first name'
-    assert new_user.lastname == u'spam ldap last name'
+    assert new_user.firstname == 'spam ldap first name'
+    assert new_user.lastname == 'spam ldap last name'
     assert new_user.email == 'spam ldap email'
 
 
@@ -126,14 +126,14 @@
     # Verify that authenication succeeded and retrieved correct attributes
     # from LDAP, with empty email.
     assert user_data is not None
-    assert user_data.get('firstname') == u'spam ldap first name'
-    assert user_data.get('lastname') == u'spam ldap last name'
+    assert user_data.get('firstname') == 'spam ldap first name'
+    assert user_data.get('lastname') == 'spam ldap last name'
     assert user_data.get('email') == ''
 
     # Verify that authentication created new user with attributes
     # retrieved from LDAP, with email == None.
     new_user = User.get_by_username(username)
     assert new_user is not None
-    assert new_user.firstname == u'spam ldap first name'
-    assert new_user.lastname == u'spam ldap last name'
+    assert new_user.firstname == 'spam ldap first name'
+    assert new_user.lastname == 'spam ldap last name'
     assert new_user.email is None
--- a/kallithea/tests/other/test_libs.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/other/test_libs.py	Mon Apr 27 13:25:28 2020 +0200
@@ -142,20 +142,20 @@
         assert expected == set(extract_mentioned_usernames(sample))
 
     @base.parametrize('age_args,expected', [
-        (dict(), u'just now'),
-        (dict(seconds= -1), u'1 second ago'),
-        (dict(seconds= -60 * 2), u'2 minutes ago'),
-        (dict(hours= -1), u'1 hour ago'),
-        (dict(hours= -24), u'1 day ago'),
-        (dict(hours= -24 * 5), u'5 days ago'),
-        (dict(months= -1), u'1 month ago'),
-        (dict(months= -1, days= -2), u'1 month and 2 days ago'),
-        (dict(months= -1, days= -20), u'1 month and 19 days ago'),
-        (dict(years= -1, months= -1), u'1 year and 1 month ago'),
-        (dict(years= -1, months= -10), u'1 year and 10 months ago'),
-        (dict(years= -2, months= -4), u'2 years and 4 months ago'),
-        (dict(years= -2, months= -11), u'2 years and 11 months ago'),
-        (dict(years= -3, months= -2), u'3 years and 2 months ago'),
+        (dict(), 'just now'),
+        (dict(seconds= -1), '1 second ago'),
+        (dict(seconds= -60 * 2), '2 minutes ago'),
+        (dict(hours= -1), '1 hour ago'),
+        (dict(hours= -24), '1 day ago'),
+        (dict(hours= -24 * 5), '5 days ago'),
+        (dict(months= -1), '1 month ago'),
+        (dict(months= -1, days= -2), '1 month and 2 days ago'),
+        (dict(months= -1, days= -20), '1 month and 19 days ago'),
+        (dict(years= -1, months= -1), '1 year and 1 month ago'),
+        (dict(years= -1, months= -10), '1 year and 10 months ago'),
+        (dict(years= -2, months= -4), '2 years and 4 months ago'),
+        (dict(years= -2, months= -11), '2 years and 11 months ago'),
+        (dict(years= -3, months= -2), '3 years and 2 months ago'),
     ])
     def test_age(self, age_args, expected):
         from kallithea.lib.utils2 import age
@@ -166,21 +166,21 @@
             assert age(n + delt(**age_args), now=n) == expected
 
     @base.parametrize('age_args,expected', [
-        (dict(), u'just now'),
-        (dict(seconds= -1), u'1 second ago'),
-        (dict(seconds= -60 * 2), u'2 minutes ago'),
-        (dict(hours= -1), u'1 hour ago'),
-        (dict(hours= -24), u'1 day ago'),
-        (dict(hours= -24 * 5), u'5 days ago'),
-        (dict(months= -1), u'1 month ago'),
-        (dict(months= -1, days= -2), u'1 month ago'),
-        (dict(months= -1, days= -20), u'1 month ago'),
-        (dict(years= -1, months= -1), u'13 months ago'),
-        (dict(years= -1, months= -10), u'22 months ago'),
-        (dict(years= -2, months= -4), u'2 years ago'),
-        (dict(years= -2, months= -11), u'3 years ago'),
-        (dict(years= -3, months= -2), u'3 years ago'),
-        (dict(years= -4, months= -8), u'5 years ago'),
+        (dict(), 'just now'),
+        (dict(seconds= -1), '1 second ago'),
+        (dict(seconds= -60 * 2), '2 minutes ago'),
+        (dict(hours= -1), '1 hour ago'),
+        (dict(hours= -24), '1 day ago'),
+        (dict(hours= -24 * 5), '5 days ago'),
+        (dict(months= -1), '1 month ago'),
+        (dict(months= -1, days= -2), '1 month ago'),
+        (dict(months= -1, days= -20), '1 month ago'),
+        (dict(years= -1, months= -1), '13 months ago'),
+        (dict(years= -1, months= -10), '22 months ago'),
+        (dict(years= -2, months= -4), '2 years ago'),
+        (dict(years= -2, months= -11), '3 years ago'),
+        (dict(years= -3, months= -2), '3 years ago'),
+        (dict(years= -4, months= -8), '5 years ago'),
     ])
     def test_age_short(self, age_args, expected):
         from kallithea.lib.utils2 import age
@@ -191,15 +191,15 @@
             assert age(n + delt(**age_args), show_short_version=True, now=n) == expected
 
     @base.parametrize('age_args,expected', [
-        (dict(), u'just now'),
-        (dict(seconds=1), u'in 1 second'),
-        (dict(seconds=60 * 2), u'in 2 minutes'),
-        (dict(hours=1), u'in 1 hour'),
-        (dict(hours=24), u'in 1 day'),
-        (dict(hours=24 * 5), u'in 5 days'),
-        (dict(months=1), u'in 1 month'),
-        (dict(months=1, days=1), u'in 1 month and 1 day'),
-        (dict(years=1, months=1), u'in 1 year and 1 month')
+        (dict(), 'just now'),
+        (dict(seconds=1), 'in 1 second'),
+        (dict(seconds=60 * 2), 'in 2 minutes'),
+        (dict(hours=1), 'in 1 hour'),
+        (dict(hours=24), 'in 1 day'),
+        (dict(hours=24 * 5), 'in 5 days'),
+        (dict(months=1), 'in 1 month'),
+        (dict(months=1, days=1), 'in 1 month and 1 day'),
+        (dict(years=1, months=1), 'in 1 year and 1 month')
     ])
     def test_age_in_future(self, age_args, expected):
         from kallithea.lib.utils2 import age
--- a/kallithea/tests/other/test_mail.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/other/test_mail.py	Mon Apr 27 13:25:28 2020 +0200
@@ -135,7 +135,7 @@
             'app_email_from': envelope_from,
         }
         with mock.patch('kallithea.lib.celerylib.tasks.config', config_mock):
-            kallithea.lib.celerylib.tasks.send_email(recipients, subject, body, html_body, author=author)
+            kallithea.lib.celerylib.tasks.send_email(recipients, subject, body, html_body, from_name=author.full_name_or_username)
 
         assert smtplib_mock.lastdest == set(recipients)
         assert smtplib_mock.lastsender == envelope_from
@@ -159,7 +159,7 @@
             'app_email_from': envelope_from,
         }
         with mock.patch('kallithea.lib.celerylib.tasks.config', config_mock):
-            kallithea.lib.celerylib.tasks.send_email(recipients, subject, body, html_body, author=author)
+            kallithea.lib.celerylib.tasks.send_email(recipients, subject, body, html_body, from_name=author.full_name_or_username)
 
         assert smtplib_mock.lastdest == set(recipients)
         assert smtplib_mock.lastsender == envelope_from
@@ -175,7 +175,7 @@
         subject = 'subject'
         body = 'body'
         html_body = 'html_body'
-        author = User(name='foo', lastname=u'(fubar) "baz"')
+        author = User(name='foo', lastname='(fubar) "baz"')
         headers = {'extra': 'yes'}
 
         config_mock = {
@@ -184,7 +184,7 @@
         }
         with mock.patch('kallithea.lib.celerylib.tasks.config', config_mock):
             kallithea.lib.celerylib.tasks.send_email(recipients, subject, body, html_body,
-                                                     author=author, headers=headers)
+                                                     from_name=author.full_name_or_username, headers=headers)
 
         assert smtplib_mock.lastdest == set(recipients)
         assert smtplib_mock.lastsender == envelope_from
--- a/kallithea/tests/other/test_validators.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/other/test_validators.py	Mon Apr 27 13:25:28 2020 +0200
@@ -54,26 +54,26 @@
     def test_ValidUserGroup(self):
         validator = v.ValidUserGroup()
         with pytest.raises(formencode.Invalid):
-            validator.to_python(u'default')
+            validator.to_python('default')
         with pytest.raises(formencode.Invalid):
-            validator.to_python(u'.,')
+            validator.to_python('.,')
 
-        gr = fixture.create_user_group(u'test')
-        gr2 = fixture.create_user_group(u'tes2')
+        gr = fixture.create_user_group('test')
+        gr2 = fixture.create_user_group('tes2')
         Session().commit()
         with pytest.raises(formencode.Invalid):
-            validator.to_python(u'test')
+            validator.to_python('test')
         assert gr.users_group_id is not None
         validator = v.ValidUserGroup(edit=True,
                                     old_data={'users_group_id':
                                               gr2.users_group_id})
 
         with pytest.raises(formencode.Invalid):
-            validator.to_python(u'test')
+            validator.to_python('test')
         with pytest.raises(formencode.Invalid):
-            validator.to_python(u'TesT')
+            validator.to_python('TesT')
         with pytest.raises(formencode.Invalid):
-            validator.to_python(u'TEST')
+            validator.to_python('TEST')
         UserGroupModel().delete(gr)
         UserGroupModel().delete(gr2)
         Session().commit()
@@ -83,7 +83,7 @@
         model = RepoGroupModel()
         with pytest.raises(formencode.Invalid):
             validator.to_python({'group_name': base.HG_REPO, })
-        gr = model.create(group_name=u'test_gr', group_description=u'desc',
+        gr = model.create(group_name='test_gr', group_description='desc',
                           parent=None,
                           just_db=True,
                           owner=base.TEST_USER_ADMIN_LOGIN)
@@ -147,8 +147,8 @@
         with pytest.raises(formencode.Invalid):
             validator.to_python({'repo_name': base.HG_REPO})
 
-        gr = RepoGroupModel().create(group_name=u'group_test',
-                                      group_description=u'desc',
+        gr = RepoGroupModel().create(group_name='group_test',
+                                      group_description='desc',
                                       parent=None,
                                       owner=base.TEST_USER_ADMIN_LOGIN)
         with pytest.raises(formencode.Invalid):
--- a/kallithea/tests/other/test_vcs_operations.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/other/test_vcs_operations.py	Mon Apr 27 13:25:28 2020 +0200
@@ -25,8 +25,6 @@
 
 """
 
-from __future__ import print_function
-
 import json
 import os
 import re
@@ -40,7 +38,7 @@
 
 from kallithea import CONFIG
 from kallithea.lib.utils2 import ascii_bytes, safe_str
-from kallithea.model.db import CacheInvalidation, Repository, Ui, User, UserIpMap, UserLog
+from kallithea.model.db import Repository, Ui, User, UserIpMap, UserLog
 from kallithea.model.meta import Session
 from kallithea.model.ssh_key import SshKeyModel
 from kallithea.model.user import UserModel
@@ -65,8 +63,8 @@
 
 class SshVcsTest(object):
     public_keys = {
-        base.TEST_USER_REGULAR_LOGIN: u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== kallithea@localhost',
-        base.TEST_USER_ADMIN_LOGIN: u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUq== kallithea@localhost',
+        base.TEST_USER_REGULAR_LOGIN: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== kallithea@localhost',
+        base.TEST_USER_ADMIN_LOGIN: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUq== kallithea@localhost',
     }
 
     @classmethod
@@ -76,7 +74,7 @@
             ssh_key = user.ssh_keys[0]
         else:
             sshkeymodel = SshKeyModel()
-            ssh_key = sshkeymodel.create(user, u'test key', cls.public_keys[user.username])
+            ssh_key = sshkeymodel.create(user, 'test key', cls.public_keys[user.username])
             Session().commit()
 
         return cls._ssh_param(repo_name, user, ssh_key, client_ip)
@@ -263,9 +261,9 @@
     @pytest.fixture(scope="module")
     def testfork(self):
         # create fork so the repo stays untouched
-        git_fork_name = u'%s_fork%s' % (base.GIT_REPO, next(_RandomNameSequence()))
+        git_fork_name = '%s_fork%s' % (base.GIT_REPO, next(_RandomNameSequence()))
         fixture.create_fork(base.GIT_REPO, git_fork_name)
-        hg_fork_name = u'%s_fork%s' % (base.HG_REPO, next(_RandomNameSequence()))
+        hg_fork_name = '%s_fork%s' % (base.HG_REPO, next(_RandomNameSequence()))
         fixture.create_fork(base.HG_REPO, hg_fork_name)
         return {'git': git_fork_name, 'hg': hg_fork_name}
 
@@ -319,7 +317,7 @@
         Session().commit()
 
         # Create an empty server repo using the API
-        repo_name = u'new_%s_%s' % (vt.repo_type, next(_RandomNameSequence()))
+        repo_name = 'new_%s_%s' % (vt.repo_type, next(_RandomNameSequence()))
         usr = User.get_by_username(base.TEST_USER_ADMIN_LOGIN)
         params = {
             "id": 7,
@@ -337,7 +335,7 @@
         result = json.loads(response.read())
         # Expect something like:
         # {u'result': {u'msg': u'Created new repository `new_XXX`', u'task': None, u'success': True}, u'id': 7, u'error': None}
-        assert result[u'result'][u'success']
+        assert result['result']['success']
 
         # Create local clone of the empty server repo
         local_clone_dir = _get_tmp_dir()
@@ -362,15 +360,15 @@
         # <UserLog('id:new_git_XXX:push:aed9d4c1732a1927da3be42c47eb9afdc200d427,d38b083a07af10a9f44193486959a96a23db78da,4841ff9a2b385bec995f4679ef649adb3f437622')>
         action_parts = [ul.action.split(':', 1) for ul in UserLog.query().order_by(UserLog.user_log_id)]
         assert [(t[0], (t[1].count(',') + 1) if len(t) == 2 else 0) for t in action_parts] == ([
-            (u'started_following_repo', 0),
-            (u'user_created_repo', 0),
-            (u'pull', 0),
-            (u'push', 3)]
+            ('started_following_repo', 0),
+            ('user_created_repo', 0),
+            ('pull', 0),
+            ('push', 3)]
             if vt.repo_type == 'git' else [
-            (u'started_following_repo', 0),
-            (u'user_created_repo', 0),
+            ('started_following_repo', 0),
+            ('user_created_repo', 0),
             # (u'pull', 0), # Mercurial outgoing hook is not called for empty clones
-            (u'push', 3)])
+            ('push', 3)])
 
     @parametrize_vcs_test
     def test_push_new_file(self, webserver, testfork, vt):
@@ -393,7 +391,7 @@
 
         action_parts = [ul.action.split(':', 1) for ul in UserLog.query().order_by(UserLog.user_log_id)]
         assert [(t[0], (t[1].count(',') + 1) if len(t) == 2 else 0) for t in action_parts] == \
-            [(u'pull', 0), (u'push', 3)]
+            [('pull', 0), ('push', 3)]
 
     @parametrize_vcs_test
     def test_pull(self, webserver, testfork, vt):
@@ -412,7 +410,7 @@
             assert 'new changesets' in stdout
 
         action_parts = [ul.action for ul in UserLog.query().order_by(UserLog.user_log_id)]
-        assert action_parts == [u'pull']
+        assert action_parts == ['pull']
 
         # Test handling of URLs with extra '/' around repo_name
         stdout, stderr = Command(dest_dir).execute(vt.repo_type, 'pull', clone_url.replace('/' + vt.repo_name, '/./%s/' % vt.repo_name), ignoreReturnCode=True)
@@ -444,31 +442,20 @@
     def test_push_invalidates_cache(self, webserver, testfork, vt):
         pre_cached_tip = [repo.get_api_data()['last_changeset']['short_id'] for repo in Repository.query().filter(Repository.repo_name == testfork[vt.repo_type])]
 
-        key = CacheInvalidation.query().filter(CacheInvalidation.cache_key
-                                               == testfork[vt.repo_type]).scalar()
-        if not key:
-            key = CacheInvalidation(testfork[vt.repo_type], testfork[vt.repo_type])
-            Session().add(key)
-
-        key.cache_active = True
-        Session().commit()
-
         dest_dir = _get_tmp_dir()
         clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type])
         stdout, stderr = Command(base.TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir)
 
         stdout, stderr = _add_files_and_push(webserver, vt, dest_dir, files_no=1, clone_url=clone_url)
 
+        Session().commit()  # expire test session to make sure SA fetch new Repository instances after last_changeset has been updated server side hook in other process
+
         if vt.repo_type == 'git':
             _check_proper_git_push(stdout, stderr)
 
         post_cached_tip = [repo.get_api_data()['last_changeset']['short_id'] for repo in Repository.query().filter(Repository.repo_name == testfork[vt.repo_type])]
         assert pre_cached_tip != post_cached_tip
 
-        key = CacheInvalidation.query().filter(CacheInvalidation.cache_key
-                                               == testfork[vt.repo_type]).all()
-        assert key == []
-
     @parametrize_vcs_test_http
     def test_push_wrong_credentials(self, webserver, vt):
         dest_dir = _get_tmp_dir()
@@ -502,7 +489,7 @@
 
         action_parts = [ul.action.split(':', 1) for ul in UserLog.query().order_by(UserLog.user_log_id)]
         assert [(t[0], (t[1].count(',') + 1) if len(t) == 2 else 0) for t in action_parts] == \
-            [(u'pull', 0)]
+            [('pull', 0)]
 
     @parametrize_vcs_test
     def test_push_back_to_wrong_url(self, webserver, vt):
--- a/kallithea/tests/scripts/manual_test_concurrency.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/scripts/manual_test_concurrency.py	Mon Apr 27 13:25:28 2020 +0200
@@ -26,8 +26,6 @@
 
 """
 
-from __future__ import print_function
-
 import logging
 import os
 import shutil
--- a/kallithea/tests/scripts/manual_test_crawler.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/scripts/manual_test_crawler.py	Mon Apr 27 13:25:28 2020 +0200
@@ -30,8 +30,6 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
-from __future__ import print_function
-
 import http.cookiejar
 import os
 import sys
--- a/kallithea/tests/vcs/base.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/vcs/base.py	Mon Apr 27 13:25:28 2020 +0200
@@ -27,8 +27,8 @@
     def _get_commits(cls):
         commits = [
             {
-                'message': u'Initial commit',
-                'author': u'Joe Doe <joe.doe@example.com>',
+                'message': 'Initial commit',
+                'author': 'Joe Doe <joe.doe@example.com>',
                 'date': datetime.datetime(2010, 1, 1, 20),
                 'added': [
                     FileNode('foobar', content='Foobar'),
@@ -37,8 +37,8 @@
                 ],
             },
             {
-                'message': u'Changes...',
-                'author': u'Jane Doe <jane.doe@example.com>',
+                'message': 'Changes...',
+                'author': 'Jane Doe <jane.doe@example.com>',
                 'date': datetime.datetime(2010, 1, 1, 21),
                 'added': [
                     FileNode('some/new.txt', content='news...'),
--- a/kallithea/tests/vcs/conf.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/vcs/conf.py	Mon Apr 27 13:25:28 2020 +0200
@@ -7,8 +7,8 @@
 # Retrieve the necessary configuration options from the test base
 # module. Some of these configuration options are subsequently
 # consumed by the VCS test module.
-from kallithea.tests.base import (
-    GIT_REMOTE_REPO, HG_REMOTE_REPO, TEST_GIT_REPO, TEST_GIT_REPO_CLONE, TEST_HG_REPO, TEST_HG_REPO_CLONE, TEST_HG_REPO_PULL, TESTS_TMP_PATH)
+from kallithea.tests.base import (GIT_REMOTE_REPO, HG_REMOTE_REPO, TEST_GIT_REPO, TEST_GIT_REPO_CLONE, TEST_HG_REPO, TEST_HG_REPO_CLONE, TEST_HG_REPO_PULL,
+                                  TESTS_TMP_PATH)
 
 
 __all__ = (
--- a/kallithea/tests/vcs/test_branches.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/vcs/test_branches.py	Mon Apr 27 13:25:28 2020 +0200
@@ -46,8 +46,8 @@
         self.imc.add(vcs.nodes.FileNode('docs/index.txt',
             content='Documentation\n'))
         foobar_tip = self.imc.commit(
-            message=u'New branch: foobar',
-            author=u'joe',
+            message='New branch: foobar',
+            author='joe',
             branch='foobar',
         )
         assert 'foobar' in self.repo.branches
@@ -59,23 +59,23 @@
         self.imc.add(vcs.nodes.FileNode('docs/index.txt',
             content='Documentation\n'))
         foobar_tip = self.imc.commit(
-            message=u'New branch: foobar',
-            author=u'joe',
+            message='New branch: foobar',
+            author='joe',
             branch='foobar',
             parents=[tip],
         )
         self.imc.change(vcs.nodes.FileNode('docs/index.txt',
             content='Documentation\nand more...\n'))
         newtip = self.imc.commit(
-            message=u'At default branch',
-            author=u'joe',
+            message='At default branch',
+            author='joe',
             branch=foobar_tip.branch,
             parents=[foobar_tip],
         )
 
         newest_tip = self.imc.commit(
-            message=u'Merged with %s' % foobar_tip.raw_id,
-            author=u'joe',
+            message='Merged with %s' % foobar_tip.raw_id,
+            author='joe',
             branch=self.backend_class.DEFAULT_BRANCH_NAME,
             parents=[newtip, foobar_tip],
         )
@@ -85,16 +85,16 @@
 
     def test_branch_with_slash_in_name(self):
         self.imc.add(vcs.nodes.FileNode('extrafile', content='Some data\n'))
-        self.imc.commit(u'Branch with a slash!', author=u'joe',
+        self.imc.commit('Branch with a slash!', author='joe',
             branch='issue/123')
         assert 'issue/123' in self.repo.branches
 
     def test_branch_with_slash_in_name_and_similar_without(self):
         self.imc.add(vcs.nodes.FileNode('extrafile', content='Some data\n'))
-        self.imc.commit(u'Branch with a slash!', author=u'joe',
+        self.imc.commit('Branch with a slash!', author='joe',
             branch='issue/123')
         self.imc.add(vcs.nodes.FileNode('extrafile II', content='Some data\n'))
-        self.imc.commit(u'Branch without a slash...', author=u'joe',
+        self.imc.commit('Branch without a slash...', author='joe',
             branch='123')
         assert 'issue/123' in self.repo.branches
         assert '123' in self.repo.branches
--- a/kallithea/tests/vcs/test_changesets.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/vcs/test_changesets.py	Mon Apr 27 13:25:28 2020 +0200
@@ -21,7 +21,7 @@
         changeset.date = datetime.datetime(2011, 1, 30, 1, 45)
         changeset.message = 'Message of a commit'
         changeset.author = 'Joe Doe <joe.doe@example.com>'
-        changeset.added = [FileNode('foo/bar/baz'), FileNode(u'foobar'), FileNode(u'blåbærgrød')]
+        changeset.added = [FileNode('foo/bar/baz'), FileNode('foobar'), FileNode('blåbærgrød')]
         changeset.changed = []
         changeset.removed = []
         assert changeset.as_dict() == {
@@ -34,7 +34,7 @@
                 'name': 'Joe Doe',
                 'email': 'joe.doe@example.com',
             },
-            'added': ['foo/bar/baz', 'foobar', u'bl\xe5b\xe6rgr\xf8d'],
+            'added': ['foo/bar/baz', 'foobar', 'bl\xe5b\xe6rgr\xf8d'],
             'changed': [],
             'removed': [],
         }
@@ -59,8 +59,8 @@
         self.imc.add(vcs.nodes.FileNode('docs/index.txt',
             content='Documentation\n'))
         foobar_tip = self.imc.commit(
-            message=u'New branch: foobar',
-            author=u'joe',
+            message='New branch: foobar',
+            author='joe',
             branch='foobar',
         )
         assert 'foobar' in self.repo.branches
@@ -75,23 +75,23 @@
         self.imc.add(vcs.nodes.FileNode('docs/index.txt',
             content='Documentation\n'))
         foobar_tip = self.imc.commit(
-            message=u'New branch: foobar',
-            author=u'joe',
+            message='New branch: foobar',
+            author='joe',
             branch='foobar',
             parents=[tip],
         )
         self.imc.change(vcs.nodes.FileNode('docs/index.txt',
             content='Documentation\nand more...\n'))
         newtip = self.imc.commit(
-            message=u'At default branch',
-            author=u'joe',
+            message='At default branch',
+            author='joe',
             branch=foobar_tip.branch,
             parents=[foobar_tip],
         )
 
         newest_tip = self.imc.commit(
-            message=u'Merged with %s' % foobar_tip.raw_id,
-            author=u'joe',
+            message='Merged with %s' % foobar_tip.raw_id,
+            author='joe',
             branch=self.backend_class.DEFAULT_BRANCH_NAME,
             parents=[newtip, foobar_tip],
         )
@@ -104,14 +104,14 @@
         self.imc.add(vcs.nodes.FileNode('docs/index.txt',
             content='Documentation\n'))
         doc_changeset = self.imc.commit(
-            message=u'New branch: docs',
-            author=u'joe',
+            message='New branch: docs',
+            author='joe',
             branch='docs',
         )
         self.imc.add(vcs.nodes.FileNode('newfile', content=''))
         self.imc.commit(
-            message=u'Back in default branch',
-            author=u'joe',
+            message='Back in default branch',
+            author='joe',
             parents=[tip],
         )
         default_branch_changesets = self.repo.get_changesets(
@@ -145,8 +145,8 @@
         start_date = datetime.datetime(2010, 1, 1, 20)
         for x in range(5):
             yield {
-                'message': u'Commit %d' % x,
-                'author': u'Joe Doe <joe.doe@example.com>',
+                'message': 'Commit %d' % x,
+                'author': 'Joe Doe <joe.doe@example.com>',
                 'date': start_date + datetime.timedelta(hours=12 * x),
                 'added': [
                     FileNode('file_%d.txt' % x, content='Foobar %d' % x),
@@ -247,15 +247,15 @@
 
     def test_author(self):
         tip = self.repo.get_changeset()
-        assert tip.author == u'Joe Doe <joe.doe@example.com>'
+        assert tip.author == 'Joe Doe <joe.doe@example.com>'
 
     def test_author_name(self):
         tip = self.repo.get_changeset()
-        assert tip.author_name == u'Joe Doe'
+        assert tip.author_name == 'Joe Doe'
 
     def test_author_email(self):
         tip = self.repo.get_changeset()
-        assert tip.author_email == u'joe.doe@example.com'
+        assert tip.author_email == 'joe.doe@example.com'
 
     def test_get_changesets_raise_changesetdoesnotexist_for_wrong_start(self):
         with pytest.raises(ChangesetDoesNotExistError):
@@ -297,8 +297,8 @@
     def _get_commits(cls):
         return [
             {
-                'message': u'Initial',
-                'author': u'Joe Doe <joe.doe@example.com>',
+                'message': 'Initial',
+                'author': 'Joe Doe <joe.doe@example.com>',
                 'date': datetime.datetime(2010, 1, 1, 20),
                 'added': [
                     FileNode('foo/bar', content='foo'),
@@ -308,8 +308,8 @@
                 ],
             },
             {
-                'message': u'Massive changes',
-                'author': u'Joe Doe <joe.doe@example.com>',
+                'message': 'Massive changes',
+                'author': 'Joe Doe <joe.doe@example.com>',
                 'date': datetime.datetime(2010, 1, 1, 22),
                 'added': [FileNode('fallout', content='War never changes')],
                 'changed': [
@@ -330,8 +330,8 @@
         ])
         assert list(changeset.changed) == []
         assert list(changeset.removed) == []
-        assert u'foo/ba\u0142' in changeset.as_dict()['added']
-        assert u'foo/ba\u0142' in changeset.__json__(with_file_list=True)['added']
+        assert 'foo/ba\u0142' in changeset.as_dict()['added']
+        assert 'foo/ba\u0142' in changeset.__json__(with_file_list=True)['added']
 
     def test_head_added(self):
         changeset = self.repo.get_changeset()
@@ -355,7 +355,7 @@
     def test_get_filemode_non_ascii(self):
         changeset = self.repo.get_changeset()
         assert 33188 == changeset.get_file_mode('foo/bał')
-        assert 33188 == changeset.get_file_mode(u'foo/bał')
+        assert 33188 == changeset.get_file_mode('foo/bał')
 
 
 class TestGitChangesetsWithCommits(_ChangesetsWithCommitsTestCaseixin):
--- a/kallithea/tests/vcs/test_filenodes_unicode_path.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/vcs/test_filenodes_unicode_path.py	Mon Apr 27 13:25:28 2020 +0200
@@ -8,7 +8,7 @@
 
 class FileNodeUnicodePathTestsMixin(_BackendTestMixin):
 
-    fname = u'ąśðąęłąć.txt'
+    fname = 'ąśðąęłąć.txt'
 
     @classmethod
     def _get_commits(cls):
--- a/kallithea/tests/vcs/test_hg.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/vcs/test_hg.py	Mon Apr 27 13:25:28 2020 +0200
@@ -27,7 +27,7 @@
 
     def test_unicode_path_repo(self):
         with pytest.raises(VCSError):
-            MercurialRepository(u'iShouldFail')
+            MercurialRepository('iShouldFail')
 
     def test_repo_clone(self):
         self.__check_for_existing_repo()
--- a/kallithea/tests/vcs/test_inmemchangesets.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/vcs/test_inmemchangesets.py	Mon Apr 27 13:25:28 2020 +0200
@@ -7,8 +7,8 @@
 
 import pytest
 
-from kallithea.lib.vcs.exceptions import (
-    EmptyRepositoryError, NodeAlreadyAddedError, NodeAlreadyChangedError, NodeAlreadyExistsError, NodeAlreadyRemovedError, NodeDoesNotExistError, NodeNotChangedError)
+from kallithea.lib.vcs.exceptions import (EmptyRepositoryError, NodeAlreadyAddedError, NodeAlreadyChangedError, NodeAlreadyExistsError, NodeAlreadyRemovedError,
+                                          NodeDoesNotExistError, NodeNotChangedError)
 from kallithea.lib.vcs.nodes import DirNode, FileNode
 from kallithea.tests.vcs.base import _BackendTestMixin
 
@@ -36,7 +36,7 @@
             for node in self.nodes]
         for node in to_add:
             self.imc.add(node)
-        message = u'Added: %s' % ', '.join((node.path for node in self.nodes))
+        message = 'Added: %s' % ', '.join((node.path for node in self.nodes))
         author = str(self.__class__)
         changeset = self.imc.commit(message=message, author=author)
 
@@ -58,7 +58,7 @@
         to_add = [FileNode(node.path, content=node.content)
             for node in self.nodes]
         self.imc.add(*to_add)
-        message = u'Added: %s' % ', '.join((node.path for node in self.nodes))
+        message = 'Added: %s' % ', '.join((node.path for node in self.nodes))
         author = str(self.__class__)
         changeset = self.imc.commit(message=message, author=author)
 
@@ -78,7 +78,7 @@
     def test_add_actually_adds_all_nodes_at_second_commit_too(self):
         self.imc.add(FileNode('foo/bar/image.png', content='\0'))
         self.imc.add(FileNode('foo/README.txt', content='readme!'))
-        changeset = self.imc.commit(u'Initial', u'joe.doe@example.com')
+        changeset = self.imc.commit('Initial', 'joe.doe@example.com')
         assert isinstance(changeset.get_node('foo'), DirNode)
         assert isinstance(changeset.get_node('foo/bar'), DirNode)
         assert changeset.get_node('foo/bar/image.png').content == b'\0'
@@ -93,7 +93,7 @@
             FileNode('foobar/barbaz', content='foo'),
         ]
         self.imc.add(*to_add)
-        changeset = self.imc.commit(u'Another', u'joe.doe@example.com')
+        changeset = self.imc.commit('Another', 'joe.doe@example.com')
         changeset.get_node('foo/bar/foobaz/bar').content == b'foo'
         changeset.get_node('foo/bar/another/bar').content == b'foo'
         changeset.get_node('foo/baz.txt').content == b'foo'
@@ -104,11 +104,11 @@
         rev_count = len(self.repo.revisions)
         to_add = [
             FileNode('żółwik/zwierzątko', content='ćććć'),
-            FileNode(u'żółwik/zwierzątko_uni', content=u'ćććć'),
+            FileNode('żółwik/zwierzątko_uni', content='ćććć'),
         ]
         for node in to_add:
             self.imc.add(node)
-        message = u'Added: %s' % ', '.join((node.path for node in self.nodes))
+        message = 'Added: %s' % ', '.join((node.path for node in self.nodes))
         author = str(self.__class__)
         changeset = self.imc.commit(message=message, author=author)
 
@@ -134,7 +134,7 @@
     def test_check_integrity_raise_already_exist(self):
         node = FileNode('foobar', content='baz')
         self.imc.add(node)
-        self.imc.commit(message=u'Added foobar', author=str(self))
+        self.imc.commit(message='Added foobar', author=str(self))
         self.imc.add(node)
         with pytest.raises(NodeAlreadyExistsError):
             self.imc.commit(message='new message',
@@ -143,12 +143,12 @@
     def test_change(self):
         self.imc.add(FileNode('foo/bar/baz', content='foo'))
         self.imc.add(FileNode('foo/fbar', content='foobar'))
-        tip = self.imc.commit(u'Initial', u'joe.doe@example.com')
+        tip = self.imc.commit('Initial', 'joe.doe@example.com')
 
         # Change node's content
         node = FileNode('foo/bar/baz', content='My **changed** content')
         self.imc.change(node)
-        self.imc.commit(u'Changed %s' % node.path, u'joe.doe@example.com')
+        self.imc.commit('Changed %s' % node.path, 'joe.doe@example.com')
 
         newtip = self.repo.get_changeset()
         assert tip != newtip
@@ -158,21 +158,21 @@
     def test_change_non_ascii(self):
         to_add = [
             FileNode('żółwik/zwierzątko', content='ćććć'),
-            FileNode(u'żółwik/zwierzątko_uni', content=u'ćććć'),
+            FileNode('żółwik/zwierzątko_uni', content='ćććć'),
         ]
         for node in to_add:
             self.imc.add(node)
 
-        tip = self.imc.commit(u'Initial', u'joe.doe@example.com')
+        tip = self.imc.commit('Initial', 'joe.doe@example.com')
 
         # Change node's content
         node = FileNode('żółwik/zwierzątko', content='My **changed** content')
         self.imc.change(node)
-        self.imc.commit(u'Changed %s' % node.path, u'joe.doe@example.com')
+        self.imc.commit('Changed %s' % node.path, 'joe.doe@example.com')
 
-        node = FileNode(u'żółwik/zwierzątko_uni', content=u'My **changed** content')
+        node = FileNode('żółwik/zwierzątko_uni', content='My **changed** content')
         self.imc.change(node)
-        self.imc.commit(u'Changed %s' % node.path, u'joe.doe@example.com')
+        self.imc.commit('Changed %s' % node.path, 'joe.doe@example.com')
 
         newtip = self.repo.get_changeset()
         assert tip != newtip
@@ -189,7 +189,7 @@
     def test_check_integrity_change_raise_node_does_not_exist(self):
         node = FileNode('foobar', content='baz')
         self.imc.add(node)
-        self.imc.commit(message=u'Added foobar', author=str(self))
+        self.imc.commit(message='Added foobar', author=str(self))
         node = FileNode('not-foobar', content='')
         self.imc.change(node)
         with pytest.raises(NodeDoesNotExistError):
@@ -198,7 +198,7 @@
     def test_change_raise_node_already_changed(self):
         node = FileNode('foobar', content='baz')
         self.imc.add(node)
-        self.imc.commit(message=u'Added foobar', author=str(self))
+        self.imc.commit(message='Added foobar', author=str(self))
         node = FileNode('foobar', content='more baz')
         self.imc.change(node)
         with pytest.raises(NodeAlreadyChangedError):
@@ -211,14 +211,14 @@
         self.imc.change(node)
         with pytest.raises(NodeNotChangedError):
             self.imc.commit(
-                message=u'Trying to mark node as changed without touching it',
+                message='Trying to mark node as changed without touching it',
                 author=str(self),
             )
 
     def test_change_raise_node_already_removed(self):
         node = FileNode('foobar', content='baz')
         self.imc.add(node)
-        self.imc.commit(message=u'Added foobar', author=str(self))
+        self.imc.commit(message='Added foobar', author=str(self))
         self.imc.remove(FileNode('foobar'))
         with pytest.raises(NodeAlreadyRemovedError):
             self.imc.change(node)
@@ -230,7 +230,7 @@
         node = self.nodes[0]
         assert node.content == tip.get_node(node.path).content
         self.imc.remove(node)
-        self.imc.commit(message=u'Removed %s' % node.path, author=str(self))
+        self.imc.commit(message='Removed %s' % node.path, author=str(self))
 
         newtip = self.repo.get_changeset()
         assert tip != newtip
@@ -241,10 +241,10 @@
     def test_remove_last_file_from_directory(self):
         node = FileNode('omg/qwe/foo/bar', content='foobar')
         self.imc.add(node)
-        self.imc.commit(u'added', u'joe doe')
+        self.imc.commit('added', 'joe doe')
 
         self.imc.remove(node)
-        tip = self.imc.commit(u'removed', u'joe doe')
+        tip = self.imc.commit('removed', 'joe doe')
         with pytest.raises(NodeDoesNotExistError):
             tip.get_node('omg/qwe/foo/bar')
 
@@ -263,7 +263,7 @@
         self.imc.remove(node)
         with pytest.raises(NodeDoesNotExistError):
             self.imc.commit(
-                message=u'Trying to remove not existing node',
+                message='Trying to remove not existing node',
                 author=str(self),
             )
 
@@ -302,7 +302,7 @@
             content = 'foobar\n' * x
             node = FileNode(fname, content=content)
             self.imc.add(node)
-            commit = self.imc.commit(u"Commit no. %s" % (x + 1), author=u'vcs')
+            commit = self.imc.commit("Commit no. %s" % (x + 1), author='vcs')
             assert last != commit
             last = commit
 
@@ -316,8 +316,8 @@
         node = FileNode('foobar.txt', content='Foobared!')
         self.imc.add(node)
         date = datetime.datetime(1985, 1, 30, 1, 45)
-        commit = self.imc.commit(u"Committed at time when I was born ;-)",
-            author=u'lb <lb@example.com>', date=date)
+        commit = self.imc.commit("Committed at time when I was born ;-)",
+            author='lb <lb@example.com>', date=date)
 
         assert commit.date == date
 
--- a/kallithea/tests/vcs/test_nodes.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/vcs/test_nodes.py	Mon Apr 27 13:25:28 2020 +0200
@@ -3,6 +3,7 @@
 
 import pytest
 
+from kallithea.lib.vcs.backends.base import EmptyChangeset
 from kallithea.lib.vcs.nodes import DirNode, FileNode, Node, NodeError, NodeKind
 
 
@@ -48,11 +49,6 @@
         with pytest.raises(NodeError):
             Node('', NodeKind.FILE)
 
-    def test_kind_setter(self):
-        node = Node('', NodeKind.DIR)
-        with pytest.raises(NodeError):
-            setattr(node, 'kind', NodeKind.FILE)
-
     def _test_parent_path(self, node_path, expected_parent_path):
         """
         Tests if node's parent path are properly computed.
@@ -103,7 +99,7 @@
         node = DirNode('any_dir')
 
         assert node.is_dir()
-        with pytest.raises(NodeError):
+        with pytest.raises(AttributeError):  # Note: this used to raise NodeError
             getattr(node, 'content')
 
     def test_dir_node_iter(self):
@@ -182,3 +178,8 @@
         data = """\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f??a\x00\x00\x00\x04gAMA\x00\x00\xaf?7\x05\x8a?\x00\x00\x00\x19tEXtSoftware\x00Adobe ImageReadyq?e<\x00\x00\x025IDAT8?\xa5\x93?K\x94Q\x14\x87\x9f\xf7?Q\x1bs4?\x03\x9a\xa8?B\x02\x8b$\x10[U;i\x13?6h?&h[?"\x14j?\xa2M\x7fB\x14F\x9aQ?&\x842?\x0b\x89"\x82??!?\x9c!\x9c2l??{N\x8bW\x9dY\xb4\t/\x1c?=\x9b?}????\xa9*;9!?\x83\x91?[?\\v*?D\x04\'`EpNp\xa2X\'U?pVq"Sw.\x1e?\x08\x01D?jw????\xbc??7{|\x9b?\x89$\x01??W@\x15\x9c\x05q`Lt/\x97?\x94\xa1d?\x18~?\x18?\x18W[%\xb0?\x83??\x14\x88\x8dB?\xa6H\tL\tl\x19>/\x01`\xac\xabx?\x9cl\nx\xb0\x98\x07\x95\x88D$"q[\x19?d\x00(o\n\xa0??\x7f\xb9\xa4?\x1bF\x1f\x8e\xac\xa8?j??eUU}?.?\x9f\x8cE??x\x94??\r\xbdtoJU5"0N\x10U?\x00??V\t\x02\x9f\x81?U?\x00\x9eM\xae2?r\x9b7\x83\x82\x8aP3????.?&"?\xb7ZP \x0c<?O\xa5\t}\xb8?\x99\xa6?\x87?\x1di|/\xa0??0\xbe\x1fp?d&\x1a\xad\x95\x8a\x07?\t*\x10??b:?d?.\x13C\x8a?\x12\xbe\xbf\x8e?{???\x08?\x80\xa7\x13+d\x13>J?\x80\x15T\x95\x9a\x00??S\x8c\r?\xa1\x03\x07?\x96\x9b\xa7\xab=E??\xa4\xb3?\x19q??B\x91=\x8d??k?J\x0bV"??\xf7x?\xa1\x00?\\.\x87\x87???\x02F@D\x99],??\x10#?X\xb7=\xb9\x10?Z\x1by???cI??\x1ag?\x92\xbc?T?t[\x92\x81?<_\x17~\x92\x88?H%?\x10Q\x02\x9f\n\x81qQ\x0bm?\x1bX?\xb1AK\xa6\x9e\xb9?u\xb2?1\xbe|/\x92M@\xa2!F?\xa9>"\r<DT?>\x92\x8e?>\x9a9Qv\x127?a\xac?Y?8?:??]X???9\x80\xb7?u?\x0b#BZ\x8d=\x1d?p\x00\x00\x00\x00IEND\xaeB`\x82"""
         filenode = FileNode('calendar.png', content=data)
         assert filenode.is_binary
+
+    def test_if_binary_empty(self):
+        empty_cs = EmptyChangeset()
+        filenode = FileNode('foo', changeset=empty_cs)
+        assert not filenode.is_binary
--- a/kallithea/tests/vcs/test_repository.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/vcs/test_repository.py	Mon Apr 27 13:25:28 2020 +0200
@@ -85,7 +85,7 @@
                 'removed': [FileNode('foobar')],
             },
             {
-                'message': u'Commit that contains glob pattern in filename',
+                'message': 'Commit that contains glob pattern in filename',
                 'author': 'Jane Doe <jane.doe@example.com>',
                 'date': datetime.datetime(2010, 1, 1, 22),
                 'added': [
--- a/kallithea/tests/vcs/test_utils.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/vcs/test_utils.py	Mon Apr 27 13:25:28 2020 +0200
@@ -191,8 +191,8 @@
                    ('justname', '')),
                   ('Mr Double Name withemail@example.com ',
                    ('Mr Double Name', 'withemail@example.com')),
-                  (u'John Doe <джондо à éẋàṁṗłê.ç°ḿ>',
-                   (u'John Doe <\u0434\u0436\u043e\u043d\u0434\u043e \xe0 \xe9\u1e8b\xe0\u1e41\u1e57\u0142\xea.\xe7\xb0\u1e3f>', '')),
+                  ('John Doe <джондо à éẋàṁṗłê.ç°ḿ>',
+                   ('John Doe <\u0434\u0436\u043e\u043d\u0434\u043e \xe0 \xe9\u1e8b\xe0\u1e41\u1e57\u0142\xea.\xe7\xb0\u1e3f>', '')),
                   ]
 
     def test_author_email(self):
--- a/kallithea/tests/vcs/test_workdirs.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/kallithea/tests/vcs/test_workdirs.py	Mon Apr 27 13:25:28 2020 +0200
@@ -12,8 +12,8 @@
     def _get_commits(cls):
         commits = [
             {
-                'message': u'Initial commit',
-                'author': u'Joe Doe <joe.doe@example.com>',
+                'message': 'Initial commit',
+                'author': 'Joe Doe <joe.doe@example.com>',
                 'date': datetime.datetime(2010, 1, 1, 20),
                 'added': [
                     FileNode('foobar', content='Foobar'),
@@ -22,8 +22,8 @@
                 ],
             },
             {
-                'message': u'Changes...',
-                'author': u'Jane Doe <jane.doe@example.com>',
+                'message': 'Changes...',
+                'author': 'Jane Doe <jane.doe@example.com>',
                 'date': datetime.datetime(2010, 1, 1, 21),
                 'added': [
                     FileNode('some/new.txt', content='news...'),
@@ -43,8 +43,8 @@
         self.imc.add(FileNode('docs/index.txt',
             content='Documentation\n'))
         self.imc.commit(
-            message=u'New branch: foobar',
-            author=u'joe',
+            message='New branch: foobar',
+            author='joe',
             branch='foobar',
         )
         assert self.repo.workdir.get_branch() == self.default_branch
@@ -54,8 +54,8 @@
         self.imc.add(FileNode('docs/index.txt',
             content='Documentation\n'))
         head = self.imc.commit(
-            message=u'New branch: foobar',
-            author=u'joe',
+            message='New branch: foobar',
+            author='joe',
             branch='foobar',
         )
         assert self.repo.workdir.get_branch() == self.default_branch
@@ -73,7 +73,7 @@
             self.repo.workdir.checkout_branch(branch='foobranch')
         # create new branch 'foobranch'.
         self.imc.add(FileNode('file1', content='blah'))
-        self.imc.commit(message=u'asd', author=u'john', branch='foobranch')
+        self.imc.commit(message='asd', author='john', branch='foobranch')
         # go back to the default branch
         self.repo.workdir.checkout_branch()
         assert self.repo.workdir.get_branch() == self.backend_class.DEFAULT_BRANCH_NAME
--- a/scripts/docs-headings.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/scripts/docs-headings.py	Mon Apr 27 13:25:28 2020 +0200
@@ -4,8 +4,6 @@
 Consistent formatting of rst section titles
 """
 
-from __future__ import print_function
-
 import re
 import subprocess
 
--- a/scripts/generate-ini.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/scripts/generate-ini.py	Mon Apr 27 13:25:28 2020 +0200
@@ -3,8 +3,6 @@
 Based on kallithea/lib/paster_commands/template.ini.mako, generate development.ini
 """
 
-from __future__ import print_function
-
 import re
 
 from kallithea.lib import inifile
@@ -62,6 +60,13 @@
         print('writing:', makofile)
         open(makofile, 'w').write(mako_marked_up)
 
+    lines = re.findall(r'\n(# [^ ].*)', mako_marked_up)
+    if lines:
+        print('ERROR: the template .ini file convention is to use "## Foo Bar" for text comments and "#foo = bar" for disabled settings')
+        for line in lines:
+            print(line)
+        raise SystemExit(1)
+
     # create ini files
     for fn, settings in ini_files:
         print('updating:', fn)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/i18n	Mon Apr 27 13:25:28 2020 +0200
@@ -0,0 +1,140 @@
+#!/usr/bin/env python3
+
+# -*- coding: utf-8 -*-
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# 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 General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import shutil
+import sys
+
+import click
+
+import i18n_utils
+
+
+"""
+Tool for maintenance of .po and .pot files
+
+Normally, the i18n-related files contain for each translatable string a
+reference to all the source code locations where this string is found. This
+meta data is useful for translators to assess how strings are used, but is not
+relevant for normal development nor for running Kallithea. Such meta data, or
+derived data like kallithea.pot, will inherently be outdated, and create
+unnecessary churn and repository growth, making it harder to spot actual and
+important changes.
+"""
+
+@click.group()
+@click.option('--debug/--no-debug', default=False)
+def cli(debug):
+    if (debug):
+        i18n_utils.do_debug = True
+    pass
+
+@cli.command()
+@click.argument('po_files', nargs=-1)
+@click.option('--merge-pot-file', default=None)
+@click.option('--strip/--no-strip', default=False)
+def normalize_po_files(po_files, merge_pot_file, strip):
+    """Normalize the specified .po and .pot files.
+
+    By default, only actual translations and essential headers will be
+    preserved, just as we want it in the main branches with minimal noise.
+
+    If a .pot file is specified, the po files will instead be updated by
+    running GNU msgmerge with this .pot file, thus updating source code
+    references and preserving comments and outdated translations.
+    """
+    for po_file in po_files:
+        i18n_utils._normalize_po_file(po_file, merge_pot_file=merge_pot_file, strip=strip)
+
+@cli.command()
+@click.argument('local')
+@click.argument('base')
+@click.argument('other')
+@click.argument('output')
+@click.option('--merge-pot-file', default=None)
+@click.option('--strip/--no-strip', default=False)
+def normalized_merge(local, base, other, output, merge_pot_file, strip):
+    """Merge tool for use with 'hg merge/rebase/graft --tool'
+
+    i18n files are partially manually editored original source of content, and
+    partially automatically generated and updated. That create a lot of churn
+    and often cause a lot of merge conflicts.
+
+    To avoid that, this merge tool wrapper will normalize .po content before
+    running the merge tool.
+
+    By default, only actual translations and essential headers will be
+    preserved, just as we want it in the main branches with minimal noise.
+
+    If a .pot file is specified, the po files will instead be updated by
+    running GNU msgmerge with this .pot file, thus updating source code
+    references and preserving comments and outdated translations.
+
+    Add the following to your user or repository-specific .hgrc file to use it:
+        [merge-tools]
+        i18n.executable = /path/to/scripts/i18n
+        i18n.args = normalized-merge $local $base $other $output
+
+    and then invoke merge/rebase/graft with the additional argument '--tool i18n'.
+    """
+    from mercurial import (
+        context,
+        simplemerge,
+        ui as uimod,
+    )
+
+    print('i18n normalized-merge: normalizing and merging %s' % output)
+
+    i18n_utils._normalize_po_file(local, merge_pot_file=merge_pot_file, strip=strip)
+    i18n_utils._normalize_po_file(base, merge_pot_file=merge_pot_file, strip=strip)
+    i18n_utils._normalize_po_file(other, merge_pot_file=merge_pot_file, strip=strip)
+    i18n_utils._normalize_po_file(output, merge_pot_file=merge_pot_file, strip=strip)
+
+    # simplemerge will write markers to 'local' if it fails, keep a copy without markers
+    localkeep = local + '.keep'
+    shutil.copyfile(local, localkeep)
+
+    ret = simplemerge.simplemerge(uimod.ui.load(),
+         context.arbitraryfilectx(local.encode('utf-8')),
+         context.arbitraryfilectx(base.encode('utf-8')),
+         context.arbitraryfilectx(other.encode('utf-8')),
+         label=[b'local', b'other', b'base'],
+         mode='merge',
+    )
+    shutil.copyfile(local, output)  # simplemerge wrote to local - either resolved or with conflict markers
+    if ret:
+        shutil.copyfile(localkeep, local)
+        basekeep = base + '.keep'
+        otherkeep = other + '.keep'
+        shutil.copyfile(base, basekeep)
+        shutil.copyfile(other, otherkeep)
+        sys.stderr.write("Error: simple merge failed and %s is left with conflict markers. Resolve the conflicts, then use 'hg resolve -m'.\n" % output)
+        sys.stderr.write('Resolve with e.g.: kdiff3 %s %s %s -o %s\n' % (basekeep, localkeep, otherkeep, output))
+        sys.exit(ret)
+
+    os.remove(localkeep)
+
+@cli.command()
+@click.argument('file1')
+@click.argument('file2')
+@click.option('--merge-pot-file', default=None)
+@click.option('--strip/--no-strip', default=False)
+def normalized_diff(file1, file2, merge_pot_file, strip):
+    """Compare two files while transparently normalizing them."""
+    sys.exit(i18n_utils._normalized_diff(file1, file2, merge_pot_file=merge_pot_file, strip=strip))
+
+if __name__ == '__main__':
+    cli()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/i18n_utils.py	Mon Apr 27 13:25:28 2020 +0200
@@ -0,0 +1,197 @@
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# 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 General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import print_function
+
+import os
+import re
+import shutil
+import subprocess
+import tempfile
+
+
+do_debug = False  # set from scripts/i18n --debug
+
+def debug(*args, **kwargs):
+    if do_debug:
+        print(*args, **kwargs)
+
+def runcmd(cmd, *args, **kwargs):
+    debug('... Executing command: %s' % ' '.join(cmd))
+    subprocess.check_call(cmd, *args, **kwargs)
+
+header_comment_strip_re = re.compile(r'''
+    ^
+    [#][ ]Translations[ ]template[ ]for[ ]Kallithea[.] \n
+    |
+    ^
+    [#][ ]FIRST[ ]AUTHOR[ ]<EMAIL@ADDRESS>,[ ]\d+[.] \n
+    (?:[#] \n)?
+    |
+    ^
+    (?:[#] \n)?
+    [#],[ ]fuzzy \n
+    |
+    ^
+    [#][ ][#],[ ]fuzzy \n
+    ''',
+    re.MULTILINE|re.VERBOSE)
+
+header_normalize_re = re.compile(r'''
+    ^ "
+    (POT-Creation-Date|PO-Revision-Date|Last-Translator|Language-Team|X-Generator|Generated-By|Project-Id-Version):
+    [ ][^\\]*\\n
+    " \n
+    ''',
+    re.MULTILINE|re.IGNORECASE|re.VERBOSE)
+
+def _normalize_po(raw_content):
+    r"""
+    >>> print(_normalize_po(r'''
+    ... # header comment
+    ...
+    ...
+    ... # comment before header
+    ... msgid ""
+    ... msgstr "yada"
+    ... "POT-Creation-Date: 2019-05-04 21:13+0200\n"
+    ... "MIME-Version: "
+    ... "1.0\n"
+    ... "Last-Translator: Jabba"
+    ... "the Hutt\n"
+    ... "X-Generator: Weblate 1.2.3\n"
+    ...
+    ... # comment, but not in header
+    ... msgid "None"
+    ... msgstr "Ingen"
+    ...
+    ...
+    ... line 2
+    ... # third comment
+    ...
+    ... msgid "Special"
+    ... msgstr ""
+    ...
+    ... msgid "Specialist"
+    ... # odd comment
+    ... msgstr ""
+    ... "Expert"
+    ...
+    ... # crazy fuzzy auto translation by msgmerge, using foo for bar
+    ... #, fuzzy
+    ... #| msgid "some foo string"
+    ... msgid "some bar string."
+    ... msgstr "translation of foo string"
+    ...
+    ... msgid "%d minute"
+    ... msgid_plural "%d minutes"
+    ... msgstr[0] "minut"
+    ... msgstr[1] "minutter"
+    ... msgstr[2] ""
+    ...
+    ... msgid "%d year"
+    ... msgid_plural "%d years"
+    ... msgstr[0] ""
+    ... msgstr[1] ""
+    ...
+    ... # last comment
+    ... ''') + '^^^')
+    # header comment
+    <BLANKLINE>
+    <BLANKLINE>
+    # comment before header
+    <BLANKLINE>
+    msgid ""
+    msgstr "yada"
+    "MIME-Version: "
+    "1.0\n"
+    <BLANKLINE>
+    msgid "None"
+    msgstr "Ingen"
+    <BLANKLINE>
+    line 2
+    <BLANKLINE>
+    msgid "Specialist"
+    msgstr ""
+    "Expert"
+    <BLANKLINE>
+    msgid "%d minute"
+    msgid_plural "%d minutes"
+    msgstr[0] "minut"
+    msgstr[1] "minutter"
+    msgstr[2] ""
+    ^^^
+    """
+    header_start = raw_content.find('\nmsgid ""\n') + 1
+    header_end = raw_content.find('\n\n', header_start) + 1 or len(raw_content)
+    chunks = [
+        header_comment_strip_re.sub('', raw_content[0:header_start])
+            .strip(),
+        '',
+        header_normalize_re.sub('', raw_content[header_start:header_end])
+            .replace(
+                r'"Content-Type: text/plain; charset=utf-8\n"',
+                r'"Content-Type: text/plain; charset=UTF-8\n"')  # maintain msgmerge casing
+            .strip(),
+        '']  # preserve normalized header
+    # all chunks are separated by empty line
+    for raw_chunk in raw_content[header_end:].split('\n\n'):
+        if '\n#, fuzzy' in raw_chunk:  # might be like "#, fuzzy, python-format"
+            continue  # drop crazy auto translation that is worse than useless
+        # strip all comment lines from chunk
+        chunk_lines = [
+            line
+            for line in raw_chunk.splitlines()
+            if line
+            and not line.startswith('#')
+        ]
+        if not chunk_lines:
+            continue
+        # check lines starting from first msgstr, skip chunk if no translation lines
+        msgstr_i = [i for i, line in enumerate(chunk_lines) if line.startswith('msgstr')]
+        if (
+            chunk_lines[0].startswith('msgid') and
+            msgstr_i and
+            all(line.endswith(' ""') for line in chunk_lines[msgstr_i[0]:])
+        ):  # skip translation chunks that doesn't have any actual translations
+            continue
+        chunks.append('\n'.join(chunk_lines) + '\n')
+    return '\n'.join(chunks)
+
+def _normalize_po_file(po_file, merge_pot_file=None, strip=False):
+    if merge_pot_file:
+        runcmd(['msgmerge', '--width=76', '--backup=none', '--previous',
+                '--update', po_file, '-q', merge_pot_file])
+    if strip:
+        po_tmp = po_file + '.tmp'
+        with open(po_file, 'r') as src, open(po_tmp, 'w') as dest:
+            raw_content = src.read()
+            normalized_content = _normalize_po(raw_content)
+            dest.write(normalized_content)
+        os.rename(po_tmp, po_file)
+
+def _normalized_diff(file1, file2, merge_pot_file=None, strip=False):
+    # Create temporary copies of both files
+    temp1 = tempfile.NamedTemporaryFile(prefix=os.path.basename(file1))
+    temp2 = tempfile.NamedTemporaryFile(prefix=os.path.basename(file2))
+    debug('normalized_diff: %s -> %s / %s -> %s' % (file1, temp1.name, file2, temp2.name))
+    shutil.copyfile(file1, temp1.name)
+    shutil.copyfile(file2, temp2.name)
+    # Normalize them in place
+    _normalize_po_file(temp1.name, merge_pot_file=merge_pot_file, strip=strip)
+    _normalize_po_file(temp2.name, merge_pot_file=merge_pot_file, strip=strip)
+    # Now compare
+    try:
+        runcmd(['diff', '-u', temp1.name, temp2.name])
+    except subprocess.CalledProcessError as e:
+        return e.returncode
--- a/scripts/logformat.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/scripts/logformat.py	Mon Apr 27 13:25:28 2020 +0200
@@ -1,7 +1,5 @@
 #!/usr/bin/env python3
 
-from __future__ import print_function
-
 import re
 import sys
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/pyflakes	Mon Apr 27 13:25:28 2020 +0200
@@ -0,0 +1,39 @@
+#!/usr/bin/env python3
+"""
+pyflakes with filter configuration for Kallithea.
+Inspired by pyflakes/api.py and flake8/plugins/pyflakes.py .
+"""
+
+import sys
+
+import pyflakes.api
+import pyflakes.messages
+
+
+class Reporter:
+
+    warned = False
+
+    def flake(self, warning):
+        # ignore known warnings
+        if isinstance(warning, pyflakes.messages.UnusedVariable):
+            return
+        if warning.filename == 'kallithea/bin/kallithea_cli_ishell.py':
+            if isinstance(warning, pyflakes.messages.ImportStarUsed) and warning.message_args == ('kallithea.model.db',):
+                return
+            if isinstance(warning, pyflakes.messages.UnusedImport) and warning.message_args == ('kallithea.model.db.*',):
+                return
+
+        print('%s:%s %s   [%s %s]' % (warning.filename, warning.lineno, warning.message % warning.message_args, type(warning).__name__, warning.message_args))
+        self.warned = True
+
+    def unexpectedError(self, filename, msg):
+        print('Unexpected error for %s: %s' % (filename, msg))
+
+
+reporter = Reporter()
+
+for filename in sorted(set(sys.argv[1:])):
+    pyflakes.api.checkPath(filename, reporter=reporter)
+if reporter.warned:
+    raise SystemExit(1)
--- a/scripts/run-all-cleanup	Mon Apr 13 21:40:33 2020 +0200
+++ b/scripts/run-all-cleanup	Mon Apr 27 13:25:28 2020 +0200
@@ -8,3 +8,6 @@
 scripts/docs-headings.py
 scripts/generate-ini.py
 scripts/whitespacecleanup.sh
+
+hg loc 'set:!binary()&grep("^#!.*python")' '*.py' | xargs scripts/pyflakes
+echo "no blocking problems found by $0"
--- a/scripts/shortlog.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/scripts/shortlog.py	Mon Apr 27 13:25:28 2020 +0200
@@ -9,7 +9,7 @@
 import os
 from collections import Counter
 
-from . import contributor_data
+import contributor_data
 
 
 def main():
--- a/scripts/update-copyrights.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/scripts/update-copyrights.py	Mon Apr 27 13:25:28 2020 +0200
@@ -42,7 +42,7 @@
 import re
 from collections import defaultdict
 
-from . import contributor_data
+import contributor_data
 
 
 def sortkey(x):
@@ -52,10 +52,13 @@
     * number of contribution years
     * name (with some unicode normalization)
     The entries must be 2-tuples of a list of string years and the name"""
-    return (x[0] and -int(x[0][-1]),
-            x[0] and int(x[0][0]),
-            -len(x[0]),
-            x[1].decode('utf-8').lower().replace(u'\xe9', u'e').replace(u'\u0142', u'l')
+    years, name = x
+    if not years:
+        years = ['0']
+    return (-int(years[-1]),  # primarily sort by latest contribution
+            int(years[0]),  # then sort by first contribution
+            -len(years),  # then sort by length of contribution (no gaps)
+            name.lower().replace('\xe9', 'e').replace('\u0142', 'l')  # finally sort by name
         )
 
 
@@ -134,7 +137,7 @@
         all_entries=repo_entries + contributor_data.other_about + contributor_data.other,
         no_entries=contributor_data.no_about,
         domain_extra=contributor_data.domain_extra,
-        split_re=r'(?:  <li>Copyright &copy; [^\n]*</li>\n)*',
+        split_re=r'(?:  <li>Copyright &copy; [^\n]+</li>\n)+',
         normalize_name=lambda name: name.split('<', 1)[0].strip(),
         format_f=lambda years, name: '  <li>Copyright &copy; %s, %s</li>\n' % (nice_years(years, '&ndash;', ', '), name),
         )
@@ -144,7 +147,7 @@
         all_entries=repo_entries + contributor_data.other_contributors + contributor_data.other,
         no_entries=contributor_data.total_ignore,
         domain_extra=contributor_data.domain_extra,
-        split_re=r'(?:    [^\n]*\n)*',
+        split_re=r'(?:    [^\n]+\n)+',
         normalize_name=lambda name: name,
         format_f=lambda years, name: ('    %s%s%s\n' % (name, ' ' if years else '', nice_years(years))),
         )
@@ -154,7 +157,7 @@
         all_entries=repo_entries,
         no_entries=contributor_data.total_ignore,
         domain_extra={},
-        split_re=r'(?<=&copy;) .* (?=by various authors)',
+        split_re=r'(?<=&copy;) .+ (?=by various authors)',
         normalize_name=lambda name: '',
         format_f=lambda years, name: ' ' + nice_years(years, '&ndash;', ', ') + ' ',
         )
@@ -165,7 +168,7 @@
         all_entries=repo_entries,
         no_entries=contributor_data.total_ignore,
         domain_extra={},
-        split_re=r"(?<=copyright = u').*(?= by various authors)",
+        split_re=r"(?<=copyright = ').+(?= by various authors)",
         normalize_name=lambda name: '',
         format_f=lambda years, name: nice_years(years, '-', ', '),
         )
--- a/scripts/validate-commits	Mon Apr 13 21:40:33 2020 +0200
+++ b/scripts/validate-commits	Mon Apr 27 13:25:28 2020 +0200
@@ -40,14 +40,18 @@
     pip install -e . -r dev_requirements.txt python-ldap python-pam
 
     # run-all-cleanup
-    scripts/run-all-cleanup
-    if ! hg update --check -q .; then
-        echo "run-all-cleanup did not give clean results!"
+    if ! scripts/run-all-cleanup ; then
+        echo "run-all-cleanup encountered errors!"
         result="NOK"
-        hg diff
-        hg revert -a
     else
-        result=" OK"
+        if ! hg update --check -q .; then
+            echo "run-all-cleanup did not give clean results!"
+            result="NOK"
+            hg diff
+            hg revert -a
+        else
+            result=" OK"
+        fi
     fi
     echo "$result: $rev (run-all-cleanup)" >> "$resultfile"
 
--- a/scripts/whitespacecleanup.sh	Mon Apr 13 21:40:33 2020 +0200
+++ b/scripts/whitespacecleanup.sh	Mon Apr 27 13:25:28 2020 +0200
@@ -1,4 +1,4 @@
-#!/bin/bash -x
+#!/bin/bash -xe
 
 # Enforce some consistency in whitespace - just to avoid spurious whitespaces changes
 
@@ -18,6 +18,7 @@
 hg loc 'set:!binary()&grep("^#!")&!(**_tmpl.py)&!(**/template**)' | xargs chmod +x
 
 # isort is installed from dev_requirements.txt
-isort --line-width 160 --wrap-length 160 --lines-after-imports 2 `hg loc '*.py'`
+hg loc 'set:!binary()&grep("^#!.*python")' '*.py' | xargs isort --line-width 160 --lines-after-imports 2
 
+echo "diff after $0:"
 hg diff
--- a/setup.py	Mon Apr 13 21:40:33 2020 +0200
+++ b/setup.py	Mon Apr 27 13:25:28 2020 +0200
@@ -20,16 +20,17 @@
     import re
     matches = re.compile(r'(?:%s)\s*=\s*(.*)' % name).search(data)
     if matches:
-        if not callable(callback_handler):
-            callback_handler = lambda v: v
-
-        return callback_handler(eval(matches.groups()[0]))
+        s = eval(matches.groups()[0])
+        if callable(callback_handler):
+            return callback_handler(s)
+        return s
 
 _meta = open(os.path.join(here, 'kallithea', '__init__.py'), 'r')
 _metadata = _meta.read()
 _meta.close()
 
-callback = lambda V: ('.'.join(map(str, V[:3])) + '.'.join(V[3:]))
+def callback(V):
+    return '.'.join(map(str, V[:3])) + '.'.join(V[3:])
 __version__ = _get_meta_var('VERSION', _metadata, callback)
 __license__ = _get_meta_var('__license__', _metadata)
 __author__ = _get_meta_var('__author__', _metadata)
@@ -40,9 +41,9 @@
 is_windows = __platform__ in ['Windows']
 
 requirements = [
-    "alembic >= 1.0.10, < 1.1",
+    "alembic >= 1.0.10, < 1.5",
     "gearbox >= 0.1.0, < 1",
-    "waitress >= 0.8.8, < 1.4",
+    "waitress >= 0.8.8, < 1.5",
     "WebOb >= 1.8, < 1.9",
     "backlash >= 0.1.2, < 1",
     "TurboGears2 >= 2.4, < 2.5",
@@ -51,30 +52,29 @@
     "WebHelpers2 >= 2.0, < 2.1",
     "FormEncode >= 1.3.1, < 1.4",
     "SQLAlchemy >= 1.2.9, < 1.4",
-    "Mako >= 0.9.1, < 1.1",
-    "Pygments >= 2.2.0, < 2.5",
+    "Mako >= 0.9.1, < 1.2",
+    "Pygments >= 2.2.0, < 2.6",
     "Whoosh >= 2.7.1, < 2.8",
-    "celery >= 3.1, < 4.0", # TODO: celery 4 doesn't work
-    "Babel >= 1.3, < 2.8",
+    "celery >= 4.3, < 4.5",
+    "Babel >= 1.3, < 2.9",
     "python-dateutil >= 2.1.0, < 2.9",
     "Markdown >= 2.2.1, < 3.2",
-    "docutils >= 0.11, < 0.15",
+    "docutils >= 0.11, < 0.17",
     "URLObject >= 2.3.4, < 2.5",
     "Routes >= 2.0, < 2.5",
     "dulwich >= 0.19.0, < 0.20",
-    "mercurial >= 5.2, < 5.4",
+    "mercurial >= 5.2, < 5.5",
     "decorator >= 4.2.1, < 4.5",
-    "Paste >= 2.0.3, < 3.1",
-    "bleach >= 3.0, < 3.2",
+    "Paste >= 2.0.3, < 3.4",
+    "bleach >= 3.0, < 3.1.4",
     "Click >= 7.0, < 8",
     "ipaddr >= 2.2.0, < 2.3",
     "paginate >= 0.5, < 0.6",
     "paginate_sqlalchemy >= 0.3.0, < 0.4",
+    "bcrypt >= 3.1.0, < 3.2",
+    "pip >= 20.0, < 999",
 ]
 
-if not is_windows:
-    requirements.append("bcrypt >= 3.1.0, < 3.2")
-
 dependency_links = [
 ]
 
@@ -112,8 +112,8 @@
     long_description = open(README_FILE).read()
 except IOError as err:
     sys.stderr.write(
-        "[WARNING] Cannot find file specified as long_description (%s)\n"
-        % README_FILE
+        "[WARNING] Cannot find file specified as long_description (%s): %s\n"
+        % (README_FILE, err)
     )
     long_description = description