changeset 8388:0cb9aae7fe42 stable-i18n

Update stable-i18n with default-i18n for 0.5 branch-off
author Mads Kiilerich <mads@kiilerich.com>
date Sun, 05 Jan 2020 04:07:51 +0100
parents d7a0b79eb047 (current diff) a62acba8124e (diff)
children 1516f0fd9fd4
files
diffstat 301 files changed, 33203 insertions(+), 22467 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Sat Aug 24 21:48:43 2019 +0200
+++ b/.hgignore	Sun Jan 05 04:07:51 2020 +0100
@@ -6,6 +6,9 @@
 *.egg-info
 *.egg
 *.mo
+*.orig
+*.rej
+*.bak
 .eggs/
 tarballcache/
 
@@ -23,6 +26,7 @@
 ^\.coverage$
 ^kallithea/front-end/node_modules$
 ^kallithea/front-end/package-lock\.json$
+^kallithea/front-end/theme\.less$
 ^kallithea/front-end/tmp$
 ^kallithea/public/codemirror$
 ^kallithea/public/css/select2-spinner\.gif$
@@ -40,7 +44,6 @@
 ^kallithea/public/js/jquery\.flot\.time\.js$
 ^kallithea/public/js/jquery\.min\.js$
 ^kallithea/public/js/select2\.js$
-^theme\.less$
 ^kallithea\.db$
 ^test\.db$
 ^Kallithea\.egg-info$
--- a/CONTRIBUTORS	Sat Aug 24 21:48:43 2019 +0200
+++ b/CONTRIBUTORS	Sun Jan 05 04:07:51 2020 +0100
@@ -49,6 +49,7 @@
     YFdyh000 <yfdyh000@gmail.com> 2016
     Aras Pranckevičius <aras@unity3d.com> 2012-2013 2015
     Sean Farley <sean.michael.farley@gmail.com> 2013-2015
+    Bradley M. Kuhn <bkuhn@sfconservancy.org> 2014-2015
     Christian Oyarzun <oyarzun@gmail.com> 2014-2015
     Joseph Rivera <rivera.d.joseph@gmail.com> 2014-2015
     Anatoly Bubenkov <bubenkoff@gmail.com> 2015
@@ -78,40 +79,58 @@
     Tuux <tuxa@galaxie.eu.org> 2015
     Viktar Palstsiuk <vipals@gmail.com> 2015
     Ante Ilic <ante@unity3d.com> 2014
-    Bradley M. Kuhn <bkuhn@sfconservancy.org> 2014
     Calinou <calinou@opmbx.org> 2014
     Daniel Anderson <daniel@dattrix.com> 2014
     Henrik Stuart <hg@hstuart.dk> 2014
     Ingo von Borstel <kallithea@planetmaker.de> 2014
+    invision70 <invision70@gmail.com> 2014
     Jelmer Vernooij <jelmer@samba.org> 2014
     Jim Hague <jim.hague@acm.org> 2014
     Matt Fellows <kallithea@matt-fellows.me.uk> 2014
     Max Roman <max@choloclos.se> 2014
     Na'Tosha Bard <natosha@unity3d.com> 2014
     Rasmus Selsmark <rasmuss@unity3d.com> 2014
+    SkryabinD <skryabind@gmail.com> 2014
     Tim Freund <tim@freunds.net> 2014
     Travis Burtrum <android@moparisthebest.com> 2014
+    whosaysni <whosaysni@gmail.com> 2014
     Zoltan Gyarmati <mr.zoltan.gyarmati@gmail.com> 2014
     Marcin Kuźmiński <marcin@python-works.com> 2010-2013
+    Nemcio <areczek01@gmail.com> 2012-2013
     xpol <xpolife@gmail.com> 2012-2013
+    Andrey Mivrenik <myvrenik@gmail.com> 2013
     Aparkar <aparkar@icloud.com> 2013
+    ArcheR <aleclitvinov1980@gmail.com> 2013
     Dennis Brakhane <brakhane@googlemail.com> 2013
+    gnustavo <gustavo@gnustavo.com> 2013
     Grzegorz Rożniecki <xaerxess@gmail.com> 2013
+    Ilya Beda <ir4y.ix@gmail.com> 2013
+    ivlevdenis <ivlevdenis.ru@gmail.com> 2013
     Jonathan Sternberg <jonathansternberg@gmail.com> 2013
     Leonardo Carneiro <leonardo@unity3d.com> 2013
     Magnus Ericmats <magnus.ericmats@gmail.com> 2013
     Martin Vium <martinv@unity3d.com> 2013
+    Mikhail Zholobov <legal90@gmail.com> 2013
+    mokeev1995 <mokeev_andre@mail.ru> 2013
+    Ruslan Bekenev <furyinbox@gmail.com> 2013
+    shirou - しろう 2013
     Simon Lopez <simon.lopez@slopez.org> 2013
+    softforwinxp <softforwinxp@gmail.com> 2013
+    stephanj <info@stephan-jauernick.de> 2013
     Ton Plomp <tcplomp@gmail.com> 2013
+    zhmylove <zhmylove@narod.ru> 2013
+    こいんとす <tkondou@gmail.com> 2013
     Augusto Herrmann <augusto.herrmann@planejamento.gov.br> 2011-2012
+    Augusto Herrmann <augusto.herrmann@gmail.com> 2012
     Dan Sheridan <djs@adelard.com> 2012
     Dies Koper <diesk@fast.au.fujitsu.com> 2012
     Erwin Kroon <e.kroon@smartmetersolutions.nl> 2012
     H Waldo G <gwaldo@gmail.com> 2012
     hppj <hppj@postmage.biz> 2012
     Indra Talip <indra.talip@gmail.com> 2012
-    mikespook 2012
+    mikespook <mikespook@gmail.com> 2012
     nansenat16 <nansenat16@null.tw> 2012
+    Nemcio <bogdan114@g.pl> 2012
     Philip Jameson <philip.j@hostdime.com> 2012
     Raoul Thill <raoul.thill@gmail.com> 2012
     Stefan Engel <mail@engel-stefan.de> 2012
--- a/Jenkinsfile	Sat Aug 24 21:48:43 2019 +0200
+++ b/Jenkinsfile	Sun Jan 05 04:07:51 2020 +0100
@@ -44,8 +44,7 @@
     }
     stage('setup') {
         def virtualenvscript = """$activatevirtualenv
-            pip install --upgrade -e .
-            pip install -r dev_requirements.txt
+            pip install --upgrade -e . -r dev_requirements.txt
             python setup.py compile_catalog
             """
         if (isUnix()) {
--- a/README.rst	Sat Aug 24 21:48:43 2019 +0200
+++ b/README.rst	Sun Jan 05 04:07:51 2020 +0100
@@ -8,17 +8,15 @@
 
 **Kallithea** is a fast and powerful management tool for Mercurial_ and Git_
 with a built-in push/pull server, full text search and code-review. It works on
-http/https and has a built in permission/authentication system with the ability
+HTTP/HTTPS and SSH, has a built-in permission/authentication system with the ability
 to authenticate via LDAP or ActiveDirectory. Kallithea also provides simple API
 so it's easy to integrate with existing external systems.
 
 Kallithea is similar in some respects to GitHub_ or Bitbucket_, however
 Kallithea can be run as standalone hosted application on your own server. It is
-open-source donationware and focuses more on providing a customised,
+open-source and focuses more on providing a customised,
 self-administered interface for Mercurial_ and Git_ repositories. Kallithea
-works on Unix-like systems and Windows, and is powered by the vcs_ library
-created by Łukasz Balcerzak and Marcin Kuźmiński to uniformly handle multiple
-version control systems.
+works on Unix-like systems and Windows.
 
 Kallithea was forked from RhodeCode in July 2014 and has been heavily modified.
 
@@ -26,7 +24,7 @@
 Installation
 ------------
 
-Kallithea requires Python_ 2.x and it is recommended to install it in a
+Kallithea requires Python_ 2.7 and it is recommended to install it in a
 virtualenv_. Official releases of Kallithea can be installed with::
 
     pip install kallithea
@@ -62,7 +60,8 @@
   request is authenticated and logged together with IP address.
 - Built for speed and performance. You can make multiple pulls/pushes
   simultaneously. Proven to work with thousands of repositories and users.
-- Supports http/https, LDAP, AD, proxy-pass authentication.
+- Supports HTTP/HTTPS with LDAP, AD, or proxy-pass authentication.
+- Supports SSH access with server-side public key management.
 - Full permissions (private/read/write/admin) together with IP restrictions for
   each repository, additional explicit forking, repositories group and
   repository creation permissions.
@@ -86,7 +85,7 @@
   including Git_ binary-patches.
 - Mercurial_ and Git_ DAG graphs and Flot-powered graphs with zooming and
   statistics to track activity for repositories.
-- Admin interface with user/permission management. Admin activity journal, logs
+- Admin interface with user/permission management. Admin activity journal logs
   pulls, pushes, forks, registrations and other actions made by all users.
 - Server side forks. It is possible to fork a project and modify it freely
   without breaking the main repository.
@@ -102,7 +101,9 @@
 - Optional async tasks for speed and performance using Celery_.
 - Backup scripts can do backup of whole app and send it over scp to desired
   location.
-- Based on Pylons, SQLAlchemy, SQLite, Whoosh, vcs.
+- Based on TurboGears2, SQLAlchemy, Whoosh, Bootstrap, and other open source
+  libraries.
+- Uses PostgreSQL, SQLite, or MariaDB/MySQL databases.
 
 
 License
@@ -181,6 +182,5 @@
 .. _Subversion: http://subversion.tigris.org/
 .. _Git: http://git-scm.com/
 .. _Celery: http://celeryproject.org/
-.. _vcs: http://pypi.python.org/pypi/vcs
 .. _Software Freedom Conservancy: http://sfconservancy.org/
 .. _Puppet module: https://forge.puppetlabs.com/rauch/kallithea
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/conftest.py	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,38 @@
+import os
+
+import mock
+import pytest
+
+
+here = os.path.dirname(__file__)
+
+def pytest_ignore_collect(path):
+    # ignore all files outside the 'kallithea' directory
+    if not str(path).startswith(os.path.join(here, 'kallithea')):
+        return True
+
+    # during doctest verification, normally all python files will be imported.
+    # Thus, files that cannot be imported normally should be ignored.
+    # Files that generate ImportErrors are ignored via
+    # '--doctest-ignore-import-errors' (pytest.ini)
+    kallithea_ignore_paths = (
+        # AttributeError: 'module' object has no attribute 'config'
+        '/kallithea/alembic/env.py',
+        # collection of the following file messes up the rest of test execution
+        '/kallithea/tests/scripts/manual_test_concurrency.py',
+    )
+    if str(path).endswith(kallithea_ignore_paths):
+        return True
+
+@pytest.fixture()
+def doctest_mock_ugettext(request):
+    """Mock ugettext ('_') in the module using this fixture.
+
+    Intended to be used for doctests.
+
+    In a doctest, enable this fixture using:
+        >>> getfixture('doctest_mock_ugettext')
+    """
+    m = __import__(request.module.__name__, globals(), locals(), [None], 0)
+    with mock.patch.object(m, '_', lambda s: s):
+        yield
--- a/dev_requirements.txt	Sat Aug 24 21:48:43 2019 +0200
+++ b/dev_requirements.txt	Sun Jan 05 04:07:51 2020 +0100
@@ -1,8 +1,8 @@
-pytest >= 3.3.0, < 3.8
-pytest-runner < 4.3
-pytest-sugar >= 0.7.0, < 0.10
-pytest-benchmark < 3.2
-pytest-localserver < 0.5
-mock < 2.1
-Sphinx < 1.8
-WebTest < 2.1
+pytest >= 4.6.6, < 4.7
+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
+WebTest >= 2.0.3, < 2.1
+isort == 4.3.21
--- a/development.ini	Sat Aug 24 21:48:43 2019 +0200
+++ b/development.ini	Sun Jan 05 04:07:51 2020 +0100
@@ -153,18 +153,6 @@
 ## Kallithea url, ie. http[s]://kallithea.example.com/_admin/gists/<gistid>
 gist_alias_url =
 
-## white list of API enabled controllers. This allows to add list of
-## controllers to which access will be enabled by api_key. eg: to enable
-## api access to raw_files put `FilesController:raw`, to enable access to patches
-## add `ChangesetController:changeset_patch`. This list should be "," separated
-## Syntax is <ControllerClass>:<function>. Check debug logs for generated names
-## Recommended settings below are commented out:
-api_access_controllers_whitelist =
-#    ChangesetController:changeset_patch,
-#    ChangesetController:changeset_raw,
-#    FilesController:raw,
-#    FilesController:archivefile
-
 ## default encoding used to convert from and to unicode
 ## can be also a comma separated list of encoding in case of mixed encodings
 default_encoding = utf-8
@@ -219,10 +207,6 @@
 ## handling that. Set this variable to 403 to return HTTPForbidden
 auth_ret_code =
 
-## locking return code. When repository is locked return this HTTP code. 2XX
-## codes don't break the transactions while 4XX codes do
-lock_ret_code = 423
-
 ## allows to change the repository location in settings page
 allow_repo_location_change = True
 
@@ -242,6 +226,25 @@
 #    CHANGELOG
 
 ####################################
+###           SSH CONFIG        ####
+####################################
+
+## SSH is disabled by default, until an Administrator decides to enable it.
+ssh_enabled = false
+
+## File where users' SSH keys will be stored *if* ssh_enabled is true.
+#ssh_authorized_keys = /home/kallithea/.ssh/authorized_keys
+
+## Path to be used in ssh_authorized_keys file to invoke kallithea-cli with ssh-serve.
+#kallithea_cli_path = /srv/kallithea/venv/bin/kallithea-cli
+
+## Locale to be used in the ssh-serve command.
+## This is needed because an SSH client may try to use its own locale
+## settings, which may not be available on the server.
+## See `locale -a` for valid values on this system.
+#ssh_locale = C.UTF-8
+
+####################################
 ###        CELERY CONFIG        ####
 ####################################
 
@@ -292,32 +295,43 @@
 
 ## Name of session cookie. Should be unique for a given host and path, even when running
 ## on different ports. Otherwise, cookie sessions will be shared and messed up.
-beaker.session.key = kallithea
+session.key = kallithea
 ## Sessions should always only be accessible by the browser, not directly by JavaScript.
-beaker.session.httponly = true
+session.httponly = true
 ## Session lifetime. 2592000 seconds is 30 days.
-beaker.session.timeout = 2592000
+session.timeout = 2592000
 
 ## Server secret used with HMAC to ensure integrity of cookies.
-#beaker.session.secret = VERY-SECRET
-beaker.session.secret = development-not-secret
+#session.secret = VERY-SECRET
+session.secret = development-not-secret
 ## Further, encrypt the data with AES.
-#beaker.session.encrypt_key = <key_for_encryption>
-#beaker.session.validate_key = <validation_key>
+#session.encrypt_key = <key_for_encryption>
+#session.validate_key = <validation_key>
 
 ## Type of storage used for the session, current types are
 ## dbm, file, memcached, database, and memory.
 
 ## File system storage of session data. (default)
-#beaker.session.type = file
+#session.type = file
 
 ## Cookie only, store all session data inside the cookie. Requires secure secrets.
-#beaker.session.type = cookie
+#session.type = cookie
 
 ## Database storage of session data.
-#beaker.session.type = ext:database
-#beaker.session.sa.url = postgresql://postgres:qwe@localhost/kallithea
-#beaker.session.table_name = db_session
+#session.type = ext:database
+#session.sa.url = postgresql://postgres:qwe@localhost/kallithea
+#session.table_name = db_session
+
+############################
+## ERROR HANDLING SYSTEMS ##
+############################
+
+# Propagate email settings to ErrorReporter of TurboGears2
+# You do not normally need to change these lines
+get trace_errors.error_email = email_to
+get trace_errors.smtp_server = smtp_server
+get trace_errors.smtp_port = smtp_port
+get trace_errors.from_address = error_email_from
 
 ################################################################################
 ## WARNING: *DEBUG MODE MUST BE OFF IN A PRODUCTION ENVIRONMENT*              ##
@@ -361,7 +375,7 @@
 keys = root, routes, kallithea, sqlalchemy, tg, gearbox, beaker, templates, whoosh_indexer, werkzeug, backlash
 
 [handlers]
-keys = console, console_sql
+keys = console, console_color, console_color_sql, null
 
 [formatters]
 keys = generic, color_formatter, color_formatter_sql
@@ -372,7 +386,10 @@
 
 [logger_root]
 level = NOTSET
-handlers = console
+#handlers = console
+handlers = console_color
+# For coloring based on log level:
+# handlers = console_color
 
 [logger_routes]
 #level = WARN
@@ -380,67 +397,61 @@
 handlers =
 qualname = routes.middleware
 ## "level = DEBUG" logs the route matched and routing variables.
-propagate = 1
 
 [logger_beaker]
 #level = WARN
 level = DEBUG
 handlers =
 qualname = beaker.container
-propagate = 1
 
 [logger_templates]
 #level = WARN
 level = INFO
 handlers =
 qualname = pylons.templating
-propagate = 1
 
 [logger_kallithea]
 #level = WARN
 level = DEBUG
 handlers =
 qualname = kallithea
-propagate = 1
 
 [logger_tg]
 #level = WARN
 level = DEBUG
 handlers =
 qualname = tg
-propagate = 1
 
 [logger_gearbox]
 #level = WARN
 level = DEBUG
 handlers =
 qualname = gearbox
-propagate = 1
 
 [logger_sqlalchemy]
 level = WARN
-handlers = console_sql
+handlers =
 qualname = sqlalchemy.engine
-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
 level = DEBUG
 handlers =
 qualname = whoosh_indexer
-propagate = 1
 
 [logger_werkzeug]
 level = WARN
 handlers =
 qualname = werkzeug
-propagate = 1
 
 [logger_backlash]
 level = WARN
 handlers =
 qualname = backlash
-propagate = 1
 
 ##############
 ## HANDLERS ##
@@ -449,15 +460,24 @@
 [handler_console]
 class = StreamHandler
 args = (sys.stderr,)
-#formatter = generic
+formatter = generic
+
+[handler_console_color]
+# ANSI color coding based on log level
+class = StreamHandler
+args = (sys.stderr,)
 formatter = color_formatter
 
-[handler_console_sql]
+[handler_console_color_sql]
+# ANSI color coding and pretty printing of SQL statements
 class = StreamHandler
 args = (sys.stderr,)
-#formatter = generic
 formatter = color_formatter_sql
 
+[handler_null]
+class = NullHandler
+args = ()
+
 ################
 ## FORMATTERS ##
 ################
@@ -475,3 +495,21 @@
 class = kallithea.lib.colored_formatter.ColorFormatterSql
 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
 datefmt = %Y-%m-%d %H:%M:%S
+
+#################
+## 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
+
+[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.
--- a/docs/api/api.rst	Sat Aug 24 21:48:43 2019 +0200
+++ b/docs/api/api.rst	Sun Jan 05 04:07:51 2020 +0100
@@ -32,7 +32,7 @@
 For example, to pull to a local "CPython" mirror using curl::
 
     curl https://kallithea.example.com/_admin/api -X POST -H 'content-type:text/plain' \
-        --data-binary '{"id":1,"api_key":"xe7cdb2v278e4evbdf5vs04v832v0efvcbcve4a3","method":"pull","args":{"repo":"CPython"}}'
+        --data-binary '{"id":1,"api_key":"xe7cdb2v278e4evbdf5vs04v832v0efvcbcve4a3","method":"pull","args":{"repoid":"CPython"}}'
 
 In general, provide
  - *id*, a value of any type, can be used to match the response with the request that it is replying to.
@@ -162,37 +162,6 @@
     result : "Caches of repository `<reponame>`"
     error :  null
 
-lock
-^^^^
-
-Set the locking state on the given repository by the given user.
-If the param ``userid`` is skipped, it is set to the ID of the user who is calling this method.
-If param ``locked`` is skipped, the current lock state of the repository is returned.
-This command can only be executed using the api_key of a user with admin rights, or that of a regular user with admin or write access to the repository.
-
-INPUT::
-
-    id : <id_for_response>
-    api_key : "<api_key>"
-    method :  "lock"
-    args :    {
-                "repoid" : "<reponame or repo_id>"
-                "userid" : "<user_id or username = Optional(=apiuser)>",
-                "locked" : "<bool true|false = Optional(=None)>"
-              }
-
-OUTPUT::
-
-    id : <id_given_in_input>
-    result : {
-                 "repo": "<reponame>",
-                 "locked": "<bool true|false>",
-                 "locked_since": "<float lock_time>",
-                 "locked_by": "<username>",
-                 "msg": "User `<username>` set lock state for repo `<reponame>` to `<false|true>`"
-             }
-    error :  null
-
 get_ip
 ^^^^^^
 
@@ -601,7 +570,6 @@
                 "repo_type" :        "<repo_type>",
                 "clone_uri" :        "<clone_uri>",
                 "enable_downloads":  "<bool>",
-                "enable_locking":    "<bool>",
                 "enable_statistics": "<bool>",
                 "private":           "<bool>",
                 "created_on" :       "<date_time_created>",
@@ -755,7 +723,6 @@
                 "owner":             "<repo_owner>",
                 "fork_of":           "<name_of_fork_parent>",
                 "enable_downloads":  "<bool>",
-                "enable_locking":    "<bool>",
                 "enable_statistics": "<bool>",
               },

@@ -820,7 +787,6 @@
                 "clone_uri" :        "<clone_uri> = Optional(None)",
                 "landing_rev" :      "<landing_rev> = Optional('tip')",
                 "enable_downloads":  "<bool> = Optional(False)",
-                "enable_locking":    "<bool> = Optional(False)",
                 "enable_statistics": "<bool> = Optional(False)",
               }
 
@@ -841,7 +807,6 @@
                 "owner":             "<username or user_id>",
                 "fork_of":           "<name_of_fork_parent>",
                 "enable_downloads":  "<bool>",
-                "enable_locking":    "<bool>",
                 "enable_statistics": "<bool>",
               },
             }
@@ -870,7 +835,6 @@
                 "clone_uri" :        "<clone_uri> = Optional(None)",
                 "landing_rev" :      "<landing_rev> = Optional('tip')",
                 "enable_downloads":  "<bool> = Optional(False)",
-                "enable_locking":    "<bool> = Optional(False)",
                 "enable_statistics": "<bool> = Optional(False)",
               }
 
@@ -891,7 +855,6 @@
                 "owner":             "<username or user_id>",
                 "fork_of":           "<name_of_fork_parent>",
                 "enable_downloads":  "<bool>",
-                "enable_locking":    "<bool>",
                 "enable_statistics": "<bool>",
                 "last_changeset":    {
                                        "author":   "<full_author>",
@@ -901,8 +864,6 @@
                                        "revision": "<numeric_revision>",
                                        "short_id": "<short_id>"
                                      }
-                "locked_by": "<username>",
-                "locked_date": "<float lock_time>",
               },
             }
     error:  null
@@ -1277,24 +1238,8 @@
 API access for web views
 ------------------------
 
-API access can also be turned on for each web view in Kallithea that is
-decorated with the ``@LoginRequired`` decorator. Some views use
-``@LoginRequired(api_access=True)`` and are always available. By default only
-RSS/Atom feed views are enabled. Other views are
-only available if they have been whitelisted. Edit the
-``api_access_controllers_whitelist`` option in your .ini file and define views
-that should have API access enabled.
-
-For example, to enable API access to patch/diff, raw file and archive::
-
-    api_access_controllers_whitelist =
-        ChangesetController:changeset_patch,
-        ChangesetController:changeset_raw,
-        FilesController:raw,
-        FilesController:archivefile
-
-After this change, a Kallithea view can be accessed without login using
-bearer authentication, by including this header with the request::
+Kallithea HTTP entry points can also be accessed without login using bearer
+authentication by including this header with the request::
 
     Authentication: Bearer <api_key>
 
--- a/docs/conf.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/docs/conf.py	Sun Jan 05 04:07:51 2020 +0100
@@ -11,8 +11,11 @@
 # All configuration values have a default; values that are commented out
 # serve to show the default.
 
+import os
 import sys
-import os
+
+from kallithea import __version__
+
 
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
@@ -44,7 +47,7 @@
 
 # General information about the project.
 project = u'Kallithea'
-copyright = u'2010-2016 by various authors, licensed as GPLv3.'
+copyright = u'2010-2019 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
@@ -53,7 +56,6 @@
 # The short X.Y version.
 root = os.path.dirname(os.path.dirname(__file__))
 sys.path.append(root)
-from kallithea import __version__
 version = __version__
 # The full version, including alpha/beta/rc tags.
 release = __version__
--- a/docs/contributing.rst	Sat Aug 24 21:48:43 2019 +0200
+++ b/docs/contributing.rst	Sun Jan 05 04:07:51 2020 +0100
@@ -35,8 +35,7 @@
         virtualenv ../kallithea-venv
         source ../kallithea-venv/bin/activate
         pip install --upgrade pip setuptools
-        pip install --upgrade -e .
-        pip install --upgrade -r dev_requirements.txt
+        pip install --upgrade -e . -r dev_requirements.txt python-ldap python-pam
         kallithea-cli config-create my.ini
         kallithea-cli db-create -c my.ini --user=user --email=user@example.com --password=password --repos=/tmp
         kallithea-cli front-end-build
@@ -88,15 +87,13 @@
 
     py.test
 
-Note that testing on Python 2.6 also requires ``unittest2``.
-
 Note that on unix systems, the temporary directory (``/tmp`` or where
 ``$TMPDIR`` points) must allow executable files; Git hooks must be executable,
 and the test suite creates repositories in the temporary directory. Linux
 systems with /tmp mounted noexec will thus fail.
 
 You can also use ``tox`` to run the tests with all supported Python versions
-(currently Python 2.6--2.7).
+(currently only Python 2.7).
 
 When running tests, Kallithea generates a `test.ini` based on template values
 in `kallithea/tests/conftest.py` and populates the SQLite database specified
@@ -202,7 +199,7 @@
 consistency with existing code. Run ``scripts/run-all-cleanup`` before
 committing to ensure some basic code formatting consistency.
 
-We support both Python 2.6.x and 2.7.x and nothing else. For now we don't care
+We currently only support Python 2.7.x and nothing else. For now we don't care
 about Python 3 compatibility.
 
 We try to support the most common modern web browsers. IE9 is still supported
--- a/docs/index.rst	Sat Aug 24 21:48:43 2019 +0200
+++ b/docs/index.rst	Sun Jan 05 04:07:51 2020 +0100
@@ -63,7 +63,6 @@
 
    usage/general
    usage/vcs_notes
-   usage/locking
    usage/statistics
    api/api
 
--- a/docs/installation.rst	Sat Aug 24 21:48:43 2019 +0200
+++ b/docs/installation.rst	Sun Jan 05 04:07:51 2020 +0100
@@ -88,15 +88,6 @@
    will "activate" a shell that terminates immediately. It is also perfectly
    acceptable (and desirable) to create a virtualenv as a normal user.
 
-.. note:: Some dependencies are optional. If you need them, install them in
-   the virtualenv too::
-
-     pip install --upgrade psycopg2
-     pip install --upgrade python-ldap
-
-   This might require installation of development packages using your
-   distribution's package manager.
-
 - Make a folder for Kallithea data files, and configuration somewhere on the
   filesystem. For example::
 
@@ -106,8 +97,16 @@
 
     pip install --upgrade kallithea
 
+.. note:: Some dependencies are optional. If you need them, install them in
+   the virtualenv too::
+
+     pip install --upgrade kallithea python-ldap python-pam psycopg2
+
+   This might require installation of development packages using your
+   distribution's package manager.
+
   Alternatively, download a .tar.gz from http://pypi.python.org/pypi/Kallithea,
-  extract it and run::
+  extract it and install from source by running::
 
     pip install --upgrade .
 
--- a/docs/installation_win.rst	Sat Aug 24 21:48:43 2019 +0200
+++ b/docs/installation_win.rst	Sun Jan 05 04:07:51 2020 +0100
@@ -17,11 +17,11 @@
 Step 1 -- Install Python
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
-Install Python 2.x.y (x = 6 or 7). Latest version is recommended. If you need another version, they can run side by side.
+Install Python 2.7.x. Latest version is recommended. If you need another version, they can run side by side.
 
 .. warning:: Python 3.x is not supported.
 
-- Download Python 2.x.y from http://www.python.org/download/
+- Download Python 2.7.x from http://www.python.org/download/
 - Choose and click on the version
 - Click on "Windows X86-64 Installer" for x64 or "Windows x86 MSI installer" for Win32.
 - Disable UAC or run the installer with admin privileges. If you chose to disable UAC, do not forget to reboot afterwards.
@@ -67,7 +67,7 @@
 
 If you installed Python 2.7.9+, you already have it (as long as you ran the installer with admin privileges or disabled UAC).
 
-If it was not installed or if you are using Python>=2.6,<2.7.9:
+If it was not installed or if you are using Python < 2.7.9:
 
 - Go to https://bootstrap.pypa.io
 - Right-click on get-pip.py and choose Saves as...
--- a/docs/installation_win_old.rst	Sat Aug 24 21:48:43 2019 +0200
+++ b/docs/installation_win_old.rst	Sun Jan 05 04:07:51 2020 +0100
@@ -60,8 +60,8 @@
 Step 2 -- Install Python
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
-Install Python 2.x.y (x = 6 or 7) x86 version (32-bit). DO NOT USE A 3.x version.
-Download Python 2.x.y from:
+Install Python 2.7.x x86 version (32-bit). DO NOT USE A 3.x version.
+Download Python 2.7.x from:
 http://www.python.org/download/
 
 Choose "Windows Installer" (32-bit version) not "Windows X86-64
--- a/docs/overview.rst	Sat Aug 24 21:48:43 2019 +0200
+++ b/docs/overview.rst	Sun Jan 05 04:07:51 2020 +0100
@@ -12,7 +12,7 @@
 ------------------
 
 **Kallithea** is written entirely in Python_ and requires Python version
-2.6 or higher. Python 3.x is currently not supported.
+2.7 or higher. Python 3.x is currently not supported.
 
 Given a Python installation, there are different ways of providing the
 environment for running Python applications. Each of them pretty much
--- a/docs/setup.rst	Sat Aug 24 21:48:43 2019 +0200
+++ b/docs/setup.rst	Sun Jan 05 04:07:51 2020 +0100
@@ -92,36 +92,82 @@
 Using Kallithea with SSH
 ------------------------
 
-Kallithea currently only hosts repositories using http and https. (The addition
-of ssh hosting is a planned future feature.) However you can easily use ssh in
-parallel with Kallithea. (Repository access via ssh is a standard "out of
-the box" feature of Mercurial_ and you can use this to access any of the
-repositories that Kallithea is hosting. See PublishingRepositories_)
+Kallithea supports repository access via SSH key based authentication.
+This means:
+
+- repository URLs like ``ssh://kallithea@example.com/name/of/repository``
+
+- all network traffic for both read and write happens over the SSH protocol on
+  port 22, without using HTTP/HTTPS nor the Kallithea WSGI application
+
+- encryption and authentication protocols are managed by the system's ``sshd``
+  process, with all users using the same Kallithea system user (e.g.
+  ``kallithea``) when connecting to the SSH server, but with users' public keys
+  in the Kallithea system user's `.ssh/authorized_keys` file granting each user
+  sandboxed access to the repositories.
+
+- users and admins can manage SSH public keys in the web UI
 
-Kallithea repository structures are kept in directories with the same name
-as the project. When using repository groups, each group is a subdirectory.
-This allows you to easily use ssh for accessing repositories.
+- in their SSH client configuration, users can configure how the client should
+  control access to their SSH key - without passphrase, with passphrase, and
+  optionally with passphrase caching in the local shell session (``ssh-agent``).
+  This is standard SSH functionality, not something Kallithea provides or
+  interferes with.
+
+- network communication between client and server happens in a bidirectional
+  stateful stream, and will in some cases be faster than HTTP/HTTPS with several
+  stateless round-trips.
 
-In order to use ssh you need to make sure that your web server and the users'
-login accounts have the correct permissions set on the appropriate directories.
+.. note:: At this moment, repository access via SSH has been tested on Unix
+    only. Windows users that care about SSH are invited to test it and report
+    problems, ideally contributing patches that solve these problems.
+
+Users and admins can upload SSH public keys (e.g. ``.ssh/id_rsa.pub``) through
+the web interface. The server's ``.ssh/authorized_keys`` file is automatically
+maintained with an entry for each SSH key. Each entry will tell ``sshd`` to run
+``kallithea-cli`` with the ``ssh-serve`` sub-command and the right Kallithea user ID
+when encountering the corresponding SSH key.
 
-.. note:: These permissions are independent of any permissions you
-          have set up using the Kallithea web interface.
+To enable SSH repository access, Kallithea must be configured with the path to
+the ``.ssh/authorized_keys`` file for the Kallithea user, and the path to the
+``kallithea-cli`` command. Put something like this in the ``.ini`` file::
+
+    ssh_enabled = true
+    ssh_authorized_keys = /home/kallithea/.ssh/authorized_keys
+    kallithea_cli_path = /srv/kallithea/venv/bin/kallithea-cli
 
-If your main directory (the same as set in Kallithea settings) is for
-example set to ``/srv/repos`` and the repository you are using is
-named ``kallithea``, then to clone via ssh you should run::
+The SSH service must be running, and the Kallithea user account must be active
+(not necessarily with password access, but public key access must be enabled),
+all file permissions must be set as sshd wants it, and ``authorized_keys`` must
+be writeable by the Kallithea user.
 
-    hg clone ssh://user@kallithea.example.com/srv/repos/kallithea
+.. note:: The ``authorized_keys`` file will be rewritten from scratch on
+    each update. If it already exists with other data, Kallithea will not
+    overwrite the existing ``authorized_keys``, and the server process will
+    instead throw an exception. The system administrator thus cannot ssh
+    directly to the Kallithea user but must use su/sudo from another account.
 
-Using other external tools such as mercurial-server_ or using ssh key-based
-authentication is fully supported.
+    If ``/home/kallithea/.ssh/`` (the directory of the path specified in the
+    ``ssh_authorized_keys`` setting of the ``.ini`` file) does not exist as a
+    directory, Kallithea will attempt to create it. If that path exists but is
+    *not* a directory, or is not readable-writable-executable by the server
+    process, the server process will raise an exception each time it attempts to
+    write the ``authorized_keys`` file.
 
-.. note:: In an advanced setup, in order for your ssh access to use
-          the same permissions as set up via the Kallithea web
-          interface, you can create an authentication hook to connect
-          to the Kallithea db and run check functions for permissions
-          against that.
+.. warning:: The handling of SSH access is steered directly by the command
+    specified in the ``authorized_keys`` file. There is no interaction with the
+    web UI.  Once SSH access is correctly configured and enabled, it will work
+    regardless of whether the Kallithea web process is actually running. Hence,
+    if you want to perform repository or server maintenance and want to fully
+    disable all access to the repositories, disable SSH access by setting
+    ``ssh_enabled = false`` in the correct ``.ini`` file (i.e. the ``.ini`` file
+    specified in the ``authorized_keys`` file.)
+
+The ``authorized_keys`` file can be updated manually with ``kallithea-cli
+ssh-update-authorized-keys -c my.ini``. This command is not needed in normal
+operation but is for example useful after changing SSH-related settings in the
+``.ini`` file or renaming that file. (The path to the ``.ini`` file is used in
+the generated ``authorized_keys`` file).
 
 
 Setting up Whoosh full text search
--- a/docs/usage/customization.rst	Sat Aug 24 21:48:43 2019 +0200
+++ b/docs/usage/customization.rst	Sun Jan 05 04:07:51 2020 +0100
@@ -23,10 +23,11 @@
 
 Kallithea uses `Bootstrap 3`_ and Less_ for its style definitions. If you want
 to make some customizations, we recommend to do so by creating a ``theme.less``
-file. When you create a file named ``theme.less`` in the Kallithea root
-directory, you can use this file to override the default style. For example,
-you can use this to override ``@kallithea-theme-main-color``,
-``@kallithea-logo-url`` or other `Bootstrap variables`_.
+file. When you create a file named ``theme.less`` in directory
+``kallithea/front-end/`` inside the Kallithea installation, you can use this
+file to override the default style. For example, you can use this to override
+``@kallithea-theme-main-color``, ``@kallithea-logo-url`` or other `Bootstrap
+variables`_.
 
 After creating the ``theme.less`` file, you need to regenerate the CSS files, by
 running::
--- a/docs/usage/locking.rst	Sat Aug 24 21:48:43 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-.. _locking:
-
-==================
-Repository locking
-==================
-
-Kallithea has a *repository locking* feature, disabled by default. When
-enabled, every initial clone and every pull gives users (with write permission)
-the exclusive right to do a push.
-
-When repository locking is enabled, repositories get a ``locked`` flag.
-The hg/git commands ``hg/git clone``, ``hg/git pull``,
-and ``hg/git push`` influence this state:
-
-- A ``clone`` or ``pull`` action locks the target repository
-  if the user has write/admin permissions on this repository.
-
-- Kallithea will remember the user who locked the repository so only this
-  specific user can unlock the repo by performing a ``push``
-  command.
-
-- Every other command on a locked repository from this user and every command
-  from any other user will result in an HTTP return code 423 (Locked).
-  Additionally, the HTTP error will mention the user that locked the repository
-  (e.g., “repository <repo> locked by user <user>”).
-
-Each repository can be manually unlocked by an administrator from the
-repository settings menu.
--- a/kallithea/__init__.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/__init__.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,10 +27,11 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+import platform
 import sys
-import platform
+
 
-VERSION = (0, 4, 1)
+VERSION = (0, 4, 99)
 BACKENDS = {
     'hg': 'Mercurial repository',
     'git': 'Git repository',
@@ -44,14 +45,6 @@
 # Linked module for extensions
 EXTENSIONS = {}
 
-try:
-    import kallithea.brand
-except ImportError:
-    pass
-else:
-    assert False, 'Database rebranding is no longer supported; see README.'
-
-
 __version__ = '.'.join(str(each) for each in VERSION)
 __platform__ = platform.system()
 __license__ = 'GPLv3'
--- a/kallithea/alembic/versions/a020f7044fd6_rename_hooks.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/alembic/versions/a020f7044fd6_rename_hooks.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,8 +27,10 @@
 depends_on = None
 
 from alembic import op
+from sqlalchemy import MetaData, Table
+
 from kallithea.model.db import Ui
-from sqlalchemy import Table, MetaData
+
 
 meta = MetaData()
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/alembic/versions/ad357ccd9521_drop_locking.py	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,61 @@
+# 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/>.
+
+"""Drop locking
+
+Revision ID: ad357ccd9521
+Revises: a020f7044fd6
+Create Date: 2019-01-08
+
+"""
+
+# The following opaque hexadecimal identifiers ("revisions") are used
+# by Alembic to track this migration script and its relations to others.
+revision = 'ad357ccd9521'
+down_revision = 'a020f7044fd6'
+branch_labels = None
+depends_on = None
+
+import sqlalchemy as sa
+from alembic import op
+from sqlalchemy import MetaData, Table
+
+from kallithea.model.db import Ui
+
+
+meta = MetaData()
+
+
+def upgrade():
+    with op.batch_alter_table('groups', schema=None) as batch_op:
+        batch_op.drop_column('enable_locking')
+
+    with op.batch_alter_table('repositories', schema=None) as batch_op:
+        batch_op.drop_column('locked')
+        batch_op.drop_column('enable_locking')
+
+    meta.bind = op.get_bind()
+    ui = Table(Ui.__tablename__, meta, autoload=True)
+    ui.delete().where(ui.c.ui_key == 'prechangegroup.push_lock_handling').execute()
+    ui.delete().where(ui.c.ui_key == 'preoutgoing.pull_lock_handling').execute()
+
+
+def downgrade():
+    with op.batch_alter_table('repositories', schema=None) as batch_op:
+        batch_op.add_column(sa.Column('enable_locking', sa.BOOLEAN(), nullable=False, default=False))
+        batch_op.add_column(sa.Column('locked', sa.VARCHAR(length=255), nullable=True, default=False))
+
+    with op.batch_alter_table('groups', schema=None) as batch_op:
+        batch_op.add_column(sa.Column('enable_locking', sa.BOOLEAN(), nullable=False, default=False))
+
+    # Note: not restoring hooks
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/alembic/versions/b74907136bc1_create_table_for_ssh_keys.py	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,61 @@
+# 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/>.
+
+"""Create table for ssh keys
+
+Revision ID: b74907136bc1
+Revises: a020f7044fd6
+Create Date: 2017-04-03 18:54:24.490346
+
+"""
+
+# The following opaque hexadecimal identifiers ("revisions") are used
+# by Alembic to track this migration script and its relations to others.
+revision = 'b74907136bc1'
+down_revision = 'ad357ccd9521'
+branch_labels = None
+depends_on = None
+
+import sqlalchemy as sa
+from alembic import op
+
+from kallithea.model import db
+
+
+def upgrade():
+    op.create_table('user_ssh_keys',
+        sa.Column('user_ssh_key_id', sa.Integer(), nullable=False),
+        sa.Column('user_id', sa.Integer(), nullable=False),
+        sa.Column('public_key', sa.UnicodeText(), nullable=False),
+        sa.Column('description', sa.UnicodeText(), nullable=False),
+        sa.Column('fingerprint', sa.String(length=255), nullable=False),
+        sa.Column('created_on', sa.DateTime(), nullable=False),
+        sa.Column('last_seen', sa.DateTime(), nullable=True),
+        sa.ForeignKeyConstraint(['user_id'], ['users.user_id'], name=op.f('fk_user_ssh_keys_user_id')),
+        sa.PrimaryKeyConstraint('user_ssh_key_id', name=op.f('pk_user_ssh_keys')),
+        sa.UniqueConstraint('fingerprint', name=op.f('uq_user_ssh_keys_fingerprint')),
+    )
+    with op.batch_alter_table('user_ssh_keys', schema=None) as batch_op:
+        batch_op.create_index('usk_fingerprint_idx', ['fingerprint'], unique=False)
+
+    session = sa.orm.session.Session(bind=op.get_bind())
+    if not session.query(db.Setting).filter(db.Setting.app_settings_name == 'clone_ssh_tmpl').all():
+        setting = db.Setting('clone_ssh_tmpl', db.Repository.DEFAULT_CLONE_SSH, 'unicode')
+        session.add(setting)
+    session.commit()
+
+
+def downgrade():
+    with op.batch_alter_table('user_ssh_keys', schema=None) as batch_op:
+        batch_op.drop_index('usk_fingerprint_idx')
+    op.drop_table('user_ssh_keys')
--- a/kallithea/bin/base.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/bin/base.py	Sun Jan 05 04:07:51 2020 +0100
@@ -26,13 +26,14 @@
 """
 
 import os
-import sys
+import pprint
 import random
+import sys
 import urllib2
-import pprint
 
 from kallithea.lib.compat import json
 
+
 CONFIG_NAME = '.config/kallithea'
 FORMAT_PRETTY = 'pretty'
 FORMAT_JSON = 'json'
--- a/kallithea/bin/kallithea_api.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/bin/kallithea_api.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,10 +25,12 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
-import sys
+from __future__ import print_function
+
 import argparse
+import sys
 
-from kallithea.bin.base import json, api_call, RcConf, FORMAT_JSON, FORMAT_PRETTY
+from kallithea.bin.base import FORMAT_JSON, FORMAT_PRETTY, RcConf, api_call, json
 
 
 def argparser(argv):
@@ -104,7 +106,7 @@
         sys.stderr.write('Error parsing arguments \n')
         sys.exit()
     if args.format == FORMAT_PRETTY:
-        print 'Calling method %s => %s' % (method, apihost)
+        print('Calling method %s => %s' % (method, apihost))
 
     json_resp = api_call(apikey, apihost, method, **margs)
     error_prefix = ''
@@ -114,11 +116,11 @@
     else:
         json_data = json_resp['result']
     if args.format == FORMAT_JSON:
-        print json.dumps(json_data)
+        print(json.dumps(json_data))
     elif args.format == FORMAT_PRETTY:
-        print 'Server response \n%s%s' % (
+        print('Server response \n%s%s' % (
             error_prefix, json.dumps(json_data, indent=4, sort_keys=True)
-        )
+        ))
     return 0
 
 
--- a/kallithea/bin/kallithea_backup.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/bin/kallithea_backup.py	Sun Jan 05 04:07:51 2020 +0100
@@ -26,14 +26,15 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+import datetime
+import logging
 import os
+import subprocess
 import sys
-import logging
 import tarfile
-import datetime
-import subprocess
 import tempfile
 
+
 logging.basicConfig(level=logging.DEBUG,
                     format="%(asctime)s %(levelname)-5.5s %(message)s")
 
--- a/kallithea/bin/kallithea_cli.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/bin/kallithea_cli.py	Sun Jan 05 04:07:51 2020 +0100
@@ -12,9 +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/>.
 
-# '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
-
 # import commands (they will add themselves to the 'cli' object)
 import kallithea.bin.kallithea_cli_celery
 import kallithea.bin.kallithea_cli_config
@@ -25,3 +22,6 @@
 import kallithea.bin.kallithea_cli_index
 import kallithea.bin.kallithea_cli_ishell
 import kallithea.bin.kallithea_cli_repo
+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
--- a/kallithea/bin/kallithea_cli_base.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/bin/kallithea_cli_base.py	Sun Jan 05 04:07:51 2020 +0100
@@ -12,21 +12,47 @@
 # 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 click
+import cStringIO
 import functools
+import logging.config
 import os
+import re
+import sys
+
+import click
+import paste.deploy
 
 import kallithea
-import logging.config
-import paste.deploy
+
+
+# kallithea_cli is usually invoked through the 'kallithea-cli' wrapper script
+# that is installed by setuptools, as specified in setup.py console_scripts
+# entry_points. The script will be using the right virtualenv (if any), and for
+# Unix, it will contain #! pointing at the right python executable. The script
+# also makes sure sys.argv[0] points back at the script path, and that is what
+# can be used to invoke 'kallithea-cli' later.
+kallithea_cli_path = sys.argv[0]
+
+
+def read_config(ini_file_name, strip_section_prefix):
+    """Read ini_file_name content, and for all sections like '[X:Y]' where X is
+    strip_section_prefix, replace the section name with '[Y]'."""
+
+    def repl(m):
+        if m.group(1) == strip_section_prefix:
+            return '[%s]' % m.group(2)
+        return m.group(0)
+
+    with open(ini_file_name) as f:
+        return re.sub(r'^\[([^:]+):(.*)]', repl, f.read(), flags=re.MULTILINE)
 
 
 # This placeholder is the main entry point for the kallithea-cli command
-@click.group()
+@click.group(context_settings=dict(help_option_names=['-h', '--help']))
 def cli():
     """Various commands to manage a Kallithea instance."""
 
-def register_command(config_file=False, config_file_initialize_app=False):
+def register_command(config_file=False, config_file_initialize_app=False, hidden=False):
     """Register a kallithea-cli subcommand.
 
     If one of the config_file flags are true, a config file must be specified
@@ -36,7 +62,7 @@
     If config_file_initialize_app is true, Kallithea, TurboGears global state
     (including tg.config), and database access will also be fully initialized.
     """
-    cli_command = cli.command()
+    cli_command = cli.command(hidden=hidden)
     if config_file or config_file_initialize_app:
         def annotator(annotated):
             @click.option('--config_file', '-c', help="Path to .ini file with app configuration.",
@@ -45,7 +71,8 @@
             def runtime_wrapper(config_file, *args, **kwargs):
                 path_to_ini_file = os.path.realpath(config_file)
                 kallithea.CONFIG = paste.deploy.appconfig('config:' + path_to_ini_file)
-                logging.config.fileConfig(path_to_ini_file)
+                config_bytes = read_config(path_to_ini_file, strip_section_prefix=annotated.__name__)
+                logging.config.fileConfig(cStringIO.StringIO(config_bytes))
                 if config_file_initialize_app:
                     kallithea.config.middleware.make_app_without_logging(kallithea.CONFIG.global_conf, **kallithea.CONFIG.local_conf)
                     kallithea.lib.utils.setup_cache_regions(kallithea.CONFIG)
--- a/kallithea/bin/kallithea_cli_celery.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/bin/kallithea_cli_celery.py	Sun Jan 05 04:07:51 2020 +0100
@@ -13,9 +13,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import click
+
+import kallithea
 import kallithea.bin.kallithea_cli_base as cli_base
 
-import kallithea
 
 @cli_base.register_command(config_file_initialize_app=True)
 @click.argument('celery_args', nargs=-1)
--- a/kallithea/bin/kallithea_cli_config.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/bin/kallithea_cli_config.py	Sun Jan 05 04:07:51 2020 +0100
@@ -12,18 +12,19 @@
 # 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 click
-import kallithea.bin.kallithea_cli_base as cli_base
-
 import os
 import sys
 import uuid
 from collections import defaultdict
 
+import click
 import mako.exceptions
 
+import kallithea.bin.kallithea_cli_base as cli_base
+import kallithea.lib.locale
 from kallithea.lib import inifile
 
+
 def show_defaults(ctx, param, value):
     # Following construct is taken from the Click documentation:
     # https://click.palletsprojects.com/en/7.x/options/#callbacks-and-eager-options
@@ -62,6 +63,9 @@
 
     mako_variable_values = {
         'git_hook_interpreter': sys.executable,
+        'user_home_path': os.path.expanduser('~'),
+        'kallithea_cli_path': cli_base.kallithea_cli_path,
+        'ssh_locale': kallithea.lib.locale.get_current_locale(),
     }
     ini_settings = defaultdict(dict)
 
--- a/kallithea/bin/kallithea_cli_db.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/bin/kallithea_cli_db.py	Sun Jan 05 04:07:51 2020 +0100
@@ -12,12 +12,13 @@
 # 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 click
-import kallithea.bin.kallithea_cli_base as cli_base
 
 import kallithea
+import kallithea.bin.kallithea_cli_base as cli_base
 from kallithea.lib.db_manage import DbManage
 from kallithea.model.meta import Session
 
+
 @cli_base.register_command(config_file=True)
 @click.option('--user', help='Username of administrator account.')
 @click.option('--password', help='Password for administrator account.')
@@ -57,8 +58,8 @@
     dbmanage = DbManage(dbconf=dbconf, root=kallithea.CONFIG['here'],
                         tests=False, cli_args=cli_args)
     dbmanage.create_tables(override=True)
-    opts = dbmanage.config_prompt(None)
-    dbmanage.create_settings(opts)
+    repo_root_path = dbmanage.prompt_repo_root_path(None)
+    dbmanage.create_settings(repo_root_path)
     dbmanage.create_default_user()
     dbmanage.admin_prompt()
     dbmanage.create_permissions()
--- a/kallithea/bin/kallithea_cli_extensions.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/bin/kallithea_cli_extensions.py	Sun Jan 05 04:07:51 2020 +0100
@@ -19,15 +19,16 @@
 :copyright: (c) 2013 RhodeCode GmbH, and others.
 :license: GPLv3, see LICENSE.md for more details.
 """
+import os
+
 import click
-import kallithea.bin.kallithea_cli_base as cli_base
-
-import os
 import pkg_resources
 
 import kallithea
+import kallithea.bin.kallithea_cli_base as cli_base
 from kallithea.lib.utils2 import ask_ok
 
+
 @cli_base.register_command(config_file=True)
 def extensions_create():
     """Write template file for extending Kallithea in Python.
--- a/kallithea/bin/kallithea_cli_front_end.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/bin/kallithea_cli_front_end.py	Sun Jan 05 04:07:51 2020 +0100
@@ -12,15 +12,16 @@
 # 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 click
-import kallithea.bin.kallithea_cli_base as cli_base
-
+import json
 import os
 import shutil
 import subprocess
-import json
+
+import click
 
 import kallithea
+import kallithea.bin.kallithea_cli_base as cli_base
+
 
 @cli_base.register_command()
 @click.option('--install-deps/--no-install-deps', default=True,
--- a/kallithea/bin/kallithea_cli_iis.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/bin/kallithea_cli_iis.py	Sun Jan 05 04:07:51 2020 +0100
@@ -11,12 +11,14 @@
 #
 # 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 sys
+
 import click
+
 import kallithea
 import kallithea.bin.kallithea_cli_base as cli_base
 
-import os
-import sys
 
 dispath_py_template = '''\
 # Created by Kallithea 'kallithea-cli iis-install'
--- a/kallithea/bin/kallithea_cli_index.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/bin/kallithea_cli_index.py	Sun Jan 05 04:07:51 2020 +0100
@@ -19,19 +19,19 @@
 :copyright: (c) 2013 RhodeCode GmbH, and others.
 :license: GPLv3, see LICENSE.md for more details.
 """
-import click
-import kallithea.bin.kallithea_cli_base as cli_base
-
 import os
-from string import strip
 import sys
 
+import click
+
 import kallithea
+import kallithea.bin.kallithea_cli_base as cli_base
 from kallithea.lib.indexers.daemon import WhooshIndexingDaemon
-from kallithea.lib.pidlock import LockHeld, DaemonLock
+from kallithea.lib.pidlock import DaemonLock, LockHeld
 from kallithea.lib.utils import load_rcextensions
 from kallithea.model.repo import RepoModel
 
+
 @cli_base.register_command(config_file_initialize_app=True)
 @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')
@@ -45,9 +45,9 @@
 
     if not repo_location:
         repo_location = RepoModel().repos_path
-    repo_list = map(strip, index_only.split(',')) \
+    repo_list = [x.strip() for x in index_only.split(',')] \
         if index_only else None
-    repo_update_list = map(strip, update_only.split(',')) \
+    repo_update_list = [x.strip() for x in update_only.split(',')] \
         if update_only else None
 
     try:
--- a/kallithea/bin/kallithea_cli_ishell.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/bin/kallithea_cli_ishell.py	Sun Jan 05 04:07:51 2020 +0100
@@ -19,21 +19,22 @@
 :copyright: (c) 2013 RhodeCode GmbH, and others.
 :license: GPLv3, see LICENSE.md for more details.
 """
-import click
-import kallithea.bin.kallithea_cli_base as cli_base
+
+from __future__ import print_function
 
 import sys
 
-# make following imports directly available inside the ishell
+import kallithea.bin.kallithea_cli_base as cli_base
 from kallithea.model.db import *
 
+
 @cli_base.register_command(config_file_initialize_app=True)
 def ishell():
     """Interactive shell for Kallithea."""
     try:
         from IPython import embed
     except ImportError:
-        print 'Kallithea ishell requires the Python package IPython 4 or later'
+        print('Kallithea ishell requires the Python package IPython 4 or later')
         sys.exit(-1)
     from traitlets.config.loader import Config
     cfg = Config()
--- a/kallithea/bin/kallithea_cli_repo.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/bin/kallithea_cli_repo.py	Sun Jan 05 04:07:51 2020 +0100
@@ -19,20 +19,21 @@
 :copyright: (c) 2013 RhodeCode GmbH, and others.
 :license: GPLv3, see LICENSE.md for more details.
 """
-import click
-import kallithea.bin.kallithea_cli_base as cli_base
-
 import datetime
 import os
 import re
 import shutil
 
-from kallithea.lib.utils import repo2db_mapper, REMOVED_REPO_PAT
-from kallithea.lib.utils2 import safe_unicode, safe_str, ask_ok
+import click
+
+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, safe_str, safe_unicode
 from kallithea.model.db import Repository, Ui
 from kallithea.model.meta import Session
 from kallithea.model.scm import ScmModel
 
+
 @cli_base.register_command(config_file_initialize_app=True)
 @click.option('--remove-missing', is_flag=True,
         help='Remove missing repositories from the Kallithea database.')
@@ -132,7 +133,8 @@
         if ('.hg' in alldirs or
             '.git' in alldirs or
             '.svn' in alldirs or
-            'objects' in alldirs and ('refs' in alldirs or 'packed-refs' in f)):
+            'objects' in alldirs and ('refs' in alldirs or 'packed-refs' in f)
+        ):
             continue
         for loc in alldirs:
             if REMOVED_REPO_PAT.match(loc):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/bin/kallithea_cli_ssh.py	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,87 @@
+# -*- 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 logging
+import os
+import re
+import shlex
+import sys
+
+import click
+
+import kallithea
+import kallithea.bin.kallithea_cli_base as cli_base
+from kallithea.lib.utils2 import str2bool
+from kallithea.lib.vcs.backends.git.ssh import GitSshHandler
+from kallithea.lib.vcs.backends.hg.ssh import MercurialSshHandler
+from kallithea.model.ssh_key import SshKeyModel
+
+
+log = logging.getLogger(__name__)
+
+
+@cli_base.register_command(config_file_initialize_app=True, hidden=True)
+@click.argument('user-id', type=click.INT, required=True)
+@click.argument('key-id', type=click.INT, required=True)
+def ssh_serve(user_id, key_id):
+    """Serve SSH repository protocol access.
+
+    The trusted command that is invoked from .ssh/authorized_keys to serve SSH
+    protocol access. The access will be granted as the specified user ID, and
+    logged as using the specified key ID.
+    """
+    ssh_enabled = kallithea.CONFIG.get('ssh_enabled', False)
+    if not str2bool(ssh_enabled):
+        sys.stderr.write("SSH access is disabled.\n")
+        return sys.exit(1)
+
+    ssh_locale = kallithea.CONFIG.get('ssh_locale')
+    if ssh_locale:
+        os.environ['LC_ALL'] = ssh_locale # trumps everything, including LANG, except LANGUAGE
+        os.environ['LANGUAGE'] = ssh_locale # trumps LC_ALL for GNU gettext message handling
+
+    ssh_original_command = os.environ.get('SSH_ORIGINAL_COMMAND', '')
+    client_ip = os.environ.get('SSH_CONNECTION', '').split(' ', 1)[0] or '0.0.0.0'
+    log.debug('ssh-serve was invoked for SSH command %r from %s', ssh_original_command, client_ip)
+
+    if not ssh_original_command:
+        if os.environ.get('SSH_CONNECTION'):
+            sys.stderr.write("'kallithea-cli ssh-serve' can only provide protocol access over SSH. Interactive SSH login for this user is disabled.\n")
+        else:
+            sys.stderr.write("'kallithea-cli ssh-serve' cannot be called directly. It must be specified as command in an SSH authorized_keys file.\n")
+        return sys.exit(1)
+
+    try:
+        ssh_command_parts = shlex.split(ssh_original_command)
+    except ValueError as e:
+        sys.stderr.write('Error parsing SSH command %r: %s\n' % (ssh_original_command, e))
+        sys.exit(1)
+    for VcsHandler in [MercurialSshHandler, GitSshHandler]:
+        vcs_handler = VcsHandler.make(ssh_command_parts)
+        if vcs_handler is not None:
+            vcs_handler.serve(user_id, key_id, client_ip)
+            assert False # serve is written so it never will terminate
+
+    sys.stderr.write("This account can only be used for repository access. SSH command %r is not supported.\n" % ssh_original_command)
+    sys.exit(1)
+
+
+@cli_base.register_command(config_file_initialize_app=True)
+def ssh_update_authorized_keys():
+    """Update .ssh/authorized_keys file.
+
+    The file is usually maintained automatically, but this command will also re-write it.
+    """
+
+    SshKeyModel().write_authorized_keys()
--- a/kallithea/bin/kallithea_gist.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/bin/kallithea_gist.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,13 +25,15 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
-import os
-import sys
-import stat
+from __future__ import print_function
+
 import argparse
 import fileinput
+import os
+import stat
+import sys
 
-from kallithea.bin.base import json, api_call, RcConf, FORMAT_JSON, FORMAT_PRETTY
+from kallithea.bin.base import FORMAT_JSON, FORMAT_PRETTY, RcConf, api_call, json
 
 
 def argparser(argv):
@@ -144,11 +146,11 @@
 
         json_data = api_call(apikey, host, 'create_gist', **margs)['result']
         if args.format == FORMAT_JSON:
-            print json.dumps(json_data)
+            print(json.dumps(json_data))
         elif args.format == FORMAT_PRETTY:
-            print json_data
-            print 'Created %s gist %s' % (json_data['gist']['type'],
-                                          json_data['gist']['url'])
+            print(json_data)
+            print('Created %s gist %s' % (json_data['gist']['type'],
+                                          json_data['gist']['url']))
     return 0
 
 
@@ -164,7 +166,7 @@
     try:
         return _run(argv)
     except Exception as e:
-        print e
+        print(e)
         return 1
 
 
--- a/kallithea/bin/ldap_sync.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/bin/ldap_sync.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,13 +25,16 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
-import ldap
+from __future__ import print_function
+
 import urllib2
 import uuid
+from ConfigParser import ConfigParser
+
+import ldap
 
 from kallithea.lib.compat import json
 
-from ConfigParser import ConfigParser
 
 config = ConfigParser()
 config.read('ldap_sync.conf')
@@ -150,7 +153,7 @@
         self.client.simple_bind(user, key)
         self.base_dn = base_dn
 
-    def __del__(self):
+    def close(self):
         self.client.unbind()
 
     def get_groups(self):
@@ -238,10 +241,13 @@
                 # TODO: handle somehow maybe..
                 pass
 
+    def close(self):
+        self.ldap_client.close()
+
 
 if __name__ == '__main__':
     sync = LdapSync()
-    print sync.update_groups_from_ldap()
+    print(sync.update_groups_from_ldap())
 
     for gr in sync.ldap_client.get_groups():
         # TODO: exception when user does not exist during add membership...
@@ -250,3 +256,5 @@
         # we need to find a way to recognize the right exception (we always get
         # ResponseError with no error code so maybe by return msg (?)
         sync.update_memberships_from_ldap(gr)
+
+    sync.close()
--- a/kallithea/config/app_cfg.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/config/app_cfg.py	Sun Jan 05 04:07:51 2020 +0100
@@ -17,30 +17,32 @@
 This file complements the .ini file.
 """
 
+import logging
+import os
 import platform
-import os, sys, logging
+import sys
 
+import alembic.config
+import mercurial
 import tg
+from alembic.migration import MigrationContext
+from alembic.script.base import ScriptDirectory
+from sqlalchemy import create_engine
 from tg import hooks
 from tg.configuration import AppConfig
 from tg.support.converters import asbool
-import alembic.config
-from alembic.script.base import ScriptDirectory
-from alembic.migration import MigrationContext
-from sqlalchemy import create_engine
-import mercurial
 
+import kallithea.lib.locale
+import kallithea.model.base
+from kallithea.lib.auth import set_available_permissions
 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.auth import set_available_permissions
-from kallithea.lib.utils import load_rcextensions, make_ui, set_app_settings, set_vcs_config, \
-    set_indexer_config, check_git_version, repo2db_mapper
+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 str2bool
-import kallithea.model.base
-from kallithea.model.scm import ScmModel
 
-import formencode
 
 log = logging.getLogger(__name__)
 
@@ -120,19 +122,7 @@
 def setup_configuration(app):
     config = app.config
 
-    # Verify that things work when Dulwich passes unicode paths to the file system layer.
-    # Note: UTF-8 is preferred, but for example ISO-8859-1 or mbcs should also work under the right cirumstances.
-    try:
-        u'\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_CTYPE', 'LC_ALL', 'LANG']:
-            if var in os.environ:
-                val = os.environ[var]
-                log.error("Note: Environment variable %s is %r - perhaps change it to some other value from 'locale -a', like 'C.UTF-8' or 'en_US.UTF-8'", var, val)
-                break
-        else:
-            log.error("Note: No locale setting found in environment variables - perhaps set LC_CTYPE to some value from 'locale -a', like 'C.UTF-8' or 'en_US.UTF-8'")
+    if not kallithea.lib.locale.current_locale_is_valid():
         log.error("Terminating ...")
         sys.exit(1)
 
@@ -166,14 +156,14 @@
             sys.exit(1)
 
     # store some globals into kallithea
-    kallithea.CELERY_ON = str2bool(config['app_conf'].get('use_celery'))
-    kallithea.CELERY_EAGER = str2bool(config['app_conf'].get('celery.always.eager'))
+    kallithea.CELERY_ON = str2bool(config.get('use_celery'))
+    kallithea.CELERY_EAGER = str2bool(config.get('celery.always.eager'))
     kallithea.CONFIG = config
 
     load_rcextensions(root_path=config['here'])
 
     set_available_permissions(config)
-    repos_path = make_ui('db').configitems('paths')[0][1]
+    repos_path = make_ui().configitems('paths')[0][1]
     config['base_path'] = repos_path
     set_app_settings(config)
 
@@ -208,6 +198,13 @@
     # Enable https redirects based on HTTP_X_URL_SCHEME set by proxy
     if any(asbool(config.get(x)) for x in ['https_fixup', 'force_https', 'use_htsts']):
         app = HttpsFixup(app, config)
+
+    app = PermanentRepoUrl(app, config)
+
+    # Optional and undocumented wrapper - gives more verbose request/response logging, but has a slight overhead
+    if str2bool(config.get('use_wsgi_wrapper')):
+        app = RequestWrapper(app, config)
+
     return app
 
 
--- a/kallithea/config/environment.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/config/environment.py	Sun Jan 05 04:07:51 2020 +0100
@@ -15,6 +15,7 @@
 
 from kallithea.config.app_cfg import base_config
 
+
 __all__ = ['load_environment']
 
 # Use base_config to setup the environment loader function
--- a/kallithea/config/middleware.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/config/middleware.py	Sun Jan 05 04:07:51 2020 +0100
@@ -14,9 +14,11 @@
 """WSGI middleware initialization for the Kallithea application."""
 
 import logging.config
+
 from kallithea.config.app_cfg import base_config
 from kallithea.config.environment import load_environment
 
+
 __all__ = ['make_app']
 
 # Use base_config to setup the necessary PasteDeploy application factory.
--- a/kallithea/config/post_receive_tmpl.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/config/post_receive_tmpl.py	Sun Jan 05 04:07:51 2020 +0100
@@ -11,6 +11,9 @@
 import os
 import sys
 
+import kallithea.lib.hooks
+
+
 # Set output mode on windows to binary for stderr.
 # This prevents python (or the windows console) from replacing \n with \r\n.
 # Git doesn't display remote output lines that contain \r,
@@ -22,7 +25,6 @@
 
 KALLITHEA_HOOK_VER = '_TMPL_'
 os.environ['KALLITHEA_HOOK_VER'] = KALLITHEA_HOOK_VER
-import kallithea.lib.hooks
 
 
 def main():
--- a/kallithea/config/pre_receive_tmpl.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/config/pre_receive_tmpl.py	Sun Jan 05 04:07:51 2020 +0100
@@ -11,6 +11,9 @@
 import os
 import sys
 
+import kallithea.lib.hooks
+
+
 # Set output mode on windows to binary for stderr.
 # This prevents python (or the windows console) from replacing \n with \r\n.
 # Git doesn't display remote output lines that contain \r,
@@ -22,7 +25,6 @@
 
 KALLITHEA_HOOK_VER = '_TMPL_'
 os.environ['KALLITHEA_HOOK_VER'] = KALLITHEA_HOOK_VER
-import kallithea.lib.hooks
 
 
 def main():
--- a/kallithea/config/rcextensions/__init__.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/config/rcextensions/__init__.py	Sun Jan 05 04:07:51 2020 +0100
@@ -105,7 +105,6 @@
       :param active:
       :param password:
       :param emails:
-      :param inherit_default_permissions:
       :param created_by:
     """
     return 0
@@ -169,7 +168,6 @@
       :param active:
       :param password:
       :param emails:
-      :param inherit_default_permissions:
       :param deleted_by:
     """
     return 0
@@ -189,7 +187,6 @@
     Post push hook
     kwargs available:
 
-      :param server_url: url of instance that triggered this hook
       :param config: path to .ini config used
       :param scm: type of VS 'git' or 'hg'
       :param username: name of user who pushed
@@ -215,7 +212,6 @@
     Post pull hook
     kwargs available::
 
-      :param server_url: url of instance that triggered this hook
       :param config: path to .ini config used
       :param scm: type of VS 'git' or 'hg'
       :param username: name of user who pulled
--- a/kallithea/config/routing.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/config/routing.py	Sun Jan 05 04:07:51 2020 +0100
@@ -19,8 +19,9 @@
 refer to the routes manual at http://routes.groovie.org/docs/
 """
 
+from routes import Mapper
 from tg import request
-from routes import Mapper
+
 
 # prefix for non repository related links needs to be prefixed with `/`
 ADMIN_PREFIX = '/_admin'
@@ -33,28 +34,18 @@
     rmap.minimization = False
     rmap.explicit = False
 
-    from kallithea.lib.utils import (is_valid_repo, is_valid_repo_group,
-                                     get_repo_by_id)
+    from kallithea.lib.utils import is_valid_repo, is_valid_repo_group
 
     def check_repo(environ, match_dict):
         """
-        check for valid repository for proper 404 handling
-
-        :param environ:
-        :param match_dict:
+        Check for valid repository for proper 404 handling.
+        Also, a bit of side effect modifying match_dict ...
         """
-        repo_name = match_dict.get('repo_name')
-
         if match_dict.get('f_path'):
             # fix for multiple initial slashes that causes errors
             match_dict['f_path'] = match_dict['f_path'].lstrip('/')
 
-        by_id_match = get_repo_by_id(repo_name)
-        if by_id_match:
-            repo_name = by_id_match
-            match_dict['repo_name'] = repo_name
-
-        return is_valid_repo(repo_name, config['base_path'])
+        return is_valid_repo(match_dict['repo_name'], config['base_path'])
 
     def check_group(environ, match_dict):
         """
@@ -193,6 +184,13 @@
         m.connect("edit_user_api_keys_delete", "/users/{id}/edit/api_keys/delete",
                   action="delete_api_key", conditions=dict(method=["POST"]))
 
+        m.connect("edit_user_ssh_keys", "/users/{id}/edit/ssh_keys",
+                  action="edit_ssh_keys", conditions=dict(method=["GET"]))
+        m.connect("edit_user_ssh_keys", "/users/{id}/edit/ssh_keys",
+                  action="ssh_keys_add", conditions=dict(method=["POST"]))
+        m.connect("edit_user_ssh_keys_delete", "/users/{id}/edit/ssh_keys/delete",
+                  action="ssh_keys_delete", conditions=dict(method=["POST"]))
+
         m.connect("edit_user_perms", "/users/{id}/edit/permissions",
                   action="edit_perms", conditions=dict(method=["GET"]))
         m.connect("edit_user_perms_update", "/users/{id}/edit/permissions",
@@ -265,7 +263,7 @@
     # ADMIN DEFAULTS ROUTES
     with rmap.submapper(path_prefix=ADMIN_PREFIX,
                         controller='admin/defaults') as m:
-        m.connect('defaults', 'defaults',
+        m.connect('defaults', '/defaults',
                   action="index")
         m.connect('defaults_update', 'defaults/{id}/update',
                   action="update", conditions=dict(method=["POST"]))
@@ -321,8 +319,6 @@
                   action="settings_system", conditions=dict(method=["POST"]))
         m.connect("admin_settings_system", "/settings/system",
                   action="settings_system", conditions=dict(method=["GET"]))
-        m.connect("admin_settings_system_update", "/settings/system/updates",
-                  action="settings_system_update", conditions=dict(method=["GET"]))
 
     # ADMIN MY ACCOUNT
     with rmap.submapper(path_prefix=ADMIN_PREFIX,
@@ -361,6 +357,13 @@
         m.connect("my_account_api_keys_delete", "/my_account/api_keys/delete",
                   action="my_account_api_keys_delete", conditions=dict(method=["POST"]))
 
+        m.connect("my_account_ssh_keys", "/my_account/ssh_keys",
+                  action="my_account_ssh_keys", conditions=dict(method=["GET"]))
+        m.connect("my_account_ssh_keys", "/my_account/ssh_keys",
+                  action="my_account_ssh_keys_add", conditions=dict(method=["POST"]))
+        m.connect("my_account_ssh_keys_delete", "/my_account/ssh_keys/delete",
+                  action="my_account_ssh_keys_delete", conditions=dict(method=["POST"]))
+
     # ADMIN GIST
     with rmap.submapper(path_prefix=ADMIN_PREFIX,
                         controller='admin/gists') as m:
@@ -394,7 +397,7 @@
     with rmap.submapper(path_prefix=ADMIN_PREFIX,
                         controller='admin/admin') as m:
         m.connect('admin_home', '', action='index')
-        m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
+        m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9. _-]*}',
                   action='add_repo')
     #==========================================================================
     # API V2
@@ -443,7 +446,7 @@
                  )
 
     # LOGIN/LOGOUT/REGISTER/SIGN IN
-    rmap.connect('authentication_token', '%s/authentication_token' % ADMIN_PREFIX, controller='login', action='authentication_token')
+    rmap.connect('session_csrf_secret_token', '%s/session_csrf_secret_token' % ADMIN_PREFIX, controller='login', action='session_csrf_secret_token')
     rmap.connect('login_home', '%s/login' % ADMIN_PREFIX, controller='login')
     rmap.connect('logout_home', '%s/logout' % ADMIN_PREFIX, controller='login',
                  action='logout')
@@ -533,13 +536,6 @@
                  controller='admin/repos', action="edit_advanced",
                  conditions=dict(method=["GET"], function=check_repo))
 
-    rmap.connect("edit_repo_advanced_locking", "/{repo_name:.*?}/settings/advanced/locking",
-                 controller='admin/repos', action="edit_advanced_locking",
-                 conditions=dict(method=["POST"], function=check_repo))
-    rmap.connect('toggle_locking', "/{repo_name:.*?}/settings/advanced/locking_toggle",
-                 controller='admin/repos', action="toggle_locking",
-                 conditions=dict(method=["GET"], function=check_repo))
-
     rmap.connect("edit_repo_advanced_journal", "/{repo_name:.*?}/settings/advanced/journal",
                  controller='admin/repos', action="edit_advanced_journal",
                  conditions=dict(method=["POST"], function=check_repo))
--- a/kallithea/controllers/admin/admin.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/admin/admin.py	Sun Jan 05 04:07:51 2020 +0100
@@ -28,20 +28,21 @@
 
 import logging
 
-from tg import request, tmpl_context as c
 from sqlalchemy.orm import joinedload
+from sqlalchemy.sql.expression import and_, func, or_
+from tg import request
+from tg import tmpl_context as c
+from whoosh import query
+from whoosh.qparser.dateparse import DateParserPlugin
 from whoosh.qparser.default import QueryParser
-from whoosh.qparser.dateparse import DateParserPlugin
-from whoosh import query
-from sqlalchemy.sql.expression import or_, and_, func
 
 from kallithea.config.routing import url
-from kallithea.model.db import UserLog
-from kallithea.lib.auth import LoginRequired, HasPermissionAnyDecorator
+from kallithea.lib.auth import HasPermissionAnyDecorator, LoginRequired
 from kallithea.lib.base import BaseController, render
-from kallithea.lib.utils2 import safe_int, remove_prefix, remove_suffix
 from kallithea.lib.indexers import JOURNAL_SCHEMA
 from kallithea.lib.page import Page
+from kallithea.lib.utils2 import remove_prefix, remove_suffix, safe_int
+from kallithea.model.db import UserLog
 
 
 log = logging.getLogger(__name__)
--- a/kallithea/controllers/admin/auth_settings.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/admin/auth_settings.py	Sun Jan 05 04:07:51 2020 +0100
@@ -24,23 +24,25 @@
 """
 
 import logging
-import formencode.htmlfill
 import traceback
 
-from tg import request, tmpl_context as c
+import formencode.htmlfill
+from tg import request
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
 from webob.exc import HTTPFound
 
 from kallithea.config.routing import url
+from kallithea.lib import auth_modules
 from kallithea.lib import helpers as h
-from kallithea.lib.compat import formatted_json
+from kallithea.lib.auth import HasPermissionAnyDecorator, LoginRequired
 from kallithea.lib.base import BaseController, render
-from kallithea.lib.auth import LoginRequired, HasPermissionAnyDecorator
-from kallithea.lib import auth_modules
+from kallithea.lib.compat import formatted_json
+from kallithea.model.db import Setting
 from kallithea.model.forms import AuthSettingsForm
-from kallithea.model.db import Setting
 from kallithea.model.meta import Session
 
+
 log = logging.getLogger(__name__)
 
 
--- a/kallithea/controllers/admin/defaults.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/admin/defaults.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,21 +27,22 @@
 
 import logging
 import traceback
+
 import formencode
 from formencode import htmlfill
-
-from tg import request, tmpl_context as c
+from tg import request
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
 from webob.exc import HTTPFound
 
 from kallithea.config.routing import url
 from kallithea.lib import helpers as h
-from kallithea.lib.auth import LoginRequired, HasPermissionAnyDecorator
+from kallithea.lib.auth import HasPermissionAnyDecorator, LoginRequired
 from kallithea.lib.base import BaseController, render
+from kallithea.model.db import Setting
 from kallithea.model.forms import DefaultsForm
 from kallithea.model.meta import Session
-from kallithea import BACKENDS
-from kallithea.model.db import Setting
+
 
 log = logging.getLogger(__name__)
 
@@ -54,7 +55,6 @@
         super(DefaultsController, self)._before(*args, **kwargs)
 
     def index(self, format='html'):
-        c.backends = BACKENDS.keys()
         defaults = Setting.get_default_repo_settings()
 
         return htmlfill.render(
--- a/kallithea/controllers/admin/gists.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/admin/gists.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,27 +25,28 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
-import time
 import logging
 import traceback
+
 import formencode.htmlfill
-
-from tg import request, response, tmpl_context as c
+from sqlalchemy.sql.expression import or_
+from tg import request, response
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
-from webob.exc import HTTPFound, HTTPNotFound, HTTPForbidden
+from webob.exc import HTTPForbidden, HTTPFound, HTTPNotFound
 
 from kallithea.config.routing import url
+from kallithea.lib import helpers as h
+from kallithea.lib.auth import LoginRequired
+from kallithea.lib.base import BaseController, jsonify, render
+from kallithea.lib.page import Page
+from kallithea.lib.utils2 import safe_int, safe_unicode, time_to_datetime
+from kallithea.lib.vcs.exceptions import NodeNotChangedError, VCSError
+from kallithea.model.db import Gist
 from kallithea.model.forms import GistForm
 from kallithea.model.gist import GistModel
 from kallithea.model.meta import Session
-from kallithea.model.db import Gist, User
-from kallithea.lib import helpers as h
-from kallithea.lib.base import BaseController, render, jsonify
-from kallithea.lib.auth import LoginRequired
-from kallithea.lib.utils2 import safe_int, safe_unicode, time_to_datetime
-from kallithea.lib.page import Page
-from sqlalchemy.sql.expression import or_
-from kallithea.lib.vcs.exceptions import VCSError, NodeNotChangedError
+
 
 log = logging.getLogger(__name__)
 
@@ -118,6 +119,7 @@
             gist = GistModel().create(
                 description=form_result['description'],
                 owner=request.authuser.user_id,
+                ip_addr=request.ip_addr,
                 gist_mapping=nodes,
                 gist_type=gist_type,
                 lifetime=form_result['lifetime']
@@ -215,7 +217,8 @@
                 GistModel().update(
                     gist=c.gist,
                     description=rpost['description'],
-                    owner=c.gist.owner,
+                    owner=c.gist.owner, # FIXME: request.authuser.user_id ?
+                    ip_addr=request.ip_addr,
                     gist_mapping=nodes,
                     gist_type=c.gist.gist_type,
                     lifetime=rpost['lifetime']
--- a/kallithea/controllers/admin/my_account.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/admin/my_account.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,26 +27,28 @@
 
 import logging
 import traceback
+
 import formencode
-
-from sqlalchemy import func
 from formencode import htmlfill
-from tg import request, tmpl_context as c
+from tg import request
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
 from webob.exc import HTTPFound
 
 from kallithea.config.routing import url
+from kallithea.lib import auth_modules
 from kallithea.lib import helpers as h
-from kallithea.lib import auth_modules
-from kallithea.lib.auth import LoginRequired, AuthUser
-from kallithea.lib.base import BaseController, render
+from kallithea.lib.auth import AuthUser, LoginRequired
+from kallithea.lib.base import BaseController, IfSshEnabled, render
 from kallithea.lib.utils2 import generate_api_key, safe_int
-from kallithea.model.db import Repository, UserEmailMap, User, UserFollowing
-from kallithea.model.forms import UserForm, PasswordChangeForm
+from kallithea.model.api_key import ApiKeyModel
+from kallithea.model.db import Repository, User, UserEmailMap, UserFollowing
+from kallithea.model.forms import PasswordChangeForm, UserForm
+from kallithea.model.meta import Session
+from kallithea.model.repo import RepoModel
+from kallithea.model.ssh_key import SshKeyModel, SshKeyModelException
 from kallithea.model.user import UserModel
-from kallithea.model.repo import RepoModel
-from kallithea.model.api_key import ApiKeyModel
-from kallithea.model.meta import Session
+
 
 log = logging.getLogger(__name__)
 
@@ -259,3 +261,36 @@
             h.flash(_("API key successfully deleted"), category='success')
 
         raise HTTPFound(location=url('my_account_api_keys'))
+
+    @IfSshEnabled
+    def my_account_ssh_keys(self):
+        c.active = 'ssh_keys'
+        self.__load_data()
+        c.user_ssh_keys = SshKeyModel().get_ssh_keys(request.authuser.user_id)
+        return render('admin/my_account/my_account.html')
+
+    @IfSshEnabled
+    def my_account_ssh_keys_add(self):
+        description = request.POST.get('description')
+        public_key = request.POST.get('public_key')
+        try:
+            new_ssh_key = SshKeyModel().create(request.authuser.user_id,
+                                               description, public_key)
+            Session().commit()
+            SshKeyModel().write_authorized_keys()
+            h.flash(_("SSH key %s successfully added") % new_ssh_key.fingerprint, category='success')
+        except SshKeyModelException as errors:
+            h.flash(errors.message, category='error')
+        raise HTTPFound(location=url('my_account_ssh_keys'))
+
+    @IfSshEnabled
+    def my_account_ssh_keys_delete(self):
+        public_key = request.POST.get('del_public_key')
+        try:
+            SshKeyModel().delete(public_key, request.authuser.user_id)
+            Session().commit()
+            SshKeyModel().write_authorized_keys()
+            h.flash(_("SSH key successfully deleted"), category='success')
+        except SshKeyModelException as errors:
+            h.flash(errors.message, category='error')
+        raise HTTPFound(location=url('my_account_ssh_keys'))
--- a/kallithea/controllers/admin/permissions.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/admin/permissions.py	Sun Jan 05 04:07:51 2020 +0100
@@ -28,21 +28,23 @@
 
 import logging
 import traceback
+
 import formencode
 from formencode import htmlfill
-
-from tg import request, tmpl_context as c
+from tg import request
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
 from webob.exc import HTTPFound
 
 from kallithea.config.routing import url
 from kallithea.lib import helpers as h
-from kallithea.lib.auth import LoginRequired, HasPermissionAnyDecorator, AuthUser
+from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator, LoginRequired
 from kallithea.lib.base import BaseController, render
+from kallithea.model.db import User, UserIpMap
 from kallithea.model.forms import DefaultPermissionsForm
+from kallithea.model.meta import Session
 from kallithea.model.permission import PermissionModel
-from kallithea.model.db import User, UserIpMap
-from kallithea.model.meta import Session
+
 
 log = logging.getLogger(__name__)
 
@@ -155,7 +157,7 @@
             if p.permission.permission_name.startswith('usergroup.'):
                 defaults['default_user_group_perm'] = p.permission.permission_name
 
-            if p.permission.permission_name.startswith('hg.create.write_on_repogroup'):
+            if p.permission.permission_name.startswith('hg.create.write_on_repogroup.'):
                 defaults['create_on_write'] = p.permission.permission_name
 
             elif p.permission.permission_name.startswith('hg.create.'):
--- a/kallithea/controllers/admin/repo_groups.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/admin/repo_groups.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,32 +25,30 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+import itertools
 import logging
 import traceback
+
 import formencode
-import itertools
-
 from formencode import htmlfill
-
-from tg import request, tmpl_context as c, app_globals
-from tg.i18n import ugettext as _, ungettext
-from webob.exc import HTTPFound, HTTPForbidden, HTTPNotFound, HTTPInternalServerError
+from tg import app_globals, request
+from tg import tmpl_context as c
+from tg.i18n import ugettext as _
+from tg.i18n import ungettext
+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 LoginRequired, \
-    HasRepoGroupPermissionLevelDecorator, HasRepoGroupPermissionLevel, \
-    HasPermissionAny
+from kallithea.lib.auth import HasPermissionAny, HasRepoGroupPermissionLevel, HasRepoGroupPermissionLevelDecorator, LoginRequired
 from kallithea.lib.base import BaseController, render
+from kallithea.lib.utils2 import safe_int
 from kallithea.model.db import RepoGroup, Repository
-from kallithea.model.scm import RepoGroupList, AvailableRepoGroupChoices
-from kallithea.model.repo_group import RepoGroupModel
 from kallithea.model.forms import RepoGroupForm, RepoGroupPermsForm
 from kallithea.model.meta import Session
 from kallithea.model.repo import RepoModel
-from kallithea.lib.utils2 import safe_int
-from sqlalchemy.sql.expression import func
+from kallithea.model.repo_group import RepoGroupModel
+from kallithea.model.scm import AvailableRepoGroupChoices, RepoGroupList
 
 
 log = logging.getLogger(__name__)
--- a/kallithea/controllers/admin/repos.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/admin/repos.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,28 +27,28 @@
 
 import logging
 import traceback
+
 import formencode
 from formencode import htmlfill
-from tg import request, tmpl_context as c
+from tg import request
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
-from sqlalchemy.sql.expression import func
-from webob.exc import HTTPFound, HTTPInternalServerError, HTTPForbidden, HTTPNotFound
+from webob.exc import HTTPForbidden, HTTPFound, HTTPInternalServerError, HTTPNotFound
 
 from kallithea.config.routing import url
 from kallithea.lib import helpers as h
-from kallithea.lib.auth import LoginRequired, \
-    HasRepoPermissionLevelDecorator, NotAnonymous, HasPermissionAny
-from kallithea.lib.base import BaseRepoController, render, jsonify
+from kallithea.lib.auth import HasPermissionAny, HasRepoPermissionLevelDecorator, LoginRequired, NotAnonymous
+from kallithea.lib.base import BaseRepoController, jsonify, render
+from kallithea.lib.exceptions import AttachedForksError
 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.forms import RepoFieldForm, RepoForm, RepoPermsForm
 from kallithea.model.meta import Session
-from kallithea.model.db import User, Repository, UserFollowing, RepoGroup, \
-    Setting, RepositoryField
-from kallithea.model.forms import RepoForm, RepoFieldForm, RepoPermsForm
-from kallithea.model.scm import ScmModel, AvailableRepoGroupChoices, RepoList
 from kallithea.model.repo import RepoModel
-from kallithea.lib.exceptions import AttachedForksError
-from kallithea.lib.utils2 import safe_int
+from kallithea.model.scm import AvailableRepoGroupChoices, RepoList, ScmModel
+
 
 log = logging.getLogger(__name__)
 
@@ -94,15 +94,14 @@
 
         defaults = RepoModel()._get_defaults(c.repo_name)
         defaults['clone_uri'] = c.repo_info.clone_uri_hidden # don't show password
+        defaults['permanent_url'] = c.repo_info.clone_url(clone_uri_tmpl=c.clone_uri_tmpl, with_id=True)
 
         return defaults
 
     def index(self, format='html'):
-        _list = Repository.query(sorted=True).all()
-
-        c.repos_list = RepoList(_list, perm_level='admin')
+        repos_list = RepoList(Repository.query(sorted=True).all(), perm_level='admin')
         # the repo list will be filtered to only show repos where the user has read permissions
-        repos_data = RepoModel().get_repos_as_dict(c.repos_list, admin=True)
+        repos_data = RepoModel().get_repos_as_dict(repos_list, admin=True)
         # data used to render the grid
         c.data = repos_data
 
@@ -339,7 +338,8 @@
                 obj_id = safe_int(request.POST.get('user_id'))
             elif obj_type == 'user_group':
                 obj_id = safe_int(request.POST.get('user_group_id'))
-            else: assert False
+            else:
+                assert False
 
             if obj_type == 'user':
                 RepoModel().revoke_user_permission(repo=repo_name, user=obj_id)
@@ -347,7 +347,8 @@
                 RepoModel().revoke_user_group_permission(
                     repo=repo_name, group_name=obj_id
                 )
-            else: assert False
+            else:
+                assert False
             # TODO: implement this
             #action_logger(request.authuser, 'admin_revoked_repo_permissions',
             #              repo_name, request.ip_addr)
@@ -415,7 +416,8 @@
         c.repos_list = [(None, _('-- Not a fork --'))]
         c.repos_list += [(x.repo_id, x.repo_name)
                          for x in read_access_repos
-                         if x.repo_id != c.repo_info.repo_id]
+                         if x.repo_id != c.repo_info.repo_id
+                         and x.repo_type == c.repo_info.repo_type]
 
         defaults = {
             'id_fork_of': c.repo_info.fork_id if c.repo_info.fork_id else ''
@@ -478,46 +480,6 @@
         raise HTTPFound(location=url('edit_repo_advanced', repo_name=repo_name))
 
     @HasRepoPermissionLevelDecorator('admin')
-    def edit_advanced_locking(self, repo_name):
-        """
-        Unlock repository when it is locked !
-
-        :param repo_name:
-        """
-        try:
-            repo = Repository.get_by_repo_name(repo_name)
-            if request.POST.get('set_lock'):
-                Repository.lock(repo, request.authuser.user_id)
-                h.flash(_('Repository has been locked'), category='success')
-            elif request.POST.get('set_unlock'):
-                Repository.unlock(repo)
-                h.flash(_('Repository has been unlocked'), category='success')
-        except Exception as e:
-            log.error(traceback.format_exc())
-            h.flash(_('An error occurred during unlocking'),
-                    category='error')
-        raise HTTPFound(location=url('edit_repo_advanced', repo_name=repo_name))
-
-    @HasRepoPermissionLevelDecorator('write')
-    def toggle_locking(self, repo_name):
-        try:
-            repo = Repository.get_by_repo_name(repo_name)
-
-            if repo.enable_locking:
-                if repo.locked[0]:
-                    Repository.unlock(repo)
-                    h.flash(_('Repository has been unlocked'), category='success')
-                else:
-                    Repository.lock(repo, request.authuser.user_id)
-                    h.flash(_('Repository has been locked'), category='success')
-
-        except Exception as e:
-            log.error(traceback.format_exc())
-            h.flash(_('An error occurred during unlocking'),
-                    category='error')
-        raise HTTPFound(location=url('summary_home', repo_name=repo_name))
-
-    @HasRepoPermissionLevelDecorator('admin')
     def edit_caches(self, repo_name):
         c.repo_info = self._load_repo()
         c.active = 'caches'
@@ -541,7 +503,7 @@
         c.active = 'remote'
         if request.POST:
             try:
-                ScmModel().pull_changes(repo_name, request.authuser.username)
+                ScmModel().pull_changes(repo_name, request.authuser.username, request.ip_addr)
                 h.flash(_('Pulled from remote location'), category='success')
             except Exception as e:
                 log.error(traceback.format_exc())
--- a/kallithea/controllers/admin/settings.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/admin/settings.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,28 +27,30 @@
 
 import logging
 import traceback
+
 import formencode
-
 from formencode import htmlfill
-from tg import request, tmpl_context as c, config
+from tg import config, request
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
 from webob.exc import HTTPFound
 
 from kallithea.config.routing import url
 from kallithea.lib import helpers as h
-from kallithea.lib.auth import LoginRequired, HasPermissionAnyDecorator
+from kallithea.lib.auth import HasPermissionAnyDecorator, LoginRequired
 from kallithea.lib.base import BaseController, render
 from kallithea.lib.celerylib import tasks
 from kallithea.lib.exceptions import HgsubversionImportError
 from kallithea.lib.utils import repo2db_mapper, set_app_settings
+from kallithea.lib.utils2 import safe_unicode
 from kallithea.lib.vcs import VCSError
-from kallithea.model.db import Ui, Repository, Setting
-from kallithea.model.forms import ApplicationSettingsForm, \
-    ApplicationUiSettingsForm, ApplicationVisualisationForm
+from kallithea.model.db import Repository, Setting, Ui
+from kallithea.model.forms import ApplicationSettingsForm, ApplicationUiSettingsForm, ApplicationVisualisationForm
+from kallithea.model.meta import Session
+from kallithea.model.notification import EmailNotificationModel
 from kallithea.model.scm import ScmModel
-from kallithea.model.notification import EmailNotificationModel
-from kallithea.model.meta import Session
-from kallithea.lib.utils2 import str2bool, safe_unicode
+
+
 log = logging.getLogger(__name__)
 
 
@@ -109,12 +111,6 @@
                 sett = Ui.get_by_key('hooks', Ui.HOOK_REPO_SIZE)
                 sett.ui_active = form_result['hooks_changegroup_repo_size']
 
-                sett = Ui.get_by_key('hooks', Ui.HOOK_PUSH_LOG)
-                sett.ui_active = form_result['hooks_changegroup_push_logger']
-
-                sett = Ui.get_by_key('hooks', Ui.HOOK_PULL_LOG)
-                sett.ui_active = form_result['hooks_outgoing_pull_logger']
-
                 ## EXTENSIONS
                 sett = Ui.get_or_create('extensions', 'largefiles')
                 sett.ui_active = form_result['extensions_largefiles']
@@ -277,6 +273,7 @@
                     ('use_gravatar', 'use_gravatar', 'bool'),
                     ('gravatar_url', 'gravatar_url', 'unicode'),
                     ('clone_uri_tmpl', 'clone_uri_tmpl', 'unicode'),
+                    ('clone_ssh_tmpl', 'clone_ssh_tmpl', 'unicode'),
                 ]
                 for setting, form_key, type_ in settings:
                     Setting.create_or_update(setting, form_result[form_key], type_)
@@ -425,7 +422,6 @@
 
         import kallithea
         c.ini = kallithea.CONFIG
-        c.update_url = defaults.get('update_url')
         server_info = Setting.get_server_info()
         for key, val in server_info.iteritems():
             setattr(c, key, val)
@@ -435,46 +431,3 @@
             defaults=defaults,
             encoding="UTF-8",
             force_defaults=False)
-
-    @HasPermissionAnyDecorator('hg.admin')
-    def settings_system_update(self):
-        import json
-        import urllib2
-        from kallithea.lib.verlib import NormalizedVersion
-        from kallithea import __version__
-
-        defaults = Setting.get_app_settings()
-        defaults.update(self._get_hg_ui_settings())
-        _update_url = defaults.get('update_url', '')
-        _update_url = "" # FIXME: disabled
-
-        _err = lambda s: '<div class="alert alert-danger">%s</div>' % (s)
-        try:
-            import kallithea
-            ver = kallithea.__version__
-            log.debug('Checking for upgrade on `%s` server', _update_url)
-            opener = urllib2.build_opener()
-            opener.addheaders = [('User-agent', 'Kallithea-SCM/%s' % ver)]
-            response = opener.open(_update_url)
-            response_data = response.read()
-            data = json.loads(response_data)
-        except urllib2.URLError as e:
-            log.error(traceback.format_exc())
-            return _err('Failed to contact upgrade server: %r' % e)
-        except ValueError as e:
-            log.error(traceback.format_exc())
-            return _err('Bad data sent from update server')
-
-        latest = data['versions'][0]
-
-        c.update_url = _update_url
-        c.latest_data = latest
-        c.latest_ver = latest['version']
-        c.cur_ver = __version__
-        c.should_upgrade = False
-
-        if NormalizedVersion(c.latest_ver) > NormalizedVersion(c.cur_ver):
-            c.should_upgrade = True
-        c.important_notices = latest['general']
-
-        return render('admin/settings/settings_system_update.html'),
--- a/kallithea/controllers/admin/user_groups.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/admin/user_groups.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,35 +27,30 @@
 
 import logging
 import traceback
+
 import formencode
-
 from formencode import htmlfill
-from tg import request, tmpl_context as c, config, app_globals
-from tg.i18n import ugettext as _
-from webob.exc import HTTPFound
-
 from sqlalchemy.orm import joinedload
 from sqlalchemy.sql.expression import func
-from webob.exc import HTTPInternalServerError
+from tg import app_globals, config, request
+from tg import tmpl_context as c
+from tg.i18n import ugettext as _
+from webob.exc import HTTPFound, HTTPInternalServerError
 
 import kallithea
 from kallithea.config.routing import url
 from kallithea.lib import helpers as h
-from kallithea.lib.exceptions import UserGroupsAssignedException, \
-    RepoGroupAssignmentError
-from kallithea.lib.utils2 import safe_unicode, safe_int
-from kallithea.lib.auth import LoginRequired, \
-    HasUserGroupPermissionLevelDecorator, HasPermissionAnyDecorator
+from kallithea.lib.auth import HasPermissionAnyDecorator, HasUserGroupPermissionLevelDecorator, LoginRequired
 from kallithea.lib.base import BaseController, render
+from kallithea.lib.exceptions import RepoGroupAssignmentError, UserGroupsAssignedException
+from kallithea.lib.utils import action_logger
+from kallithea.lib.utils2 import safe_int, safe_unicode
+from kallithea.model.db import User, UserGroup, UserGroupRepoGroupToPerm, UserGroupRepoToPerm, UserGroupToPerm
+from kallithea.model.forms import CustomDefaultPermissionsForm, UserGroupForm, UserGroupPermsForm
+from kallithea.model.meta import Session
 from kallithea.model.scm import UserGroupList
 from kallithea.model.user_group import UserGroupModel
-from kallithea.model.repo import RepoModel
-from kallithea.model.db import User, UserGroup, UserGroupToPerm, \
-    UserGroupRepoToPerm, UserGroupRepoGroupToPerm
-from kallithea.model.forms import UserGroupForm, UserGroupPermsForm, \
-    CustomDefaultPermissionsForm
-from kallithea.model.meta import Session
-from kallithea.lib.utils import action_logger
+
 
 log = logging.getLogger(__name__)
 
@@ -369,8 +364,6 @@
             form = CustomDefaultPermissionsForm()()
             form_result = form.to_python(request.POST)
 
-            inherit_perms = form_result['inherit_default_permissions']
-            user_group.inherit_default_permissions = inherit_perms
             usergroup_model = UserGroupModel()
 
             defs = UserGroupToPerm.query() \
--- a/kallithea/controllers/admin/users.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/admin/users.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,31 +27,31 @@
 
 import logging
 import traceback
+
 import formencode
-
 from formencode import htmlfill
-from tg import request, tmpl_context as c, config, app_globals
+from sqlalchemy.sql.expression import func
+from tg import app_globals, config, request
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
-from sqlalchemy.sql.expression import func
 from webob.exc import HTTPFound, HTTPNotFound
 
 import kallithea
 from kallithea.config.routing import url
-from kallithea.lib.exceptions import DefaultUserException, \
-    UserOwnsReposException, UserCreationError
+from kallithea.lib import auth_modules
 from kallithea.lib import helpers as h
-from kallithea.lib.auth import LoginRequired, HasPermissionAnyDecorator, \
-    AuthUser
-from kallithea.lib import auth_modules
-from kallithea.lib.base import BaseController, render
+from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator, LoginRequired
+from kallithea.lib.base import BaseController, IfSshEnabled, render
+from kallithea.lib.exceptions import DefaultUserException, UserCreationError, UserOwnsReposException
+from kallithea.lib.utils import action_logger
+from kallithea.lib.utils2 import datetime_to_time, generate_api_key, safe_int
 from kallithea.model.api_key import ApiKeyModel
-
 from kallithea.model.db import User, UserEmailMap, UserIpMap, UserToPerm
-from kallithea.model.forms import UserForm, CustomDefaultPermissionsForm
+from kallithea.model.forms import CustomDefaultPermissionsForm, UserForm
+from kallithea.model.meta import Session
+from kallithea.model.ssh_key import SshKeyModel, SshKeyModelException
 from kallithea.model.user import UserModel
-from kallithea.model.meta import Session
-from kallithea.lib.utils import action_logger
-from kallithea.lib.utils2 import datetime_to_time, safe_int, generate_api_key
+
 
 log = logging.getLogger(__name__)
 
@@ -315,8 +315,6 @@
             form = CustomDefaultPermissionsForm()()
             form_result = form.to_python(request.POST)
 
-            inherit_perms = form_result['inherit_default_permissions']
-            user.inherit_default_permissions = inherit_perms
             user_model = UserModel()
 
             defs = UserToPerm.query() \
@@ -391,7 +389,6 @@
         c.user_ip_map = UserIpMap.query() \
             .filter(UserIpMap.user == c.user).all()
 
-        c.inherit_default_ips = c.user.inherit_default_permissions
         c.default_user_ip_map = UserIpMap.query() \
             .filter(UserIpMap.user == User.get_default_user()).all()
 
@@ -432,3 +429,45 @@
         if 'default_user' in request.POST:
             raise HTTPFound(location=url('admin_permissions_ips'))
         raise HTTPFound(location=url('edit_user_ips', id=id))
+
+    @IfSshEnabled
+    def edit_ssh_keys(self, id):
+        c.user = self._get_user_or_raise_if_default(id)
+        c.active = 'ssh_keys'
+        c.user_ssh_keys = SshKeyModel().get_ssh_keys(c.user.user_id)
+        defaults = c.user.get_dict()
+        return htmlfill.render(
+            render('admin/users/user_edit.html'),
+            defaults=defaults,
+            encoding="UTF-8",
+            force_defaults=False)
+
+    @IfSshEnabled
+    def ssh_keys_add(self, id):
+        c.user = self._get_user_or_raise_if_default(id)
+
+        description = request.POST.get('description')
+        public_key = request.POST.get('public_key')
+        try:
+            new_ssh_key = SshKeyModel().create(c.user.user_id,
+                                               description, public_key)
+            Session().commit()
+            SshKeyModel().write_authorized_keys()
+            h.flash(_("SSH key %s successfully added") % new_ssh_key.fingerprint, category='success')
+        except SshKeyModelException as errors:
+            h.flash(errors.message, category='error')
+        raise HTTPFound(location=url('edit_user_ssh_keys', id=c.user.user_id))
+
+    @IfSshEnabled
+    def ssh_keys_delete(self, id):
+        c.user = self._get_user_or_raise_if_default(id)
+
+        public_key = request.POST.get('del_public_key')
+        try:
+            SshKeyModel().delete(public_key, c.user.user_id)
+            Session().commit()
+            SshKeyModel().write_authorized_keys()
+            h.flash(_("SSH key successfully deleted"), category='success')
+        except SshKeyModelException as errors:
+            h.flash(errors.message, category='error')
+        raise HTTPFound(location=url('edit_user_ssh_keys', id=c.user.user_id))
--- a/kallithea/controllers/api/__init__.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/api/__init__.py	Sun Jan 05 04:07:51 2020 +0100
@@ -26,22 +26,22 @@
 """
 
 import inspect
+import itertools
 import logging
-import types
-import traceback
 import time
-import itertools
-
-from tg import Response, response, request, TGController
+import traceback
+import types
 
-from webob.exc import HTTPError, HTTPException, WSGIHTTPException
+from tg import Response, TGController, request, response
+from webob.exc import HTTPError, HTTPException
 
+from kallithea.lib.auth import AuthUser
+from kallithea.lib.base import _get_access_path
+from kallithea.lib.base import _get_ip_addr as _get_ip
+from kallithea.lib.compat import json
+from kallithea.lib.utils2 import safe_str, safe_unicode
 from kallithea.model.db import User
-from kallithea.model import meta
-from kallithea.lib.compat import json
-from kallithea.lib.auth import AuthUser
-from kallithea.lib.base import _get_ip_addr as _get_ip, _get_access_path
-from kallithea.lib.utils2 import safe_unicode, safe_str
+
 
 log = logging.getLogger('JSONRPC')
 
@@ -103,7 +103,7 @@
 
         environ = state.request.environ
         start = time.time()
-        ip_addr = request.ip_addr = self._get_ip_addr(environ)
+        ip_addr = self._get_ip_addr(environ)
         self._req_id = None
         if 'CONTENT_LENGTH' not in environ:
             log.debug("No Content-Length")
@@ -146,21 +146,17 @@
         # check if we can find this session using api_key
         try:
             u = User.get_by_api_key(self._req_api_key)
-            if u is None:
+            auth_user = AuthUser.make(dbuser=u, ip_addr=ip_addr)
+            if auth_user is None:
                 raise JSONRPCErrorResponse(retid=self._req_id,
                                            message='Invalid API key')
-
-            auth_u = AuthUser(dbuser=u)
-            if not AuthUser.check_ip_allowed(auth_u, ip_addr):
-                raise JSONRPCErrorResponse(retid=self._req_id,
-                                           message='request from IP:%s not allowed' % (ip_addr,))
-            else:
-                log.info('Access for IP:%s allowed', ip_addr)
-
         except Exception as e:
             raise JSONRPCErrorResponse(retid=self._req_id,
                                        message='Invalid API key')
 
+        request.authuser = auth_user
+        request.ip_addr = ip_addr
+
         self._error = None
         try:
             self._func = self._find_method()
@@ -179,11 +175,6 @@
         func_kwargs = dict(itertools.izip_longest(reversed(arglist), reversed(defaults),
                                                   fillvalue=default_empty))
 
-        # this is little trick to inject logged in user for
-        # perms decorators to work they expect the controller class to have
-        # authuser attribute set
-        request.authuser = auth_u
-
         # This attribute will need to be first param of a method that uses
         # api_key, which is translated to instance of user at that name
         USER_SESSION_ATTR = 'apiuser'
@@ -205,11 +196,11 @@
 
         extra = set(self._request_params).difference(func_kwargs)
         if extra:
-                raise JSONRPCErrorResponse(
-                    retid=self._req_id,
-                    message='Unknown %s arg in JSON DATA' %
-                            ', '.join('`%s`' % arg for arg in extra),
-                )
+            raise JSONRPCErrorResponse(
+                retid=self._req_id,
+                message='Unknown %s arg in JSON DATA' %
+                        ', '.join('`%s`' % arg for arg in extra),
+            )
 
         self._rpc_args = {}
         self._rpc_args.update(self._request_params)
--- a/kallithea/controllers/api/api.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/api/api.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,42 +25,32 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
-import time
+import logging
 import traceback
-import logging
-
 from datetime import datetime
-from sqlalchemy import or_
 
 from tg import request
 
 from kallithea.controllers.api import JSONRPCController, JSONRPCError
 from kallithea.lib.auth import (
-    PasswordGenerator, AuthUser, HasPermissionAnyDecorator,
-    HasPermissionAnyDecorator, HasPermissionAny, HasRepoPermissionLevel,
-    HasRepoGroupPermissionLevel, HasUserGroupPermissionLevel)
-from kallithea.lib.utils import map_groups, repo2db_mapper
-from kallithea.lib.utils2 import (
-    str2bool, time_to_datetime, safe_int, Optional, OAttr)
+    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
+from kallithea.lib.vcs.backends.base import EmptyChangeset
+from kallithea.lib.vcs.exceptions import EmptyRepositoryError
+from kallithea.model.changeset_status import ChangesetStatusModel
+from kallithea.model.comment import ChangesetCommentsModel
+from kallithea.model.db import ChangesetStatus, Gist, Permission, PullRequest, RepoGroup, Repository, Setting, User, UserGroup, UserIpMap
+from kallithea.model.gist import GistModel
 from kallithea.model.meta import Session
+from kallithea.model.pull_request import PullRequestModel
+from kallithea.model.repo import RepoModel
 from kallithea.model.repo_group import RepoGroupModel
 from kallithea.model.scm import ScmModel, UserGroupList
-from kallithea.model.repo import RepoModel
 from kallithea.model.user import UserModel
 from kallithea.model.user_group import UserGroupModel
-from kallithea.model.gist import GistModel
-from kallithea.model.changeset_status import ChangesetStatusModel
-from kallithea.model.comment import ChangesetCommentsModel
-from kallithea.model.pull_request import PullRequestModel
-from kallithea.model.db import (
-    Repository, Setting, UserIpMap, Permission, User, Gist,
-    RepoGroup, UserGroup, PullRequest, ChangesetStatus)
-from kallithea.lib.compat import json
-from kallithea.lib.exceptions import (
-    DefaultUserException, UserGroupsAssignedException)
-from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError, EmptyRepositoryError
-from kallithea.lib.vcs.backends.base import EmptyChangeset
-from kallithea.lib.utils import action_logger
+
 
 log = logging.getLogger(__name__)
 
@@ -206,6 +196,7 @@
         try:
             ScmModel().pull_changes(repo.repo_name,
                                     request.authuser.username,
+                                    request.ip_addr,
                                     clone_uri=Optional.extract(clone_uri))
             return dict(
                 msg='Pulled from `%s`' % repo.repo_name,
@@ -303,168 +294,6 @@
                 'Error occurred during cache invalidation action'
             )
 
-    # permission check inside
-    def lock(self, repoid, locked=Optional(None),
-             userid=Optional(OAttr('apiuser'))):
-        """
-        Set locking state on given repository by given user. If userid param
-        is skipped, then it is set to id of user who is calling this method.
-        If locked param is skipped then function shows current lock state of
-        given repo. This command can be executed only using api_key belonging
-        to user with admin rights or regular user that have admin or write
-        access to repository.
-
-        :param repoid: repository name or repository id
-        :type repoid: str or int
-        :param locked: lock state to be set
-        :type locked: Optional(bool)
-        :param userid: set lock as user
-        :type userid: Optional(str or int)
-
-        OUTPUT::
-
-          id : <id_given_in_input>
-          result : {
-            'repo': '<reponame>',
-            'locked': <bool: lock state>,
-            'locked_since': <int: lock timestamp>,
-            'locked_by': <username of person who made the lock>,
-            'lock_state_changed': <bool: True if lock state has been changed in this request>,
-            'msg': 'Repo `<reponame>` locked by `<username>` on <timestamp>.'
-            or
-            'msg': 'Repo `<repository name>` not locked.'
-            or
-            'msg': 'User `<user name>` set lock state for repo `<repository name>` to `<new lock state>`'
-          }
-          error :  null
-
-        ERROR OUTPUT::
-
-          id : <id_given_in_input>
-          result : null
-          error :  {
-            'Error occurred locking repository `<reponame>`
-          }
-
-        """
-        repo = get_repo_or_error(repoid)
-        if HasPermissionAny('hg.admin')():
-            pass
-        elif HasRepoPermissionLevel('write')(repo.repo_name):
-            # make sure normal user does not pass someone else userid,
-            # he is not allowed to do that
-            if not isinstance(userid, Optional) and userid != request.authuser.user_id:
-                raise JSONRPCError(
-                    'userid is not the same as your user'
-                )
-        else:
-            raise JSONRPCError('repository `%s` does not exist' % (repoid,))
-
-        if isinstance(userid, Optional):
-            userid = request.authuser.user_id
-
-        user = get_user_or_error(userid)
-
-        if isinstance(locked, Optional):
-            lockobj = Repository.getlock(repo)
-
-            if lockobj[0] is None:
-                _d = {
-                    'repo': repo.repo_name,
-                    'locked': False,
-                    'locked_since': None,
-                    'locked_by': None,
-                    'lock_state_changed': False,
-                    'msg': 'Repo `%s` not locked.' % repo.repo_name
-                }
-                return _d
-            else:
-                userid, time_ = lockobj
-                lock_user = get_user_or_error(userid)
-                _d = {
-                    'repo': repo.repo_name,
-                    'locked': True,
-                    'locked_since': time_,
-                    'locked_by': lock_user.username,
-                    'lock_state_changed': False,
-                    'msg': ('Repo `%s` locked by `%s` on `%s`.'
-                            % (repo.repo_name, lock_user.username,
-                               json.dumps(time_to_datetime(time_))))
-                }
-                return _d
-
-        # force locked state through a flag
-        else:
-            locked = str2bool(locked)
-            try:
-                if locked:
-                    lock_time = time.time()
-                    Repository.lock(repo, user.user_id, lock_time)
-                else:
-                    lock_time = None
-                    Repository.unlock(repo)
-                _d = {
-                    'repo': repo.repo_name,
-                    'locked': locked,
-                    'locked_since': lock_time,
-                    'locked_by': user.username,
-                    'lock_state_changed': True,
-                    'msg': ('User `%s` set lock state for repo `%s` to `%s`'
-                            % (user.username, repo.repo_name, locked))
-                }
-                return _d
-            except Exception:
-                log.error(traceback.format_exc())
-                raise JSONRPCError(
-                    'Error occurred locking repository `%s`' % repo.repo_name
-                )
-
-    def get_locks(self, userid=Optional(OAttr('apiuser'))):
-        """
-        Get all repositories with locks for given userid, if
-        this command is run by non-admin account userid is set to user
-        who is calling this method, thus returning locks for himself.
-
-        :param userid: User to get locks for
-        :type userid: Optional(str or int)
-
-        OUTPUT::
-
-          id : <id_given_in_input>
-          result : {
-            [repo_object, repo_object,...]
-          }
-          error :  null
-        """
-
-        if not HasPermissionAny('hg.admin')():
-            # make sure normal user does not pass someone else userid,
-            # he is not allowed to do that
-            if not isinstance(userid, Optional) and userid != request.authuser.user_id:
-                raise JSONRPCError(
-                    'userid is not the same as your user'
-                )
-
-        ret = []
-        if isinstance(userid, Optional):
-            user = None
-        else:
-            user = get_user_or_error(userid)
-
-        # show all locks
-        for r in Repository.query():
-            userid, time_ = r.locked
-            if time_:
-                _api_data = r.get_api_data()
-                # if we use userfilter just show the locks for this user
-                if user is not None:
-                    if safe_int(userid) == user.user_id:
-                        ret.append(_api_data)
-                else:
-                    ret.append(_api_data)
-
-        return ret
-
     @HasPermissionAnyDecorator('hg.admin')
     def get_ip(self, userid=Optional(OAttr('apiuser'))):
         """
@@ -1069,7 +898,7 @@
 
         try:
             ugm = UserGroupModel().add_user_to_group(user_group, user)
-            success = True if ugm != True else False
+            success = True if ugm is not True else False
             msg = 'added member `%s` to user group `%s`' % (
                 user.username, user_group.users_group_name
             )
@@ -1155,7 +984,6 @@
                 "repo_type" :        "<repo_type>",
                 "clone_uri" :        "<clone_uri>",
                 "enable_downloads":  "<bool>",
-                "enable_locking":    "<bool>",
                 "enable_statistics": "<bool>",
                 "private":           "<bool>",
                 "created_on" :       "<date_time_created>",
@@ -1266,7 +1094,6 @@
                         "owner":             "<repo_owner>",
                         "fork_of":           "<name_of_fork_parent>",
                         "enable_downloads":  "<bool>",
-                        "enable_locking":    "<bool>",
                         "enable_statistics": "<bool>",
                       },

@@ -1346,7 +1173,6 @@
                     private=Optional(False), clone_uri=Optional(None),
                     landing_rev=Optional('rev:tip'),
                     enable_statistics=Optional(False),
-                    enable_locking=Optional(False),
                     enable_downloads=Optional(False),
                     copy_permissions=Optional(False)):
         """
@@ -1371,8 +1197,6 @@
         :type clone_uri: str
         :param landing_rev: <rev_type>:<rev>
         :type landing_rev: str
-        :param enable_locking:
-        :type enable_locking: bool
         :param enable_downloads:
         :type enable_downloads: bool
         :param enable_statistics:
@@ -1421,8 +1245,6 @@
             repo_type = defs.get('repo_type')
         if isinstance(enable_statistics, Optional):
             enable_statistics = defs.get('repo_enable_statistics')
-        if isinstance(enable_locking, Optional):
-            enable_locking = defs.get('repo_enable_locking')
         if isinstance(enable_downloads, Optional):
             enable_downloads = defs.get('repo_enable_downloads')
 
@@ -1450,7 +1272,6 @@
                 repo_group=repo_group,
                 repo_landing_rev=landing_rev,
                 enable_statistics=enable_statistics,
-                enable_locking=enable_locking,
                 enable_downloads=enable_downloads,
                 repo_copy_permissions=copy_permissions,
             )
@@ -1476,7 +1297,6 @@
                     description=Optional(''), private=Optional(False),
                     clone_uri=Optional(None), landing_rev=Optional('rev:tip'),
                     enable_statistics=Optional(False),
-                    enable_locking=Optional(False),
                     enable_downloads=Optional(False)):
 
         """
@@ -1492,7 +1312,6 @@
         :param clone_uri:
         :param landing_rev:
         :param enable_statistics:
-        :param enable_locking:
         :param enable_downloads:
         """
         repo = get_repo_or_error(repoid)
@@ -1502,7 +1321,7 @@
 
             if (name != repo.repo_name and
                 not HasPermissionAny('hg.create.repository')()
-                ):
+            ):
                 raise JSONRPCError('no permission to create (or move) repositories')
 
             if not isinstance(owner, Optional):
@@ -1525,7 +1344,6 @@
             store_update(updates, clone_uri, 'clone_uri')
             store_update(updates, landing_rev, 'repo_landing_rev')
             store_update(updates, enable_statistics, 'repo_enable_statistics')
-            store_update(updates, enable_locking, 'repo_enable_locking')
             store_update(updates, enable_downloads, 'repo_enable_downloads')
 
             RepoModel().update(repo, **updates)
@@ -2020,7 +1838,7 @@
     def update_repo_group(self, repogroupid, group_name=Optional(''),
                           description=Optional(''),
                           owner=Optional(OAttr('apiuser')),
-                          parent=Optional(None), enable_locking=Optional(False)):
+                          parent=Optional(None)):
         repo_group = get_repo_group_or_error(repogroupid)
 
         updates = {}
@@ -2029,7 +1847,6 @@
             store_update(updates, description, 'group_description')
             store_update(updates, owner, 'owner')
             store_update(updates, parent, 'parent_group')
-            store_update(updates, enable_locking, 'enable_locking')
             repo_group = RepoGroupModel().update(repo_group, updates)
             Session().commit()
             return dict(
@@ -2443,6 +2260,7 @@
 
             gist = GistModel().create(description=description,
                                       owner=owner,
+                                      ip_addr=request.ip_addr,
                                       gist_mapping=files,
                                       gist_type=gist_type,
                                       lifetime=lifetime)
@@ -2536,9 +2354,9 @@
 
         with_reviews = Optional.extract(with_reviews)
         if with_reviews:
-                reviews = ChangesetStatusModel().get_statuses(
-                                    repo.repo_name, raw_id)
-                info["reviews"] = reviews
+            reviews = ChangesetStatusModel().get_statuses(
+                                repo.repo_name, raw_id)
+            info["reviews"] = reviews
 
         return info
 
--- a/kallithea/controllers/changelog.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/changelog.py	Sun Jan 05 04:07:51 2020 +0100
@@ -28,19 +28,19 @@
 import logging
 import traceback
 
-from tg import request, session, tmpl_context as c
+from tg import request, session
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
-from webob.exc import HTTPFound, HTTPNotFound, HTTPBadRequest
+from webob.exc import HTTPBadRequest, HTTPFound, HTTPNotFound
 
 import kallithea.lib.helpers as h
 from kallithea.config.routing import url
-from kallithea.lib.auth import LoginRequired, HasRepoPermissionLevelDecorator
+from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
 from kallithea.lib.base import BaseRepoController, render
 from kallithea.lib.graphmod import graph_data
 from kallithea.lib.page import RepoPage
-from kallithea.lib.vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
-    ChangesetError, NodeDoesNotExistError, EmptyRepositoryError
 from kallithea.lib.utils2 import safe_int, safe_str
+from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError, ChangesetError, EmptyRepositoryError, NodeDoesNotExistError, RepositoryError
 
 
 log = logging.getLogger(__name__)
@@ -88,7 +88,8 @@
         if (branch_name and
             branch_name not in c.db_repo_scm_instance.branches and
             branch_name not in c.db_repo_scm_instance.closed_branches and
-            not revision):
+            not revision
+        ):
             raise HTTPFound(location=url('changelog_file_home', repo_name=c.repo_name,
                                     revision=branch_name, f_path=f_path or ''))
 
--- a/kallithea/controllers/changeset.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/changeset.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,30 +27,28 @@
 
 import logging
 import traceback
-from collections import defaultdict
+from collections import OrderedDict, defaultdict
 
-from tg import tmpl_context as c, request, response
+from tg import request, response
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
-from webob.exc import HTTPFound, HTTPForbidden, HTTPBadRequest, HTTPNotFound
-
-from kallithea.lib.vcs.exceptions import RepositoryError, \
-    ChangesetDoesNotExistError, EmptyRepositoryError
+from webob.exc import HTTPBadRequest, HTTPForbidden, HTTPFound, HTTPNotFound
 
 import kallithea.lib.helpers as h
-from kallithea.lib.auth import LoginRequired, HasRepoPermissionLevelDecorator
-from kallithea.lib.base import BaseRepoController, render, jsonify
+from kallithea.lib import diffs
+from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
+from kallithea.lib.base import BaseRepoController, jsonify, render
+from kallithea.lib.graphmod import graph_data
 from kallithea.lib.utils import action_logger
-from kallithea.lib.compat import OrderedDict
-from kallithea.lib import diffs
+from kallithea.lib.utils2 import safe_unicode
+from kallithea.lib.vcs.backends.base import EmptyChangeset
+from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError
+from kallithea.model.changeset_status import ChangesetStatusModel
+from kallithea.model.comment import ChangesetCommentsModel
 from kallithea.model.db import ChangesetComment, ChangesetStatus
-from kallithea.model.comment import ChangesetCommentsModel
-from kallithea.model.changeset_status import ChangesetStatusModel
 from kallithea.model.meta import Session
 from kallithea.model.pull_request import PullRequestModel
-from kallithea.model.repo import RepoModel
-from kallithea.lib.vcs.backends.base import EmptyChangeset
-from kallithea.lib.utils2 import safe_unicode
-from kallithea.lib.graphmod import graph_data
+
 
 log = logging.getLogger(__name__)
 
@@ -208,7 +206,7 @@
             h.HasPermissionAny('hg.admin')() or
             h.HasRepoPermissionLevel('admin')(pull_request.org_repo.repo_name) or
             h.HasRepoPermissionLevel('admin')(pull_request.other_repo.repo_name)
-            ) and not pull_request.is_closed():
+        ) and not pull_request.is_closed():
             PullRequestModel().delete(pull_request)
             Session().commit()
             h.flash(_('Successfully deleted pull request %s') % pull_request_id,
--- a/kallithea/controllers/compare.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/compare.py	Sun Jan 05 04:07:51 2020 +0100
@@ -30,20 +30,22 @@
 import logging
 import re
 
-from tg import request, tmpl_context as c
+from tg import request
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
-from webob.exc import HTTPFound, HTTPBadRequest, HTTPNotFound
+from webob.exc import HTTPBadRequest, HTTPFound, HTTPNotFound
 
 from kallithea.config.routing import url
-from kallithea.lib.utils2 import safe_str, safe_int
-from kallithea.lib.vcs.utils.hgcompat import unionrepo
+from kallithea.controllers.changeset import _context_url, _ignorews_url
+from kallithea.lib import diffs
 from kallithea.lib import helpers as h
+from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
 from kallithea.lib.base import BaseRepoController, render
-from kallithea.lib.auth import LoginRequired, HasRepoPermissionLevelDecorator
-from kallithea.lib import diffs
+from kallithea.lib.graphmod import graph_data
+from kallithea.lib.utils2 import safe_int, safe_str
+from kallithea.lib.vcs.utils.hgcompat import unionrepo
 from kallithea.model.db import Repository
-from kallithea.controllers.changeset import _ignorews_url, _context_url
-from kallithea.lib.graphmod import graph_data
+
 
 log = logging.getLogger(__name__)
 
--- a/kallithea/controllers/error.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/error.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,14 +25,15 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
-import os
 import cgi
 import logging
 
-from tg import tmpl_context as c, request, config, expose
+from tg import config, expose, request
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
 
-from kallithea.lib.base import BaseController, render
+from kallithea.lib.base import BaseController
+
 
 log = logging.getLogger(__name__)
 
--- a/kallithea/controllers/feed.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/feed.py	Sun Jan 05 04:07:51 2020 +0100
@@ -28,19 +28,19 @@
 
 import logging
 
-from tg import response, tmpl_context as c
+from beaker.cache import cache_region
+from tg import response
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
-
-from beaker.cache import cache_region, region_invalidate
 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
 
 from kallithea import CONFIG
 from kallithea.lib import helpers as h
-from kallithea.lib.auth import LoginRequired, HasRepoPermissionLevelDecorator
+from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
 from kallithea.lib.base import BaseRepoController
 from kallithea.lib.diffs import DiffProcessor
-from kallithea.model.db import CacheInvalidation
-from kallithea.lib.utils2 import safe_int, str2bool, safe_unicode
+from kallithea.lib.utils2 import safe_int, safe_unicode, str2bool
+
 
 log = logging.getLogger(__name__)
 
@@ -51,7 +51,7 @@
 
 class FeedController(BaseRepoController):
 
-    @LoginRequired(api_access=True, allow_default_user=True)
+    @LoginRequired(allow_default_user=True)
     @HasRepoPermissionLevelDecorator('read')
     def _before(self, *args, **kwargs):
         super(FeedController, self)._before(*args, **kwargs)
@@ -106,7 +106,7 @@
         """Produce an atom-1.0 feed via feedgenerator module"""
 
         @cache_region('long_term', '_get_feed_from_cache')
-        def _get_feed_from_cache(key, kind):
+        def _get_feed_from_cache(*_cache_keys):  # parameters are not really used - only as caching key
             feed = Atom1Feed(
                 title=_('%s %s feed') % (c.site_name, repo_name),
                 link=h.canonical_url('summary_home', repo_name=repo_name),
@@ -129,16 +129,13 @@
             return feed.writeString('utf-8')
 
         kind = 'ATOM'
-        valid = CacheInvalidation.test_and_set_valid(repo_name, kind)
-        if not valid:
-            region_invalidate(_get_feed_from_cache, None, '_get_feed_from_cache', repo_name, kind)
-        return _get_feed_from_cache(repo_name, kind)
+        return _get_feed_from_cache(repo_name, kind, c.db_repo.changeset_cache.get('raw_id'))
 
     def rss(self, repo_name):
         """Produce an rss2 feed via feedgenerator module"""
 
         @cache_region('long_term', '_get_feed_from_cache')
-        def _get_feed_from_cache(key, kind):
+        def _get_feed_from_cache(*_cache_keys):  # parameters are not really used - only as caching key
             feed = Rss201rev2Feed(
                 title=_('%s %s feed') % (c.site_name, repo_name),
                 link=h.canonical_url('summary_home', repo_name=repo_name),
@@ -161,7 +158,4 @@
             return feed.writeString('utf-8')
 
         kind = 'RSS'
-        valid = CacheInvalidation.test_and_set_valid(repo_name, kind)
-        if not valid:
-            region_invalidate(_get_feed_from_cache, None, '_get_feed_from_cache', repo_name, kind)
-        return _get_feed_from_cache(repo_name, kind)
+        return _get_feed_from_cache(repo_name, kind, c.db_repo.changeset_cache.get('raw_id'))
--- a/kallithea/controllers/files.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/files.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,43 +25,36 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+import logging
 import os
 import posixpath
-import logging
-import traceback
+import shutil
 import tempfile
-import shutil
+import traceback
+from collections import OrderedDict
 
-from tg import request, response, tmpl_context as c
+from tg import request, response
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
-from webob.exc import HTTPFound
+from webob.exc import HTTPFound, HTTPNotFound
 
 from kallithea.config.routing import url
-from kallithea.lib.utils import action_logger
+from kallithea.controllers.changeset import _context_url, _ignorews_url, anchor_url, get_ignore_ws, get_line_ctx
 from kallithea.lib import diffs
 from kallithea.lib import helpers as h
-
-from kallithea.lib.compat import OrderedDict
-from kallithea.lib.utils2 import convert_line_endings, detect_mode, safe_str, \
-    str2bool, safe_int
-from kallithea.lib.auth import LoginRequired, HasRepoPermissionLevelDecorator
-from kallithea.lib.base import BaseRepoController, render, jsonify
+from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
+from kallithea.lib.base import BaseRepoController, jsonify, render
+from kallithea.lib.exceptions import NonRelativePathError
+from kallithea.lib.utils import action_logger
+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 RepositoryError, \
-    ChangesetDoesNotExistError, EmptyRepositoryError, \
-    ImproperArchiveTypeError, VCSError, NodeAlreadyExistsError, \
-    NodeDoesNotExistError, ChangesetError, NodeError
+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.repo import RepoModel
 from kallithea.model.scm import ScmModel
-from kallithea.model.db import Repository
-
-from kallithea.controllers.changeset import anchor_url, _ignorews_url, \
-    _context_url, get_line_ctx, get_ignore_ws
-from webob.exc import HTTPNotFound
-from kallithea.lib.exceptions import NonRelativePathError
 
 
 log = logging.getLogger(__name__)
@@ -295,14 +288,6 @@
     @HasRepoPermissionLevelDecorator('write')
     def delete(self, repo_name, revision, f_path):
         repo = c.db_repo
-        if repo.enable_locking and repo.locked[0]:
-            h.flash(_('This repository has been locked by %s on %s')
-                % (h.person_by_id(repo.locked[0]),
-                   h.fmt_date(h.time_to_datetime(repo.locked[1]))),
-                'warning')
-            raise HTTPFound(location=h.url('files_home',
-                                  repo_name=repo_name, revision='tip'))
-
         # check if revision is a branch identifier- basically we cannot
         # create multiple heads via file editing
         _branches = repo.scm_instance.branches
@@ -334,7 +319,9 @@
                     }
                 }
                 self.scm_model.delete_nodes(
-                    user=request.authuser.user_id, repo=c.db_repo,
+                    user=request.authuser.user_id,
+                    ip_addr=request.ip_addr,
+                    repo=c.db_repo,
                     message=message,
                     nodes=nodes,
                     parent_cs=c.cs,
@@ -355,14 +342,6 @@
     @HasRepoPermissionLevelDecorator('write')
     def edit(self, repo_name, revision, f_path):
         repo = c.db_repo
-        if repo.enable_locking and repo.locked[0]:
-            h.flash(_('This repository has been locked by %s on %s')
-                % (h.person_by_id(repo.locked[0]),
-                   h.fmt_date(h.time_to_datetime(repo.locked[1]))),
-                'warning')
-            raise HTTPFound(location=h.url('files_home',
-                                  repo_name=repo_name, revision='tip'))
-
         # check if revision is a branch identifier- basically we cannot
         # create multiple heads via file editing
         _branches = repo.scm_instance.branches
@@ -405,6 +384,7 @@
                 self.scm_model.commit_change(repo=c.db_repo_scm_instance,
                                              repo_name=repo_name, cs=c.cs,
                                              user=request.authuser.user_id,
+                                             ip_addr=request.ip_addr,
                                              author=author, message=message,
                                              content=content, f_path=f_path)
                 h.flash(_('Successfully committed to %s') % f_path,
@@ -422,14 +402,6 @@
     def add(self, repo_name, revision, f_path):
 
         repo = c.db_repo
-        if repo.enable_locking and repo.locked[0]:
-            h.flash(_('This repository has been locked by %s on %s')
-                % (h.person_by_id(repo.locked[0]),
-                   h.fmt_date(h.time_to_datetime(repo.locked[1]))),
-                  'warning')
-            raise HTTPFound(location=h.url('files_home',
-                                  repo_name=repo_name, revision='tip'))
-
         r_post = request.POST
         c.cs = self.__get_cs(revision, silent_empty=True)
         if c.cs is None:
@@ -474,7 +446,9 @@
                     }
                 }
                 self.scm_model.create_nodes(
-                    user=request.authuser.user_id, repo=c.db_repo,
+                    user=request.authuser.user_id,
+                    ip_addr=request.ip_addr,
+                    repo=c.db_repo,
                     message=message,
                     nodes=nodes,
                     parent_cs=c.cs,
--- a/kallithea/controllers/followers.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/followers.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,14 +27,16 @@
 
 import logging
 
-from tg import tmpl_context as c, request
+from tg import request
+from tg import tmpl_context as c
 
-from kallithea.lib.auth import LoginRequired, HasRepoPermissionLevelDecorator
+from kallithea.lib.auth import 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 UserFollowing
 
+
 log = logging.getLogger(__name__)
 
 
--- a/kallithea/controllers/forks.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/forks.py	Sun Jan 05 04:07:51 2020 +0100
@@ -26,26 +26,26 @@
 """
 
 import logging
+import traceback
+
 import formencode
-import traceback
 from formencode import htmlfill
-
-from tg import tmpl_context as c, request
+from tg import request
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
 from webob.exc import HTTPFound
 
 import kallithea.lib.helpers as h
-
 from kallithea.config.routing import url
-from kallithea.lib.auth import LoginRequired, HasRepoPermissionLevelDecorator, \
-    HasRepoPermissionLevel, HasPermissionAnyDecorator, HasPermissionAny
+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, UserFollowing, User, Ui
+from kallithea.model.db import Repository, Ui, User, UserFollowing
+from kallithea.model.forms import RepoForkForm
 from kallithea.model.repo import RepoModel
-from kallithea.model.forms import RepoForkForm
-from kallithea.model.scm import ScmModel, AvailableRepoGroupChoices
+from kallithea.model.scm import AvailableRepoGroupChoices, ScmModel
+
 
 log = logging.getLogger(__name__)
 
@@ -82,7 +82,7 @@
             .filter(UserFollowing.follows_repository == c.repo_info).scalar()
 
         if c.repo_info.stats:
-            last_rev = c.repo_info.stats.stat_on_revision+1
+            last_rev = c.repo_info.stats.stat_on_revision + 1
         else:
             last_rev = 0
         c.stats_revision = last_rev
--- a/kallithea/controllers/home.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/home.py	Sun Jan 05 04:07:51 2020 +0100
@@ -28,20 +28,21 @@
 
 import logging
 
-from tg import tmpl_context as c, request
+from sqlalchemy import or_
+from tg import request
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
 from webob.exc import HTTPBadRequest
-from sqlalchemy.sql.expression import func
-from sqlalchemy import or_, and_
 
+from kallithea.lib import helpers as h
+from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
+from kallithea.lib.base import BaseController, jsonify, render
 from kallithea.lib.utils import conditional_cache
-from kallithea.lib.auth import LoginRequired, HasRepoPermissionLevelDecorator
-from kallithea.lib.base import BaseController, render, jsonify
-from kallithea.lib import helpers as h
-from kallithea.model.db import Repository, RepoGroup, User, UserGroup
+from kallithea.model.db import RepoGroup, Repository, User, UserGroup
 from kallithea.model.repo import RepoModel
 from kallithea.model.scm import UserGroupList
 
+
 log = logging.getLogger(__name__)
 
 
@@ -173,9 +174,9 @@
                     .filter(User.is_default_user == False) \
                     .filter(User.active == True) \
                     .filter(or_(
-                        User.username.ilike("%%"+query+"%%"),
-                        User.name.ilike("%%"+query+"%%"),
-                        User.lastname.ilike("%%"+query+"%%"),
+                        User.username.ilike("%%" + query + "%%"),
+                        User.name.ilike("%%" + query + "%%"),
+                        User.lastname.ilike("%%" + query + "%%"),
                     )) \
                     .order_by(User.username) \
                     .limit(500) \
@@ -198,7 +199,7 @@
                     grp_list = [grp]
             elif query:
                 grp_list = UserGroup.query() \
-                    .filter(UserGroup.users_group_name.ilike("%%"+query+"%%")) \
+                    .filter(UserGroup.users_group_name.ilike("%%" + query + "%%")) \
                     .filter(UserGroup.users_group_active == True) \
                     .order_by(UserGroup.users_group_name) \
                     .limit(500) \
--- a/kallithea/controllers/journal.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/journal.py	Sun Jan 05 04:07:51 2020 +0100
@@ -32,24 +32,23 @@
 
 from sqlalchemy import or_
 from sqlalchemy.orm import joinedload
-from sqlalchemy.sql.expression import func
-
+from tg import request, response
+from tg import tmpl_context as c
+from tg.i18n import ugettext as _
 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
+from webob.exc import HTTPBadRequest
 
-from webob.exc import HTTPBadRequest
-from tg import request, tmpl_context as c, response
-from tg.i18n import ugettext as _
-
+import kallithea.lib.helpers as h
 from kallithea.config.routing import url
 from kallithea.controllers.admin.admin import _journal_filter
-from kallithea.model.db import UserLog, UserFollowing, Repository, User
-from kallithea.model.meta import Session
-from kallithea.model.repo import RepoModel
-import kallithea.lib.helpers as h
 from kallithea.lib.auth import LoginRequired
 from kallithea.lib.base import BaseController, render
 from kallithea.lib.page import Page
-from kallithea.lib.utils2 import safe_int, AttributeDict
+from kallithea.lib.utils2 import AttributeDict, safe_int
+from kallithea.model.db import Repository, User, UserFollowing, UserLog
+from kallithea.model.meta import Session
+from kallithea.model.repo import RepoModel
+
 
 log = logging.getLogger(__name__)
 
@@ -220,7 +219,7 @@
 
         return render('journal/journal.html')
 
-    @LoginRequired(api_access=True)
+    @LoginRequired()
     def journal_atom(self):
         """
         Produce an atom-1.0 feed via feedgenerator module
@@ -231,7 +230,7 @@
             .all()
         return self._atom_feed(following, public=False)
 
-    @LoginRequired(api_access=True)
+    @LoginRequired()
     def journal_rss(self):
         """
         Produce an rss feed via feedgenerator module
@@ -289,7 +288,7 @@
 
         return render('journal/public_journal.html')
 
-    @LoginRequired(api_access=True, allow_default_user=True)
+    @LoginRequired(allow_default_user=True)
     def public_journal_atom(self):
         """
         Produce an atom-1.0 feed via feedgenerator module
@@ -301,7 +300,7 @@
 
         return self._atom_feed(c.following)
 
-    @LoginRequired(api_access=True, allow_default_user=True)
+    @LoginRequired(allow_default_user=True)
     def public_journal_rss(self):
         """
         Produce an rss2 feed via feedgenerator module
--- a/kallithea/controllers/login.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/login.py	Sun Jan 05 04:07:51 2020 +0100
@@ -28,12 +28,13 @@
 
 import logging
 import re
+
 import formencode
-
 from formencode import htmlfill
+from tg import request, session
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
-from tg import request, session, tmpl_context as c
-from webob.exc import HTTPFound, HTTPBadRequest
+from webob.exc import HTTPBadRequest, HTTPFound
 
 import kallithea.lib.helpers as h
 from kallithea.config.routing import url
@@ -41,11 +42,10 @@
 from kallithea.lib.base import BaseController, log_in_user, render
 from kallithea.lib.exceptions import UserCreationError
 from kallithea.lib.utils2 import safe_str
-from kallithea.model.db import User, Setting
-from kallithea.model.forms import \
-    LoginForm, RegisterForm, PasswordResetRequestForm, PasswordResetConfirmationForm
+from kallithea.model.db import Setting, User
+from kallithea.model.forms import LoginForm, PasswordResetConfirmationForm, PasswordResetRequestForm, RegisterForm
+from kallithea.model.meta import Session
 from kallithea.model.user import UserModel
-from kallithea.model.meta import Session
 
 
 log = logging.getLogger(__name__)
@@ -102,13 +102,14 @@
                 # Exception itself
                 h.flash(e, 'error')
             else:
-                log_in_user(user, c.form_result['remember'],
-                    is_external_auth=False)
+                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)
         else:
             # redirect if already logged in
-            if request.authuser.is_authenticated:
+            if not request.authuser.is_anonymous:
                 raise HTTPFound(location=c.came_from)
+            # continue to show login to default user
 
         return render('/login.html')
 
@@ -248,10 +249,10 @@
         log.info('Logging out and deleting session for user')
         raise HTTPFound(location=url('home'))
 
-    def authentication_token(self):
+    def session_csrf_secret_token(self):
         """Return the CSRF protection token for the session - just like it
         could have been screen scraped from a page with a form.
         Only intended for testing but might also be useful for other kinds
         of automation.
         """
-        return h.authentication_token()
+        return h.session_csrf_secret_token()
--- a/kallithea/controllers/pullrequests.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/pullrequests.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,35 +27,32 @@
 
 import logging
 import traceback
+
 import formencode
-
-from tg import request, tmpl_context as c
+from tg import request
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
-from webob.exc import HTTPFound, HTTPNotFound, HTTPForbidden, HTTPBadRequest
+from webob.exc import HTTPBadRequest, HTTPForbidden, HTTPFound, HTTPNotFound
 
 from kallithea.config.routing import url
-from kallithea.lib import helpers as h
+from kallithea.controllers.changeset import _context_url, _ignorews_url, create_cs_pr_comment, delete_cs_pr_comment
 from kallithea.lib import diffs
-from kallithea.lib.auth import LoginRequired, HasRepoPermissionLevelDecorator
-from kallithea.lib.base import BaseRepoController, render, jsonify
+from kallithea.lib import helpers as h
+from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
+from kallithea.lib.base import BaseRepoController, jsonify, render
+from kallithea.lib.graphmod import graph_data
 from kallithea.lib.page import Page
-from kallithea.lib.utils import action_logger
-from kallithea.lib.vcs.exceptions import EmptyRepositoryError, ChangesetDoesNotExistError
+from kallithea.lib.utils2 import safe_int
+from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError, EmptyRepositoryError
 from kallithea.lib.vcs.utils import safe_str
 from kallithea.lib.vcs.utils.hgcompat import unionrepo
-from kallithea.model.db import PullRequest, ChangesetStatus, \
-    PullRequestReviewer, Repository, User
-from kallithea.model.pull_request import CreatePullRequestAction, CreatePullRequestIterationAction, PullRequestModel
-from kallithea.model.meta import Session
-from kallithea.model.repo import RepoModel
+from kallithea.model.changeset_status import ChangesetStatusModel
 from kallithea.model.comment import ChangesetCommentsModel
-from kallithea.model.changeset_status import ChangesetStatusModel
+from kallithea.model.db import ChangesetStatus, PullRequest, PullRequestReviewer, Repository, User
 from kallithea.model.forms import PullRequestForm, PullRequestPostForm
-from kallithea.lib.utils2 import safe_int
-from kallithea.controllers.changeset import _ignorews_url, _context_url, \
-    create_cs_pr_comment, delete_cs_pr_comment
-from kallithea.controllers.compare import CompareController
-from kallithea.lib.graphmod import graph_data
+from kallithea.model.meta import Session
+from kallithea.model.pull_request import CreatePullRequestAction, CreatePullRequestIterationAction, PullRequestModel
+
 
 log = logging.getLogger(__name__)
 
@@ -101,7 +98,8 @@
             peerbranches = set()
             for i in repo._repo.revs(
                 "sort(parents(branch(id(%s)) and merge()) - branch(id(%s)), -rev)",
-                branch_rev, branch_rev):
+                branch_rev, branch_rev
+            ):
                 for abranch in repo.get_changeset(i).branches:
                     if abranch not in peerbranches:
                         n = 'branch:%s:%s' % (abranch, repo.get_changeset(abranch).raw_id)
@@ -532,9 +530,14 @@
                             # Note: org_scm_instance.path must come first so all
                             # valid revision numbers are 100% org_scm compatible
                             # - both for avail_revs and for revset results
-                            hgrepo = unionrepo.unionrepository(org_scm_instance.baseui,
-                                                               org_scm_instance.path,
-                                                               other_scm_instance.path)
+                            try:
+                                hgrepo = unionrepo.makeunionrepository(org_scm_instance.baseui,
+                                                                       org_scm_instance.path,
+                                                                       other_scm_instance.path)
+                            except AttributeError: # makeunionrepository was introduced in Mercurial 4.8 23f2299e9e53
+                                hgrepo = unionrepo.unionrepository(org_scm_instance.baseui,
+                                                                   org_scm_instance.path,
+                                                                   other_scm_instance.path)
                         else:
                             hgrepo = org_scm_instance._repo
                         show = set(hgrepo.revs('::%ld & !::parents(%s) & !::%s',
--- a/kallithea/controllers/root.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/root.py	Sun Jan 05 04:07:51 2020 +0100
@@ -11,11 +11,12 @@
 #
 # 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 tg import config
 from tgext.routes import RoutedController
+
 from kallithea.config.routing import make_map
+from kallithea.controllers.error import ErrorController
 from kallithea.lib.base import BaseController
-from kallithea.controllers.error import ErrorController
-from tg import config
 
 
 # This is the main Kallithea entry point; TurboGears will forward all requests
@@ -27,7 +28,8 @@
 # inheriting from its RoutedController class.
 class RootController(RoutedController, BaseController):
 
-    mapper = make_map(config)
+    def __init__(self):
+        self.mapper = make_map(config)
 
-    # the following assignment hooks in error handling
-    error = ErrorController()
+        # the following assignment hooks in error handling
+        self.error = ErrorController()
--- a/kallithea/controllers/search.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/search.py	Sun Jan 05 04:07:51 2020 +0100
@@ -28,22 +28,23 @@
 import logging
 import traceback
 import urllib
+
+from tg import config, request
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
-from tg import request, config, tmpl_context as c
-
-from whoosh.index import open_dir, exists_in, EmptyIndexError
+from webhelpers2.html.tools import update_params
+from whoosh.index import EmptyIndexError, exists_in, open_dir
 from whoosh.qparser import QueryParser, QueryParserError
 from whoosh.query import Phrase, Prefix
-from webhelpers.util import update_params
 
 from kallithea.lib.auth import LoginRequired
 from kallithea.lib.base import BaseRepoController, render
-from kallithea.lib.indexers import CHGSETS_SCHEMA, SCHEMA, CHGSET_IDX_NAME, \
-    IDX_NAME, WhooshResultWrapper
+from kallithea.lib.indexers import CHGSET_IDX_NAME, CHGSETS_SCHEMA, IDX_NAME, SCHEMA, WhooshResultWrapper
 from kallithea.lib.page import Page
-from kallithea.lib.utils2 import safe_str, safe_int
+from kallithea.lib.utils2 import safe_int, safe_str
 from kallithea.model.repo import RepoModel
 
+
 log = logging.getLogger(__name__)
 
 
@@ -84,7 +85,7 @@
         if c.cur_query:
             p = safe_int(request.GET.get('page'), 1)
             highlight_items = set()
-            index_dir = config['app_conf']['index_dir']
+            index_dir = config['index_dir']
             try:
                 if not exists_in(index_dir, index_name):
                     raise EmptyIndexError
@@ -120,8 +121,7 @@
 
                     def url_generator(**kw):
                         q = urllib.quote(safe_str(c.cur_query))
-                        return update_params("?q=%s&type=%s" \
-                        % (q, safe_str(c.cur_type)), **kw)
+                        return update_params("?q=%s&type=%s" % (q, safe_str(c.cur_type)), **kw)
                     repo_location = RepoModel().repos_path
                     c.formated_results = Page(
                         WhooshResultWrapper(search_type, searcher, matcher,
--- a/kallithea/controllers/summary.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/controllers/summary.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,32 +25,32 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
-import traceback
 import calendar
-import logging
 import itertools
+import logging
+import traceback
+from datetime import date, timedelta
 from time import mktime
-from datetime import timedelta, date
 
-from tg import tmpl_context as c, request
+from beaker.cache import cache_region
+from tg import request
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
 from webob.exc import HTTPBadRequest
 
-from beaker.cache import cache_region, region_invalidate
-
-from kallithea.lib.vcs.exceptions import ChangesetError, EmptyRepositoryError, \
-    NodeDoesNotExistError
-from kallithea.config.conf import ALL_READMES, ALL_EXTS, LANGUAGES_EXTENSIONS_MAP
-from kallithea.model.db import Statistics, CacheInvalidation, User
-from kallithea.lib.utils2 import safe_int, safe_str
-from kallithea.lib.auth import LoginRequired, HasRepoPermissionLevelDecorator
-from kallithea.lib.base import BaseRepoController, render, jsonify
-from kallithea.lib.vcs.backends.base import EmptyChangeset
-from kallithea.lib.markup_renderer import MarkupRenderer
+from kallithea.config.conf import ALL_EXTS, ALL_READMES, LANGUAGES_EXTENSIONS_MAP
+from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
+from kallithea.lib.base import BaseRepoController, jsonify, render
 from kallithea.lib.celerylib.tasks import get_commits_stats
 from kallithea.lib.compat import json
+from kallithea.lib.markup_renderer import MarkupRenderer
+from kallithea.lib.page import RepoPage
+from kallithea.lib.utils2 import safe_int
+from kallithea.lib.vcs.backends.base import EmptyChangeset
+from kallithea.lib.vcs.exceptions import ChangesetError, EmptyRepositoryError, NodeDoesNotExistError
 from kallithea.lib.vcs.nodes import FileNode
-from kallithea.lib.page import RepoPage
+from kallithea.model.db import Statistics
+
 
 log = logging.getLogger(__name__)
 
@@ -66,7 +66,7 @@
         log.debug('Looking for README file')
 
         @cache_region('long_term', '_get_readme_from_cache')
-        def _get_readme_from_cache(key, kind):
+        def _get_readme_from_cache(*_cache_keys):  # parameters are not really used - only as caching key
             readme_data = None
             readme_file = None
             try:
@@ -97,10 +97,7 @@
             return readme_data, readme_file
 
         kind = 'README'
-        valid = CacheInvalidation.test_and_set_valid(repo_name, kind)
-        if not valid:
-            region_invalidate(_get_readme_from_cache, None, '_get_readme_from_cache', repo_name, kind)
-        return _get_readme_from_cache(repo_name, kind)
+        return _get_readme_from_cache(repo_name, kind, c.db_repo.changeset_cache.get('raw_id'))
 
     @LoginRequired(allow_default_user=True)
     @HasRepoPermissionLevelDecorator('read')
@@ -113,23 +110,16 @@
         c.cs_comments = c.db_repo.get_comments(page_revisions)
         c.cs_statuses = c.db_repo.statuses(page_revisions)
 
+        c.ssh_repo_url = None
         if request.authuser.is_default_user:
-            username = ''
+            username = None
         else:
-            username = safe_str(request.authuser.username)
+            username = request.authuser.username
+            if c.ssh_enabled:
+                c.ssh_repo_url = c.db_repo.clone_url(clone_uri_tmpl=c.clone_ssh_tmpl)
 
-        _def_clone_uri = _def_clone_uri_by_id = c.clone_uri_tmpl
-        if '{repo}' in _def_clone_uri_by_id:
-            _def_clone_uri_by_id = _def_clone_uri_by_id.replace('{repo}', '_{repoid}')
-        elif '_{repoid}' in _def_clone_uri:
-            _def_clone_uri = _def_clone_uri.replace('_{repoid}', '{repo}')
-        else:
-            log.error("Configured clone_uri_tmpl %r has no '{repo}' or '_{repoid}' and cannot toggle to use repo id URLs", c.clone_uri_tmpl)
-
-        c.clone_repo_url = c.db_repo.clone_url(user=username,
-                                                uri_tmpl=_def_clone_uri)
-        c.clone_repo_url_id = c.db_repo.clone_url(user=username,
-                                                uri_tmpl=_def_clone_uri_by_id)
+        c.clone_repo_url = c.db_repo.clone_url(clone_uri_tmpl=c.clone_uri_tmpl, with_id=False, username=username)
+        c.clone_repo_url_id = c.db_repo.clone_url(clone_uri_tmpl=c.clone_uri_tmpl, with_id=True, username=username)
 
         if c.db_repo.enable_statistics:
             c.show_stats = True
@@ -146,13 +136,12 @@
             c.no_data = False is c.db_repo.enable_statistics
             lang_stats_d = json.loads(stats.languages)
 
-            lang_stats = ((x, {"count": y,
-                               "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
-                          for x, y in lang_stats_d.items())
+            lang_stats = [(x, {"count": y,
+                               "desc": LANGUAGES_EXTENSIONS_MAP.get(x, '?')})
+                          for x, y in lang_stats_d.items()]
+            lang_stats.sort(key=lambda k: (-k[1]['count'], k[0]))
 
-            c.trending_languages = (
-                sorted(lang_stats, reverse=True, key=lambda k: k[1])[:10]
-            )
+            c.trending_languages = lang_stats[:10]
         else:
             c.no_data = True
             c.trending_languages = []
--- a/kallithea/front-end/kallithea-select2.less	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/front-end/kallithea-select2.less	Sun Jan 05 04:07:51 2020 +0100
@@ -19,6 +19,7 @@
     > .select2-chosen {
       margin-right: inherit; // don't leave room for .select2-arrow
       line-height: inherit;
+      padding: 0;
     }
     > .select2-arrow {
       display: none;
@@ -26,6 +27,12 @@
   }
 }
 
+.select2-chosen,
+.select2-choice > span:first-child,
+.select2-container .select2-choices .select2-search-field input {
+    padding: 0 12px;
+}
+
 // Style these like Bootstrap .dropdown-menu
 .branch-switcher-dropdown.select2-drop.select2-drop-active,
 .repo-switcher-dropdown.select2-drop.select2-drop-active {
@@ -66,3 +73,7 @@
 .select2-container.input-sm input {
   .input-sm;
 }
+
+.form-inline .select2-container.form-control {
+  display: inline-block;
+}
--- a/kallithea/front-end/kallithea-variables.less	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/front-end/kallithea-variables.less	Sun Jan 05 04:07:51 2020 +0100
@@ -41,7 +41,7 @@
 @panel-primary-border:              @panel-primary-heading-bg;
 @headings-font-weight:              700;
 @table-cell-padding:                2px 4px;
-@icon-font-path:                    ; /* no glyphicons */
+@icon-font-path:                    ""; /* no glyphicons */
 @icon-font-name:                    none;
 
 /* custom variables */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/front-end/package-lock.json	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,1063 @@
+{
+  "name": "kallithea",
+  "requires": true,
+  "lockfileVersion": 1,
+  "dependencies": {
+    "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
+    },
+    "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",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      }
+    },
+    "amdefine": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+      "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
+      "dev": true
+    },
+    "ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "requires": {
+        "color-convert": "^1.9.0"
+      }
+    },
+    "array-find-index": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+      "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+      "dev": true
+    },
+    "asap": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+      "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
+      "dev": true
+    },
+    "asn1": {
+      "version": "0.2.4",
+      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+      "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "safer-buffer": "~2.1.0"
+      }
+    },
+    "assert-plus": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+      "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+      "dev": true,
+      "optional": true
+    },
+    "asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+      "dev": true,
+      "optional": true
+    },
+    "at.js": {
+      "version": "1.5.4",
+      "resolved": "https://registry.npmjs.org/at.js/-/at.js-1.5.4.tgz",
+      "integrity": "sha512-G8mgUb/PqShPoH8AyjuxsTGvIr1o716BtQUKDM44C8qN2W615y7KGJ68MlTGamd0J0D/m28emUkzagaHTdrGZw=="
+    },
+    "aws-sign2": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+      "dev": true,
+      "optional": true
+    },
+    "aws4": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
+      "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
+      "dev": true,
+      "optional": true
+    },
+    "balanced-match": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+      "dev": true
+    },
+    "bcrypt-pbkdf": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+      "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "tweetnacl": "^0.14.3"
+      }
+    },
+    "bootstrap": {
+      "version": "3.3.7",
+      "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.3.7.tgz",
+      "integrity": "sha1-WjiTlFSfIzMIdaOxUGVldPip63E="
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "caseless": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+      "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+      "dev": true,
+      "optional": true
+    },
+    "chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      }
+    },
+    "clean-css": {
+      "version": "3.4.28",
+      "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz",
+      "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=",
+      "dev": true,
+      "requires": {
+        "commander": "2.8.x",
+        "source-map": "0.4.x"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.4.4",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+          "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+          "dev": true,
+          "requires": {
+            "amdefine": ">=0.0.4"
+          }
+        }
+      }
+    },
+    "clone": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+      "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
+      "dev": true
+    },
+    "codemirror": {
+      "version": "5.49.0",
+      "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.49.0.tgz",
+      "integrity": "sha512-Hyzr0HToBdZpLBN9dYFO/KlJAsKH37/cXVHPAqa+imml0R92tb9AkmsvjnXL+SluEvjjdfkDgRjc65NG5jnMYA=="
+    },
+    "color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dev": true,
+      "requires": {
+        "color-name": "1.1.3"
+      }
+    },
+    "color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+      "dev": true
+    },
+    "combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "delayed-stream": "~1.0.0"
+      }
+    },
+    "commander": {
+      "version": "2.8.1",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
+      "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
+      "dev": true,
+      "requires": {
+        "graceful-readlink": ">= 1.0.0"
+      }
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+      "dev": true
+    },
+    "core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+      "dev": true,
+      "optional": true
+    },
+    "dashdash": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+      "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "assert-plus": "^1.0.0"
+      }
+    },
+    "datatables.net": {
+      "version": "1.10.20",
+      "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-1.10.20.tgz",
+      "integrity": "sha512-4E4S7tTU607N3h0fZPkGmAtr9mwy462u+VJ6gxYZ8MxcRIjZqHy3Dv1GNry7i3zQCktTdWbULVKBbkAJkuHEnQ==",
+      "requires": {
+        "jquery": ">=1.7"
+      }
+    },
+    "datatables.net-bs": {
+      "version": "1.10.20",
+      "resolved": "https://registry.npmjs.org/datatables.net-bs/-/datatables.net-bs-1.10.20.tgz",
+      "integrity": "sha512-NsMoOOYZ6NlteOpzhltw21lXsNdhjIMbIOxnqmcrb62ntl8eL9pYzk2AeiDXBlIKY4e550ZrExCq3CYKQ9myEg==",
+      "requires": {
+        "datatables.net": "1.10.20",
+        "jquery": ">=1.7"
+      }
+    },
+    "debug": {
+      "version": "3.2.6",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+      "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+      "dev": true,
+      "requires": {
+        "ms": "^2.1.1"
+      }
+    },
+    "debuglog": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz",
+      "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=",
+      "dev": true
+    },
+    "delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+      "dev": true,
+      "optional": true
+    },
+    "dezalgo": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz",
+      "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=",
+      "dev": true,
+      "requires": {
+        "asap": "^2.0.0",
+        "wrappy": "1"
+      }
+    },
+    "ecc-jsbn": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+      "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "jsbn": "~0.1.0",
+        "safer-buffer": "^2.1.0"
+      }
+    },
+    "errno": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+      "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "prr": "~1.0.1"
+      }
+    },
+    "escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+      "dev": true
+    },
+    "extend": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+      "dev": true,
+      "optional": true
+    },
+    "extsprintf": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+      "dev": true,
+      "optional": true
+    },
+    "fast-deep-equal": {
+      "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
+    },
+    "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,
+      "optional": true
+    },
+    "forever-agent": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+      "dev": true,
+      "optional": true
+    },
+    "form-data": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+      "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.6",
+        "mime-types": "^2.1.12"
+      }
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+      "dev": true
+    },
+    "getpass": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+      "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "assert-plus": "^1.0.0"
+      }
+    },
+    "glob": {
+      "version": "7.1.6",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+      "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+      "dev": true,
+      "requires": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      }
+    },
+    "graceful-fs": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
+      "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
+      "dev": true
+    },
+    "graceful-readlink": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
+      "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
+      "dev": true
+    },
+    "har-schema": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+      "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+      "dev": true,
+      "optional": true
+    },
+    "har-validator": {
+      "version": "5.1.3",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
+      "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "ajv": "^6.5.5",
+        "har-schema": "^2.0.0"
+      }
+    },
+    "has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+      "dev": true
+    },
+    "hosted-git-info": {
+      "version": "2.8.5",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz",
+      "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==",
+      "dev": true
+    },
+    "http-signature": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+      "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "assert-plus": "^1.0.0",
+        "jsprim": "^1.2.2",
+        "sshpk": "^1.7.0"
+      }
+    },
+    "image-size": {
+      "version": "0.5.5",
+      "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
+      "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=",
+      "dev": true,
+      "optional": true
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "dev": true,
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true
+    },
+    "is-typedarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+      "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+      "dev": true,
+      "optional": true
+    },
+    "isstream": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+      "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+      "dev": true,
+      "optional": true
+    },
+    "jquery": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
+      "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw=="
+    },
+    "jquery.caret": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/jquery.caret/-/jquery.caret-0.3.1.tgz",
+      "integrity": "sha1-nAkzGPrzJ+/zIugmyp8yQTaLx7g="
+    },
+    "jquery.flot": {
+      "version": "0.8.3",
+      "resolved": "https://registry.npmjs.org/jquery.flot/-/jquery.flot-0.8.3.tgz",
+      "integrity": "sha512-/tEE8J5NjwvStHDaCHkvTJpD7wDS4hE1OEL8xEmhgQfUe0gLUem923PIceNez1mz4yBNx6Hjv7pJcowLNd+nbg=="
+    },
+    "jsbn": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+      "dev": true,
+      "optional": true
+    },
+    "json-parse-better-errors": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+      "dev": true
+    },
+    "json-schema": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+      "dev": true,
+      "optional": true
+    },
+    "json-schema-traverse": {
+      "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
+    },
+    "json-stringify-safe": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+      "dev": true,
+      "optional": true
+    },
+    "jsprim": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+      "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "assert-plus": "1.0.0",
+        "extsprintf": "1.3.0",
+        "json-schema": "0.2.3",
+        "verror": "1.10.0"
+      }
+    },
+    "less": {
+      "version": "3.10.3",
+      "resolved": "https://registry.npmjs.org/less/-/less-3.10.3.tgz",
+      "integrity": "sha512-vz32vqfgmoxF1h3K4J+yKCtajH0PWmjkIFgbs5d78E/c/e+UQTnI+lWK+1eQRE95PXM2mC3rJlLSSP9VQHnaow==",
+      "dev": true,
+      "requires": {
+        "clone": "^2.1.2",
+        "errno": "^0.1.1",
+        "graceful-fs": "^4.1.2",
+        "image-size": "~0.5.0",
+        "mime": "^1.4.1",
+        "mkdirp": "^0.5.0",
+        "promise": "^7.1.1",
+        "request": "^2.83.0",
+        "source-map": "~0.6.0"
+      }
+    },
+    "less-plugin-clean-css": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/less-plugin-clean-css/-/less-plugin-clean-css-1.5.1.tgz",
+      "integrity": "sha1-zFeveqM5iVflbezr5jy2DCNClwM=",
+      "dev": true,
+      "requires": {
+        "clean-css": "^3.0.1"
+      }
+    },
+    "license-checker": {
+      "version": "25.0.1",
+      "resolved": "https://registry.npmjs.org/license-checker/-/license-checker-25.0.1.tgz",
+      "integrity": "sha512-mET5AIwl7MR2IAKYYoVBBpV0OnkKQ1xGj2IMMeEFIs42QAkEVjRtFZGWmQ28WeU7MP779iAgOaOy93Mn44mn6g==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.4.1",
+        "debug": "^3.1.0",
+        "mkdirp": "^0.5.1",
+        "nopt": "^4.0.1",
+        "read-installed": "~4.0.3",
+        "semver": "^5.5.0",
+        "spdx-correct": "^3.0.0",
+        "spdx-expression-parse": "^3.0.0",
+        "spdx-satisfies": "^4.0.0",
+        "treeify": "^1.1.0"
+      }
+    },
+    "mime": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+      "dev": true,
+      "optional": true
+    },
+    "mime-db": {
+      "version": "1.40.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+      "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
+      "dev": true,
+      "optional": true
+    },
+    "mime-types": {
+      "version": "2.1.24",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+      "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "mime-db": "1.40.0"
+      }
+    },
+    "minimatch": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "dev": true,
+      "requires": {
+        "brace-expansion": "^1.1.7"
+      }
+    },
+    "minimist": {
+      "version": "0.0.8",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+      "dev": true
+    },
+    "mkdirp": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+      "dev": true,
+      "requires": {
+        "minimist": "0.0.8"
+      }
+    },
+    "ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "nopt": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
+      "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
+      "dev": true,
+      "requires": {
+        "abbrev": "1",
+        "osenv": "^0.1.4"
+      }
+    },
+    "normalize-package-data": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+      "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+      "dev": true,
+      "requires": {
+        "hosted-git-info": "^2.1.4",
+        "resolve": "^1.10.0",
+        "semver": "2 || 3 || 4 || 5",
+        "validate-npm-package-license": "^3.0.1"
+      }
+    },
+    "oauth-sign": {
+      "version": "0.9.0",
+      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+      "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+      "dev": true,
+      "optional": true
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "dev": true,
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "os-homedir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+      "dev": true
+    },
+    "os-tmpdir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+      "dev": true
+    },
+    "osenv": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+      "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+      "dev": true,
+      "requires": {
+        "os-homedir": "^1.0.0",
+        "os-tmpdir": "^1.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-parse": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+      "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+      "dev": true
+    },
+    "performance-now": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+      "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+      "dev": true,
+      "optional": true
+    },
+    "promise": {
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+      "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "asap": "~2.0.3"
+      }
+    },
+    "prr": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+      "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
+      "dev": true,
+      "optional": true
+    },
+    "psl": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz",
+      "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==",
+      "dev": true,
+      "optional": true
+    },
+    "punycode": {
+      "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
+    },
+    "qs": {
+      "version": "6.5.2",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+      "dev": true,
+      "optional": true
+    },
+    "read-installed": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/read-installed/-/read-installed-4.0.3.tgz",
+      "integrity": "sha1-/5uLZ/GH0eTCm5/rMfayI6zRkGc=",
+      "dev": true,
+      "requires": {
+        "debuglog": "^1.0.1",
+        "graceful-fs": "^4.1.2",
+        "read-package-json": "^2.0.0",
+        "readdir-scoped-modules": "^1.0.0",
+        "semver": "2 || 3 || 4 || 5",
+        "slide": "~1.1.3",
+        "util-extend": "^1.0.1"
+      }
+    },
+    "read-package-json": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.0.tgz",
+      "integrity": "sha512-KLhu8M1ZZNkMcrq1+0UJbR8Dii8KZUqB0Sha4mOx/bknfKI/fyrQVrG/YIt2UOtG667sD8+ee4EXMM91W9dC+A==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.1.1",
+        "graceful-fs": "^4.1.2",
+        "json-parse-better-errors": "^1.0.1",
+        "normalize-package-data": "^2.0.0",
+        "slash": "^1.0.0"
+      }
+    },
+    "readdir-scoped-modules": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz",
+      "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==",
+      "dev": true,
+      "requires": {
+        "debuglog": "^1.0.1",
+        "dezalgo": "^1.0.0",
+        "graceful-fs": "^4.1.2",
+        "once": "^1.3.0"
+      }
+    },
+    "request": {
+      "version": "2.88.0",
+      "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+      "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "aws-sign2": "~0.7.0",
+        "aws4": "^1.8.0",
+        "caseless": "~0.12.0",
+        "combined-stream": "~1.0.6",
+        "extend": "~3.0.2",
+        "forever-agent": "~0.6.1",
+        "form-data": "~2.3.2",
+        "har-validator": "~5.1.0",
+        "http-signature": "~1.2.0",
+        "is-typedarray": "~1.0.0",
+        "isstream": "~0.1.2",
+        "json-stringify-safe": "~5.0.1",
+        "mime-types": "~2.1.19",
+        "oauth-sign": "~0.9.0",
+        "performance-now": "^2.1.0",
+        "qs": "~6.5.2",
+        "safe-buffer": "^5.1.2",
+        "tough-cookie": "~2.4.3",
+        "tunnel-agent": "^0.6.0",
+        "uuid": "^3.3.2"
+      }
+    },
+    "resolve": {
+      "version": "1.12.0",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
+      "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
+      "dev": true,
+      "requires": {
+        "path-parse": "^1.0.6"
+      }
+    },
+    "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
+    },
+    "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
+    },
+    "select2": {
+      "version": "3.5.1",
+      "resolved": "https://registry.npmjs.org/select2/-/select2-3.5.1.tgz",
+      "integrity": "sha1-8oGUibvGX9bTKL5yu+K5XdfofP4="
+    },
+    "select2-bootstrap-css": {
+      "version": "1.4.6",
+      "resolved": "https://registry.npmjs.org/select2-bootstrap-css/-/select2-bootstrap-css-1.4.6.tgz",
+      "integrity": "sha1-XPtoJG9SmcoYWOAe/XiIBMc0mX4="
+    },
+    "semver": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+      "dev": true
+    },
+    "slash": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+      "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+      "dev": true
+    },
+    "slide": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
+      "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=",
+      "dev": true
+    },
+    "source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "dev": true,
+      "optional": true
+    },
+    "spdx-compare": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/spdx-compare/-/spdx-compare-1.0.0.tgz",
+      "integrity": "sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==",
+      "dev": true,
+      "requires": {
+        "array-find-index": "^1.0.2",
+        "spdx-expression-parse": "^3.0.0",
+        "spdx-ranges": "^2.0.0"
+      }
+    },
+    "spdx-correct": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
+      "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
+      "dev": true,
+      "requires": {
+        "spdx-expression-parse": "^3.0.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-exceptions": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+      "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
+      "dev": true
+    },
+    "spdx-expression-parse": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+      "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+      "dev": true,
+      "requires": {
+        "spdx-exceptions": "^2.1.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-license-ids": {
+      "version": "3.0.5",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
+      "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
+      "dev": true
+    },
+    "spdx-ranges": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/spdx-ranges/-/spdx-ranges-2.1.1.tgz",
+      "integrity": "sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA==",
+      "dev": true
+    },
+    "spdx-satisfies": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/spdx-satisfies/-/spdx-satisfies-4.0.1.tgz",
+      "integrity": "sha512-WVzZ/cXAzoNmjCWiEluEA3BjHp5tiUmmhn9MK+X0tBbR9sOqtC6UQwmgCNrAIZvNlMuBUYAaHYfb2oqlF9SwKA==",
+      "dev": true,
+      "requires": {
+        "spdx-compare": "^1.0.0",
+        "spdx-expression-parse": "^3.0.0",
+        "spdx-ranges": "^2.0.0"
+      }
+    },
+    "sshpk": {
+      "version": "1.16.1",
+      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
+      "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "asn1": "~0.2.3",
+        "assert-plus": "^1.0.0",
+        "bcrypt-pbkdf": "^1.0.0",
+        "dashdash": "^1.12.0",
+        "ecc-jsbn": "~0.1.1",
+        "getpass": "^0.1.1",
+        "jsbn": "~0.1.0",
+        "safer-buffer": "^2.0.2",
+        "tweetnacl": "~0.14.0"
+      }
+    },
+    "supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "dev": true,
+      "requires": {
+        "has-flag": "^3.0.0"
+      }
+    },
+    "tough-cookie": {
+      "version": "2.4.3",
+      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+      "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "psl": "^1.1.24",
+        "punycode": "^1.4.1"
+      },
+      "dependencies": {
+        "punycode": {
+          "version": "1.4.1",
+          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+          "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+          "dev": true,
+          "optional": true
+        }
+      }
+    },
+    "treeify": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz",
+      "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==",
+      "dev": true
+    },
+    "tunnel-agent": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "tweetnacl": {
+      "version": "0.14.5",
+      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+      "dev": true,
+      "optional": 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-extend": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz",
+      "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=",
+      "dev": true
+    },
+    "uuid": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
+      "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==",
+      "dev": true,
+      "optional": 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",
+      "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+      "dev": true,
+      "requires": {
+        "spdx-correct": "^3.0.0",
+        "spdx-expression-parse": "^3.0.0"
+      }
+    },
+    "verror": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+      "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "assert-plus": "^1.0.0",
+        "core-util-is": "1.0.2",
+        "extsprintf": "^1.2.0"
+      }
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+      "dev": true
+    }
+  }
+}
--- a/kallithea/front-end/package.json	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/front-end/package.json	Sun Jan 05 04:07:51 2020 +0100
@@ -4,18 +4,18 @@
   "dependencies": {
     "at.js": "1.5.4",
     "bootstrap": "3.3.7",
-    "codemirror": "4.7",
-    "datatables.net": "1.10.13",
-    "datatables.net-bs": "1.10.13",
-    "jquery": "1.12.3",
+    "codemirror": "5.49.0",
+    "datatables.net": "1.10.20",
+    "datatables.net-bs": "1.10.20",
+    "jquery": "3.4.1",
     "jquery.caret": "0.3.1",
     "jquery.flot": "0.8.3",
     "select2": "3.5.1",
-    "select2-bootstrap-css": "1.2.4"
+    "select2-bootstrap-css": "1.4.6"
   },
   "devDependencies": {
-    "less": "~2.7",
-    "less-plugin-clean-css": "~1.5",
-    "license-checker": "24.1.0"
+    "less": "3.10.3",
+    "less-plugin-clean-css": "1.5.1",
+    "license-checker": "25.0.1"
   }
 }
--- a/kallithea/i18n/be/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/be/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,13 +1,11 @@
-# Belarusian translations for Kallithea.
 # Copyright (C) 2016 Various authors, licensing as GPLv3
 # This file is distributed under the same license as the Kallithea project.
-# Automatically generated, 2016.
 # #, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\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/"
@@ -21,14 +19,14 @@
 "X-Generator: Weblate 2.17-dev\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr "Яшчэ не было змен"
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -37,92 +35,92 @@
 msgid "None"
 msgstr "Нічога"
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr "(зачынена)"
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr "Паказваць прабелы"
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr "Ігнараваць прабелы"
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr "Павялічыць кантэкст да %(num)s радкоў"
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 #, fuzzy
 #| msgid "No permission to change pull request status"
 msgid "No permission to change status"
 msgstr "Няма правоў змяняць статус pull-запыту"
 
-#: kallithea/controllers/changeset.py:214
+#: kallithea/controllers/changeset.py:212
 #, python-format
 msgid "Successfully deleted pull request %s"
 msgstr "Pull-запыт %s паспяхова выдалены"
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr "Няма такой рэвізіі ў гэтым рэпазітары"
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, python-format
 msgid "Could not find other repository %s"
 msgstr "Не атрымалася знайсці іншы рэпазітар %s"
 
-#: kallithea/controllers/compare.py:72
+#: kallithea/controllers/compare.py:74
 msgid "Cannot compare repositories of different types"
 msgstr "Немагчыма параўноўваць рэпазітары розных тыпаў"
 
-#: kallithea/controllers/compare.py:244
-msgid "Cannot show empty diff"
-msgstr ""
-
 #: kallithea/controllers/compare.py:246
+msgid "Cannot show empty diff"
+msgstr ""
+
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr ""
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr "Немагчыма параўноўваць рэпазітары без агульнага продка"
 
-#: kallithea/controllers/error.py:70
+#: kallithea/controllers/error.py:71
 msgid "No response"
 msgstr "Няма адказу"
 
-#: kallithea/controllers/error.py:71
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr "Невядомая памылка"
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr "Запыт не распазнаны серверам з-за няправільнага сінтаксісу."
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr "Несанкцыянаваны доступ да рэсурсу"
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr "У вас няма правоў для прагляду гэтай старонкі"
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr "Рэсурс не знойдзены"
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
@@ -145,124 +143,118 @@
 msgid "Changeset was too big and was cut off..."
 msgstr "Змены апынуліся занадта вялікімі і былі скарочаныя..."
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr "Стужка навін %s %s"
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
 msgstr "Змены ў рэпазітары %s"
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr "Націсніце каб дадаць новы файл"
 
-#: kallithea/controllers/files.py:93
+#: kallithea/controllers/files.py:86
 #, fuzzy
 #| msgid "There are no files yet. %s"
 msgid "There are no files yet."
 msgstr "Няма файлаў. %s"
 
-#: kallithea/controllers/files.py:193
+#: kallithea/controllers/files.py:186
 #, python-format
 msgid "%s at %s"
 msgstr "%s (%s)"
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr "Рэпазітар заблакаваў %s у %s"
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 msgid "You can only delete files with revision being a valid branch"
 msgstr "Вы можаце выдаляць файлы толькі ў рэвізіі, злучанай з існай галінай"
 
-#: kallithea/controllers/files.py:322
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr "Файл %s выдалены з дапамогай Kallithea"
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr "Файл %s выдалены"
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr "Падчас каміта адбылася памылка"
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 msgid "You can only edit files with revision being a valid branch"
 msgstr ""
 "Вы можаце рэдагаваць файлы толькі ў рэвізіі, злучанай з існай галінай"
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr "Файл %s адрэдагаваны з дапамогай Kallithea"
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr "Без змен"
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr "Змены захаваныя ў %s"
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr "Файл дададзены з дапамогай Kallithea"
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr "Пуста"
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr "Безназоўны"
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr ""
 "Размяшчэнне павінна быць адносным шляхам, і не можа ўтрымліваць \"..\" у "
 "шляхі"
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr "Магчымасць спампоўваць адключаная"
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr "Невядомая рэвізія %s"
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr "Пусты рэпазітар"
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr "Невядомы тып архіва"
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr "Набор змен"
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
 msgstr "Галіны"
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr "Тэгі"
 
@@ -271,11 +263,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr "Памылка падчас стварэння форка рэпазітара %s"
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr "Групы"
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -283,187 +275,187 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr "Рэпазітары"
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
 msgstr "Галіна"
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr "Зачыненыя галіны"
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr "Тэгі"
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr "Закладкі"
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr "Публічны журнал"
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr "Журнал"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
 msgstr "Няслушная капча"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "Рэгістрацыя ў %s прайшла паспяхова"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:190
 msgid "A password reset confirmation code has been sent"
 msgstr "Код для скідання пароля адпраўлены"
 
-#: kallithea/controllers/login.py:238
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Няслушны код скідання пароля"
 
-#: kallithea/controllers/admin/my_account.py:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Пароль абноўлены"
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr "Няслушны рэцэнзент \"%s\""
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr "%s (зачынена)"
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr "Змены"
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr "Адмысловы"
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr "Галіны ўдзельніка"
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr "Закладкі"
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr "Памылка пры стварэнні pull-запыту: %s"
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr "Адбылася памылка пры стварэнні pull-запыту"
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr "Pull-запыт створаны паспяхова"
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 #, fuzzy
 #| msgid "Pull request update created"
 msgid "New pull request iteration created"
 msgstr "Абнаўленне для pull-запыту створана"
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr "Няма апісання"
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
 msgstr "Pull-запыт абноўлены"
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr "Pull-запыт паспяхова выдалены"
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, fuzzy, python-format
 #| msgid "Changeset for %s %s not found in %s"
 msgid "Revision %s not found in %s"
 msgstr "Набор змен для %s %s не знойдзены ў %s"
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, fuzzy, python-format
 #| msgid "No changesets found for updating this pull request."
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr "Няма змен для абнаўлення гэтага pull-запыту."
 
-#: kallithea/controllers/pullrequests.py:522
+#: kallithea/controllers/pullrequests.py:520
 #, python-format
 msgid "This pull request has already been merged to %s."
 msgstr "Гэты pull-запыт ужо прыняты на галіну %s."
 
-#: kallithea/controllers/pullrequests.py:524
+#: kallithea/controllers/pullrequests.py:522
 msgid "This pull request has been closed and can not be updated."
 msgstr "Гэты pull-запыт быў зачынены і не можа быць абноўлены."
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, fuzzy, python-format
 #| msgid "The following changes are available on %s:"
 msgid "The following additional changes are available on %s:"
 msgstr "Гэтыя змены даступныя на %s:"
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 #, fuzzy
 #| msgid "No changesets found for updating this pull request."
 msgid "No additional changesets found for iterating on this pull request."
 msgstr "Няма змен для абнаўлення гэтага pull-запыту."
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr "Увага: Галіна %s мае яшчэ адну верхавіну: %s."
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 #, fuzzy
 #| msgid "Git pull requests don't support updates yet."
 msgid "Git pull requests don't support iterating yet."
 msgstr "Абнаўленне pull-запытаў git яшчэ не падтрымліваецца."
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, fuzzy, python-format
 #| msgid "No changesets found for updating this pull request."
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
 msgstr "Няма змен для абнаўлення гэтага pull-запыту."
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 
@@ -479,21 +471,21 @@
 msgid "An error occurred during search operation."
 msgstr "Памылка пры выкананні гэтага пошуку."
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr "Няма дадзеных"
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr "Статыстычныя дадзеныя адключаны для гэтага рэпазітара"
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr "Налады аўтарызацыі паспяхова абноўлены"
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr "памылка пры абнаўленні налад аўтарызацыі"
 
@@ -505,125 +497,139 @@
 msgid "Error occurred during update of defaults"
 msgstr "Памылка пры абнаўленні стандартных налад"
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 msgid "Forever"
 msgstr "Назаўжды"
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
 #: kallithea/controllers/admin/users.py:249
 msgid "5 minutes"
 msgstr "5 хвілін"
 
-#: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
 #: kallithea/controllers/admin/users.py:250
 msgid "1 hour"
 msgstr "1 гадзіна"
 
-#: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
 #: kallithea/controllers/admin/users.py:251
 msgid "1 day"
 msgstr "1 дзень"
 
-#: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr "1 месяц"
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr "Тэрмін"
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr "Адбылася памылка падчас стварэння gist-запіса"
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr "Gist-запіс %s выдалены"
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
 msgstr "Без змен"
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr "Gist-запіс абноўлены"
 
-#: kallithea/controllers/admin/gists.py:230
-msgid "Successfully updated gist data"
-msgstr "Gist-запіс абноўлены"
-
 #: kallithea/controllers/admin/gists.py:233
+msgid "Successfully updated gist data"
+msgstr "Gist-запіс абноўлены"
+
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
 msgstr "Памылка пры абнаўленні gist-запісу %s"
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 "Вы не можаце змяніць дадзеныя гэтага карыстальніка, паколькі ён важны для "
 "працы ўсёй праграмы"
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr "Ваш уліковы запіс паспяхова абноўлены"
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr "Памылка пры абнаўленні карыстальніка %s"
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr "Памылка пры абнаўленні пароля"
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr "Карыстальніку дададзены e-mail %s"
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr "Памылка пры захаванні e-mail"
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr "E-mail карыстальніка выдалены"
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr "API-ключ паспяхова створаны"
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr "API-ключ паспяхова скінуты"
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr "API-ключ паспяхова выдалены"
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, fuzzy, python-format
+#| msgid "API key successfully created"
+msgid "SSH key %s successfully added"
+msgstr "API-ключ паспяхова створаны"
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+#, fuzzy
+#| msgid "API key successfully deleted"
+msgid "SSH key successfully deleted"
+msgstr "API-ключ паспяхова выдалены"
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -631,9 +637,9 @@
 msgid "Read"
 msgstr "Чытанне"
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -641,9 +647,9 @@
 msgid "Write"
 msgstr "Запіс"
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -666,254 +672,239 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr "Адміністратар"
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:50
 msgid "Disabled"
 msgstr "Адключана"
 
-#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:80
 msgid "Allowed with manual account activation"
 msgstr "Дазволена, з ручной актывацыяй уліковага запісу"
 
-#: kallithea/controllers/admin/permissions.py:80
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr "Дазволена, з аўтаматычнай актывацыяй уліковага запісу"
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr "Ручная актывацыя вонкавага ўліковага запісу"
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr "Аўтаматычная актывацыя вонкавага ўліковага запісу"
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr "Уключана"
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr "Глабальныя прывілеі паспяхова абноўленыя"
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr "Адбылася памылка падчас абнаўлення прывілеяў"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr "Адбылася памылка пры стварэнні групы рэпазітароў %s"
 
-#: kallithea/controllers/admin/repo_groups.py:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr "Створаная новая група рэпазітароў %s"
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Група рэпазітароў %s абноўленая"
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr "Адбылася памылка пры абнаўленні групы рэпазітароў %s"
 
-#: kallithea/controllers/admin/repo_groups.py:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "Група ўтрымлівае %s рэпазітароў і не можа быць выдаленая"
 
-#: kallithea/controllers/admin/repo_groups.py:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr "Група ўтрымлівае ў сабе %s падгруп і не можа быць выдаленая"
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Група рэпазітароў %s выдаленая"
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr "Памылка пры выдаленні групы рэпазітароў %s"
 
-#: kallithea/controllers/admin/repo_groups.py:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Адміністратар не можа адклікаць свае прывелеі"
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr "Прывілеі групы рэпазітароў абноўленыя"
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr "Памылка пры водгуку прывелея"
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Памылка пры стварэнні рэпазітара %s"
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Рэпазітар %s створаны з %s"
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Зроблены форк рэпазітара %s на %s"
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr "Рэпазітар %s створаны"
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Рэпазітар %s паспяхова абноўлены"
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "Памылка падчас абнаўлення рэпазітара %s"
 
-#: kallithea/controllers/admin/repos.py:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr "Форкі %s адлучаныя"
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr "Выдаленыя форки рэпазітара %s"
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Рэпазітар %s выдалены"
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr "Немагчыма выдаліць %s, ён усё яшчэ мае форкі"
 
-#: kallithea/controllers/admin/repos.py:290
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "Памылка падчас выдалення %s"
 
-#: kallithea/controllers/admin/repos.py:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr "Прывілеі рэпазітара абноўленыя"
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:390
+#: kallithea/controllers/admin/repos.py:391
 #, 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:401
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr "Памылка пры выдаленні поля"
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr "-- Не форк --"
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr "Бачнасць рэпазітара ў публічным часопісе абноўлена"
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 msgid "An error occurred during setting this repository in public journal"
 msgstr "Памылка пры даданні рэпазітара ў агульнадаступны часопіс"
 
-#: kallithea/controllers/admin/repos.py:466
+#: kallithea/controllers/admin/repos.py:468
 msgid "Nothing"
 msgstr "Нічога"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:470
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "Рэпазітар %s адзначаны як форк %s"
 
-#: kallithea/controllers/admin/repos.py:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr "Памылка пры выкананні аперацыі"
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-msgid "Repository has been locked"
-msgstr "Рэпазітар заблакаваны"
-
-#: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-msgid "Repository has been unlocked"
-msgstr "Рэпазітар разблакаваны"
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr "Памылка падчас разблакавання"
-
-#: kallithea/controllers/admin/repos.py:528
+#: kallithea/controllers/admin/repos.py:490
 msgid "Cache invalidation successful"
 msgstr "Кэш скінуты"
 
-#: kallithea/controllers/admin/repos.py:532
+#: kallithea/controllers/admin/repos.py:494
 msgid "An error occurred during cache invalidation"
 msgstr "Памылка пры скіданні кэша"
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr "Занесеныя змены з аддаленага рэпазітара"
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 msgid "An error occurred during pull from remote location"
 msgstr "Памылка пры занясенні змен з аддаленага рэпазітара"
 
-#: kallithea/controllers/admin/repos.py:579
+#: kallithea/controllers/admin/repos.py:541
 msgid "An error occurred during deletion of repository stats"
 msgstr "Адбылася памылка пры выдаленні статыстыкі рэпазітара"
 
-#: kallithea/controllers/admin/settings.py:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr "Абноўлены налады VCS"
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
@@ -921,110 +912,110 @@
 "Немагчыма ўключыць падтрымку hgsubversion. Бібліятэка hgsubversion "
 "адсутнічае"
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
 msgstr "Памылка пры абнаўленні наладаў праграмы"
 
-#: kallithea/controllers/admin/settings.py:180
+#: kallithea/controllers/admin/settings.py:176
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr "Рэпазітары паспяхова перасканаваныя, дададзена: %s, выдалена: %s."
 
-#: kallithea/controllers/admin/settings.py:192
+#: kallithea/controllers/admin/settings.py:188
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr "Скінуць кэш для %s рэпазітароў"
 
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr "Абноўленыя налады праграмы"
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr "Налады візуалізацыі абноўленыя"
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
 msgstr "Адбылася памылка пры абнаўленні наладаў візуалізацыі"
 
-#: kallithea/controllers/admin/settings.py:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr "Калі ласка, увядзіце e-mail-адрас"
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr "Задача адпраўкі e-mail створаная"
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "Няма дадзеных"
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:357
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:363
+#: kallithea/controllers/admin/settings.py:360
 msgid "Added new hook"
 msgstr "Дададзены новы хук"
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr "Абноўленыя хукі"
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr "Памылка пры стварэнні хука"
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr "Запланаванае пераіндэксаванне базы Whoosh"
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr "Створана група карыстальнікаў %s"
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr "Памылка пры стварэнні групы карыстальнікаў %s"
 
-#: kallithea/controllers/admin/user_groups.py:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr "Група карыстальнікаў %s абноўленая"
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr "Памылка пры абнаўленні групы карыстальнікаў %s"
 
-#: kallithea/controllers/admin/user_groups.py:217
+#: kallithea/controllers/admin/user_groups.py:212
 msgid "Successfully deleted user group"
 msgstr "Група карыстальнікаў паспяхова выдаленая"
 
-#: kallithea/controllers/admin/user_groups.py:222
+#: kallithea/controllers/admin/user_groups.py:217
 msgid "An error occurred during deletion of user group"
 msgstr "Памылка пры выдаленні групы карыстальнікаў"
 
-#: kallithea/controllers/admin/user_groups.py:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr "Мэтавая група не можа быць той жа самай"
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr "Прывілеі групы карыстальнікаў абноўленыя"
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr "Абноўленыя прывілеі"
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr "Памылка пры захаванні прывілеяў"
 
@@ -1054,221 +1045,223 @@
 msgid "The default user cannot be edited"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr "Дададзены IP %s у белы спіс карыстальніка"
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr "Адбылася памылка пры захаванні IP"
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr "Выдалены IP %s з белага спісу карыстальніка"
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 "Вы павінны быць зарэгістраваным карыстальнікам, каб выканаць гэта дзеянне"
 
-#: kallithea/lib/auth.py:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr "Старонка даступная толькі аўтарызаваным карыстальнікам"
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr "Няслушны API-ключ"
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr "Рэпазітар не знойдзены на файлавай сістэме"
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, python-format
 msgid "Changeset for %s %s not found in %s"
 msgstr "Набор змен для %s %s не знойдзены ў %s"
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+#, fuzzy
+#| msgid "Your account is disabled"
+msgid "SSH access is disabled."
+msgstr "Ваш акаўнт выключаны"
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr "Двайковы файл"
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 "Набор змены апынуўся занадта вялікімі і быў падрэзаны, выкарыстоўвайце "
 "меню параўнання для паказу выніку параўнання"
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr "Змен не выяўлена"
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "Выдаленая галіна: %s"
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr "Створаны тэг: %s"
 
-#: kallithea/lib/helpers.py:625
+#: kallithea/lib/helpers.py:666
 #, python-format
 msgid "Changeset %s not found"
 msgstr "Набор змен %s не знойдзены"
 
-#: kallithea/lib/helpers.py:674
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "Паказаць адрозненні разам %s->%s"
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 msgid "Compare view"
 msgstr "Параўнанне"
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr "і"
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr "на %s больш"
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "версіі"
 
-#: kallithea/lib/helpers.py:725
+#: kallithea/lib/helpers.py:766
 #, python-format
 msgid "Fork name %s"
 msgstr "Імя форка %s"
 
-#: kallithea/lib/helpers.py:746
+#: kallithea/lib/helpers.py:787
 #, python-format
 msgid "Pull request %s"
 msgstr "Pull-запыт %s"
 
-#: kallithea/lib/helpers.py:756
+#: kallithea/lib/helpers.py:797
 msgid "[deleted] repository"
 msgstr "[выдалены] рэпазітар"
 
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
 msgid "[created] repository"
 msgstr "[створаны] рэпазітар"
 
-#: kallithea/lib/helpers.py:760
+#: kallithea/lib/helpers.py:801
 msgid "[created] repository as fork"
 msgstr "[створаны] рэпазітар як форк"
 
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
 msgid "[forked] repository"
 msgstr "[форкнуты] рэпазітар"
 
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
 msgid "[updated] repository"
 msgstr "[абноўлены] рэпазітар"
 
-#: kallithea/lib/helpers.py:766
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr "[загружаны] архіў з рэпазітара"
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr "[выдалены] рэпазітар"
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr "[створаны] карыстальнік"
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr "[абноўлены] карыстальнік"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr "[створана] група карыстальнікаў"
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr "[абноўлена] група карыстальнікаў"
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr "[каментар] да рэвізіі ў рэпазітары"
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr "[каментар] у pull-запыце для"
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr "[зачынены] pull-запыт для"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr "[адпраўлена] у"
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr "[каміт праз Kallithea] у рэпазітары"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr "[занесены з аддаленага рэпазітара] у рэпазітар"
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr "[занесены] з"
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr "[дададзены ў назіранні] рэпазітар"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr "[выдалены з назірання] рэпазітар"
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr " і на %s больш"
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "Няма файлаў"
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr "новы файл"
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr "зменены"
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr "выдалены"
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr "пераназваны"
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1279,7 +1272,34 @@
 "пераназваны з файлавай сістэмы. Калі ласка, перазапусціце прыкладанне для "
 "сканавання рэпазітароў"
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
@@ -1287,7 +1307,7 @@
 msgstr[1] "%d гады"
 msgstr[2] "%d гадоў"
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
@@ -1295,7 +1315,7 @@
 msgstr[1] "%d месяцы"
 msgstr[2] "%d месяцаў"
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
@@ -1303,7 +1323,7 @@
 msgstr[1] "%d дні"
 msgstr[2] "%d дзён"
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
@@ -1311,7 +1331,7 @@
 msgstr[1] "%d гадзіны"
 msgstr[2] "%d гадзін"
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
@@ -1319,7 +1339,7 @@
 msgstr[1] "%d хвіліны"
 msgstr[2] "%d хвілін"
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
@@ -1327,27 +1347,27 @@
 msgstr[1] "%d секунды"
 msgstr[2] "%d секунд"
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr "у %s"
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr "%s назад"
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr "у %s і %s"
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s і %s назад"
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr "цяпер"
 
@@ -1356,137 +1376,137 @@
 msgid "on line %s"
 msgstr "на радку %s"
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr "[Згадванне]"
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr "верхні ўзровень"
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr "Адміністратар Kallithea"
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1706
+#: kallithea/model/db.py:1640
 #, fuzzy
 msgid "Default user has read access to new repositories"
 msgstr "Несанкцыянаваны доступ да рэсурсу"
 
-#: kallithea/model/db.py:1707
+#: kallithea/model/db.py:1641
 #, fuzzy
 msgid "Default user has write access to new repositories"
 msgstr "Несанкцыянаваны доступ да рэсурсу"
 
-#: kallithea/model/db.py:1708
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1711
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 msgid "Only admins can create repository groups"
 msgstr "Толькі адміністратары могуць ствараць групы репазітароў"
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 msgid "Non-admins can create repository groups"
 msgstr "Неадміністратары могуць ствараць групы репазітароў"
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 msgid "Only admins can create user groups"
 msgstr "Толькі адміністратары могуць ствараць групы карыстальнікаў"
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 msgid "Non-admins can create user groups"
 msgstr "Неадміністратары могуць ствараць групы карыстальнікаў"
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr "Толькі адміністратары могуць ствараць рэпазітары верхняга ўзроўню"
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr "Неадміністратары могуць ствараць рэпазітары верхняга ўзроўню"
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1730
+#: kallithea/model/db.py:1664
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1732
+#: kallithea/model/db.py:1666
 msgid "Only admins can fork repositories"
 msgstr "Месцазнаходжанне рэпазітароў"
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr "Рэгістрацыя адключаная"
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr "Рэгістрацыя карыстальніка з ручной актывацыяй уліковага запісу"
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr "Рэгістрацыя карыстальніка з аўтаматычнай актывацыяй"
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 msgid "Not reviewed"
 msgstr "Не прагледжана"
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 msgid "Under review"
 msgstr "На разглядзе"
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 #, fuzzy
 #| msgid "Approved"
 msgid "Not approved"
 msgstr "Ухвалена"
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr "Ухвалена"
 
@@ -1512,7 +1532,7 @@
 msgid "Name must not contain only digits"
 msgstr "Імя не можа ўтрымліваць толькі лічбы"
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, fuzzy, python-format
 #| msgid "[Comment] %(repo_name)s pull request %(pr_nice_id)s from %(ref)s"
 msgid ""
@@ -1520,72 +1540,72 @@
 "%(branch)s"
 msgstr "[пракаментавана] у запыце на занясенне змен для"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr "Новы карыстальнік \"%(new_username)s\" зарэгістраваны"
 
-#: kallithea/model/notification.py:170
+#: kallithea/model/notification.py:169
 #, 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:171
+#: kallithea/model/notification.py:170
 #, 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:184
+#: kallithea/model/notification.py:183
 msgid "Closing"
 msgstr "Зачынены"
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
 msgstr ""
 "%(user)s просіць вас разгледзець pull request %(pr_nice_id)s: %(pr_title)s"
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 #, fuzzy
 #| msgid "Error creating pull request: %s"
 msgid "Cannot create empty pull request"
 msgstr "Памылка пры стварэнні pull-запыту: %s"
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 #, fuzzy
 #| msgid "Confirm to delete this pull request"
 msgid "You are not authorized to create the pull request"
 msgstr "Пацвердзіце выдаленне гэтага pull-request'а"
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 #, fuzzy
 #| msgid "Missing changesets since the previous pull request:"
 msgid "Missing changesets since the previous iteration:"
 msgstr "Адсутныя рэвізіі адносна папярэдняга pull-запыту:"
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, fuzzy, python-format
 #| msgid "New changesets on %s %s since the previous pull request:"
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr "Новыя рэвізіі на %s %s адносна папярэдняга pull-запыту:"
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, fuzzy, python-format
 msgid ""
 "This iteration is based on another %s revision and there is no simple "
@@ -1593,33 +1613,49 @@
 msgstr ""
 "Гэты pull-запыт заснаваны на іншай рэвізіі %s, просты diff немагчымы."
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, fuzzy, python-format
 #| msgid "No changes found on %s %s since previous version."
 msgid "No changes found on %s %s since previous iteration."
 msgstr "Няма змен на %s %s адносна папярэдняй версіі."
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr "апошняя версія"
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, fuzzy, python-format
+#| msgid "Changeset %s not found"
+msgid "SSH key %r not found"
+msgstr "Набор змен %s не знойдзены"
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr "Рэгістрацыя новага карыстальніка"
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 "Вы не можаце выдаліць карыстальніка, паколькі гэта крытычна для працы "
 "ўсёй праграмы"
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:255
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
@@ -1629,7 +1665,7 @@
 "таму не можа быць выдалены. Змяніце ўладальніка ці выдаліце гэтыя "
 "рэпазітары: %s"
 
-#: kallithea/model/user.py:263
+#: kallithea/model/user.py:260
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
@@ -1639,7 +1675,7 @@
 "і таму не можа быць выдалены. Змяніце ўладальніка ці выдаліце гэтая "
 "групы: %s"
 
-#: kallithea/model/user.py:270
+#: kallithea/model/user.py:267
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
@@ -1649,36 +1685,36 @@
 "карыстальнікаў і таму не можа быць выдалены. Змяніце ўладальніка ці "
 "выдаліце гэтыя групы: %s"
 
-#: kallithea/model/user.py:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr "Спасылка скіду пароля"
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 msgid "Password reset notification"
 msgstr "Паведамленне пра скіданне пароля"
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr "Значэнне не можа быць пустым спісам"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:72
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "Карыстальнік з імем \"%(username)s\" ужо існуе"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:74
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "Імя \"%(username)s\" недапушчальнае"
 
-#: kallithea/model/validators.py:78
+#: kallithea/model/validators.py:76
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
@@ -1687,25 +1723,25 @@
 "падкрэслення, кропкі і працяжнік; а гэтак жа павінна пачынацца з літары, "
 "лічбы або са знака падкрэслення"
 
-#: kallithea/model/validators.py:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr "Імя \"%(username)s\" недапушчальнае"
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr "Няслушнае імя групы карыстальнікаў"
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:132
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr "Група карыстальнікаў \"%(usergroup)s\" ужо існуе"
 
-#: kallithea/model/validators.py:136
+#: kallithea/model/validators.py:134
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
@@ -1714,65 +1750,61 @@
 "падкрэслення, кропкі і працяжнік; а гэтак жа павінна пачынацца з літары "
 "ці лічбы"
 
-#: kallithea/model/validators.py:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr "Немагчыма выкарыстоўваць гэту групу як бацькоўскую"
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:175
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr "Група \"%(group_name)s\" ужо існуе"
 
-#: kallithea/model/validators.py:179
+#: kallithea/model/validators.py:177
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr "Рэпазітар з  імем \"%(group_name)s\" ужо існуе"
 
-#: kallithea/model/validators.py:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr "Недапушчальныя знакі (не ascii) у паролі"
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr "Няслушна зададзены стары пароль"
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr "Паролі не супадаюць"
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 msgid "Invalid username or password"
 msgstr "Няслушнае імя ці пароль"
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr "Несупадзенне токенаў"
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr "Імя рэпазітара %(repo)s забароненае"
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr "Рэпазітар %(repo)s ужо існуе"
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr "Рэпазітар \"%(repo)s\" ужо існуе ў групе \"%(group)s\""
 
-#: kallithea/model/validators.py:333
+#: kallithea/model/validators.py:318
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr "Група рэпазітароў \"%(repo)s\" ужо існуе"
 
-#: kallithea/model/validators.py:419
+#: kallithea/model/validators.py:404
 msgid "Invalid repository URL"
 msgstr "Няслушны URL рэпазітара"
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
@@ -1780,40 +1812,40 @@
 "Няслушны URL рэпазітара. Ён мусіць быць карэктным URL http, https, ssh, "
 "svn+http ці svn+https"
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:430
 msgid "Fork has to be the same type as parent"
 msgstr "Тып форка будзе супадаць з бацькоўскім"
 
-#: kallithea/model/validators.py:460
+#: kallithea/model/validators.py:445
 msgid "You don't have permissions to create repository in this group"
 msgstr "У вас недастаткова правоў для стварэння рэпазітароў у гэтай групе"
 
-#: kallithea/model/validators.py:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
 msgstr "недастаткова правоў для стварэння рэпазітара ў каранёвым каталогу"
 
-#: kallithea/model/validators.py:512
+#: kallithea/model/validators.py:497
 msgid "You don't have permissions to create a group in this location"
 msgstr "У Вас недастаткова прывілеяў для стварэння групы ў гэтым месцы"
 
-#: kallithea/model/validators.py:552
+#: kallithea/model/validators.py:537
 msgid "This username or user group name is not valid"
 msgstr "Дадзенае імя карыстальніка ці групы карыстальнікаў недапушчальна"
 
-#: kallithea/model/validators.py:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr "Гэты шлях хібны"
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 msgid "This email address is already in use"
 msgstr "Гэты e-mail ужо ўжываецца"
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "Email-адрас \"%(email)s\" не знойдзены"
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
@@ -1821,11 +1853,11 @@
 "Для ўваходу па LDAP павінна быць паказана значэнне атрыбута CN - гэта "
 "эквівалент імя карыстальніка"
 
-#: kallithea/model/validators.py:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr "Калі ласка, увядзіце існы IPv4 ці IPv6 адрас"
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
@@ -1833,17 +1865,17 @@
 "Значэнне маскі падсеткі павінна быць у межах ад 0 да 32 (%(bits)r - "
 "няслушна)"
 
-#: kallithea/model/validators.py:765
+#: kallithea/model/validators.py:750
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 "Ключавое імя можа толькі складацца з літар, знака падкрэслення, працяжнік "
 "ці лікаў"
 
-#: kallithea/model/validators.py:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr "Файла няма ў каталогу"
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1885,24 +1917,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr "Апісанне"
 
@@ -1919,7 +1957,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1927,11 +1965,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr "Уладальнік"
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr "Увайсці"
@@ -1946,7 +1984,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1954,7 +1992,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr "Пароль"
@@ -2114,10 +2152,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr "Дзеянне"
@@ -2168,22 +2208,22 @@
 msgstr "Плагін"
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr "Захаваць"
 
@@ -2201,14 +2241,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr "Прыватны рэпазітар"
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2216,36 +2256,25 @@
 msgstr "Прыватныя рэпазітары бачныя толькі іх удзельнікам."
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr "Уключыць статыстыку"
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr "Уключыць акно статыстыкі на старонцы «Агульныя звесткі»."
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr "Уключыць спампоўку"
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr "Уключыць меню спампоўкі на старонцы «Агульныя звесткі»."
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr "Уключыць блакаванне"
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr "Уключыць аўтаблакаванне для рэпазітара."
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2292,8 +2321,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 msgid "Never"
 msgstr "Ніколі"
 
@@ -2326,7 +2357,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr "Стварыць новы gist-запіс"
 
@@ -2362,23 +2393,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2406,7 +2439,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2466,7 +2499,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr "Мой Акаўнт"
 
@@ -2479,25 +2512,32 @@
 msgid "Email Addresses"
 msgstr "E-mail адрэсы"
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
+#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/users/user_edit.html:32
+#, fuzzy
+#| msgid "API Keys"
+msgid "SSH Keys"
+msgstr "API-ключы"
+
+#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
 msgid "API Keys"
 msgstr "API-ключы"
 
-#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/my_account/my_account.html:32
 msgid "Owned Repositories"
 msgstr "Мае рэпазітары"
 
-#: kallithea/templates/admin/my_account/my_account.html:30
+#: kallithea/templates/admin/my_account/my_account.html:33
 #: kallithea/templates/journal/journal.html:33
 #, fuzzy
 msgid "Watched Repositories"
 msgstr "Стварыць рэпазітары"
 
-#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 msgid "Show Permissions"
 msgstr "Паказаць прывілеі"
 
@@ -2524,7 +2564,9 @@
 msgstr "Пацвердзіце выдаленне гэтага API-ключа: %s"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 msgid "Remove"
 msgstr "Выдаліць"
 
@@ -2540,12 +2582,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr "Дадаць"
 
@@ -2647,6 +2691,49 @@
 msgid "Name"
 msgstr "Імя"
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+#, fuzzy
+#| msgid "Last Name"
+msgid "Last Used"
+msgstr "Прозвішча"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, fuzzy, python-format
+#| msgid "Confirm to remove this API key: %s"
+msgid "Confirm to remove this SSH key: %s"
+msgstr "Пацвердзіце выдаленне гэтага API-ключа: %s"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+#, fuzzy
+#| msgid "New API key"
+msgid "New SSH key"
+msgstr "Новы API-ключ"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+#, fuzzy
+#| msgid "Public repository"
+msgid "Public key"
+msgstr "Публічны рэпазітар"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 msgid "Repositories You are Watching"
 msgstr "Рэпазітары, за якімі Вы назіраеце"
@@ -2663,7 +2750,7 @@
 msgstr "Глабальныя"
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr "Белы спіс IP"
 
@@ -2704,7 +2791,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2872,7 +2959,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr "Дадаткова"
 
@@ -2986,19 +3073,11 @@
 "private repositories and other groups if selected."
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-"Уключыць аўтаблакоўку для групы. Гэта опцыя будзе ўжыта да ўсіх даччыных "
-"груп і рэпазітарам"
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
 msgstr "Выдаліць гэту групу"
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Confirm to delete this group"
 msgstr "Пацвердзіце выдаленне гэтай групы карыстальнікаў"
 
@@ -3028,7 +3107,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
@@ -3037,7 +3116,7 @@
 "README."
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr "Апцыянальна абраць групу, у якую змясціць дадзены рэпазітар."
@@ -3047,7 +3126,7 @@
 msgstr "Тып стваранага рэпазітара."
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr "Рэвізія для выгрузкі"
@@ -3099,8 +3178,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr "Статыстыка"
 
@@ -3136,54 +3215,17 @@
 "Усе выконваемыя з гэтым рэпазітаром дзеянні будуць адлюстроўвацца ў "
 "публічным журнал."
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-msgid "Change Locking"
-msgstr "Уключыць блакаванне"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-msgid "Confirm to unlock repository."
-msgstr "Пацвердзіце разблакаванне рэпазітара."
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-msgid "Unlock Repository"
-msgstr "Разблакаваць рэпазітар"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr "Заблакавана %s %s"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-msgid "Confirm to lock repository."
-msgstr "Пацвердзіце блакаванне рэпазітара."
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-msgid "Lock Repository"
-msgstr "Заблакаваць рэпазітар"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr "Рэпазітар не заблакаваны"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
 #: kallithea/templates/data_table/_dt_elements.html:68
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "Пацвердзіце выдаленне гэтага рэпазітара: %s"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
 msgid "Delete this Repository"
 msgstr "Выдаліць гэты рэпазітар"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
@@ -3191,15 +3233,15 @@
 msgstr[1] "Дадзены рэпазітар мае %s копіі"
 msgstr[2] "Дадзены рэпазітар мае %s копій"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr "Адлучыць форкі"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr "Выдаліць форкі"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3298,19 +3340,13 @@
 msgid "This repository does not have a remote repository URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "Permanent Repository ID"
+#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#, fuzzy
+#| msgid "Permanent Repository ID"
+msgid "Permanent URL"
 msgstr "Пастаяннае ШВ рэпазітара"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr "Што гэта?"
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3320,31 +3356,31 @@
 "other cases that you need to hardcode the URL into a 3rd party service."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 msgid "Remote repository"
 msgstr "Аддалены рэпазітар"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 msgid "Repository URL"
 msgstr "URL рэпазітара"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr ""
 "Рэвізія па змоўчанні, з якой будзе рабіцца выгрузка файлаў пры спампоўцы"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr "Змяніць уладальніка рэпазітара."
 
@@ -3453,8 +3489,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 msgid "Save Settings"
 msgstr "Захаваць налады"
 
@@ -3551,10 +3587,6 @@
 msgid "Kallithea version"
 msgstr "Версія Kallithea"
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr "Праверыць наяўнасць абнаўленняў"
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr ""
@@ -3575,15 +3607,7 @@
 msgid "Git path"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr ""
 
@@ -3592,40 +3616,32 @@
 msgstr "Паказваць памер рэпазітара пасля адпраўкі"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
-msgstr "Лагаваць карыстацкія каманды адпраўкі"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr "Лагаваць карыстацкія каманды атрымання"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
 msgid "Update repository after push (hg update)"
 msgstr "Абнаўляць рэпазітар пасля адпраўкі (hg update)"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:33
+#: kallithea/templates/admin/settings/settings_vcs.html:21
 msgid "Mercurial extensions"
 msgstr "Пашырэнні Mercurial"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr "Уключыць падтрымку вялікіх файлаў"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr "Уключыць падтрымку hgsubversion"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:47
+#: kallithea/templates/admin/settings/settings_vcs.html:35
 msgid ""
 "Requires hgsubversion library to be installed. Enables cloning of remote "
 "Subversion repositories while converting them to Mercurial."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:59
+#: kallithea/templates/admin/settings/settings_vcs.html:47
 msgid "Location of repositories"
 msgstr "Месцазнаходжанне рэпазітароў"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
@@ -3633,7 +3649,7 @@
 "Націсніце для разблакавання. Змены набудуць моц пасля перазагрузкі "
 "Kallithea."
 
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3682,8 +3698,9 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-msgid "Clone URL"
+#, fuzzy
+#| msgid "Clone URL"
+msgid "HTTP Clone URL"
 msgstr "URL для кланавання"
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
@@ -3701,16 +3718,33 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+#, fuzzy
+#| msgid "Clone URL"
+msgid "SSH Clone URL"
+msgstr "URL для кланавання"
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 #, fuzzy
 #| msgid "Repository Size"
 msgid "Repository page size"
 msgstr "Памер рэпазітара"
 
-#: kallithea/templates/admin/settings/settings_visual.html:57
+#: kallithea/templates/admin/settings/settings_visual.html:68
 #, fuzzy
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
@@ -3719,43 +3753,43 @@
 "Колькасць элементаў, што паказваюцца на галоўнай старонцы панэлі "
 "кіравання перад паказам нумарацыі старонак."
 
-#: kallithea/templates/admin/settings/settings_visual.html:62
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:70
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr "Абразкі"
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
 msgstr "Паказваць абразкі публічных рэпазітароў"
 
-#: kallithea/templates/admin/settings/settings_visual.html:81
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr "Паказваць абразкі прыватных рэпазітароў"
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 msgid "Show public/private icons next to repository names."
 msgstr "Паказваць абразкі публічных рэпазітароў."
 
-#: kallithea/templates/admin/settings/settings_visual.html:89
+#: kallithea/templates/admin/settings/settings_visual.html:100
 msgid "Meta Tagging"
 msgstr "Метатэгаванне"
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr ""
 
@@ -3916,12 +3950,12 @@
 msgstr "Падтрымка"
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr "Рэпазітар Mercurial"
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr "Git рэпазітар"
 
@@ -3969,157 +4003,132 @@
 msgstr "Параўнаць"
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr "Пошук"
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr "Разблакаваць"
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr "Заблакаваць"
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr "Назіраць"
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr "Не назіраць"
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr "Форк"
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr "Стварыць pull-запыт"
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr "Пераключыцца на"
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr "Супадзенняў не знойдзена"
 
-#: kallithea/templates/base/base.html:296
+#: kallithea/templates/base/base.html:289
 msgid "Show recent activity"
 msgstr "Паказаць апошнюю актыўнасць"
 
-#: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
+#: kallithea/templates/base/base.html:295
+#: kallithea/templates/base/base.html:296
 msgid "Public journal"
 msgstr "Агульнадаступны журнал"
 
-#: kallithea/templates/base/base.html:308
+#: kallithea/templates/base/base.html:301
 msgid "Show public gists"
 msgstr "Паказаць публічныя запісы"
 
-#: kallithea/templates/base/base.html:309
+#: kallithea/templates/base/base.html:302
 msgid "Gists"
 msgstr "Gist"
 
-#: kallithea/templates/base/base.html:313
+#: kallithea/templates/base/base.html:306
 msgid "All Public Gists"
 msgstr "Усе публічныя Gist-запісы"
 
-#: kallithea/templates/base/base.html:315
+#: kallithea/templates/base/base.html:308
 msgid "My Public Gists"
 msgstr "Мае публічныя Gist-запісы"
 
-#: kallithea/templates/base/base.html:316
+#: kallithea/templates/base/base.html:309
 msgid "My Private Gists"
 msgstr "Мае прыватныя Gist-запісы"
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr "Пошук па рэпазітарах"
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 msgid "My Pull Requests"
 msgstr "Мае pull-запыты"
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr "Не аўтарызаваны"
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 msgid "Login to Your Account"
 msgstr "Аўтарызавацца"
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 #, fuzzy
 #| msgid "Forgot password ?"
 msgid "Forgot password?"
 msgstr "Забыліся на пароль?"
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 #, fuzzy
 #| msgid "Don't have an account ?"
 msgid "Don't have an account?"
 msgstr "Няма акаўнта?"
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr "Выйсці"
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-msgid "Inherit defaults"
-msgstr "Ужываць значэнні па змоўчанні"
-
-#: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-#, fuzzy
-#| msgid "Default permissions"
-msgid "default permissions"
-msgstr "Стандартныя прывілеі"
-
-#: kallithea/templates/base/default_perms_box.html:23
 msgid "Create repositories"
 msgstr "Стварыць рэпазітары"
 
-#: kallithea/templates/base/default_perms_box.html:27
+#: kallithea/templates/base/default_perms_box.html:15
 msgid "Select this option to allow repository creation for this user"
 msgstr "Опцыя дазваляе карыстальніку ствараць рэпазітары"
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr "Ствараць групы карыстальнікаў"
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr "Опцыя дазваляе карыстальніку ствараць групы карыстальнікаў"
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr "Ствараць fork ад рэпазітароў"
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 "Абярыце гэту опцыю каб дазволіць дадзенаму карыстальніку ствараць форкі "
@@ -4874,7 +4883,7 @@
 msgstr "Параўнанне файла %s"
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr "%s Файлы"
@@ -4886,7 +4895,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr "Дадаць новы файл"
 
@@ -4938,7 +4947,7 @@
 msgstr "Загружаецца спіс файлаў..."
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr "Памер"
 
@@ -5068,8 +5077,8 @@
 msgstr "%s Назіральнікі"
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr "Назіральнікі"
 
@@ -5122,8 +5131,8 @@
 msgstr "Форкі %s"
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr "Адгалінаванні"
 
@@ -5435,9 +5444,9 @@
 msgid "File names"
 msgstr "Імя файла"
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr "Недастаткова правоў"
 
@@ -5447,20 +5456,20 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr "Atom стужка рэпазітара %s"
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr "RSS стужка рэпазітара %s"
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr "Уключана"
 
@@ -5469,12 +5478,12 @@
 msgstr "Атрыманая статыстыка: "
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr "файлы"
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr "Паказаць яшчэ"
 
@@ -5515,94 +5524,190 @@
 msgid "%s Summary"
 msgstr "%s агульныя звесткі"
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr "Рэпазітар заблакаваны %s"
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr "Рэпазітар разблакаваны"
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr "Форк ад"
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr "Кланаваць з"
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr "Паводле ID"
-
+#: kallithea/templates/summary/summary.html:54
+msgid "Clone URL"
+msgstr "URL для кланавання"
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr "Паводле імя"
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+#, fuzzy
+#| msgid "Last Name"
+msgid "Use Name"
+msgstr "Прозвішча"
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr "Папулярныя файлы"
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr "Спампаваць"
 
-#: kallithea/templates/summary/summary.html:101
-msgid "There are no downloads yet"
-msgstr "Спамповак яшчэ няма"
-
-#: kallithea/templates/summary/summary.html:103
-msgid "Downloads are disabled for this repository"
-msgstr "Спампоўванне адключанае ў гэтым рэпазітары"
-
 #: kallithea/templates/summary/summary.html:109
+msgid "There are no downloads yet"
+msgstr "Спамповак яшчэ няма"
+
+#: kallithea/templates/summary/summary.html:111
+msgid "Downloads are disabled for this repository"
+msgstr "Спампоўванне адключанае ў гэтым рэпазітары"
+
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr "Спампаваць у zip"
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr "Адзначце для спампоўкі архіва з даччынымі рэпазітарамі"
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 msgid "With subrepos"
 msgstr "З даччынымі рэпазітарамі"
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr "Стужка навін"
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 msgid "Latest Changes"
 msgstr "Апошнія змены"
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 msgid "Quick Start"
 msgstr "Хуткі старт"
 
-#: kallithea/templates/summary/summary.html:188
+#: kallithea/templates/summary/summary.html:196
 msgid "Add or upload files directly via Kallithea"
 msgstr "Дадаць ці загрузіць файлы праз Kallithea"
 
-#: kallithea/templates/summary/summary.html:196
+#: kallithea/templates/summary/summary.html:204
 msgid "Push new repository"
 msgstr "Адправіць новы рэпазітар"
 
-#: kallithea/templates/summary/summary.html:204
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr "Існы рэпазітар?"
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr "Спампаваць %s як %s"
 
+#~ msgid "This repository has been locked by %s on %s"
+#~ msgstr "Рэпазітар заблакаваў %s у %s"
+
+#~ msgid "Repository has been locked"
+#~ msgstr "Рэпазітар заблакаваны"
+
+#~ msgid "Repository has been unlocked"
+#~ msgstr "Рэпазітар разблакаваны"
+
+#~ msgid "An error occurred during unlocking"
+#~ msgstr "Памылка падчас разблакавання"
+
+#~ msgid "Invalid API key"
+#~ msgstr "Няслушны API-ключ"
+
+#~ msgid "Token mismatch"
+#~ msgstr "Несупадзенне токенаў"
+
+#~ msgid "Enable locking"
+#~ msgstr "Уключыць блакаванне"
+
+#~ msgid "Enable lock-by-pulling on repository."
+#~ msgstr "Уключыць аўтаблакаванне для рэпазітара."
+
+#~ msgid ""
+#~ "Enable lock-by-pulling on group. This option will be applied to all "
+#~ "other groups and repositories inside"
+#~ msgstr ""
+#~ "Уключыць аўтаблакоўку для групы. Гэта опцыя будзе ўжыта да ўсіх "
+#~ "даччыных груп і рэпазітарам"
+
+#~ msgid "Change Locking"
+#~ msgstr "Уключыць блакаванне"
+
+#~ msgid "Confirm to unlock repository."
+#~ msgstr "Пацвердзіце разблакаванне рэпазітара."
+
+#~ msgid "Unlock Repository"
+#~ msgstr "Разблакаваць рэпазітар"
+
+#~ msgid "Locked by %s on %s"
+#~ msgstr "Заблакавана %s %s"
+
+#~ msgid "Confirm to lock repository."
+#~ msgstr "Пацвердзіце блакаванне рэпазітара."
+
+#~ msgid "Lock Repository"
+#~ msgstr "Заблакаваць рэпазітар"
+
+#~ msgid "Repository is not locked"
+#~ msgstr "Рэпазітар не заблакаваны"
+
+#~ msgid "What is that?"
+#~ msgstr "Што гэта?"
+
+#~ msgid "Check for updates"
+#~ msgstr "Праверыць наяўнасць абнаўленняў"
+
+#~ msgid "Log user push commands"
+#~ msgstr "Лагаваць карыстацкія каманды адпраўкі"
+
+#~ msgid "Log user pull commands"
+#~ msgstr "Лагаваць карыстацкія каманды атрымання"
+
+#~ msgid "Unlock"
+#~ msgstr "Разблакаваць"
+
+#~ msgid "Lock"
+#~ msgstr "Заблакаваць"
+
+#~ msgid "Inherit defaults"
+#~ msgstr "Ужываць значэнні па змоўчанні"
+
+#, fuzzy
+#~| msgid "Default permissions"
+#~ msgid "default permissions"
+#~ msgstr "Стандартныя прывілеі"
+
+#~ msgid "Repository locked by %s"
+#~ msgstr "Рэпазітар заблакаваны %s"
+
+#~ msgid "Repository unlocked"
+#~ msgstr "Рэпазітар разблакаваны"
+
+#~ msgid "Show by ID"
+#~ msgstr "Паводле ID"
+
+#~ msgid "Show by Name"
+#~ msgstr "Паводле імя"
+
 #~ msgid "There is no index to search in. Please run whoosh indexer"
 #~ msgstr "Індэксы адсутнічаюць. Калі ласка, запусціце індэксатар Whoosh"
 
@@ -5853,9 +5958,6 @@
 #~ msgid "invalid user name"
 #~ msgstr "няслушнае імя карыстальніка"
 
-#~ msgid "Your account is disabled"
-#~ msgstr "Ваш акаўнт выключаны"
-
 #~ msgid "invalid clone URL"
 #~ msgstr "няслушны URL для кланавання"
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/i18n/bg/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,5403 @@
+# Translations template for Kallithea.
+# Copyright (C) 2019 Various authors, licensing as GPLv3
+# This file is distributed under the same license as the Kallithea project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2019.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Kallithea 0.4.99\n"
+"Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: bg\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.6.0\n"
+
+#: kallithea/controllers/changelog.py:67
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
+msgid "There are no changesets yet"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:7
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:7
+#: kallithea/templates/base/perms_summary.html:14
+msgid "None"
+msgstr ""
+
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
+msgid "(closed)"
+msgstr ""
+
+#: kallithea/controllers/changeset.py:81
+msgid "Show whitespace"
+msgstr ""
+
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
+#: kallithea/templates/files/diff_2way.html:55
+msgid "Ignore whitespace"
+msgstr ""
+
+#: kallithea/controllers/changeset.py:161
+#, python-format
+msgid "Increase diff context to %(num)s lines"
+msgstr ""
+
+#: kallithea/controllers/changeset.py:201
+msgid "No permission to change status"
+msgstr ""
+
+#: kallithea/controllers/changeset.py:212
+#, python-format
+msgid "Successfully deleted pull request %s"
+msgstr ""
+
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
+msgid "Such revision does not exist for this repository"
+msgstr ""
+
+#: kallithea/controllers/compare.py:68
+#, python-format
+msgid "Could not find other repository %s"
+msgstr ""
+
+#: kallithea/controllers/compare.py:74
+msgid "Cannot compare repositories of different types"
+msgstr ""
+
+#: kallithea/controllers/compare.py:246
+msgid "Cannot show empty diff"
+msgstr ""
+
+#: kallithea/controllers/compare.py:248
+msgid "No ancestor found for merge diff"
+msgstr ""
+
+#: kallithea/controllers/compare.py:252
+msgid "Multiple merge ancestors found for merge compare"
+msgstr ""
+
+#: kallithea/controllers/compare.py:268
+msgid "Cannot compare repositories without using common ancestor"
+msgstr ""
+
+#: kallithea/controllers/error.py:71
+msgid "No response"
+msgstr ""
+
+#: kallithea/controllers/error.py:72
+msgid "Unknown error"
+msgstr ""
+
+#: kallithea/controllers/error.py:85
+msgid ""
+"The request could not be understood by the server due to malformed syntax."
+msgstr ""
+
+#: kallithea/controllers/error.py:88
+msgid "Unauthorized access to resource"
+msgstr ""
+
+#: kallithea/controllers/error.py:90
+msgid "You don't have permission to view this page"
+msgstr ""
+
+#: kallithea/controllers/error.py:92
+msgid "The resource could not be found"
+msgstr ""
+
+#: kallithea/controllers/error.py:94
+msgid ""
+"The server encountered an unexpected condition which prevented it from "
+"fulfilling the request."
+msgstr ""
+
+#: kallithea/controllers/feed.py:63
+#, python-format
+msgid "%s committed on %s"
+msgstr ""
+
+#: kallithea/controllers/feed.py:88
+#: kallithea/templates/changeset/changeset.html:154
+#: kallithea/templates/changeset/changeset.html:173
+#: kallithea/templates/compare/compare_diff.html:81
+#: kallithea/templates/compare/compare_diff.html:95
+#: kallithea/templates/pullrequests/pullrequest_show.html:309
+#: kallithea/templates/pullrequests/pullrequest_show.html:333
+msgid "Changeset was too big and was cut off..."
+msgstr ""
+
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
+#, python-format
+msgid "%s %s feed"
+msgstr ""
+
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
+#, python-format
+msgid "Changes on %s repository"
+msgstr ""
+
+#: kallithea/controllers/files.py:85
+msgid "Click here to add new file"
+msgstr ""
+
+#: kallithea/controllers/files.py:86
+msgid "There are no files yet."
+msgstr ""
+
+#: kallithea/controllers/files.py:186
+#, python-format
+msgid "%s at %s"
+msgstr ""
+
+#: kallithea/controllers/files.py:296
+msgid "You can only delete files with revision being a valid branch"
+msgstr ""
+
+#: kallithea/controllers/files.py:307
+#, python-format
+msgid "Deleted file %s via Kallithea"
+msgstr ""
+
+#: kallithea/controllers/files.py:331
+#, python-format
+msgid "Successfully deleted file %s"
+msgstr ""
+
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
+msgid "Error occurred during commit"
+msgstr ""
+
+#: kallithea/controllers/files.py:350
+msgid "You can only edit files with revision being a valid branch"
+msgstr ""
+
+#: kallithea/controllers/files.py:364
+#, python-format
+msgid "Edited file %s via Kallithea"
+msgstr ""
+
+#: kallithea/controllers/files.py:380
+msgid "No changes"
+msgstr ""
+
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
+#, python-format
+msgid "Successfully committed to %s"
+msgstr ""
+
+#: kallithea/controllers/files.py:409
+msgid "Added file via Kallithea"
+msgstr ""
+
+#: kallithea/controllers/files.py:430
+msgid "No content"
+msgstr ""
+
+#: kallithea/controllers/files.py:434
+msgid "No filename"
+msgstr ""
+
+#: kallithea/controllers/files.py:461
+msgid "Location must be relative path and must not contain .. in path"
+msgstr ""
+
+#: kallithea/controllers/files.py:493
+msgid "Downloads disabled"
+msgstr ""
+
+#: kallithea/controllers/files.py:504
+#, python-format
+msgid "Unknown revision %s"
+msgstr ""
+
+#: kallithea/controllers/files.py:506
+msgid "Empty repository"
+msgstr ""
+
+#: kallithea/controllers/files.py:508
+msgid "Unknown archive type"
+msgstr ""
+
+#: kallithea/controllers/files.py:729
+#: kallithea/templates/changeset/changeset_range.html:9
+#: kallithea/templates/email_templates/pull_request.html:64
+#: kallithea/templates/pullrequests/pullrequest.html:84
+msgid "Changesets"
+msgstr ""
+
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
+msgid "Branches"
+msgstr ""
+
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
+msgid "Tags"
+msgstr ""
+
+#: kallithea/controllers/forks.py:174
+#, python-format
+msgid "An error occurred during repository forking %s"
+msgstr ""
+
+#: kallithea/controllers/home.py:79
+msgid "Groups"
+msgstr ""
+
+#: kallithea/controllers/home.py:89
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
+#: kallithea/templates/admin/repos/repo_add.html:12
+#: kallithea/templates/admin/repos/repo_add.html:16
+#: kallithea/templates/admin/repos/repos.html:9
+#: kallithea/templates/admin/users/user_edit_advanced.html:6
+#: kallithea/templates/base/base.html:56
+#: kallithea/templates/base/base.html:73
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
+msgid "Repositories"
+msgstr ""
+
+#: kallithea/controllers/home.py:122
+#: kallithea/templates/files/files_add.html:32
+#: kallithea/templates/files/files_delete.html:23
+#: kallithea/templates/files/files_edit.html:32
+msgid "Branch"
+msgstr ""
+
+#: kallithea/controllers/home.py:128
+msgid "Closed Branches"
+msgstr ""
+
+#: kallithea/controllers/home.py:134
+msgid "Tag"
+msgstr ""
+
+#: kallithea/controllers/home.py:140
+msgid "Bookmark"
+msgstr ""
+
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
+#: kallithea/templates/journal/public_journal.html:4
+#: kallithea/templates/journal/public_journal.html:18
+msgid "Public Journal"
+msgstr ""
+
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
+#: kallithea/templates/journal/journal.html:5
+#: kallithea/templates/journal/journal.html:13
+msgid "Journal"
+msgstr ""
+
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
+msgid "Bad captcha"
+msgstr ""
+
+#: kallithea/controllers/login.py:146
+#, python-format
+msgid "You have successfully registered with %s"
+msgstr ""
+
+#: kallithea/controllers/login.py:190
+msgid "A password reset confirmation code has been sent"
+msgstr ""
+
+#: kallithea/controllers/login.py:239
+msgid "Invalid password reset token"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
+msgid "Successfully updated password"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:68
+#, python-format
+msgid "Invalid reviewer \"%s\" specified"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:131
+#, python-format
+msgid "%s (closed)"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:158
+#: kallithea/templates/changeset/changeset.html:12
+msgid "Changeset"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:179
+msgid "Special"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:180
+msgid "Peer branches"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
+msgid "Bookmarks"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:318
+#, python-format
+msgid "Error creating pull request: %s"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
+msgid "Error occurred while creating pull request"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:350
+msgid "Successfully opened new pull request"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:373
+msgid "New pull request iteration created"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:401
+#, python-format
+msgid "Meanwhile, the following reviewers have been added: %s"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:405
+#, python-format
+msgid "Meanwhile, the following reviewers have been removed: %s"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
+msgid "No description"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:430
+msgid "Pull request updated"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:443
+msgid "Successfully deleted pull request"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:479
+#, python-format
+msgid "Revision %s not found in %s"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:506
+#, python-format
+msgid "Error: changesets not found when displaying pull request from %s."
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:520
+#, python-format
+msgid "This pull request has already been merged to %s."
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:522
+msgid "This pull request has been closed and can not be updated."
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:546
+#, python-format
+msgid "The following additional changes are available on %s:"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
+msgid "No additional changesets found for iterating on this pull request."
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:560
+#, python-format
+msgid "Note: Branch %s has another head: %s."
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:567
+msgid "Git pull requests don't support iterating yet."
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:569
+#, python-format
+msgid ""
+"Error: some changesets not found when displaying pull request from %s."
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:593
+msgid "The diff can't be shown - the PR revisions could not be found."
+msgstr ""
+
+#: kallithea/controllers/search.py:136
+msgid "Invalid search query. Try quoting it."
+msgstr ""
+
+#: kallithea/controllers/search.py:140
+msgid "The server has no search index."
+msgstr ""
+
+#: kallithea/controllers/search.py:143
+msgid "An error occurred during search operation."
+msgstr ""
+
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
+msgid "No data ready yet"
+msgstr ""
+
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
+msgid "Statistics are disabled for this repository"
+msgstr ""
+
+#: kallithea/controllers/admin/auth_settings.py:137
+msgid "Auth settings updated successfully"
+msgstr ""
+
+#: kallithea/controllers/admin/auth_settings.py:148
+msgid "error occurred during update of auth settings"
+msgstr ""
+
+#: kallithea/controllers/admin/defaults.py:75
+msgid "Default settings updated successfully"
+msgstr ""
+
+#: kallithea/controllers/admin/defaults.py:90
+msgid "Error occurred during update of defaults"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/users.py:248
+msgid "Forever"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/users.py:249
+msgid "5 minutes"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/users.py:250
+msgid "1 hour"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
+#: kallithea/controllers/admin/users.py:251
+msgid "1 day"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/users.py:252
+msgid "1 month"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
+#: kallithea/controllers/admin/users.py:254
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:65
+#: kallithea/templates/admin/users/user_edit_api_keys.html:65
+msgid "Lifetime"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:142
+msgid "Error occurred during gist creation"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:158
+#, python-format
+msgid "Deleted gist %s"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:198
+msgid "Unmodified"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:228
+msgid "Successfully updated gist content"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:233
+msgid "Successfully updated gist data"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:236
+#, python-format
+msgid "Error occurred during update of gist %s"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
+msgid "You can't edit this user since it's crucial for entire application"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:119
+msgid "Your account was updated successfully"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:134
+#: kallithea/controllers/admin/users.py:181
+#, python-format
+msgid "Error occurred during update of user %s"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:168
+msgid "Error occurred during update of user password"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
+#, python-format
+msgid "Added email %s to user"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
+msgid "An error occurred during email saving"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
+msgid "Removed email from user"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:248
+#: kallithea/controllers/admin/users.py:271
+msgid "API key successfully created"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:257
+#: kallithea/controllers/admin/users.py:281
+msgid "API key successfully reset"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:261
+#: kallithea/controllers/admin/users.py:285
+msgid "API key successfully deleted"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, python-format
+msgid "SSH key %s successfully added"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+msgid "SSH key successfully deleted"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:8
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
+#: kallithea/templates/base/perms_summary.html:15
+msgid "Read"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:9
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
+#: kallithea/templates/base/perms_summary.html:16
+msgid "Write"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
+#: kallithea/templates/admin/auth/auth_settings.html:9
+#: kallithea/templates/admin/defaults/defaults.html:9
+#: kallithea/templates/admin/permissions/permissions.html:9
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:9
+#: kallithea/templates/admin/repo_groups/repo_group_edit.html:9
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:47
+#: kallithea/templates/admin/repo_groups/repo_groups.html:9
+#: kallithea/templates/admin/repos/repo_add.html:10
+#: kallithea/templates/admin/repos/repo_add.html:14
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:10
+#: kallithea/templates/admin/settings/settings.html:9
+#: kallithea/templates/admin/user_groups/user_group_add.html:8
+#: kallithea/templates/admin/user_groups/user_group_edit.html:9
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:10
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:47
+#: kallithea/templates/admin/user_groups/user_groups.html:9
+#: kallithea/templates/admin/users/user_add.html:8
+#: kallithea/templates/admin/users/user_edit.html:9
+#: kallithea/templates/admin/users/user_edit_profile.html:81
+#: kallithea/templates/admin/users/users.html:9
+#: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:327
+#: kallithea/templates/base/base.html:328
+#: kallithea/templates/base/perms_summary.html:17
+msgid "Admin"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
+#: kallithea/templates/admin/auth/auth_settings.html:42
+#: kallithea/templates/base/root.html:50
+msgid "Disabled"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:80
+msgid "Allowed with manual account activation"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:82
+msgid "Allowed with automatic account activation"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
+msgid "Manual activation of external account"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
+msgid "Automatic activation of external account"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
+#: kallithea/templates/admin/auth/auth_settings.html:42
+#: kallithea/templates/base/root.html:49
+msgid "Enabled"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:127
+msgid "Global permissions updated successfully"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:142
+msgid "Error occurred during update of permissions"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:172
+#, python-format
+msgid "Error occurred during creation of repository group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:177
+#, python-format
+msgid "Created repository group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:224
+#, python-format
+msgid "Updated repository group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:240
+#, python-format
+msgid "Error occurred during update of repository group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:250
+#, python-format
+msgid "This group contains %s repositories and cannot be deleted"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:257
+#, python-format
+msgid "This group contains %s subgroups and cannot be deleted"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:263
+#, python-format
+msgid "Removed repository group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:268
+#, python-format
+msgid "Error occurred during deletion of repository group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
+msgid "Cannot revoke permission for yourself as admin"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:367
+msgid "Repository group permissions updated"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
+msgid "An error occurred during revoking of permission"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:136
+#, python-format
+msgid "Error creating repository %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:194
+#, python-format
+msgid "Created repository %s from %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:203
+#, python-format
+msgid "Forked repository %s as %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:206
+#, python-format
+msgid "Created repository %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:235
+#, python-format
+msgid "Repository %s updated successfully"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:255
+#, python-format
+msgid "Error occurred during update of repository %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:273
+#, python-format
+msgid "Detached %s forks"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:276
+#, python-format
+msgid "Deleted %s forks"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:281
+#, python-format
+msgid "Deleted repository %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:284
+#, python-format
+msgid "Cannot delete repository %s which still has forks"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:289
+#, python-format
+msgid "An error occurred during deletion of %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:329
+msgid "Repository permissions updated"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:388
+#, python-format
+msgid "Field validation error: %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:391
+#, python-format
+msgid "An error occurred during creation of field: %r"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:402
+msgid "An error occurred during removal of field"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:416
+msgid "-- Not a fork --"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:448
+msgid "Updated repository visibility in public journal"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:452
+msgid "An error occurred during setting this repository in public journal"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:468
+msgid "Nothing"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:470
+#, python-format
+msgid "Marked repository %s as fork of %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:477
+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
+msgid "Pulled from remote location"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:510
+msgid "An error occurred during pull from remote location"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:541
+msgid "An error occurred during deletion of repository stats"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:131
+msgid "Updated VCS settings"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
+msgid ""
+"Unable to activate hgsubversion support. The \"hgsubversion\" library is "
+"missing"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
+msgid "Error occurred while updating application settings"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:176
+#, python-format
+msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:188
+#, python-format
+msgid "Invalidated %s repositories"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:229
+msgid "Updated application settings"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:283
+msgid "Updated visualisation settings"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:288
+msgid "Error occurred during updating visualisation settings"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:312
+msgid "Please enter email address"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:327
+msgid "Send email task created"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:355
+msgid "Hook already exists"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:357
+msgid "Builtin hooks are read-only. Please use another hook name."
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:360
+msgid "Added new hook"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:376
+msgid "Updated hooks"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:380
+msgid "Error occurred during hook creation"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:404
+msgid "Whoosh reindex task scheduled"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:138
+#, python-format
+msgid "Created user group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:151
+#, python-format
+msgid "Error occurred during creation of user group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:179
+#, python-format
+msgid "Updated user group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:201
+#, python-format
+msgid "Error occurred during update of user group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:212
+msgid "Successfully deleted user group"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:217
+msgid "An error occurred during deletion of user group"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:273
+msgid "Target group cannot be the same"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:279
+msgid "User group permissions updated"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
+msgid "Updated permissions"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
+msgid "An error occurred during permissions saving"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:123
+#, python-format
+msgid "Created user %s"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:138
+#, python-format
+msgid "Error occurred during creation of user %s"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:162
+msgid "User updated successfully"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:190
+msgid "Successfully deleted user"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:195
+msgid "An error occurred during deletion of user"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:203
+msgid "The default user cannot be edited"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:409
+#, python-format
+msgid "Added IP address %s to user whitelist"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:415
+msgid "An error occurred while adding IP address"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:427
+msgid "Removed IP address from user whitelist"
+msgstr ""
+
+#: kallithea/lib/auth.py:684
+msgid "You need to be a registered user to perform this action"
+msgstr ""
+
+#: kallithea/lib/auth.py:712
+msgid "You need to be signed in to view this page"
+msgstr ""
+
+#: kallithea/lib/base.py:483
+msgid ""
+"CSRF token leak has been detected - all form tokens have been expired"
+msgstr ""
+
+#: kallithea/lib/base.py:580
+msgid "Repository not found in the filesystem"
+msgstr ""
+
+#: kallithea/lib/base.py:605
+#, python-format
+msgid "Changeset for %s %s not found in %s"
+msgstr ""
+
+#: kallithea/lib/base.py:647
+msgid "SSH access is disabled."
+msgstr ""
+
+#: kallithea/lib/diffs.py:194
+msgid "Binary file"
+msgstr ""
+
+#: kallithea/lib/diffs.py:214
+msgid ""
+"Changeset was too big and was cut off, use diff menu to display this diff"
+msgstr ""
+
+#: kallithea/lib/diffs.py:224
+msgid "No changes detected"
+msgstr ""
+
+#: kallithea/lib/helpers.py:653
+#, python-format
+msgid "Deleted branch: %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:655
+#, python-format
+msgid "Created tag: %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:666
+#, python-format
+msgid "Changeset %s not found"
+msgstr ""
+
+#: kallithea/lib/helpers.py:715
+#, python-format
+msgid "Show all combined changesets %s->%s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:721
+msgid "Compare view"
+msgstr ""
+
+#: kallithea/lib/helpers.py:740
+msgid "and"
+msgstr ""
+
+#: kallithea/lib/helpers.py:741
+#, python-format
+msgid "%s more"
+msgstr ""
+
+#: kallithea/lib/helpers.py:742
+#: kallithea/templates/changelog/changelog.html:43
+msgid "revisions"
+msgstr ""
+
+#: kallithea/lib/helpers.py:766
+#, python-format
+msgid "Fork name %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:787
+#, python-format
+msgid "Pull request %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:797
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
+msgid "[created] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:801
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
+msgid "[updated] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:807
+msgid "[downloaded] archive from repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:809
+msgid "[delete] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:817
+msgid "[created] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:819
+msgid "[updated] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:821
+msgid "[created] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:823
+msgid "[updated] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:825
+msgid "[commented] on revision in repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:827
+msgid "[commented] on pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:829
+msgid "[closed] pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:831
+msgid "[pushed] into"
+msgstr ""
+
+#: kallithea/lib/helpers.py:833
+msgid "[committed via Kallithea] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:835
+msgid "[pulled from remote] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:837
+msgid "[pulled] from"
+msgstr ""
+
+#: kallithea/lib/helpers.py:839
+msgid "[started following] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:841
+msgid "[stopped following] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:961
+#, python-format
+msgid " and %s more"
+msgstr ""
+
+#: kallithea/lib/helpers.py:965
+#: kallithea/templates/compare/compare_diff.html:69
+#: kallithea/templates/pullrequests/pullrequest_show.html:297
+msgid "No files"
+msgstr ""
+
+#: kallithea/lib/helpers.py:990
+msgid "new file"
+msgstr ""
+
+#: kallithea/lib/helpers.py:993
+msgid "mod"
+msgstr ""
+
+#: kallithea/lib/helpers.py:996
+msgid "del"
+msgstr ""
+
+#: kallithea/lib/helpers.py:999
+msgid "rename"
+msgstr ""
+
+#: kallithea/lib/helpers.py:1004
+msgid "chmod"
+msgstr ""
+
+#: kallithea/lib/helpers.py:1297
+#, python-format
+msgid ""
+"%s repository is not mapped to db perhaps it was created or renamed from "
+"the filesystem please run the application again in order to rescan "
+"repositories"
+msgstr ""
+
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
+#, python-format
+msgid "%d year"
+msgid_plural "%d years"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/lib/utils2.py:335
+#, python-format
+msgid "%d month"
+msgid_plural "%d months"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/lib/utils2.py:336
+#, python-format
+msgid "%d day"
+msgid_plural "%d days"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/lib/utils2.py:337
+#, python-format
+msgid "%d hour"
+msgid_plural "%d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/lib/utils2.py:338
+#, python-format
+msgid "%d minute"
+msgid_plural "%d minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/lib/utils2.py:339
+#, python-format
+msgid "%d second"
+msgid_plural "%d seconds"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/lib/utils2.py:355
+#, python-format
+msgid "in %s"
+msgstr ""
+
+#: kallithea/lib/utils2.py:357
+#, python-format
+msgid "%s ago"
+msgstr ""
+
+#: kallithea/lib/utils2.py:359
+#, python-format
+msgid "in %s and %s"
+msgstr ""
+
+#: kallithea/lib/utils2.py:362
+#, python-format
+msgid "%s and %s ago"
+msgstr ""
+
+#: kallithea/lib/utils2.py:365
+msgid "just now"
+msgstr ""
+
+#: kallithea/model/comment.py:68
+#, python-format
+msgid "on line %s"
+msgstr ""
+
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
+msgid "[Mention]"
+msgstr ""
+
+#: kallithea/model/db.py:1496
+msgid "top level"
+msgstr ""
+
+#: kallithea/model/db.py:1637
+msgid "Kallithea Administrator"
+msgstr ""
+
+#: kallithea/model/db.py:1639
+msgid "Default user has no access to new repositories"
+msgstr ""
+
+#: kallithea/model/db.py:1640
+msgid "Default user has read access to new repositories"
+msgstr ""
+
+#: kallithea/model/db.py:1641
+msgid "Default user has write access to new repositories"
+msgstr ""
+
+#: kallithea/model/db.py:1642
+msgid "Default user has admin access to new repositories"
+msgstr ""
+
+#: kallithea/model/db.py:1644
+msgid "Default user has no access to new repository groups"
+msgstr ""
+
+#: kallithea/model/db.py:1645
+msgid "Default user has read access to new repository groups"
+msgstr ""
+
+#: kallithea/model/db.py:1646
+msgid "Default user has write access to new repository groups"
+msgstr ""
+
+#: kallithea/model/db.py:1647
+msgid "Default user has admin access to new repository groups"
+msgstr ""
+
+#: kallithea/model/db.py:1649
+msgid "Default user has no access to new user groups"
+msgstr ""
+
+#: kallithea/model/db.py:1650
+msgid "Default user has read access to new user groups"
+msgstr ""
+
+#: kallithea/model/db.py:1651
+msgid "Default user has write access to new user groups"
+msgstr ""
+
+#: kallithea/model/db.py:1652
+msgid "Default user has admin access to new user groups"
+msgstr ""
+
+#: kallithea/model/db.py:1654
+msgid "Only admins can create repository groups"
+msgstr ""
+
+#: kallithea/model/db.py:1655
+msgid "Non-admins can create repository groups"
+msgstr ""
+
+#: kallithea/model/db.py:1657
+msgid "Only admins can create user groups"
+msgstr ""
+
+#: kallithea/model/db.py:1658
+msgid "Non-admins can create user groups"
+msgstr ""
+
+#: kallithea/model/db.py:1660
+msgid "Only admins can create top level repositories"
+msgstr ""
+
+#: kallithea/model/db.py:1661
+msgid "Non-admins can create top level repositories"
+msgstr ""
+
+#: kallithea/model/db.py:1663
+msgid ""
+"Repository creation enabled with write permission to a repository group"
+msgstr ""
+
+#: kallithea/model/db.py:1664
+msgid ""
+"Repository creation disabled with write permission to a repository group"
+msgstr ""
+
+#: kallithea/model/db.py:1666
+msgid "Only admins can fork repositories"
+msgstr ""
+
+#: kallithea/model/db.py:1667
+msgid "Non-admins can fork repositories"
+msgstr ""
+
+#: kallithea/model/db.py:1669
+msgid "Registration disabled"
+msgstr ""
+
+#: kallithea/model/db.py:1670
+msgid "User registration with manual account activation"
+msgstr ""
+
+#: kallithea/model/db.py:1671
+msgid "User registration with automatic account activation"
+msgstr ""
+
+#: kallithea/model/db.py:2206
+msgid "Not reviewed"
+msgstr ""
+
+#: kallithea/model/db.py:2207
+msgid "Under review"
+msgstr ""
+
+#: kallithea/model/db.py:2208
+msgid "Not approved"
+msgstr ""
+
+#: kallithea/model/db.py:2209
+msgid "Approved"
+msgstr ""
+
+#: kallithea/model/forms.py:58
+msgid "Please enter a login"
+msgstr ""
+
+#: kallithea/model/forms.py:59
+#, python-format
+msgid "Enter a value %(min)i characters long or more"
+msgstr ""
+
+#: kallithea/model/forms.py:67
+msgid "Please enter a password"
+msgstr ""
+
+#: kallithea/model/forms.py:68
+#, python-format
+msgid "Enter %(min)i characters or more"
+msgstr ""
+
+#: kallithea/model/forms.py:170
+msgid "Name must not contain only digits"
+msgstr ""
+
+#: kallithea/model/notification.py:164
+#, python-format
+msgid ""
+"[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
+"%(branch)s"
+msgstr ""
+
+#: kallithea/model/notification.py:167
+#, python-format
+msgid "New user %(new_username)s registered"
+msgstr ""
+
+#: kallithea/model/notification.py:169
+#, 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:170
+#, 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:183
+msgid "Closing"
+msgstr ""
+
+#: kallithea/model/pull_request.py:73
+#, python-format
+msgid ""
+"%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
+msgstr ""
+
+#: kallithea/model/pull_request.py:209
+msgid "Cannot create empty pull request"
+msgstr ""
+
+#: kallithea/model/pull_request.py:217
+#, python-format
+msgid ""
+"Cannot create pull request - criss cross merge detected, please merge a "
+"later %s revision to %s"
+msgstr ""
+
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
+msgid "You are not authorized to create the pull request"
+msgstr ""
+
+#: kallithea/model/pull_request.py:339
+msgid "Missing changesets since the previous iteration:"
+msgstr ""
+
+#: kallithea/model/pull_request.py:346
+#, python-format
+msgid "New changesets on %s %s since the previous iteration:"
+msgstr ""
+
+#: kallithea/model/pull_request.py:353
+msgid "Ancestor didn't change - diff since previous iteration:"
+msgstr ""
+
+#: kallithea/model/pull_request.py:360
+#, python-format
+msgid ""
+"This iteration is based on another %s revision and there is no simple "
+"diff."
+msgstr ""
+
+#: kallithea/model/pull_request.py:362
+#, python-format
+msgid "No changes found on %s %s since previous iteration."
+msgstr ""
+
+#: kallithea/model/pull_request.py:388
+#, python-format
+msgid "Closed, next iteration: %s ."
+msgstr ""
+
+#: kallithea/model/scm.py:668
+msgid "latest tip"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, python-format
+msgid "SSH key %r not found"
+msgstr ""
+
+#: kallithea/model/user.py:186
+msgid "New user registration"
+msgstr ""
+
+#: kallithea/model/user.py:250
+msgid ""
+"You can't remove this user since it is crucial for the entire application"
+msgstr ""
+
+#: kallithea/model/user.py:255
+#, 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:260
+#, 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:267
+#, 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:361
+msgid "Password reset link"
+msgstr ""
+
+#: kallithea/model/user.py:408
+msgid "Password reset notification"
+msgstr ""
+
+#: kallithea/model/user.py:409
+#, 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
+msgid "Value cannot be an empty list"
+msgstr ""
+
+#: kallithea/model/validators.py:72
+#, python-format
+msgid "Username \"%(username)s\" already exists"
+msgstr ""
+
+#: kallithea/model/validators.py:74
+#, python-format
+msgid "Username \"%(username)s\" cannot be used"
+msgstr ""
+
+#: kallithea/model/validators.py:76
+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
+msgid "The input is not valid"
+msgstr ""
+
+#: kallithea/model/validators.py:110
+#, 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
+#, python-format
+msgid "User group \"%(usergroup)s\" already exists"
+msgstr ""
+
+#: kallithea/model/validators.py:134
+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
+#, python-format
+msgid "Group \"%(group_name)s\" already exists"
+msgstr ""
+
+#: kallithea/model/validators.py:177
+#, python-format
+msgid "Repository with name \"%(group_name)s\" already exists"
+msgstr ""
+
+#: kallithea/model/validators.py:233
+msgid "Invalid characters (non-ascii) in password"
+msgstr ""
+
+#: kallithea/model/validators.py:248
+msgid "Invalid old password"
+msgstr ""
+
+#: kallithea/model/validators.py:264
+msgid "Passwords do not match"
+msgstr ""
+
+#: kallithea/model/validators.py:279
+msgid "Invalid username or password"
+msgstr ""
+
+#: kallithea/model/validators.py:313
+#, python-format
+msgid "Repository name %(repo)s is not allowed"
+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
+msgid "Invalid repository URL"
+msgstr ""
+
+#: kallithea/model/validators.py:405
+msgid ""
+"Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
+"svn+https URL"
+msgstr ""
+
+#: kallithea/model/validators.py:430
+msgid "Fork has to be the same type as parent"
+msgstr ""
+
+#: kallithea/model/validators.py:445
+msgid "You don't have permissions to create repository in this group"
+msgstr ""
+
+#: kallithea/model/validators.py:447
+msgid "no permission to create repository in root location"
+msgstr ""
+
+#: kallithea/model/validators.py:497
+msgid "You don't have permissions to create a group in this location"
+msgstr ""
+
+#: kallithea/model/validators.py:537
+msgid "This username or user group name is not valid"
+msgstr ""
+
+#: kallithea/model/validators.py:630
+msgid "This is not a valid path"
+msgstr ""
+
+#: kallithea/model/validators.py:647
+msgid "This email address is already in use"
+msgstr ""
+
+#: kallithea/model/validators.py:667
+#, python-format
+msgid "Email address \"%(email)s\" not found"
+msgstr ""
+
+#: kallithea/model/validators.py:704
+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
+msgid "Please enter a valid IPv4 or IPv6 address"
+msgstr ""
+
+#: kallithea/model/validators.py:717
+#, python-format
+msgid ""
+"The network size (bits) must be within the range of 0-32 (not %(bits)r)"
+msgstr ""
+
+#: kallithea/model/validators.py:750
+msgid "Key name can only consist of letters, underscore, dash or numbers"
+msgstr ""
+
+#: kallithea/model/validators.py:764
+msgid "Filename cannot be inside a directory"
+msgstr ""
+
+#: kallithea/model/validators.py:780
+#, python-format
+msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
+msgstr ""
+
+#: kallithea/templates/about.html:4 kallithea/templates/about.html:13
+msgid "About"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_add.html:5
+#: kallithea/templates/admin/repos/repo_add.html:19
+#: kallithea/templates/admin/repos/repos.html:23
+#: kallithea/templates/index_base.html:25
+#: kallithea/templates/index_base.html:30
+msgid "Add Repository"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:5
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:13
+#: kallithea/templates/admin/repo_groups/repo_groups.html:25
+#: kallithea/templates/index_base.html:27
+#: kallithea/templates/index_base.html:32
+msgid "Add Repository Group"
+msgstr ""
+
+#: kallithea/templates/index_base.html:37
+msgid "You have admin right to this group, and can edit it"
+msgstr ""
+
+#: kallithea/templates/index_base.html:37
+msgid "Edit Repository Group"
+msgstr ""
+
+#: kallithea/templates/admin/admin_log.html:7
+#: kallithea/templates/admin/permissions/permissions_globals.html:14
+#: kallithea/templates/index_base.html:53
+msgid "Repository"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:59
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
+#: kallithea/templates/admin/repo_groups/repo_groups.html:40
+#: kallithea/templates/admin/repos/repo_add_base.html:21
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
+#: kallithea/templates/admin/repos/repos.html:39
+#: kallithea/templates/admin/user_groups/user_group_add.html:33
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
+#: kallithea/templates/admin/user_groups/user_groups.html:39
+#: kallithea/templates/admin/users/user_edit_api_keys.html:59
+#: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
+#: kallithea/templates/pullrequests/pullrequest_show.html:38
+#: kallithea/templates/pullrequests/pullrequest_show.html:59
+#: kallithea/templates/summary/summary.html:87
+msgid "Description"
+msgstr ""
+
+#: kallithea/templates/index_base.html:60
+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
+msgid "Tip"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
+#: kallithea/templates/admin/repo_groups/repo_groups.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
+#: 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/pullrequests/pullrequest_data.html:16
+#: kallithea/templates/pullrequests/pullrequest_show.html:124
+#: kallithea/templates/pullrequests/pullrequest_show.html:219
+#: kallithea/templates/summary/summary.html:132
+msgid "Owner"
+msgstr ""
+
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
+#: kallithea/templates/login.html:19
+msgid "Log In"
+msgstr ""
+
+#: kallithea/templates/login.html:17
+#, python-format
+msgid "Log In to %s"
+msgstr ""
+
+#: kallithea/templates/admin/admin_log.html:5
+#: kallithea/templates/admin/my_account/my_account_profile.html:18
+#: kallithea/templates/admin/users/user_add.html:27
+#: 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/login.html:28 kallithea/templates/register.html:31
+msgid "Username"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:27
+#: kallithea/templates/admin/users/user_add.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
+#: kallithea/templates/register.html:38
+msgid "Password"
+msgstr ""
+
+#: kallithea/templates/login.html:44
+msgid "Stay logged in after browser restart"
+msgstr ""
+
+#: kallithea/templates/login.html:52
+msgid "Forgot your password ?"
+msgstr ""
+
+#: kallithea/templates/login.html:55
+msgid "Don't have an account ?"
+msgstr ""
+
+#: kallithea/templates/login.html:62
+msgid "Sign In"
+msgstr ""
+
+#: kallithea/templates/password_reset.html:5
+msgid "Password Reset"
+msgstr ""
+
+#: kallithea/templates/password_reset.html:21
+#: kallithea/templates/password_reset_confirmation.html:16
+#, python-format
+msgid "Reset Your Password to %s"
+msgstr ""
+
+#: kallithea/templates/password_reset.html:23
+#: kallithea/templates/password_reset_confirmation.html:5
+#: kallithea/templates/password_reset_confirmation.html:18
+msgid "Reset Your Password"
+msgstr ""
+
+#: kallithea/templates/password_reset.html:30
+msgid "Email Address"
+msgstr ""
+
+#: kallithea/templates/password_reset.html:38
+#: kallithea/templates/register.html:74
+msgid "Captcha"
+msgstr ""
+
+#: kallithea/templates/password_reset.html:47
+msgid "Send Password Reset Email"
+msgstr ""
+
+#: kallithea/templates/password_reset.html:52
+msgid ""
+"A password reset link will be sent to the specified email address if it "
+"is registered in the system."
+msgstr ""
+
+#: kallithea/templates/password_reset_confirmation.html:23
+#, python-format
+msgid "You are about to set a new password for the email address %s."
+msgstr ""
+
+#: kallithea/templates/password_reset_confirmation.html:24
+msgid ""
+"Note that you must use the same browser session for this as the one used "
+"to request the password reset."
+msgstr ""
+
+#: kallithea/templates/password_reset_confirmation.html:29
+msgid "Code you received in the email"
+msgstr ""
+
+#: kallithea/templates/password_reset_confirmation.html:36
+msgid "New Password"
+msgstr ""
+
+#: kallithea/templates/password_reset_confirmation.html:43
+msgid "Confirm New Password"
+msgstr ""
+
+#: kallithea/templates/password_reset_confirmation.html:51
+msgid "Confirm"
+msgstr ""
+
+#: kallithea/templates/register.html:5 kallithea/templates/register.html:24
+#: kallithea/templates/register.html:83
+msgid "Sign Up"
+msgstr ""
+
+#: kallithea/templates/register.html:22
+#, python-format
+msgid "Sign Up to %s"
+msgstr ""
+
+#: kallithea/templates/register.html:45
+msgid "Re-enter password"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_profile.html:25
+#: kallithea/templates/admin/users/user_add.html:48
+#: kallithea/templates/admin/users/user_edit_profile.html:60
+#: kallithea/templates/admin/users/users.html:38
+#: kallithea/templates/register.html:52
+msgid "First Name"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_profile.html:32
+#: kallithea/templates/admin/users/user_add.html:55
+#: kallithea/templates/admin/users/user_edit_profile.html:67
+#: kallithea/templates/admin/users/users.html:39
+#: kallithea/templates/register.html:59
+msgid "Last Name"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_profile.html:39
+#: 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/register.html:66
+msgid "Email"
+msgstr ""
+
+#: kallithea/templates/register.html:85
+msgid "Registered accounts are ready to use and need no further action."
+msgstr ""
+
+#: kallithea/templates/register.html:87
+msgid "Please wait for an administrator to activate your account."
+msgstr ""
+
+#: kallithea/templates/admin/admin.html:5
+#: kallithea/templates/admin/admin.html:13
+#: kallithea/templates/base/base.html:55
+msgid "Admin Journal"
+msgstr ""
+
+#: kallithea/templates/admin/admin.html:10
+#: kallithea/templates/journal/journal.html:10
+msgid "journal filter..."
+msgstr ""
+
+#: kallithea/templates/admin/admin.html:12
+#: kallithea/templates/journal/journal.html:12
+msgid "Filter"
+msgstr ""
+
+#: kallithea/templates/admin/admin.html:13
+#: kallithea/templates/journal/journal.html:13
+#, python-format
+msgid "%s Entry"
+msgid_plural "%s Entries"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/admin/admin_log.html:6
+#: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
+#: kallithea/templates/admin/repo_groups/repo_groups.html:43
+#: kallithea/templates/admin/repos/repo_edit_fields.html:9
+#: kallithea/templates/admin/repos/repos.html:44
+#: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
+#: kallithea/templates/admin/users/users.html:45
+msgid "Action"
+msgstr ""
+
+#: kallithea/templates/admin/admin_log.html:8
+msgid "Date"
+msgstr ""
+
+#: kallithea/templates/admin/admin_log.html:9
+msgid "From IP"
+msgstr ""
+
+#: kallithea/templates/admin/admin_log.html:61
+msgid "No actions yet"
+msgstr ""
+
+#: kallithea/templates/admin/auth/auth_settings.html:5
+msgid "Authentication Settings"
+msgstr ""
+
+#: kallithea/templates/admin/auth/auth_settings.html:11
+#: kallithea/templates/base/base.html:61
+msgid "Authentication"
+msgstr ""
+
+#: kallithea/templates/admin/auth/auth_settings.html:27
+msgid "Authentication Plugins"
+msgstr ""
+
+#: kallithea/templates/admin/auth/auth_settings.html:29
+msgid "Enabled Plugins"
+msgstr ""
+
+#: kallithea/templates/admin/auth/auth_settings.html:32
+msgid ""
+"Comma-separated list of plugins; Kallithea will try user authentication "
+"in plugin order"
+msgstr ""
+
+#: kallithea/templates/admin/auth/auth_settings.html:36
+msgid "Available built-in plugins"
+msgstr ""
+
+#: kallithea/templates/admin/auth/auth_settings.html:53
+msgid "Plugin"
+msgstr ""
+
+#: kallithea/templates/admin/auth/auth_settings.html:101
+#: kallithea/templates/admin/defaults/defaults.html:59
+#: kallithea/templates/admin/my_account/my_account_password.html:30
+#: kallithea/templates/admin/my_account/my_account_profile.html:47
+#: kallithea/templates/admin/permissions/permissions_globals.html:95
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:58
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:84
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
+#: kallithea/templates/admin/settings/settings_hooks.html:46
+#: kallithea/templates/admin/user_groups/user_group_add.html:48
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
+#: kallithea/templates/admin/users/user_add.html:80
+#: kallithea/templates/admin/users/user_edit_profile.html:89
+#: kallithea/templates/base/default_perms_box.html:42
+msgid "Save"
+msgstr ""
+
+#: kallithea/templates/admin/defaults/defaults.html:5
+#: kallithea/templates/admin/defaults/defaults.html:11
+#: kallithea/templates/base/base.html:62
+msgid "Repository Defaults"
+msgstr ""
+
+#: kallithea/templates/admin/defaults/defaults.html:27
+#: kallithea/templates/admin/repos/repo_add_base.html:42
+#: kallithea/templates/admin/repos/repo_edit_fields.html:8
+msgid "Type"
+msgstr ""
+
+#: kallithea/templates/admin/defaults/defaults.html:34
+#: kallithea/templates/admin/repos/repo_add_base.html:56
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
+#: kallithea/templates/data_table/_dt_elements.html:21
+msgid "Private repository"
+msgstr ""
+
+#: kallithea/templates/admin/defaults/defaults.html:37
+#: kallithea/templates/admin/repos/repo_add_base.html:59
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
+#: kallithea/templates/forks/fork.html:61
+msgid ""
+"Private repositories are only visible to people explicitly added as "
+"collaborators."
+msgstr ""
+
+#: kallithea/templates/admin/defaults/defaults.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
+msgid "Enable statistics"
+msgstr ""
+
+#: kallithea/templates/admin/defaults/defaults.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
+msgid "Enable statistics window on summary page."
+msgstr ""
+
+#: kallithea/templates/admin/defaults/defaults.html:50
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
+msgid "Enable downloads"
+msgstr ""
+
+#: kallithea/templates/admin/defaults/defaults.html:53
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
+msgid "Enable download menu on summary page."
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:5
+#: kallithea/templates/admin/gists/edit.html:18
+msgid "Edit Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:35
+#, python-format
+msgid ""
+"Gist was updated since you started editing. Copy your changes and click "
+"%(here)s to reload new version."
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:36
+msgid "here"
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:51
+#: kallithea/templates/admin/gists/new.html:35
+msgid "Gist description ..."
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:54
+#: kallithea/templates/admin/gists/new.html:38
+msgid "Gist lifetime"
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:59
+#: kallithea/templates/admin/gists/edit.html:61
+#: kallithea/templates/admin/gists/index.html:54
+#: kallithea/templates/admin/gists/index.html:56
+#: kallithea/templates/admin/gists/show.html:45
+#: kallithea/templates/admin/gists/show.html:47
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:7
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:31
+#: kallithea/templates/admin/users/user_edit_api_keys.html:7
+#: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_api_keys.html:31
+msgid "Expires"
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:59
+#: kallithea/templates/admin/gists/index.html:54
+#: kallithea/templates/admin/gists/show.html:45
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:7
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
+#: kallithea/templates/admin/users/user_edit_api_keys.html:7
+#: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
+msgid "Never"
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:145
+msgid "Update Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:146
+#: kallithea/templates/base/root.html:27
+#: kallithea/templates/changeset/changeset_file_comment.html:130
+msgid "Cancel"
+msgstr ""
+
+#: kallithea/templates/admin/gists/index.html:6
+#: kallithea/templates/admin/gists/index.html:16
+#, python-format
+msgid "Private Gists for User %s"
+msgstr ""
+
+#: kallithea/templates/admin/gists/index.html:8
+#: kallithea/templates/admin/gists/index.html:18
+#, python-format
+msgid "Public Gists for User %s"
+msgstr ""
+
+#: kallithea/templates/admin/gists/index.html:10
+#: kallithea/templates/admin/gists/index.html:20
+msgid "Public Gists"
+msgstr ""
+
+#: kallithea/templates/admin/gists/index.html:37
+#: kallithea/templates/admin/gists/show.html:25
+#: kallithea/templates/base/base.html:305
+msgid "Create New Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/index.html:51
+#: kallithea/templates/data_table/_dt_elements.html:78
+msgid "Created"
+msgstr ""
+
+#: kallithea/templates/admin/gists/index.html:66
+msgid "There are no gists yet"
+msgstr ""
+
+#: kallithea/templates/admin/gists/new.html:5
+#: kallithea/templates/admin/gists/new.html:18
+msgid "New Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/new.html:45
+msgid "Name this gist ..."
+msgstr ""
+
+#: kallithea/templates/admin/gists/new.html:53
+msgid "Create Private Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/new.html:54
+msgid "Create Public Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/new.html:55
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:14
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:73
+#: kallithea/templates/admin/my_account/my_account_emails.html:47
+#: kallithea/templates/admin/my_account/my_account_password.html:31
+#: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
+#: kallithea/templates/admin/permissions/permissions_globals.html:96
+#: kallithea/templates/admin/permissions/permissions_ips.html:34
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
+#: kallithea/templates/admin/repos/repo_edit_fields.html:54
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:85
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
+#: kallithea/templates/admin/settings/settings_global.html:50
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
+#: kallithea/templates/admin/users/user_edit_api_keys.html:14
+#: kallithea/templates/admin/users/user_edit_api_keys.html:73
+#: kallithea/templates/admin/users/user_edit_emails.html:47
+#: kallithea/templates/admin/users/user_edit_ips.html:45
+#: kallithea/templates/admin/users/user_edit_profile.html:90
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/files/files_add.html:69
+#: kallithea/templates/files/files_delete.html:41
+#: kallithea/templates/files/files_edit.html:72
+#: kallithea/templates/pullrequests/pullrequest.html:78
+msgid "Reset"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:5
+#: kallithea/templates/admin/gists/show.html:9
+msgid "Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:10
+msgid "URL"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:35
+msgid "Public Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:37
+msgid "Private Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:54
+#: kallithea/templates/admin/my_account/my_account_emails.html:23
+#: kallithea/templates/admin/permissions/permissions_ips.html:11
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
+#: kallithea/templates/admin/repos/repo_edit_fields.html:19
+#: kallithea/templates/admin/settings/settings_hooks.html:30
+#: kallithea/templates/admin/users/user_edit_emails.html:23
+#: 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/files/files_source.html:35
+#: kallithea/templates/files/files_source.html:38
+#: kallithea/templates/files/files_source.html:41
+#: kallithea/templates/pullrequests/pullrequest_data.html:20
+msgid "Delete"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:54
+msgid "Confirm to delete this Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:61
+#: 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/files/diff_2way.html:56
+#: kallithea/templates/files/files_source.html:37
+#: kallithea/templates/files/files_source.html:40
+#: kallithea/templates/pullrequests/pullrequest_show.html:41
+msgid "Edit"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:63
+#: kallithea/templates/files/files_edit.html:52
+#: kallithea/templates/files/files_source.html:30
+msgid "Show as Raw"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:69
+msgid "created"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:82
+msgid "Show as raw"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:5
+#: kallithea/templates/admin/my_account/my_account.html:9
+#: kallithea/templates/base/base.html:390
+msgid "My Account"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:25
+#: kallithea/templates/admin/users/user_edit.html:29
+msgid "Profile"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:26
+msgid "Email Addresses"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/users/user_edit.html:32
+msgid "SSH Keys"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
+msgid "API Keys"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:32
+msgid "Owned Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:33
+#: kallithea/templates/journal/journal.html:33
+msgid "Watched Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:34
+#: kallithea/templates/admin/permissions/permissions.html:30
+#: kallithea/templates/admin/user_groups/user_group_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:37
+msgid "Show Permissions"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:5
+#: kallithea/templates/admin/users/user_edit_api_keys.html:5
+msgid "Built-in"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:13
+#: kallithea/templates/admin/users/user_edit_api_keys.html:13
+#, python-format
+msgid "Confirm to reset this API key: %s"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:29
+#: kallithea/templates/admin/users/user_edit_api_keys.html:29
+msgid "Expired"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:39
+#: kallithea/templates/admin/users/user_edit_api_keys.html:39
+#, python-format
+msgid "Confirm to remove this API key: %s"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
+#: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
+msgid "Remove"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:48
+#: kallithea/templates/admin/users/user_edit_api_keys.html:48
+msgid "No additional API keys specified"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:56
+#: kallithea/templates/admin/users/user_edit_api_keys.html:56
+msgid "New API key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:72
+#: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
+#: kallithea/templates/admin/permissions/permissions_ips.html:33
+#: kallithea/templates/admin/repos/repo_add_base.html:64
+#: kallithea/templates/admin/repos/repo_edit_fields.html:53
+#: kallithea/templates/admin/users/user_edit_api_keys.html:72
+#: kallithea/templates/admin/users/user_edit_emails.html:46
+#: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
+msgid "Add"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:81
+#, python-format
+msgid ""
+"\n"
+"API keys are used to let scripts or services access %s using your\n"
+"account, as if you had provided the script or service with your actual\n"
+"password.\n"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:86
+msgid ""
+"\n"
+"Like passwords, API keys should therefore never be shared with others,\n"
+"nor passed to untrusted scripts or services. If such sharing should\n"
+"happen anyway, reset the API key on this page to prevent further use.\n"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_emails.html:9
+#: kallithea/templates/admin/users/user_edit_emails.html:9
+msgid "Primary"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_emails.html:24
+#: kallithea/templates/admin/users/user_edit_emails.html:24
+#, python-format
+msgid "Confirm to delete this email: %s"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_emails.html:30
+#: kallithea/templates/admin/users/user_edit_emails.html:30
+msgid "No additional emails specified."
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_emails.html:39
+#: kallithea/templates/admin/users/user_edit_emails.html:39
+msgid "New email address"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_password.html:1
+msgid "Change Your Account Password"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_password.html:8
+msgid "Current password"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_password.html:15
+#: kallithea/templates/admin/users/user_edit_profile.html:46
+msgid "New password"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_password.html:22
+msgid "Confirm new password"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_password.html:39
+#, python-format
+msgid ""
+"This account is managed with %s and the password cannot be changed here"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_perms.html:3
+msgid "Current IP"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_profile.html:4
+#: kallithea/templates/admin/users/user_edit_profile.html:4
+msgid "Gravatar"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_profile.html:10
+#: kallithea/templates/admin/users/user_edit_profile.html:10
+#, python-format
+msgid "Change %s avatar at"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_profile.html:12
+#: kallithea/templates/admin/users/user_edit_profile.html:12
+msgid "Avatars are disabled"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_repos.html:1
+msgid "Repositories You Own"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_repos.html:13
+#: kallithea/templates/admin/my_account/my_account_watched.html:13
+#: kallithea/templates/admin/repo_groups/repo_groups.html:39
+#: kallithea/templates/admin/repos/repo_add_base.html:6
+#: kallithea/templates/admin/repos/repo_edit_settings.html:4
+#: kallithea/templates/admin/repos/repos.html:38
+#: kallithea/templates/admin/user_groups/user_groups.html:38
+#: kallithea/templates/base/perms_summary.html:54
+#: kallithea/templates/files/files_browser.html:54
+msgid "Name"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+msgid "Last Used"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, python-format
+msgid "Confirm to remove this SSH key: %s"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+msgid "New SSH key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+msgid "Public key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_watched.html:1
+msgid "Repositories You are Watching"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions.html:5
+#: kallithea/templates/admin/permissions/permissions.html:11
+#: kallithea/templates/base/base.html:60
+msgid "Default Permissions"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions.html:28
+#: kallithea/templates/admin/settings/settings.html:29
+msgid "Global"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions.html:29
+#: kallithea/templates/admin/users/user_edit.html:35
+msgid "IP Whitelist"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:4
+msgid "Anonymous access"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:8
+msgid "Allow anonymous access"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:10
+#, python-format
+msgid ""
+"Allow access to Kallithea without needing to log in. Anonymous users use "
+"%s user permissions."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:19
+msgid ""
+"All default permissions on each repository will be reset to chosen "
+"permission, note that all custom default permission on repositories will "
+"be lost"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:20
+msgid "Apply to all existing repositories"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:23
+msgid "Permissions for the Default user on new repositories."
+msgstr ""
+
+#: 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/forks/fork.html:42
+msgid "Repository group"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:32
+msgid ""
+"All default permissions on each repository group will be reset to chosen "
+"permission, note that all custom default permission on repository groups "
+"will be lost"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:33
+msgid "Apply to all existing repository groups"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:36
+msgid "Permissions for the Default user on new repository groups."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:40
+#: kallithea/templates/data_table/_dt_elements.html:141
+msgid "User group"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:45
+msgid ""
+"All default permissions on each user group will be reset to chosen "
+"permission, note that all custom default permission on user groups will "
+"be lost"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:46
+msgid "Apply to all existing user groups"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:49
+msgid "Permissions for the Default user on new user groups."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:53
+msgid "Top level repository creation"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:56
+msgid ""
+"Enable this to allow non-admins to create repositories at the top level."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:57
+msgid ""
+"Note: This will also give all users API access to create repositories "
+"everywhere. That might change in future versions."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:61
+msgid "Repository creation with group write access"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:64
+msgid ""
+"With this, write permission to a repository group allows creating "
+"repositories inside that group. Without this, group write permissions "
+"mean nothing."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:68
+msgid "User group creation"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:71
+msgid "Enable this to allow non-admins to create user groups."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:75
+msgid "Repository forking"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:78
+msgid "Enable this to allow non-admins to fork repositories."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:82
+msgid "Registration"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:88
+msgid "External auth account activation"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_ips.html:12
+#: kallithea/templates/admin/users/user_edit_ips.html:22
+#, python-format
+msgid "Confirm to delete this IP address: %s"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_ips.html:18
+#: kallithea/templates/admin/users/user_edit_ips.html:29
+msgid "All IP addresses are allowed."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_ips.html:25
+#: kallithea/templates/admin/users/user_edit_ips.html:37
+msgid "New IP address"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:11
+#: kallithea/templates/admin/repo_groups/repo_group_edit.html:11
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:89
+#: kallithea/templates/admin/repo_groups/repo_groups.html:9
+#: kallithea/templates/base/base.html:57
+#: kallithea/templates/base/base.html:76
+msgid "Repository Groups"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:28
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:5
+#: kallithea/templates/admin/user_groups/user_group_add.html:27
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:4
+msgid "Group name"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:42
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:19
+msgid "Group parent"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:49
+#: kallithea/templates/admin/repos/repo_add_base.html:35
+msgid "Copy parent group permissions"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:52
+#: kallithea/templates/admin/repos/repo_add_base.html:38
+msgid "Copy permission set from parent repository group."
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit.html:5
+#, python-format
+msgid "%s Repository Group Settings"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit.html:29
+msgid "Add Child Group"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit.html:36
+#: kallithea/templates/admin/repos/repo_edit.html:12
+#: kallithea/templates/admin/repos/repo_edit.html:25
+#: kallithea/templates/admin/settings/settings.html:11
+#: kallithea/templates/admin/user_groups/user_group_edit.html:29
+#: kallithea/templates/base/base.html:63
+#: kallithea/templates/base/base.html:152
+msgid "Settings"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
+#: kallithea/templates/admin/repos/repo_edit.html:31
+#: kallithea/templates/admin/user_groups/user_group_edit.html:30
+#: kallithea/templates/admin/users/user_edit.html:36
+msgid "Advanced"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit.html:38
+#: kallithea/templates/admin/repos/repo_edit.html:28
+#: kallithea/templates/admin/user_groups/user_group_edit.html:31
+msgid "Permissions"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:1
+#, python-format
+msgid "Repository Group: %s"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:6
+msgid "Top level repositories"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:7
+msgid "Total repositories"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:8
+msgid "Children groups"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:9
+#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:7
+#: kallithea/templates/admin/users/user_edit_advanced.html:8
+#: kallithea/templates/pullrequests/pullrequest_show.html:118
+msgid "Created on"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
+#: kallithea/templates/data_table/_dt_elements.html:121
+#, python-format
+msgid "Confirm to delete this group: %s with %s repository"
+msgid_plural "Confirm to delete this group: %s with %s repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:25
+msgid "Delete this repository group"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
+msgid "Not visible"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
+msgid "Visible"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
+msgid "Add repos"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10
+msgid "Add/Edit groups"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:11
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:11
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:11
+msgid "User/User Group"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:28
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:45
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:23
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:36
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:28
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:45
+msgid "Default"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:34
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:71
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:42
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:67
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:34
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:71
+msgid "Revoke"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:81
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:77
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:81
+msgid "Add new"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:87
+msgid "Apply to children"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:91
+msgid "Both"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:92
+msgid ""
+"Set or revoke permission to all children of that group, including non-"
+"private repositories and other groups if selected."
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
+msgid "Remove this group"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
+msgid "Confirm to delete this group"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_show.html:4
+#, python-format
+msgid "Repository group %s"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_groups.html:5
+msgid "Repository Groups Administration"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_groups.html:41
+msgid "Number of Top-level Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_add_base.html:12
+msgid "Clone remote repository"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_add_base.html:16
+msgid ""
+"Optional: URL of a remote repository. If set, the repository will be "
+"created as a clone from this URL."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_add_base.html:24
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/forks/fork.html:37
+msgid ""
+"Keep it short and to the point. Use a README file for longer descriptions."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_add_base.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
+#: kallithea/templates/forks/fork.html:45
+msgid "Optionally select a group to put this repository into."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_add_base.html:45
+msgid "Type of repository to create."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_add_base.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
+#: kallithea/templates/forks/fork.html:50
+msgid "Landing revision"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_add_base.html:52
+msgid ""
+"Default revision for files page, downloads, full text search index and "
+"readme generation"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_creating.html:9
+#, python-format
+msgid "%s Creating Repository"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_creating.html:13
+msgid "Creating repository"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_creating.html:27
+#, python-format
+msgid ""
+"Repository \"%(repo_name)s\" is being created, you will be redirected "
+"when this process is finished.repo_name"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_creating.html:39
+msgid ""
+"We're sorry but error occurred during this operation. Please check your "
+"Kallithea server logs, or contact administrator."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit.html:8
+#, python-format
+msgid "%s Repository Settings"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit.html:34
+msgid "Extra Fields"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit.html:37
+msgid "Caches"
+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
+msgid "Statistics"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:1
+msgid "Parent"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:5
+msgid "Set"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:7
+msgid "Manually set this repository as a fork of another from the list."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:20
+msgid "Public Journal Visibility"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:27
+msgid "Remove from public journal"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:32
+msgid "Add to Public Journal"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:37
+msgid ""
+"All actions done in this repository will be visible to everyone in the "
+"public journal."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
+#: kallithea/templates/data_table/_dt_elements.html:68
+#, python-format
+msgid "Confirm to delete this repository: %s"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
+msgid "Delete this Repository"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
+#, python-format
+msgid "This repository has %s fork"
+msgid_plural "This repository has %s forks"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
+msgid "Detach forks"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
+msgid "Delete forks"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
+msgid ""
+"The deleted repository will be moved away and hidden until the "
+"administrator expires it. The administrator can both permanently delete "
+"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: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"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_fields.html:31
+msgid "New field key"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_fields.html:38
+msgid "New field label"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_fields.html:40
+msgid "Enter short label"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_fields.html:45
+msgid "New field description"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_fields.html:47
+msgid "Enter description of a field"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_fields.html:61
+msgid "Extra fields are disabled."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:20
+msgid "Private Repository"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_remote.html:4
+msgid "Fork of repository"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_remote.html:7
+msgid "Remote repository URL"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_remote.html:15
+msgid "Pull Changes from Remote Repository"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_remote.html:17
+msgid "Confirm to pull changes from remote repository."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_remote.html:23
+msgid "This repository does not have a remote repository URL."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+msgid "Permanent URL"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
+msgid ""
+"In case this repository is renamed or moved into another group the "
+"repository URL changes.\n"
+"                               Using the above permanent URL guarantees "
+"that this repository always will be accessible on that URL.\n"
+"                               This is useful for CI systems, or any "
+"other cases that you need to hardcode the URL into a 3rd party service."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
+msgid "Remote repository"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
+msgid "Repository URL"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
+msgid ""
+"Optional: URL of a remote repository. If set, the repository can be "
+"pulled from this URL."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
+msgid "Default revision for files page, downloads, whoosh and readme"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/pullrequests/pullrequest_show.html:131
+msgid "Type name of user"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
+msgid "Change owner of this repository."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_statistics.html:5
+msgid "Processed commits"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_statistics.html:6
+msgid "Processed progress"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_statistics.html:10
+msgid "Reset Statistics"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_statistics.html:10
+msgid "Confirm to remove current statistics."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repos.html:5
+msgid "Repositories Administration"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repos.html:43
+msgid "State"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings.html:5
+msgid "Settings Administration"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings.html:27
+msgid "VCS"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings.html:28
+msgid "Remap and Rescan"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings.html:30
+msgid "Visual"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings.html:32
+#: kallithea/templates/admin/settings/settings_vcs.html:4
+msgid "Hooks"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings.html:33
+msgid "Full Text Search"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings.html:34
+msgid "System Info"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_email.html:4
+msgid "Send test email to"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_email.html:12
+msgid "Send"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:4
+msgid "Site branding"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:7
+msgid "Set a custom title for your Kallithea Service."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:12
+msgid "HTTP authentication realm"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:19
+msgid "HTML/JavaScript/CSS customization block"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:22
+msgid ""
+"HTML (possibly with                         JavaScript and/or CSS) that "
+"will be added to the bottom                         of every page. This "
+"can be used for web analytics                         systems, but also "
+"to                         perform instance-specific customizations like "
+"adding a                         project banner at the top of every page."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:32
+msgid "ReCaptcha public key"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:35
+msgid "Public key for reCaptcha system."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:40
+msgid "ReCaptcha private key"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:43
+msgid ""
+"Private key for reCaptcha system. Setting this value will enable captcha "
+"on registration."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:49
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
+msgid "Save Settings"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_hooks.html:3
+msgid "Built-in Mercurial Hooks (Read-Only)"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_hooks.html:17
+msgid "Custom Hooks"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_hooks.html:18
+msgid ""
+"Hooks can be used to trigger actions on certain events such as push / "
+"pull. They can trigger Python functions or external applications."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_hooks.html:60
+msgid "Failed to remove hook"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:4
+msgid "Rescan options"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:9
+msgid "Delete records of missing repositories"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:12
+msgid ""
+"Check this option to remove all comments, pull requests and other records "
+"related to repositories that no longer exist in the filesystem."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:17
+msgid "Invalidate cache for all repositories"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:20
+msgid "Check this to reload data and clear cache keys for all repositories."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:25
+msgid "Install Git hooks"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:28
+msgid ""
+"Verify if Kallithea's Git hooks are installed for each repository. "
+"Current hooks will be updated to the latest version."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:32
+msgid "Overwrite existing Git hooks"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:35
+msgid ""
+"If installing Git hooks, overwrite any existing hooks, even if they do "
+"not seem to come from Kallithea. WARNING: This operation will destroy any "
+"custom git hooks you may have deployed by hand!"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:41
+msgid "Rescan Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_search.html:4
+msgid "Index build option"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_search.html:9
+msgid "Build from scratch"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_search.html:12
+msgid ""
+"This option completely reindexeses all of the repositories for proper "
+"fulltext search capabilities."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_search.html:18
+msgid "Reindex"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_system.html:2
+msgid "Checking for updates..."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_system.html:7
+msgid "Kallithea version"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_system.html:8
+msgid "Kallithea configuration file"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_system.html:9
+msgid "Python version"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_system.html:10
+msgid "Platform"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_system.html:11
+msgid "Git version"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_system.html:12
+msgid "Git path"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_system.html:22
+msgid "Python Packages"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:9
+msgid "Show repository size after push"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:15
+msgid "Update repository after push (hg update)"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:21
+msgid "Mercurial extensions"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:26
+msgid "Enable largefiles extension"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:32
+msgid "Enable hgsubversion extension"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:35
+msgid ""
+"Requires hgsubversion library to be installed. Enables cloning of remote "
+"Subversion repositories while converting them to Mercurial."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:47
+msgid "Location of repositories"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:52
+msgid ""
+"Click to unlock. You must restart Kallithea in order to make this setting "
+"take effect."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:56
+msgid ""
+"Filesystem location where repositories are stored. After changing this "
+"value, a restart and rescan of the repository folder are both required."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:4
+msgid "General"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:9
+msgid "Use repository extra fields"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:12
+msgid "Allows storing additional customized fields per repository."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:17
+msgid "Show Kallithea version"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:20
+msgid ""
+"Shows or hides a version number of Kallithea displayed in the footer."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:25
+msgid "Show user Gravatars"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:29
+msgid ""
+"Gravatar URL allows you to use another avatar server application.\n"
+"                                                        The following "
+"variables of the URL will be replaced accordingly.\n"
+"                                                        {scheme}    "
+"'http' or 'https' sent from running Kallithea server,\n"
+"                                                        {email}     user "
+"email,\n"
+"                                                        {md5email}  md5 "
+"hash of the user email (like at gravatar.com),\n"
+"                                                        {size}      size "
+"of the image that is expected from the server application,\n"
+"                                                        {netloc}    "
+"network location/server host of running Kallithea server"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:40
+msgid "HTTP Clone URL"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:43
+msgid ""
+"Schema of clone URL construction eg. '{scheme}://{user}@{netloc}/"
+"{repo}'.\n"
+"                                                    The following "
+"variables are available:\n"
+"                                                    {scheme} 'http' or "
+"'https' sent from running Kallithea server,\n"
+"                                                    {user}   current user "
+"username,\n"
+"                                                    {netloc} network "
+"location/server host of running Kallithea server,\n"
+"                                                    {repo}   full "
+"repository name,\n"
+"                                                    {repoid} ID of "
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+msgid "SSH Clone URL"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
+msgid "Repository page size"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:68
+msgid ""
+"Number of items displayed in the repository pages before pagination is "
+"shown."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:73
+msgid "Admin page size"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:76
+msgid ""
+"Number of items displayed in the admin pages grids before pagination is "
+"shown."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:81
+msgid "Icons"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:86
+msgid "Show public repository icon on repositories"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:92
+msgid "Show private repository icon on repositories"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:95
+msgid "Show public/private icons next to repository names."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:100
+msgid "Meta Tagging"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:105
+msgid ""
+"Parses meta tags from the repository description field and turns them "
+"into colored tags."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:109
+msgid "Stylify recognised meta tags:"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_add.html:5
+msgid "Add user group"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_add.html:10
+#: kallithea/templates/admin/user_groups/user_group_edit.html:11
+#: kallithea/templates/admin/user_groups/user_groups.html:9
+#: kallithea/templates/base/base.html:59
+#: kallithea/templates/base/base.html:79
+msgid "User Groups"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_add.html:12
+#: kallithea/templates/admin/user_groups/user_groups.html:24
+msgid "Add User Group"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_add.html:36
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:13
+msgid "Short, optional description for this user group."
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit.html:5
+#, python-format
+msgid "%s user group settings"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit.html:33
+msgid "Show Members"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:1
+#, python-format
+msgid "User Group: %s"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:6
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:23
+#: kallithea/templates/admin/user_groups/user_groups.html:40
+msgid "Members"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
+#: kallithea/templates/data_table/_dt_elements.html:102
+#, python-format
+msgid "Confirm to delete this user group: %s"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:21
+msgid "Delete this user group"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit_members.html:11
+msgid "No members yet"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:26
+msgid "Chosen group members"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:39
+msgid "Available members"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_groups.html:5
+msgid "User Groups Administration"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_add.html:5
+msgid "Add user"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_add.html:10
+#: kallithea/templates/admin/users/user_edit.html:11
+#: kallithea/templates/admin/users/users.html:9
+#: kallithea/templates/base/base.html:58
+msgid "Users"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_add.html:12
+#: kallithea/templates/admin/users/users.html:23
+msgid "Add User"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_add.html:41
+msgid "Password confirmation"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit.html:5
+#, python-format
+msgid "%s user settings"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit.html:30
+msgid "Emails"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_advanced.html:1
+#, python-format
+msgid "User: %s"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_advanced.html:7
+#: kallithea/templates/admin/users/user_edit_profile.html:32
+msgid "Source of Record"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_advanced.html:9
+#: kallithea/templates/admin/users/users.html:41
+msgid "Last Login"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_advanced.html:10
+msgid "Member of User Groups"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_advanced.html:21
+#: kallithea/templates/data_table/_dt_elements.html:90
+#, python-format
+msgid "Confirm to delete this user: %s"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_advanced.html:23
+msgid "Delete this user"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_ips.html:7
+#, python-format
+msgid "Inherited from %s"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_profile.html:39
+msgid "Name in Source of Record"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_profile.html:53
+msgid "New password confirmation"
+msgstr ""
+
+#: kallithea/templates/admin/users/users.html:5
+msgid "Users Administration"
+msgstr ""
+
+#: kallithea/templates/admin/users/users.html:44
+msgid "Auth Type"
+msgstr ""
+
+#: kallithea/templates/base/base.html:16
+#, python-format
+msgid "Server instance: %s"
+msgstr ""
+
+#: kallithea/templates/base/base.html:28
+msgid "Support"
+msgstr ""
+
+#: kallithea/templates/base/base.html:86
+#: kallithea/templates/base/base.html:417
+msgid "Mercurial repository"
+msgstr ""
+
+#: kallithea/templates/base/base.html:89
+#: kallithea/templates/base/base.html:420
+msgid "Git repository"
+msgstr ""
+
+#: kallithea/templates/base/base.html:115
+msgid "Create Fork"
+msgstr ""
+
+#: kallithea/templates/base/base.html:127
+#: kallithea/templates/summary/summary.html:9
+msgid "Summary"
+msgstr ""
+
+#: kallithea/templates/base/base.html:129
+#: kallithea/templates/base/base.html:131
+#: kallithea/templates/changelog/changelog.html:16
+msgid "Changelog"
+msgstr ""
+
+#: kallithea/templates/base/base.html:133
+#: kallithea/templates/files/files.html:11
+msgid "Files"
+msgstr ""
+
+#: kallithea/templates/base/base.html:135
+#, python-format
+msgid "Show Pull Requests for %s"
+msgstr ""
+
+#: kallithea/templates/base/base.html:135
+msgid "Pull Requests"
+msgstr ""
+
+#: kallithea/templates/base/base.html:146
+#: kallithea/templates/base/base.html:148
+msgid "Options"
+msgstr ""
+
+#: kallithea/templates/base/base.html:156
+#: kallithea/templates/forks/forks_data.html:18
+msgid "Compare Fork"
+msgstr ""
+
+#: kallithea/templates/base/base.html:158
+msgid "Compare"
+msgstr ""
+
+#: kallithea/templates/base/base.html:160
+#: kallithea/templates/base/base.html:315
+#: kallithea/templates/search/search.html:14
+#: kallithea/templates/search/search.html:67
+msgid "Search"
+msgstr ""
+
+#: kallithea/templates/base/base.html:167
+msgid "Follow"
+msgstr ""
+
+#: kallithea/templates/base/base.html:168
+msgid "Unfollow"
+msgstr ""
+
+#: kallithea/templates/base/base.html:171
+#: kallithea/templates/forks/fork.html:9
+msgid "Fork"
+msgstr ""
+
+#: kallithea/templates/base/base.html:172
+#: kallithea/templates/pullrequests/pullrequest.html:77
+msgid "Create Pull Request"
+msgstr ""
+
+#: kallithea/templates/base/base.html:184
+msgid "Switch To"
+msgstr ""
+
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
+msgid "No matches found"
+msgstr ""
+
+#: kallithea/templates/base/base.html:289
+msgid "Show recent activity"
+msgstr ""
+
+#: kallithea/templates/base/base.html:295
+#: kallithea/templates/base/base.html:296
+msgid "Public journal"
+msgstr ""
+
+#: kallithea/templates/base/base.html:301
+msgid "Show public gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:302
+msgid "Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:306
+msgid "All Public Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:308
+msgid "My Public Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:309
+msgid "My Private Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:314
+msgid "Search in repositories"
+msgstr ""
+
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
+#: kallithea/templates/pullrequests/pullrequest_show_my.html:6
+#: kallithea/templates/pullrequests/pullrequest_show_my.html:10
+msgid "My Pull Requests"
+msgstr ""
+
+#: kallithea/templates/base/base.html:353
+msgid "Not Logged In"
+msgstr ""
+
+#: kallithea/templates/base/base.html:362
+msgid "Login to Your Account"
+msgstr ""
+
+#: kallithea/templates/base/base.html:372
+msgid "Forgot password?"
+msgstr ""
+
+#: kallithea/templates/base/base.html:376
+msgid "Don't have an account?"
+msgstr ""
+
+#: kallithea/templates/base/base.html:393
+msgid "Log Out"
+msgstr ""
+
+#: kallithea/templates/base/base.html:517
+msgid "Parent rev."
+msgstr ""
+
+#: kallithea/templates/base/base.html:526
+msgid "Child rev."
+msgstr ""
+
+#: kallithea/templates/base/default_perms_box.html:11
+msgid "Create repositories"
+msgstr ""
+
+#: kallithea/templates/base/default_perms_box.html:15
+msgid "Select this option to allow repository creation for this user"
+msgstr ""
+
+#: kallithea/templates/base/default_perms_box.html:21
+msgid "Create user groups"
+msgstr ""
+
+#: kallithea/templates/base/default_perms_box.html:25
+msgid "Select this option to allow user group creation for this user"
+msgstr ""
+
+#: kallithea/templates/base/default_perms_box.html:31
+msgid "Fork repositories"
+msgstr ""
+
+#: kallithea/templates/base/default_perms_box.html:35
+msgid "Select this option to allow repository forking for this user"
+msgstr ""
+
+#: kallithea/templates/base/perms_summary.html:13
+#: kallithea/templates/changelog/changelog.html:41
+msgid "Show"
+msgstr ""
+
+#: kallithea/templates/base/perms_summary.html:22
+msgid "No permissions defined yet"
+msgstr ""
+
+#: kallithea/templates/base/perms_summary.html:30
+#: kallithea/templates/base/perms_summary.html:55
+msgid "Permission"
+msgstr ""
+
+#: kallithea/templates/base/perms_summary.html:32
+#: kallithea/templates/base/perms_summary.html:57
+msgid "Edit Permission"
+msgstr ""
+
+#: kallithea/templates/base/perms_summary.html:92
+msgid "No permission defined"
+msgstr ""
+
+#: kallithea/templates/base/root.html:28
+msgid "Retry"
+msgstr ""
+
+#: kallithea/templates/base/root.html:29
+#: kallithea/templates/changeset/changeset_file_comment.html:65
+msgid "Submitting ..."
+msgstr ""
+
+#: kallithea/templates/base/root.html:30
+msgid "Unable to post"
+msgstr ""
+
+#: kallithea/templates/base/root.html:31
+msgid "Add Another Comment"
+msgstr ""
+
+#: kallithea/templates/base/root.html:32
+msgid "Stop following this repository"
+msgstr ""
+
+#: kallithea/templates/base/root.html:33
+msgid "Start following this repository"
+msgstr ""
+
+#: kallithea/templates/base/root.html:34
+msgid "Group"
+msgstr ""
+
+#: kallithea/templates/base/root.html:35
+msgid "Loading ..."
+msgstr ""
+
+#: kallithea/templates/base/root.html:36
+msgid "loading ..."
+msgstr ""
+
+#: kallithea/templates/base/root.html:37
+msgid "Search truncated"
+msgstr ""
+
+#: kallithea/templates/base/root.html:38
+msgid "No matching files"
+msgstr ""
+
+#: kallithea/templates/base/root.html:39
+msgid "Open New Pull Request from {0}"
+msgstr ""
+
+#: kallithea/templates/base/root.html:40
+msgid "Open New Pull Request for {0} &rarr; {1}"
+msgstr ""
+
+#: kallithea/templates/base/root.html:41
+msgid "Show Selected Changesets {0} &rarr; {1}"
+msgstr ""
+
+#: kallithea/templates/base/root.html:42
+msgid "Selection Link"
+msgstr ""
+
+#: kallithea/templates/base/root.html:43
+#: kallithea/templates/changeset/diff_block.html:7
+msgid "Collapse Diff"
+msgstr ""
+
+#: kallithea/templates/base/root.html:44
+msgid "Expand Diff"
+msgstr ""
+
+#: kallithea/templates/base/root.html:45
+msgid "No revisions"
+msgstr ""
+
+#: kallithea/templates/base/root.html:46
+msgid "Type name of user or member to grant permission"
+msgstr ""
+
+#: kallithea/templates/base/root.html:47
+msgid "Failed to revoke permission"
+msgstr ""
+
+#: kallithea/templates/base/root.html:48
+msgid "Confirm to revoke permission for {0}: {1} ?"
+msgstr ""
+
+#: kallithea/templates/base/root.html:51
+#: kallithea/templates/compare/compare_diff.html:108
+msgid "Select changeset"
+msgstr ""
+
+#: kallithea/templates/base/root.html:52
+msgid "Specify changeset"
+msgstr ""
+
+#: kallithea/templates/base/root.html:53
+msgid "Click to sort ascending"
+msgstr ""
+
+#: kallithea/templates/base/root.html:54
+msgid "Click to sort descending"
+msgstr ""
+
+#: kallithea/templates/base/root.html:55
+msgid "No records found."
+msgstr ""
+
+#: kallithea/templates/base/root.html:56
+msgid "Data error."
+msgstr ""
+
+#: kallithea/templates/base/root.html:57
+msgid "Loading..."
+msgstr ""
+
+#: kallithea/templates/changelog/changelog.html:8
+#, python-format
+msgid "%s Changelog"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog.html:23
+#, python-format
+msgid "showing %d out of %d revision"
+msgid_plural "showing %d out of %d revisions"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/changelog/changelog.html:47
+msgid "Clear selection"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog.html:54
+msgid "Go to tip of repository"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog.html:59
+#: kallithea/templates/forks/forks_data.html:16
+#, python-format
+msgid "Compare fork with %s"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog.html:61
+#, python-format
+msgid "Compare fork with parent repository (%s)"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog.html:65
+#: kallithea/templates/files/files.html:29
+msgid "Branch filter:"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog.html:221
+msgid "There are no changes yet"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_details.html:4
+#: kallithea/templates/changeset/changeset.html:77
+msgid "Removed"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_details.html:5
+#: kallithea/templates/changeset/changeset.html:78
+msgid "Changed"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_details.html:6
+#: kallithea/templates/changeset/changeset.html:79
+#: kallithea/templates/changeset/diff_block.html:38
+msgid "Added"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_details.html:8
+#: kallithea/templates/changelog/changelog_details.html:9
+#: kallithea/templates/changelog/changelog_details.html:10
+#: kallithea/templates/changeset/changeset.html:81
+#: kallithea/templates/changeset/changeset.html:82
+#: kallithea/templates/changeset/changeset.html:83
+#, python-format
+msgid "Affected %s files"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:20
+msgid "First (oldest) changeset in this list"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:22
+msgid "Last (most recent) changeset in this list"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:24
+msgid "Position in this list of changesets"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:35
+#, python-format
+msgid ""
+"Changeset status: %s by %s\n"
+"Click to open associated pull request %s"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:41
+#, python-format
+msgid "Changeset status: %s by %s"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:60
+msgid "Expand commit message"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:76
+#, python-format
+msgid "%s comments"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:80
+#: kallithea/templates/changeset/changeset.html:63
+#: kallithea/templates/changeset/changeset_range.html:84
+#, python-format
+msgid "Bookmark %s"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:83
+#: kallithea/templates/changeset/changeset.html:67
+#: kallithea/templates/changeset/changeset_range.html:90
+#: kallithea/templates/pullrequests/pullrequest_show.html:165
+#, python-format
+msgid "Tag %s"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:102
+#: kallithea/templates/changeset/changeset.html:71
+#: kallithea/templates/changeset/changeset_range.html:94
+#, python-format
+msgid "Branch %s"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:8
+#, python-format
+msgid "%s Changeset"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:34
+msgid "Changeset status"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:43
+#: kallithea/templates/changeset/diff_block.html:64
+#: kallithea/templates/files/diff_2way.html:51
+msgid "Raw diff"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:46
+msgid "Patch diff"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:49
+#: kallithea/templates/changeset/diff_block.html:66
+#: kallithea/templates/files/diff_2way.html:54
+msgid "Download diff"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:59
+#: kallithea/templates/changeset/changeset_range.html:80
+msgid "Merge"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:96
+msgid "Grafted from:"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:102
+msgid "Transplanted from:"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:108
+msgid "Replaced by:"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:122
+msgid "Preceded by:"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:139
+#: kallithea/templates/compare/compare_diff.html:59
+#: kallithea/templates/pullrequests/pullrequest_show.html:290
+#, python-format
+msgid "%s file changed"
+msgid_plural "%s files changed"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/changeset/changeset.html:141
+#: kallithea/templates/compare/compare_diff.html:61
+#: kallithea/templates/pullrequests/pullrequest_show.html:292
+#, python-format
+msgid "%s file changed with %s insertions and %s deletions"
+msgid_plural "%s files changed with %s insertions and %s deletions"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/changeset/changeset.html:154
+#: kallithea/templates/changeset/changeset.html:173
+#: kallithea/templates/compare/compare_diff.html:81
+#: kallithea/templates/pullrequests/pullrequest_show.html:309
+#: kallithea/templates/pullrequests/pullrequest_show.html:333
+msgid "Show full diff anyway"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:20
+msgid "comment"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:21
+msgid "on pull request"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:22
+msgid "No title"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:24
+msgid "on this changeset"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:30
+msgid "Delete comment?"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:38
+#: kallithea/templates/changeset/changeset_file_comment.html:71
+msgid "Status change"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:87
+msgid "Comments are in plain text. Use @username to notify another user."
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:93
+msgid "Set changeset status"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:95
+msgid "Vote for pull request status"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:101
+#: kallithea/templates/changeset/diff_block.html:46
+msgid "No change"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:114
+msgid "Finish pull request"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:117
+msgid "Close"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:129
+msgid "Comment"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:137
+msgid "You need to be logged in to comment."
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:137
+msgid "Login now"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:141
+msgid "Hide"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:153
+#, python-format
+msgid "%d comment"
+msgid_plural "%d comments"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:154
+#, python-format
+msgid "%d inline"
+msgid_plural "%d inline"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:155
+#, python-format
+msgid "%d general"
+msgid_plural "%d general"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/changeset/changeset_range.html:5
+#, python-format
+msgid "%s Changesets"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_range.html:43
+#, python-format
+msgid "Changeset status: %s"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_range.html:50
+msgid "Files affected"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:30
+msgid "No file before"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:33
+msgid "File before"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:40
+msgid "Modified"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:42
+msgid "Deleted"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:44
+msgid "Renamed"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:48
+#, python-format
+msgid "Unknown operation: %r"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:52
+msgid "No file after"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:55
+msgid "File after"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:60
+#: kallithea/templates/files/diff_2way.html:43
+msgid "Show full diff for this file"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:62
+#: kallithea/templates/files/diff_2way.html:47
+msgid "Show full side-by-side diff for this file"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:72
+msgid "Show inline comments"
+msgstr ""
+
+#: kallithea/templates/compare/compare_cs.html:5
+msgid "No changesets"
+msgstr ""
+
+#: kallithea/templates/compare/compare_cs.html:12
+msgid "Criss cross merge situation with multiple merge ancestors detected!"
+msgstr ""
+
+#: kallithea/templates/compare/compare_cs.html:15
+msgid ""
+"Please merge the target branch to your branch before creating a pull "
+"request."
+msgstr ""
+
+#: kallithea/templates/compare/compare_cs.html:19
+msgid "Merge Ancestor"
+msgstr ""
+
+#: kallithea/templates/compare/compare_cs.html:40
+msgid "Show merge diff"
+msgstr ""
+
+#: kallithea/templates/compare/compare_cs.html:54
+msgid "is"
+msgstr ""
+
+#: kallithea/templates/compare/compare_cs.html:55
+#, python-format
+msgid "%s changesets"
+msgstr ""
+
+#: kallithea/templates/compare/compare_cs.html:56
+msgid "behind"
+msgstr ""
+
+#: kallithea/templates/compare/compare_diff.html:6
+#: kallithea/templates/compare/compare_diff.html:8
+#, python-format
+msgid "%s Compare"
+msgstr ""
+
+#: kallithea/templates/compare/compare_diff.html:13
+#: kallithea/templates/compare/compare_diff.html:41
+msgid "Compare Revisions"
+msgstr ""
+
+#: kallithea/templates/compare/compare_diff.html:39
+msgid "Swap"
+msgstr ""
+
+#: kallithea/templates/compare/compare_diff.html:48
+msgid "Compare revisions, branches, bookmarks, or tags."
+msgstr ""
+
+#: kallithea/templates/compare/compare_diff.html:53
+#: kallithea/templates/pullrequests/pullrequest_show.html:278
+#, python-format
+msgid "Showing %s commit"
+msgid_plural "Showing %s commits"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/compare/compare_diff.html:95
+msgid "Show full diff"
+msgstr ""
+
+#: kallithea/templates/data_table/_dt_elements.html:23
+msgid "Public repository"
+msgstr ""
+
+#: kallithea/templates/data_table/_dt_elements.html:29
+msgid "Repository creation in progress..."
+msgstr ""
+
+#: kallithea/templates/data_table/_dt_elements.html:42
+msgid "No changesets yet"
+msgstr ""
+
+#: kallithea/templates/data_table/_dt_elements.html:48
+#: kallithea/templates/data_table/_dt_elements.html:50
+#, 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
+#, python-format
+msgid "Subscribe to %s atom feed"
+msgstr ""
+
+#: kallithea/templates/data_table/_dt_elements.html:76
+msgid "Creating"
+msgstr ""
+
+#: kallithea/templates/email_templates/changeset_comment.html:4
+#, python-format
+msgid "Mention in Comment on Changeset \"%s\""
+msgstr ""
+
+#: kallithea/templates/email_templates/changeset_comment.html:4
+#, python-format
+msgid "Comment on Changeset \"%s\""
+msgstr ""
+
+#: kallithea/templates/email_templates/changeset_comment.html:20
+msgid "Changeset on"
+msgstr ""
+
+#: kallithea/templates/email_templates/changeset_comment.html:23
+#: kallithea/templates/email_templates/pull_request.html:22
+#: kallithea/templates/email_templates/pull_request.html:28
+#: kallithea/templates/email_templates/pull_request_comment.html:30
+#: kallithea/templates/email_templates/pull_request_comment.html:36
+msgid "branch"
+msgstr ""
+
+#: kallithea/templates/email_templates/changeset_comment.html:29
+#: kallithea/templates/email_templates/pull_request.html:15
+#: kallithea/templates/email_templates/pull_request_comment.html:23
+msgid "by"
+msgstr ""
+
+#: kallithea/templates/email_templates/comment.html:27
+msgid "Status change:"
+msgstr ""
+
+#: kallithea/templates/email_templates/comment.html:33
+msgid "The pull request has been closed."
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:9
+#, python-format
+msgid "Hello %s"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:16
+msgid "We have received a request to reset the password for your account."
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:25
+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
+msgid "To set a new password, click the following link"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:33
+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
+msgid ""
+"If it weren't you who requested the password reset, just disregard this "
+"message."
+msgstr ""
+
+#: kallithea/templates/email_templates/pull_request.html:4
+#, python-format
+msgid "Mention on Pull Request %s \"%s\" by %s"
+msgstr ""
+
+#: kallithea/templates/email_templates/pull_request.html:4
+#, python-format
+msgid "Added as Reviewer of Pull Request %s \"%s\" by %s"
+msgstr ""
+
+#: kallithea/templates/email_templates/pull_request.html:12
+#: kallithea/templates/email_templates/pull_request_comment.html:20
+msgid "Pull request"
+msgstr ""
+
+#: kallithea/templates/email_templates/pull_request.html:19
+#: kallithea/templates/email_templates/pull_request_comment.html:27
+msgid "from"
+msgstr ""
+
+#: kallithea/templates/email_templates/pull_request.html:25
+#: kallithea/templates/email_templates/pull_request_comment.html:33
+msgid "to"
+msgstr ""
+
+#: kallithea/templates/email_templates/pull_request_comment.html:4
+#, python-format
+msgid "Mention in Comment on Pull Request %s \"%s\""
+msgstr ""
+
+#: kallithea/templates/email_templates/pull_request_comment.html:4
+#, python-format
+msgid "Pull Request %s \"%s\" Closed"
+msgstr ""
+
+#: kallithea/templates/email_templates/pull_request_comment.html:4
+#, python-format
+msgid "Comment on Pull Request %s \"%s\""
+msgstr ""
+
+#: kallithea/templates/email_templates/registration.html:22
+msgid "Full Name"
+msgstr ""
+
+#: kallithea/templates/files/diff_2way.html:15
+#, python-format
+msgid "%s File side-by-side diff"
+msgstr ""
+
+#: kallithea/templates/files/diff_2way.html:19
+#: kallithea/templates/files/file_diff.html:8
+msgid "File diff"
+msgstr ""
+
+#: kallithea/templates/files/file_diff.html:4
+#, python-format
+msgid "%s File Diff"
+msgstr ""
+
+#: kallithea/templates/files/files.html:4
+#: kallithea/templates/files/files.html:74
+#, python-format
+msgid "%s Files"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:4
+#, python-format
+msgid "%s Files Add"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:21
+#: kallithea/templates/files/files_ypjax.html:9
+#: kallithea/templates/summary/summary.html:199
+msgid "Add New File"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:39
+#: kallithea/templates/files/files_edit.html:39
+#: kallithea/templates/files/files_ypjax.html:3
+msgid "Location"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:41
+msgid "Enter filename..."
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:43
+#: kallithea/templates/files/files_add.html:47
+msgid "or"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:43
+msgid "Upload File"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:47
+msgid "Create New File"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:53
+msgid "New file type"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:64
+#: kallithea/templates/files/files_delete.html:34
+#: kallithea/templates/files/files_edit.html:67
+msgid "Commit Message"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:68
+#: kallithea/templates/files/files_delete.html:40
+#: kallithea/templates/files/files_edit.html:71
+msgid "Commit Changes"
+msgstr ""
+
+#: kallithea/templates/files/files_browser.html:40
+msgid "Search File List"
+msgstr ""
+
+#: kallithea/templates/files/files_browser.html:45
+msgid "Loading file list..."
+msgstr ""
+
+#: kallithea/templates/files/files_browser.html:55
+#: kallithea/templates/summary/summary.html:153
+msgid "Size"
+msgstr ""
+
+#: kallithea/templates/files/files_browser.html:56
+msgid "Last Revision"
+msgstr ""
+
+#: kallithea/templates/files/files_browser.html:57
+msgid "Last Modified"
+msgstr ""
+
+#: kallithea/templates/files/files_browser.html:58
+msgid "Last Committer"
+msgstr ""
+
+#: kallithea/templates/files/files_delete.html:4
+#, python-format
+msgid "%s Files Delete"
+msgstr ""
+
+#: kallithea/templates/files/files_delete.html:12
+#: kallithea/templates/files/files_delete.html:30
+msgid "Delete file"
+msgstr ""
+
+#: kallithea/templates/files/files_edit.html:4
+#, python-format
+msgid "%s File Edit"
+msgstr ""
+
+#: kallithea/templates/files/files_edit.html:21
+msgid "Edit file"
+msgstr ""
+
+#: kallithea/templates/files/files_edit.html:51
+#: kallithea/templates/files/files_source.html:28
+msgid "Show Annotation"
+msgstr ""
+
+#: kallithea/templates/files/files_edit.html:53
+#: kallithea/templates/files/files_source.html:31
+msgid "Download as Raw"
+msgstr ""
+
+#: kallithea/templates/files/files_edit.html:56
+msgid "Source"
+msgstr ""
+
+#: kallithea/templates/files/files_history_box.html:2
+#, python-format
+msgid "%s author"
+msgid_plural "%s authors"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/files/files_source.html:6
+msgid "Diff to Revision"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:7
+msgid "Show at Revision"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:9
+msgid "Show Full History"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:10
+msgid "Show Authors"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:26
+msgid "Show Source"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:34
+#, python-format
+msgid "Edit on Branch: %s"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:37
+msgid "Editing binary files not allowed"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:40
+msgid "Editing files allowed only when on branch head revision"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:41
+msgid "Deleting files allowed only when on branch head revision"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:58
+#, python-format
+msgid "Binary file (%s)"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:69
+msgid "File is too big to display."
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:71
+msgid "Show full annotation anyway."
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:73
+msgid "Show as raw."
+msgstr ""
+
+#: kallithea/templates/files/files_ypjax.html:5
+msgid "annotation"
+msgstr ""
+
+#: kallithea/templates/files/files_ypjax.html:23
+msgid "Go Back"
+msgstr ""
+
+#: kallithea/templates/files/files_ypjax.html:24
+msgid "No files at given path"
+msgstr ""
+
+#: kallithea/templates/followers/followers.html:5
+#, python-format
+msgid "%s Followers"
+msgstr ""
+
+#: kallithea/templates/followers/followers.html:9
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
+msgid "Followers"
+msgstr ""
+
+#: kallithea/templates/followers/followers_data.html:9
+msgid "Started following -"
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:5
+#, python-format
+msgid "Fork repository %s"
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:25
+msgid "Fork name"
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:53
+msgid "Default revision for files page, downloads, whoosh, and readme."
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:58
+msgid "Private"
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:66
+msgid "Copy permissions"
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:69
+msgid "Copy permissions from forked repository"
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:75
+msgid "Update after clone"
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:78
+msgid "Checkout source after making a clone"
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:85
+msgid "Fork this Repository"
+msgstr ""
+
+#: kallithea/templates/forks/forks.html:5
+#, python-format
+msgid "%s Forks"
+msgstr ""
+
+#: kallithea/templates/forks/forks.html:9
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
+msgid "Forks"
+msgstr ""
+
+#: kallithea/templates/forks/forks_data.html:14
+msgid "Forked"
+msgstr ""
+
+#: kallithea/templates/forks/forks_data.html:24
+msgid "There are no forks yet"
+msgstr ""
+
+#: kallithea/templates/journal/journal.html:22
+msgid "ATOM journal feed"
+msgstr ""
+
+#: kallithea/templates/journal/journal.html:23
+msgid "RSS journal feed"
+msgstr ""
+
+#: kallithea/templates/journal/journal.html:34
+msgid "My Repositories"
+msgstr ""
+
+#: kallithea/templates/journal/journal_data.html:42
+msgid "No entries yet"
+msgstr ""
+
+#: kallithea/templates/journal/public_journal.html:10
+msgid "ATOM public journal feed"
+msgstr ""
+
+#: kallithea/templates/journal/public_journal.html:11
+msgid "RSS public journal feed"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest.html:4
+#: kallithea/templates/pullrequests/pullrequest.html:8
+msgid "New Pull Request"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest.html:26
+#: kallithea/templates/pullrequests/pullrequest_data.html:15
+#: kallithea/templates/pullrequests/pullrequest_show.html:29
+#: kallithea/templates/pullrequests/pullrequest_show.html:52
+msgid "Title"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest.html:28
+msgid "Summarize the changes - or leave empty"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest.html:35
+#: kallithea/templates/pullrequests/pullrequest_show.html:61
+msgid "Write a short description on this pull request"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest.html:40
+msgid "Changeset flow"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest.html:46
+msgid "Origin repository"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest.html:52
+#: kallithea/templates/pullrequests/pullrequest.html:68
+msgid "Revision"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest.html:62
+msgid "Destination repository"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:6
+msgid "No entries"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:14
+msgid "Vote"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:17
+msgid "Age"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:18
+msgid "From"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:19
+msgid "To"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:28
+#, python-format
+msgid "You voted: %s"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:30
+msgid "You didn't vote"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:35
+msgid "(no title)"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:37
+#: kallithea/templates/pullrequests/pullrequest_show.html:31
+#: kallithea/templates/pullrequests/pullrequest_show.html:73
+msgid "Closed"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:67
+msgid "Delete Pull Request"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:68
+msgid "Confirm to delete this pull request"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:70
+#, python-format
+msgid "Confirm again to delete this pull request with %s comments"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:6
+#, python-format
+msgid "%s Pull Request %s"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:10
+#, python-format
+msgid "Pull request %s from %s#%s"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:54
+msgid "Summarize the changes"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:67
+msgid "Voting Result"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:70
+#: kallithea/templates/pullrequests/pullrequest_show.html:71
+msgid "Pull request status calculated from votes"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:81
+msgid "Origin"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:86
+msgid "on"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:92
+msgid "Target"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:95
+msgid ""
+"This is just a range of changesets and doesn't have a target or a real "
+"merge ancestor."
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:103
+msgid "Pull changes"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:136
+msgid "Next iteration"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:153
+msgid "Current revision - no change"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:177
+msgid ""
+"Pull request iterations do not change content once created. Select a "
+"revision to create a new iteration."
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:187
+msgid "Save Changes"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:188
+msgid "Create New Iteration with Changes"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:189
+msgid "Cancel Changes"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:197
+msgid "Reviewers"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:223
+msgid "Remove reviewer"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:234
+msgid "Type name of reviewer to add"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:240
+msgid "Potential Reviewers"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:243
+msgid "Click to add the repository owner as reviewer:"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:268
+msgid "Pull Request Content"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:283
+msgid "Common ancestor"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_all.html:6
+#, python-format
+msgid "%s Pull Requests"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_all.html:11
+#, python-format
+msgid "Pull Requests from '%s'"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_all.html:13
+#, python-format
+msgid "Pull Requests to '%s'"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_all.html:31
+msgid "Open New Pull Request"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_all.html:34
+#, python-format
+msgid "Show Pull Requests to %s"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_all.html:36
+#, python-format
+msgid "Show Pull Requests from '%s'"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_all.html:44
+#: kallithea/templates/pullrequests/pullrequest_show_my.html:28
+msgid "Hide closed pull requests (only show open pull requests)"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_all.html:46
+#: kallithea/templates/pullrequests/pullrequest_show_my.html:30
+msgid "Show closed pull requests (in addition to open pull requests)"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_my.html:34
+msgid "Pull Requests Created by Me"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_my.html:37
+msgid "Pull Requests Needing My Review"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_my.html:40
+msgid "Pull Requests I Participate In"
+msgstr ""
+
+#: kallithea/templates/search/search.html:6
+#, python-format
+msgid "%s Search"
+msgstr ""
+
+#: kallithea/templates/search/search.html:8
+#: kallithea/templates/search/search.html:16
+msgid "Search in All Repositories"
+msgstr ""
+
+#: kallithea/templates/search/search.html:47
+msgid "Search term"
+msgstr ""
+
+#: kallithea/templates/search/search.html:54
+msgid "Search in"
+msgstr ""
+
+#: kallithea/templates/search/search.html:56
+msgid "File contents"
+msgstr ""
+
+#: kallithea/templates/search/search.html:57
+msgid "Commit messages"
+msgstr ""
+
+#: kallithea/templates/search/search.html:58
+msgid "File names"
+msgstr ""
+
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
+msgid "Permission denied"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:4
+#, python-format
+msgid "%s Statistics"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:16
+#: kallithea/templates/summary/summary.html:27
+#, python-format
+msgid "%s ATOM feed"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:17
+#: kallithea/templates/summary/summary.html:28
+#, python-format
+msgid "%s RSS feed"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:35
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
+msgid "Enable"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:38
+msgid "Stats gathered: "
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:87
+#: kallithea/templates/summary/summary.html:371
+msgid "files"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:111
+#: kallithea/templates/summary/summary.html:401
+msgid "Show more"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:405
+msgid "commits"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:406
+msgid "files added"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:407
+msgid "files changed"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:408
+msgid "files removed"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:410
+msgid "commit"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:411
+msgid "file added"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:412
+msgid "file changed"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:413
+msgid "file removed"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:5
+#, python-format
+msgid "%s Summary"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:13
+msgid "Fork of"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:18
+msgid "Clone from"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:54
+msgid "Clone URL"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
+#: kallithea/templates/summary/summary.html:73
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+msgid "Use Name"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
+msgid "Trending files"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:106
+msgid "Download"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:109
+msgid "There are no downloads yet"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:111
+msgid "Downloads are disabled for this repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:117
+msgid "Download as zip"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:121
+msgid "Check this to download archive with subrepos"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:123
+msgid "With subrepos"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
+msgid "Feed"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:183
+msgid "Latest Changes"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:185
+msgid "Quick Start"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:196
+msgid "Add or upload files directly via Kallithea"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:204
+msgid "Push new repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:212
+msgid "Existing repository?"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:230
+#, python-format
+msgid "Readme file from revision %s:%s"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:315
+#, python-format
+msgid "Download %s as %s"
+msgstr ""
--- a/kallithea/i18n/cs/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/cs/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,13 +1,11 @@
-# Czech translations for Kallithea.
 # Copyright (C) 2014 Various authors, licensing as GPLv3
 # This file is distributed under the same license as the Kallithea project.
-# Automatically generated, 2014.
 # #, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\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/"
@@ -20,14 +18,14 @@
 "X-Generator: Weblate 2.5-dev\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -36,93 +34,93 @@
 msgid "None"
 msgstr ""
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr "(zavřeno)"
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 #, fuzzy
 msgid "No permission to change status"
 msgstr "Změny"
 
-#: kallithea/controllers/changeset.py:214
+#: kallithea/controllers/changeset.py:212
 #, fuzzy, python-format
 msgid "Successfully deleted pull request %s"
 msgstr "Úspěšně aktualizované heslo"
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr "Taková revize neexistuje"
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, fuzzy, python-format
 #| msgid "Go to tip of repository"
 msgid "Could not find other repository %s"
 msgstr "Prázdný repozitář"
 
-#: kallithea/controllers/compare.py:72
+#: kallithea/controllers/compare.py:74
 msgid "Cannot compare repositories of different types"
 msgstr ""
 
-#: kallithea/controllers/compare.py:244
-msgid "Cannot show empty diff"
-msgstr ""
-
 #: kallithea/controllers/compare.py:246
+msgid "Cannot show empty diff"
+msgstr ""
+
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr ""
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr ""
 
-#: kallithea/controllers/error.py:70
+#: kallithea/controllers/error.py:71
 #, fuzzy
 msgid "No response"
 msgstr "Neznámá revize %s"
 
-#: kallithea/controllers/error.py:71
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr ""
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr ""
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr ""
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr "Nemáte oprávnění k zobrazení této stránky"
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr ""
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
@@ -143,121 +141,115 @@
 msgid "Changeset was too big and was cut off..."
 msgstr ""
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr ""
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
 msgstr "Změny na repozitáři %s"
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr "Klikněte pro přidání nového souboru"
 
-#: kallithea/controllers/files.py:93
+#: kallithea/controllers/files.py:86
 #, fuzzy
 #| msgid "There are no files yet. %s"
 msgid "There are no files yet."
 msgstr "Zatím nejsou žádné soubory. %s"
 
-#: kallithea/controllers/files.py:193
+#: kallithea/controllers/files.py:186
 #, python-format
 msgid "%s at %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr ""
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 msgid "You can only delete files with revision being a valid branch"
 msgstr ""
 
-#: kallithea/controllers/files.py:322
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr ""
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr ""
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 msgid "You can only edit files with revision being a valid branch"
 msgstr ""
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr ""
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr "Žádné změny"
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr "Přidaný soubor přes Kallithea"
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr "Žádný obsah"
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr ""
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr ""
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr "Stahování vypnuto"
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr "Neznámá revize %s"
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr "Prázdný repozitář"
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr ""
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr "Změny"
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
 msgstr "Větve"
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr "Tagy"
 
@@ -266,11 +258,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr ""
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr "Skupiny"
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -278,177 +270,177 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr "Repozitáře"
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
 msgstr "Větev"
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr ""
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr "Tag"
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr "Záložka"
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr ""
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr ""
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
 msgstr "Špatná captcha"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr ""
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:190
 msgid "A password reset confirmation code has been sent"
 msgstr ""
 
-#: kallithea/controllers/login.py:238
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Úspěšně aktualizované heslo"
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr "%s (zavřené)"
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr "Záložky"
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 msgid "New pull request iteration created"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, python-format
 msgid "Revision %s not found in %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, python-format
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr ""
 
+#: kallithea/controllers/pullrequests.py:520
+#, python-format
+msgid "This pull request has already been merged to %s."
+msgstr ""
+
 #: kallithea/controllers/pullrequests.py:522
-#, python-format
-msgid "This pull request has already been merged to %s."
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:524
 msgid "This pull request has been closed and can not be updated."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, python-format
 msgid "The following additional changes are available on %s:"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 msgid "No additional changesets found for iterating on this pull request."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 msgid "Git pull requests don't support iterating yet."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, python-format
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 
@@ -464,21 +456,21 @@
 msgid "An error occurred during search operation."
 msgstr "Došlo k chybě při vyhledávání."
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr ""
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -490,123 +482,135 @@
 msgid "Error occurred during update of defaults"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 msgid "Forever"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
 #: kallithea/controllers/admin/users.py:249
 msgid "5 minutes"
 msgstr "5 minut"
 
-#: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
 #: kallithea/controllers/admin/users.py:250
 msgid "1 hour"
 msgstr "1 hodina"
 
-#: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
 #: kallithea/controllers/admin/users.py:251
 msgid "1 day"
 msgstr "1 den"
 
-#: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr "1 měsíc"
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr "Došlo k chybě při vytváření gist"
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:230
-msgid "Successfully updated gist data"
-msgstr ""
-
 #: kallithea/controllers/admin/gists.py:233
+msgid "Successfully updated gist data"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr "Došlo k chybě při aktualizaci hesla uživatele"
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr "Došlo k chybě při ukládání e-mailové adresy"
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, python-format
+msgid "SSH key %s successfully added"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+#, fuzzy
+msgid "SSH key successfully deleted"
+msgstr "Úspěšně aktualizované heslo"
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -614,9 +618,9 @@
 msgid "Read"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -624,9 +628,9 @@
 msgid "Write"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -649,362 +653,347 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
-#: kallithea/templates/admin/auth/auth_settings.html:42
-#: kallithea/templates/base/root.html:50
-msgid "Disabled"
-msgstr ""
-
 #: kallithea/controllers/admin/permissions.py:78
-msgid "Allowed with manual account activation"
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
+#: kallithea/templates/admin/auth/auth_settings.html:42
+#: kallithea/templates/base/root.html:50
+msgid "Disabled"
 msgstr ""
 
 #: kallithea/controllers/admin/permissions.py:80
+msgid "Allowed with manual account activation"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Chyba při vytváření repozitáře %s"
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:290
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:390
+#: kallithea/controllers/admin/repos.py:391
 #, 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:401
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:466
+#: kallithea/controllers/admin/repos.py:468
 msgid "Nothing"
 msgstr "Nic"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:470
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-msgid "Repository has been locked"
-msgstr "Repozitář byl uzamčen"
+#: kallithea/controllers/admin/repos.py:490
+msgid "Cache invalidation successful"
+msgstr ""
 
 #: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-msgid "Repository has been unlocked"
-msgstr "Repozitář byl odemčen"
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:528
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:532
 msgid "An error occurred during cache invalidation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:579
+#: kallithea/controllers/admin/repos.py:541
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:180
+#: kallithea/controllers/admin/settings.py:176
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:192
+#: kallithea/controllers/admin/settings.py:188
 #, fuzzy, python-format
 #| msgid "Watched Repositories"
 msgid "Invalidated %s repositories"
 msgstr "Repozitáře"
 
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 msgid "Hook already exists"
 msgstr ""
 
+#: kallithea/controllers/admin/settings.py:357
+msgid "Builtin hooks are read-only. Please use another hook name."
+msgstr ""
+
 #: kallithea/controllers/admin/settings.py:360
-msgid "Builtin hooks are read-only. Please use another hook name."
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:363
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
+#: kallithea/controllers/admin/user_groups.py:212
+msgid "Successfully deleted user group"
+msgstr ""
+
 #: kallithea/controllers/admin/user_groups.py:217
-msgid "Successfully deleted user group"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:222
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr ""
 
@@ -1034,219 +1023,219 @@
 msgid "The default user cannot be edited"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr ""
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr ""
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr ""
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, python-format
 msgid "Changeset for %s %s not found in %s"
 msgstr ""
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+msgid "SSH access is disabled."
+msgstr ""
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr ""
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:625
+#: kallithea/lib/helpers.py:666
 #, fuzzy, python-format
 #| msgid "Set changeset status"
 msgid "Changeset %s not found"
 msgstr "Změny"
 
-#: kallithea/lib/helpers.py:674
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr ""
 
-#: kallithea/lib/helpers.py:725
-#, python-format
-msgid "Fork name %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:746
-#, python-format
-msgid "Pull request %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:756
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:760
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
-msgid "[updated] repository"
-msgstr ""
-
 #: kallithea/lib/helpers.py:766
+#, python-format
+msgid "Fork name %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:787
+#, python-format
+msgid "Pull request %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:797
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
+msgid "[created] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:801
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
+msgid "[updated] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr ""
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr ""
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr ""
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1254,7 +1243,34 @@
 "repositories"
 msgstr ""
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
@@ -1262,7 +1278,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
@@ -1270,7 +1286,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
@@ -1278,7 +1294,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
@@ -1286,7 +1302,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
@@ -1294,7 +1310,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
@@ -1302,27 +1318,27 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr ""
 
@@ -1331,135 +1347,135 @@
 msgid "on line %s"
 msgstr ""
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1706
+#: kallithea/model/db.py:1640
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1707
+#: kallithea/model/db.py:1641
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1708
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1711
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1730
+#: kallithea/model/db.py:1664
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1732
+#: kallithea/model/db.py:1666
 #, fuzzy
 msgid "Only admins can fork repositories"
 msgstr "Chyba při vytváření repozitáře %s"
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 #, fuzzy
 msgid "Non-admins can fork repositories"
 msgstr "Chyba při vytváření repozitáře %s"
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr ""
 
@@ -1485,303 +1501,315 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:169
+#, 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:170
 #, 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:171
-#, 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:184
+#: kallithea/model/notification.py:183
 msgid "Closing"
 msgstr ""
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 msgid "Cannot create empty pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 msgid "You are not authorized to create the pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 msgid "Missing changesets since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, python-format
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, python-format
 msgid ""
 "This iteration is based on another %s revision and there is no simple "
 "diff."
 msgstr ""
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, python-format
 msgid "No changes found on %s %s since previous iteration."
 msgstr ""
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr ""
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, fuzzy, python-format
+#| msgid "Set changeset status"
+msgid "SSH key %r not found"
+msgstr "Změny"
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:255
 #, 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:263
+#: kallithea/model/user.py:260
 #, 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:270
+#: kallithea/model/user.py:267
 #, 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:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr ""
 
+#: kallithea/model/validators.py:72
+#, python-format
+msgid "Username \"%(username)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:74
 #, python-format
-msgid "Username \"%(username)s\" already exists"
+msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
 #: kallithea/model/validators.py:76
-#, python-format
-msgid "Username \"%(username)s\" cannot be used"
-msgstr ""
-
-#: kallithea/model/validators.py:78
 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:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr ""
 
+#: kallithea/model/validators.py:132
+#, python-format
+msgid "User group \"%(usergroup)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:134
-#, python-format
-msgid "User group \"%(usergroup)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:136
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr ""
 
+#: kallithea/model/validators.py:175
+#, python-format
+msgid "Group \"%(group_name)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:177
 #, python-format
-msgid "Group \"%(group_name)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:179
-#, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 msgid "Invalid username or password"
 msgstr ""
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr ""
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr ""
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
-#: kallithea/model/validators.py:333
+#: kallithea/model/validators.py:318
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:419
+#: kallithea/model/validators.py:404
 #, fuzzy
 msgid "Invalid repository URL"
 msgstr "Prázdný repozitář"
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:430
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:460
+#: kallithea/model/validators.py:445
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:512
+#: kallithea/model/validators.py:497
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:552
+#: kallithea/model/validators.py:537
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 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:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:765
+#: kallithea/model/validators.py:750
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1822,24 +1850,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr ""
 
@@ -1856,7 +1890,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1864,11 +1898,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr ""
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr ""
@@ -1883,7 +1917,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1891,7 +1925,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr ""
@@ -2048,10 +2082,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr ""
@@ -2100,22 +2136,22 @@
 msgstr ""
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr ""
 
@@ -2134,14 +2170,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2149,36 +2185,25 @@
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr ""
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr ""
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr ""
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2225,8 +2250,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 msgid "Never"
 msgstr ""
 
@@ -2259,7 +2286,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr ""
 
@@ -2295,23 +2322,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2339,7 +2368,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2399,7 +2428,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr ""
 
@@ -2412,26 +2441,31 @@
 msgid "Email Addresses"
 msgstr ""
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
+#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/users/user_edit.html:32
+msgid "SSH Keys"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
 msgid "API Keys"
 msgstr ""
 
-#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/my_account/my_account.html:32
 #, fuzzy
 msgid "Owned Repositories"
 msgstr "Repozitáře"
 
-#: kallithea/templates/admin/my_account/my_account.html:30
+#: kallithea/templates/admin/my_account/my_account.html:33
 #: kallithea/templates/journal/journal.html:33
 #, fuzzy
 msgid "Watched Repositories"
 msgstr "Repozitáře"
 
-#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 msgid "Show Permissions"
 msgstr ""
 
@@ -2458,7 +2492,9 @@
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 msgid "Remove"
 msgstr ""
 
@@ -2474,12 +2510,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr ""
 
@@ -2581,6 +2619,42 @@
 msgid "Name"
 msgstr ""
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+msgid "Last Used"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, python-format
+msgid "Confirm to remove this SSH key: %s"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+msgid "New SSH key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+msgid "Public key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 #, fuzzy
 msgid "Repositories You are Watching"
@@ -2598,7 +2672,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr ""
 
@@ -2635,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2795,7 +2869,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr "Pokročilé"
 
@@ -2904,17 +2978,11 @@
 "private repositories and other groups if selected."
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Confirm to delete this group"
 msgstr ""
 
@@ -2944,14 +3012,14 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr ""
@@ -2961,7 +3029,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr ""
@@ -3013,8 +3081,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr ""
 
@@ -3048,58 +3116,18 @@
 "public journal."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-msgid "Change Locking"
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
+#: kallithea/templates/data_table/_dt_elements.html:68
+#, python-format
+msgid "Confirm to delete this repository: %s"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-msgid "Confirm to unlock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-#, fuzzy
-msgid "Unlock Repository"
-msgstr "Prázdný repozitář"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-#, fuzzy
-msgid "Confirm to lock repository."
-msgstr "Prázdný repozitář"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-#, fuzzy
-msgid "Lock Repository"
-msgstr "Prázdný repozitář"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
-#: kallithea/templates/data_table/_dt_elements.html:68
-#, python-format
-msgid "Confirm to delete this repository: %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
 #, fuzzy
 msgid "Delete this Repository"
 msgstr "Prázdný repozitář"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
@@ -3107,15 +3135,15 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3218,20 +3246,12 @@
 msgid "This repository does not have a remote repository URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
+#: kallithea/templates/admin/repos/repo_edit_settings.html:10
 #, fuzzy
-msgid "Permanent Repository ID"
+msgid "Permanent URL"
 msgstr "Prázdný repozitář"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3241,32 +3261,32 @@
 "other cases that you need to hardcode the URL into a 3rd party service."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 #, fuzzy
 msgid "Remote repository"
 msgstr "Prázdný repozitář"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 #, fuzzy
 msgid "Repository URL"
 msgstr "Repozitáře"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr ""
 
@@ -3376,8 +3396,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 #, fuzzy
 msgid "Save Settings"
 msgstr "Nastavení"
@@ -3473,10 +3493,6 @@
 msgid "Kallithea version"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr ""
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr ""
@@ -3497,15 +3513,7 @@
 msgid "Git path"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr ""
 
@@ -3514,47 +3522,39 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
+msgid "Update repository after push (hg update)"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
-msgid "Update repository after push (hg update)"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:33
 msgid "Mercurial extensions"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr ""
 
+#: kallithea/templates/admin/settings/settings_vcs.html:35
+msgid ""
+"Requires hgsubversion library to be installed. Enables cloning of remote "
+"Subversion repositories while converting them to Mercurial."
+msgstr ""
+
 #: kallithea/templates/admin/settings/settings_vcs.html:47
-msgid ""
-"Requires hgsubversion library to be installed. Enables cloning of remote "
-"Subversion repositories while converting them to Mercurial."
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:59
 #, fuzzy
 msgid "Location of repositories"
 msgstr "Chyba při vytváření repozitáře %s"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3603,8 +3603,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-msgid "Clone URL"
+msgid "HTTP Clone URL"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
@@ -3622,59 +3621,74 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+msgid "SSH Clone URL"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 #, fuzzy
 #| msgid "Repositories"
 msgid "Repository page size"
 msgstr "Repozitáře"
 
-#: kallithea/templates/admin/settings/settings_visual.html:57
+#: kallithea/templates/admin/settings/settings_visual.html:68
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:62
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:70
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:81
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 msgid "Show public/private icons next to repository names."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:89
+#: kallithea/templates/admin/settings/settings_visual.html:100
 #, fuzzy
 msgid "Meta Tagging"
 msgstr "Nastavení"
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr ""
 
@@ -3835,12 +3849,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr ""
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr ""
 
@@ -3888,152 +3902,128 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr ""
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr ""
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr ""
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr ""
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr ""
 
+#: kallithea/templates/base/base.html:289
+msgid "Show recent activity"
+msgstr ""
+
+#: kallithea/templates/base/base.html:295
 #: kallithea/templates/base/base.html:296
-msgid "Show recent activity"
+msgid "Public journal"
+msgstr ""
+
+#: kallithea/templates/base/base.html:301
+msgid "Show public gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
-msgid "Public journal"
+msgid "Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:306
+msgid "All Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:308
-msgid "Show public gists"
+msgid "My Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:309
-msgid "Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:313
-msgid "All Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:315
-msgid "My Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:316
 msgid "My Private Gists"
 msgstr ""
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr ""
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 msgid "My Pull Requests"
 msgstr ""
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr ""
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 msgid "Login to Your Account"
 msgstr ""
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 msgid "Forgot password?"
 msgstr ""
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 msgid "Don't have an account?"
 msgstr ""
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr ""
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-#, fuzzy
-msgid "Inherit defaults"
-msgstr "Repozitáře"
+msgid "Create repositories"
+msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-msgid "default permissions"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 
@@ -4767,7 +4757,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr ""
@@ -4779,7 +4769,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr ""
 
@@ -4832,7 +4822,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr ""
 
@@ -4961,8 +4951,8 @@
 msgstr ""
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr ""
 
@@ -5013,8 +5003,8 @@
 msgstr ""
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr ""
 
@@ -5321,9 +5311,9 @@
 msgid "File names"
 msgstr ""
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr ""
 
@@ -5333,20 +5323,20 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr ""
 
@@ -5355,12 +5345,12 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr ""
 
@@ -5401,96 +5391,122 @@
 msgid "%s Summary"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr ""
-
+#: kallithea/templates/summary/summary.html:54
+msgid "Clone URL"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+msgid "Use Name"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:101
-msgid "There are no downloads yet"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:103
-msgid "Downloads are disabled for this repository"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:109
+msgid "There are no downloads yet"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:111
+msgid "Downloads are disabled for this repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 msgid "With subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 #, fuzzy
 msgid "Latest Changes"
 msgstr "Změna stavu-> %s"
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 msgid "Quick Start"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:188
-msgid "Add or upload files directly via Kallithea"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:196
+msgid "Add or upload files directly via Kallithea"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:204
 #, fuzzy
 msgid "Push new repository"
 msgstr "Prázdný repozitář"
 
-#: kallithea/templates/summary/summary.html:204
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr ""
 
+#~ msgid "Repository has been locked"
+#~ msgstr "Repozitář byl uzamčen"
+
+#~ msgid "Repository has been unlocked"
+#~ msgstr "Repozitář byl odemčen"
+
+#, fuzzy
+#~ msgid "Unlock Repository"
+#~ msgstr "Prázdný repozitář"
+
+#, fuzzy
+#~ msgid "Confirm to lock repository."
+#~ msgstr "Prázdný repozitář"
+
+#, fuzzy
+#~ msgid "Lock Repository"
+#~ msgstr "Prázdný repozitář"
+
+#, fuzzy
+#~ msgid "Inherit defaults"
+#~ msgstr "Repozitáře"
+
 #, fuzzy
 #~| msgid "Repository URL"
 #~ msgid "Repository Group"
--- a/kallithea/i18n/da/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/da/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,13 +1,10 @@
-# Translations template for Kallithea.
 # Copyright (C) 2017 Various authors, licensing as GPLv3
 # This file is distributed under the same license as the Kallithea project.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2017.
-#
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3.99\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\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/"
@@ -20,14 +17,14 @@
 "X-Generator: Weblate 3.5.1\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr "Der er ingen changesets endnu"
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -36,94 +33,94 @@
 msgid "None"
 msgstr "Ingen"
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr "(lukket)"
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr "Vis mellemrum"
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr "Ignorer mellemrum"
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr "Øg diff konteksten med %(num)s linjer"
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 #, fuzzy
 #| msgid "No permission to change pull request status"
 msgid "No permission to change status"
 msgstr "Ingen tilladelse til ændring af status for pull-forespørgsel"
 
-#: kallithea/controllers/changeset.py:214
+#: kallithea/controllers/changeset.py:212
 #, python-format
 msgid "Successfully deleted pull request %s"
 msgstr "Pull-forespørgsel %s slettet successfuldt"
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr "En sådan revision findes ikke for dette repository"
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, python-format
 msgid "Could not find other repository %s"
 msgstr "Kunne ikke finde andet repository %s"
 
-#: kallithea/controllers/compare.py:72
+#: kallithea/controllers/compare.py:74
 msgid "Cannot compare repositories of different types"
 msgstr "Kan ikke sammenligne repositories af forskellige typer"
 
-#: kallithea/controllers/compare.py:244
+#: kallithea/controllers/compare.py:246
 msgid "Cannot show empty diff"
 msgstr "Kan ikke vise en tom diff"
 
-#: kallithea/controllers/compare.py:246
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr "Ingen forfader fundet for merge diff"
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr "Flere merge forfædre fundet for merge sammenligning"
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr "Kan ikke sammenligne repositories uden en fælles forfader"
 
-#: kallithea/controllers/error.py:70
+#: kallithea/controllers/error.py:71
 msgid "No response"
 msgstr "Intet svar"
 
-#: kallithea/controllers/error.py:71
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr "Ukendt fejl"
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr ""
 "Forespørgslen kunne ikke forstås af serveren på grund af fejlformet "
 "syntaks."
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr "Uautoriseret adgang til ressource"
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr "Du har ikke tilladelse til at se denne side"
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr "Kunne ikke finde ressourcen"
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
@@ -146,109 +143,103 @@
 msgid "Changeset was too big and was cut off..."
 msgstr "Changesettet var for stor og blev afskåret..."
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr "Feed for %s %s"
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
 msgstr "Ændringer på repository %s"
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr "Klik her  for at tilføje en ny fil"
 
-#: kallithea/controllers/files.py:93
+#: kallithea/controllers/files.py:86
 #, fuzzy
 #| msgid "There are no files yet. %s"
 msgid "There are no files yet."
 msgstr "Der er ingen filer endnu. %s"
 
-#: kallithea/controllers/files.py:193
+#: kallithea/controllers/files.py:186
 #, python-format
 msgid "%s at %s"
 msgstr "%s fra %s"
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr "Dette repository er låst af %s den %s"
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 msgid "You can only delete files with revision being a valid branch"
 msgstr "Du kan kun slette filer, hvor revisionen er en gyldig branch"
 
-#: kallithea/controllers/files.py:322
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr "Slettet fil %s via Kallithea"
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr "Successfuldt slettet filen %s"
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr "Fejl opstået under commit"
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 msgid "You can only edit files with revision being a valid branch"
 msgstr "Du kan kun redigere filer, hvor revisionen er en gyldig branch"
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr "Redigeret fil %s via Kallithea"
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr "Ingen ændringer"
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr "Successfuldt committed til %s"
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr "Tilføjet fil via Kallithea"
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr "Intet indhold"
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr "Intet filnavn"
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr ""
 "Placeringen skal være en relativ sti og må ikke indeholde .. i stien"
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr "Downloads er deaktiveret"
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr "Ukendt revision %s"
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr "Tomt repository"
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr "Ukendt arkivtype"
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
@@ -256,14 +247,14 @@
 msgid "Changesets"
 msgstr "Changesets"
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 #, fuzzy
 msgid "Branches"
 msgstr "Branches"
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr "Tags"
 
@@ -272,11 +263,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr "Der opstod en fejl under repository forking %s"
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr "Grupper"
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -284,12 +275,12 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 #, fuzzy
 msgid "Repositories"
 msgstr "Repositories"
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
@@ -297,164 +288,164 @@
 msgid "Branch"
 msgstr "Branch"
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr "Lukkede Branches"
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr "Tag"
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr "Bogmærke"
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr "Offentlig journal"
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr "Journal"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
 msgstr "Dårlig captcha"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, 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:190
 msgid "A password reset confirmation code has been sent"
 msgstr "En bekræftelseskode til ændring af adgangskode er sendt"
 
-#: kallithea/controllers/login.py:238
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Ugyldig token for ændring af adgangskode"
 
-#: kallithea/controllers/admin/my_account.py:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Successfuld ændring af adgangskode"
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr "Ugyldig reviewer \"%s\" angivet"
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr "%s (lukket)"
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 #, fuzzy
 msgid "Changeset"
 msgstr "Changeset"
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr "Speciel"
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr "Bogmærker"
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr "Fejl ved oprettelse af pull-forespørgsel: %s"
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr "Der opstod en fejl under oprettelse af pull-forespørgsel"
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr "Åbnede ny pull-forespørgsel med success"
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 msgid "New pull request iteration created"
 msgstr "Ny pull-forespørgsel iteration oprettet"
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr "I mellemtiden er de følgende reviewers tilføjet: %s"
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr "I mellemtiden er de følgende reviewers fjernet: %s"
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr "Ingen beskrivelse"
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
 msgstr "Pull-forespørgsel opdateret"
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr "Slettede pull-forespørgsel med success"
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, python-format
 msgid "Revision %s not found in %s"
 msgstr "Revision %s er ikke fundet i %s"
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, python-format
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr ""
 "Fejl: Changesets ikke fundet, ved visning af pull-forespørgsel fra %s."
 
-#: kallithea/controllers/pullrequests.py:522
+#: kallithea/controllers/pullrequests.py:520
 #, python-format
 msgid "This pull request has already been merged to %s."
 msgstr "Denne pull-forespørgsel er allerede merged til %s."
 
-#: kallithea/controllers/pullrequests.py:524
+#: kallithea/controllers/pullrequests.py:522
 msgid "This pull request has been closed and can not be updated."
 msgstr "Denne pull-forespørgsel er lukket og kan ikke opdateres."
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, python-format
 msgid "The following additional changes are available on %s:"
 msgstr "Følgende yderligere ændringer er tilgængelige på %s:"
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 msgid "No additional changesets found for iterating on this pull request."
 msgstr ""
 "Ingen yderligere changesets fundet ved iteration på denne pull-"
 "forespørgsel."
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr "Bemærk: Branch %s har et andet head: %s."
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 msgid "Git pull requests don't support iterating yet."
 msgstr "Git pull-forespørgsler supportere ej iteration endnu."
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, python-format
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
@@ -462,7 +453,7 @@
 "Fejl: Nogle changesets kunne ikke findes ved visning af pull-forespørgsel "
 "fra %s."
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 "Diff'en kunne ikke vises - pull-forespørgslens revisions kunne ikke "
@@ -480,21 +471,21 @@
 msgid "An error occurred during search operation."
 msgstr "Der opstod en fejl under søgning."
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr "Ingen data er klar endnu"
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr "Statistik er slået fra for dette repository"
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr "Auth-indstillinger opdateret successfuldt"
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr "Der opstod en fejl under opdatering af auth-indstillinger"
 
@@ -506,125 +497,139 @@
 msgid "Error occurred during update of defaults"
 msgstr "Der opstod en fejl under opdatering af standarder"
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 msgid "Forever"
 msgstr "For evigt"
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
 #: kallithea/controllers/admin/users.py:249
 msgid "5 minutes"
 msgstr "5 minutter"
 
-#: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
 #: kallithea/controllers/admin/users.py:250
 msgid "1 hour"
 msgstr "1 time"
 
-#: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
 #: kallithea/controllers/admin/users.py:251
 msgid "1 day"
 msgstr "1 dag"
 
-#: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr "1 måned"
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr "Levetid"
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr "Der opstod en fejl under oprettelse af gist"
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr "Slettet gist %s"
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
 msgstr "Uændret"
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr "Opdateret gist-indhold successfuldt"
 
-#: kallithea/controllers/admin/gists.py:230
+#: kallithea/controllers/admin/gists.py:233
 msgid "Successfully updated gist data"
 msgstr "Opdateret gist-data successfuldt"
 
-#: kallithea/controllers/admin/gists.py:233
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
 msgstr "Der opstod en fejl under opdatering af gist %s"
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 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 "
 "applikationen"
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr "Din konto er blevet opdateret successfuldt"
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr "Der opstod en fejl under opdatering af bruger %s"
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr "Der opstod en fejl under opdatering af bruger adgangskode"
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr "Tilføjet email %s til bruger"
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr "Der opstod en fejl under tilføjelse af email"
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr "Fjernet email fra brugeren"
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr "API-nøgle oprettet successfuldt"
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr "API-nøgle nulstillet successfuldt"
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr "API-nøgle slettet successfuldt"
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, fuzzy, python-format
+#| msgid "API key successfully created"
+msgid "SSH key %s successfully added"
+msgstr "API-nøgle oprettet successfuldt"
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+#, fuzzy
+#| msgid "API key successfully deleted"
+msgid "SSH key successfully deleted"
+msgstr "API-nøgle slettet successfuldt"
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -632,9 +637,9 @@
 msgid "Read"
 msgstr "Læs"
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -642,9 +647,9 @@
 msgid "Write"
 msgstr "Skriv"
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -667,256 +672,241 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr "Admin"
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:50
 msgid "Disabled"
 msgstr "Deaktiveret"
 
-#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:80
 msgid "Allowed with manual account activation"
 msgstr "Tilladt med manuel kontoaktivering"
 
-#: kallithea/controllers/admin/permissions.py:80
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr "Tilladt med automatisk kontoaktivering"
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr "Manuel aktivering af ekstern konto"
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr "Automatisk aktivering af ekstern konto"
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr "Aktiveret"
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr "Globale tilladelser opdateret"
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr "Der opstod en fejl under opdatering af tilladelser"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, 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:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr "Oprettet repository-gruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Opdateret repository-gruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, 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:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, 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:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, 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:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Fjernet repository-gruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, 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:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Kan ikke tilbagekalde tilladelse for én selv som admin"
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr "Repository-gruppe tilladelser opdateret"
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr "Der opstod en fejl under tilbagekaldelse af tilladelse"
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Fejl ved oprettelse af repository %s"
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Oprettet repository %s fra %s"
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Forked repository %s som %s"
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr "Oprettet repository %s"
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Repository %s opdateret"
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, 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:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr "Fraskilt %s forks"
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr "Slettet %s forks"
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Slettet repository %s"
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, 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:290
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "Der opstod en fejl under sletning af %s"
 
-#: kallithea/controllers/admin/repos.py:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr "Repository tilladelser opdateret"
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr "Feltvaliderings fejl: %s"
 
-#: kallithea/controllers/admin/repos.py:390
+#: kallithea/controllers/admin/repos.py:391
 #, 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:401
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr "Der opstod en fejl under fjernelse af feltet"
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr "-- Ikke en fork --"
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr "Opdateret repository's synlighed i den offentlige journal"
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 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:466
+#: kallithea/controllers/admin/repos.py:468
 msgid "Nothing"
 msgstr "Intet"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:470
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "Mærket repository %s som fork af %s"
 
-#: kallithea/controllers/admin/repos.py:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr "Der opstod en fejl under denne operation"
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-msgid "Repository has been locked"
-msgstr "Repository er blevet låst"
+#: kallithea/controllers/admin/repos.py:490
+msgid "Cache invalidation successful"
+msgstr "Ugyldiggørelse af cache er succesfuld"
 
 #: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-msgid "Repository has been unlocked"
-msgstr "Repository er blevet låst op"
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr "Der opstod en fejl ved oplåsning"
-
-#: kallithea/controllers/admin/repos.py:528
-msgid "Cache invalidation successful"
-msgstr "Ugyldiggørelse af cache er succesfuld"
-
-#: kallithea/controllers/admin/repos.py:532
 msgid "An error occurred during cache invalidation"
 msgstr "Der opstod en fejl under cache ugyldiggørelse"
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 #, fuzzy
 msgid "Pulled from remote location"
 msgstr "Pulled fra remote placering"
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 msgid "An error occurred during pull from remote location"
 msgstr "Der opstod en fejl under pull fra remote placering"
 
-#: kallithea/controllers/admin/repos.py:579
+#: kallithea/controllers/admin/repos.py:541
 msgid "An error occurred during deletion of repository stats"
 msgstr "Der opstod en fejl under sletning af repository statistik"
 
-#: kallithea/controllers/admin/settings.py:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr "Opdateret VCS-indstillinger"
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
@@ -924,110 +914,110 @@
 "Ude af stand til at aktivere hgsubversion understøttelse. \"hgsubversion"
 "\" biblioteket mangler"
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
 msgstr "Der opstod en fejl ved opdatering af applikationsindstillinger"
 
-#: kallithea/controllers/admin/settings.py:180
+#: kallithea/controllers/admin/settings.py:176
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr "Repositories genscannet successfuldt. Tilføjet: %s. Fjernet: %s."
 
-#: kallithea/controllers/admin/settings.py:192
+#: kallithea/controllers/admin/settings.py:188
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr "Ugyldiggjort %s repositories"
 
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr "Opdateret applikationsindstillinger"
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr "Opdateret visualiseringsindstillinger"
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
 msgstr "Der opstod en fejl under opdatering af visualiseringsindstillinger"
 
-#: kallithea/controllers/admin/settings.py:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr "Indtast email-adresse"
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr "Send email-opgave oprettet"
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "Ingen data er klar endnu"
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:357
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:363
+#: kallithea/controllers/admin/settings.py:360
 msgid "Added new hook"
 msgstr "Tilføjet nyt hook"
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr "Opdateret hooks"
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr "Der opstod en fejl under oprettelse af et hook"
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr "Whoosh reindex-opgave skeduleret"
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr "Oprettet brugergruppe %s"
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, 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:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr "Opdateret brugergruppe %s"
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, 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:217
+#: kallithea/controllers/admin/user_groups.py:212
 msgid "Successfully deleted user group"
 msgstr "Brugergruppe slettet succesfuldt"
 
-#: kallithea/controllers/admin/user_groups.py:222
+#: kallithea/controllers/admin/user_groups.py:217
 msgid "An error occurred during deletion of user group"
 msgstr "Der opstod en fejl under sletning af brugergruppe"
 
-#: kallithea/controllers/admin/user_groups.py:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr "Brugergrupper-tilladelser opdateret"
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr "Tilladelser opdateret"
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr "Der opstod en fejl under gemning af tilladelser"
 
@@ -1057,220 +1047,220 @@
 msgid "The default user cannot be edited"
 msgstr "Standardbrugeren kan ikke redigeres"
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr "Tilføjet IP-adresse %s til bruger-whitelist"
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr "Der opstod en fejl under tilføjelse af IP-adresse"
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr "Fjernet IP-adresse fra bruger-whitelist"
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 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:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr "Du skal være logget ind for at se denne side"
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr "Ugyldig API-nøgle"
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr "CSRF-token lækage opdaget, alle form-tokens er invalideret"
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr "Repository ikke fundet i filsystemet"
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, python-format
 msgid "Changeset for %s %s not found in %s"
 msgstr "Changeset for %s %s ikke fundet i %s"
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+msgid "SSH access is disabled."
+msgstr ""
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr "Binær fil"
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 "Changeset var for stor, og blev afskåret, brug diff menu for at få vist "
 "denne diff"
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr "Ingen ændringer fundet"
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "Slettet branch: %s"
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr "Oprettet tag: %s"
 
-#: kallithea/lib/helpers.py:625
+#: kallithea/lib/helpers.py:666
 #, python-format
 msgid "Changeset %s not found"
 msgstr "Changeset %s ikke fundet"
 
-#: kallithea/lib/helpers.py:674
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "Vis alle kombineret changesets %s->%s"
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 msgid "Compare view"
 msgstr "Sammenlign visning"
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr "og"
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr "%s flere"
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "revisioner"
 
-#: kallithea/lib/helpers.py:725
+#: kallithea/lib/helpers.py:766
 #, python-format
 msgid "Fork name %s"
 msgstr "Fork-navn %s"
 
-#: kallithea/lib/helpers.py:746
+#: kallithea/lib/helpers.py:787
 #, python-format
 msgid "Pull request %s"
 msgstr "Pull-forespørgsel %s"
 
-#: kallithea/lib/helpers.py:756
+#: kallithea/lib/helpers.py:797
 msgid "[deleted] repository"
 msgstr "[slettet] repository"
 
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
 msgid "[created] repository"
 msgstr "[oprettet] repository"
 
-#: kallithea/lib/helpers.py:760
+#: kallithea/lib/helpers.py:801
 msgid "[created] repository as fork"
 msgstr "[oprettet] repository som fork"
 
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
 msgid "[forked] repository"
 msgstr "[forked] repository"
 
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
 msgid "[updated] repository"
 msgstr "[opdateret] repository"
 
-#: kallithea/lib/helpers.py:766
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr "[hentet] arkiv fra repository"
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr "[slettet] repository"
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr "[oprettet] bruger"
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr "[opdateret] bruger"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr "[oprettet] brugergruppe"
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr "[opdateret] brugergruppe"
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr "[kommenterede] på revision i repository"
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr "[kommenterede] på pull-forespørgsel for"
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr "[lukket] pull-forespørgsel for"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr "[pushed] ind i"
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr "[committed via kallithea] ind i repository"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr "[pulled fra remote] ind i repository"
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr "[pulled] fra"
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr "[begyndt at følge] repository"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr "[stoppet at følge] repository"
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr " og %s flere"
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "Ingen filer"
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr "ny fil"
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr "mod"
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr "del"
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr "omdøb"
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1280,69 +1270,96 @@
 "%s repository er ikke knyttet til db, måske var det skabt eller omdøbt "
 "fra filsystemet, kør applikationen igen for at scanne repositories"
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr "i %s"
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr "%s siden"
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr "i %s og %s"
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s og %s siden"
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr "lige nu"
 
@@ -1351,136 +1368,136 @@
 msgid "on line %s"
 msgstr "på linje %s"
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr "[Omtale]"
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr "top-niveau"
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr "Kallithea Administrator"
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
 msgstr "Standard-bruger har ikke adgang til nye repositories"
 
-#: kallithea/model/db.py:1706
+#: kallithea/model/db.py:1640
 msgid "Default user has read access to new repositories"
 msgstr "Standard-bruger har læse-adgang til nye repositories"
 
-#: kallithea/model/db.py:1707
+#: kallithea/model/db.py:1641
 msgid "Default user has write access to new repositories"
 msgstr "Standard-bruger har skrive-adgang til nye repositories"
 
-#: kallithea/model/db.py:1708
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr "Standard-bruger har admin-adgang til nye repositories"
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr "Standard-bruger har ikke adgang til nye repository-grupper"
 
-#: kallithea/model/db.py:1711
+#: kallithea/model/db.py:1645
 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:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr "Standard-bruger har skrive-adgang til nye repository-grupper"
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr "Standard-bruger har admin-adgang til nye repository-grupper"
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr "Standard-bruger har ikke adgang til nye brugergrupper"
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr "Standard-bruger har læse-adgang til nye brugergrupper"
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr "Standard-bruger har skrive-adgang til nye brugergrupper"
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr "Standard-bruger har admin-adgang til nye brugergrupper"
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 msgid "Only admins can create repository groups"
 msgstr "Kun administratorer kan oprette repository-grupper"
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 msgid "Non-admins can create repository groups"
 msgstr "Ikke-administratorer kan oprette repository-grupper"
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 msgid "Only admins can create user groups"
 msgstr "Kun administratorer kan oprette brugergrupper"
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 msgid "Non-admins can create user groups"
 msgstr "Ikke-administratorer kan oprette brugergrupper"
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr "Kun administratorer kan oprette top-niveau repositories"
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr "Ikke-administratorer kan oprette top-niveau repositories"
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 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:1730
+#: kallithea/model/db.py:1664
 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:1732
+#: kallithea/model/db.py:1666
 msgid "Only admins can fork repositories"
 msgstr "Kun admins kan fork repositories"
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 msgid "Non-admins can fork repositories"
 msgstr "Ikke-administratorer kan forke repositories"
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr "Registrering deaktiveret"
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr "Brugerregistrering med manuel kontoaktivering"
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr "Brugerregistrering med automatisk kontoaktivering"
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 msgid "Not reviewed"
 msgstr "Ikke gennemgået"
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 msgid "Under review"
 msgstr "Under gennemgang"
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 msgid "Not approved"
 msgstr "Ikke godkendt"
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr "Godkendt"
 
@@ -1506,7 +1523,7 @@
 msgid "Name must not contain only digits"
 msgstr "Navn må ikke kun indeholde cifre"
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
@@ -1515,12 +1532,12 @@
 "[Kommentar] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" på "
 "%(branch)s"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr "Ny bruger %(new_username)s registreret"
 
-#: kallithea/model/notification.py:170
+#: kallithea/model/notification.py:169
 #, python-format
 msgid ""
 "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
@@ -1529,7 +1546,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:171
+#: kallithea/model/notification.py:170
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
@@ -1538,11 +1555,11 @@
 "[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:184
+#: kallithea/model/notification.py:183
 msgid "Closing"
 msgstr "Lukning"
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
@@ -1550,266 +1567,278 @@
 "%(user)s vil have dig til at gennemgå pull-forespørgsel %(pr_nice_id)s: "
 "%(pr_title)s"
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 msgid "Cannot create empty pull request"
 msgstr "Kan ikke oprette en tom pull-forespørgsel"
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 msgid "You are not authorized to create the pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 msgid "Missing changesets since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, python-format
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, python-format
 msgid ""
 "This iteration is based on another %s revision and there is no simple "
 "diff."
 msgstr ""
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, python-format
 msgid "No changes found on %s %s since previous iteration."
 msgstr ""
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr ""
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, fuzzy, python-format
+#| msgid "Changeset %s not found"
+msgid "SSH key %r not found"
+msgstr "Changeset %s ikke fundet"
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:255
 #, 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:263
+#: kallithea/model/user.py:260
 #, 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:270
+#: kallithea/model/user.py:267
 #, 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:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr ""
 
+#: kallithea/model/validators.py:72
+#, python-format
+msgid "Username \"%(username)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:74
 #, python-format
-msgid "Username \"%(username)s\" already exists"
+msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
 #: kallithea/model/validators.py:76
-#, python-format
-msgid "Username \"%(username)s\" cannot be used"
-msgstr ""
-
-#: kallithea/model/validators.py:78
 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:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr ""
 
+#: kallithea/model/validators.py:132
+#, python-format
+msgid "User group \"%(usergroup)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:134
-#, python-format
-msgid "User group \"%(usergroup)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:136
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr ""
 
+#: kallithea/model/validators.py:175
+#, python-format
+msgid "Group \"%(group_name)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:177
 #, python-format
-msgid "Group \"%(group_name)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:179
-#, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 msgid "Invalid username or password"
 msgstr ""
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr ""
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr ""
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
-#: kallithea/model/validators.py:333
+#: kallithea/model/validators.py:318
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:419
+#: kallithea/model/validators.py:404
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:430
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:460
+#: kallithea/model/validators.py:445
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:512
+#: kallithea/model/validators.py:497
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:552
+#: kallithea/model/validators.py:537
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 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:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:765
+#: kallithea/model/validators.py:750
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1850,24 +1879,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr ""
 
@@ -1884,7 +1919,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1892,11 +1927,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr ""
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr ""
@@ -1911,7 +1946,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1919,7 +1954,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr ""
@@ -2075,10 +2110,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr ""
@@ -2127,22 +2164,22 @@
 msgstr ""
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr ""
 
@@ -2160,14 +2197,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2175,36 +2212,25 @@
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr ""
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr ""
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr ""
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2251,8 +2277,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 msgid "Never"
 msgstr ""
 
@@ -2285,7 +2313,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr ""
 
@@ -2321,23 +2349,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2365,7 +2395,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2425,7 +2455,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr ""
 
@@ -2438,24 +2468,29 @@
 msgid "Email Addresses"
 msgstr ""
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
-msgid "API Keys"
-msgstr ""
-
 #: kallithea/templates/admin/my_account/my_account.html:29
-msgid "Owned Repositories"
-msgstr ""
-
-#: kallithea/templates/admin/my_account/my_account.html:30
-#: kallithea/templates/journal/journal.html:33
-msgid "Watched Repositories"
+#: kallithea/templates/admin/users/user_edit.html:32
+msgid "SSH Keys"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
+msgid "API Keys"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:32
+msgid "Owned Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:33
+#: kallithea/templates/journal/journal.html:33
+msgid "Watched Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 msgid "Show Permissions"
 msgstr ""
 
@@ -2482,7 +2517,9 @@
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 msgid "Remove"
 msgstr ""
 
@@ -2498,12 +2535,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr ""
 
@@ -2604,6 +2643,42 @@
 msgid "Name"
 msgstr ""
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+msgid "Last Used"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, python-format
+msgid "Confirm to remove this SSH key: %s"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+msgid "New SSH key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+msgid "Public key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 msgid "Repositories You are Watching"
 msgstr ""
@@ -2620,7 +2695,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr ""
 
@@ -2656,7 +2731,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2816,7 +2891,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr ""
 
@@ -2922,17 +2997,11 @@
 "private repositories and other groups if selected."
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Confirm to delete this group"
 msgstr ""
 
@@ -2960,14 +3029,14 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr ""
@@ -2977,7 +3046,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr ""
@@ -3029,8 +3098,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr ""
 
@@ -3064,69 +3133,32 @@
 "public journal."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-msgid "Change Locking"
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
+#: kallithea/templates/data_table/_dt_elements.html:68
+#, python-format
+msgid "Confirm to delete this repository: %s"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-msgid "Confirm to unlock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-msgid "Unlock Repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-msgid "Confirm to lock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-msgid "Lock Repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
-#: kallithea/templates/data_table/_dt_elements.html:68
-#, python-format
-msgid "Confirm to delete this repository: %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
 msgid "Delete this Repository"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3223,19 +3255,11 @@
 msgid "This repository does not have a remote repository URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "Permanent Repository ID"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_settings.html:10
+msgid "Permanent URL"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3245,30 +3269,30 @@
 "other cases that you need to hardcode the URL into a 3rd party service."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 msgid "Remote repository"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 msgid "Repository URL"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr ""
 
@@ -3377,8 +3401,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 msgid "Save Settings"
 msgstr ""
 
@@ -3473,10 +3497,6 @@
 msgid "Kallithea version"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr ""
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr ""
@@ -3497,15 +3517,7 @@
 msgid "Git path"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr ""
 
@@ -3514,46 +3526,38 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
+msgid "Update repository after push (hg update)"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
-msgid "Update repository after push (hg update)"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:33
 msgid "Mercurial extensions"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr ""
 
+#: kallithea/templates/admin/settings/settings_vcs.html:35
+msgid ""
+"Requires hgsubversion library to be installed. Enables cloning of remote "
+"Subversion repositories while converting them to Mercurial."
+msgstr ""
+
 #: kallithea/templates/admin/settings/settings_vcs.html:47
-msgid ""
-"Requires hgsubversion library to be installed. Enables cloning of remote "
-"Subversion repositories while converting them to Mercurial."
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:59
 msgid "Location of repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3602,8 +3606,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-msgid "Clone URL"
+msgid "HTTP Clone URL"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
@@ -3621,56 +3624,71 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+msgid "SSH Clone URL"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 msgid "Repository page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:57
+#: kallithea/templates/admin/settings/settings_visual.html:68
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:62
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:70
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:81
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 msgid "Show public/private icons next to repository names."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:89
+#: kallithea/templates/admin/settings/settings_visual.html:100
 msgid "Meta Tagging"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr ""
 
@@ -3831,12 +3849,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr ""
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr ""
 
@@ -3884,153 +3902,128 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr ""
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr ""
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr ""
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr ""
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr ""
 
+#: kallithea/templates/base/base.html:289
+msgid "Show recent activity"
+msgstr ""
+
+#: kallithea/templates/base/base.html:295
 #: kallithea/templates/base/base.html:296
-msgid "Show recent activity"
+msgid "Public journal"
+msgstr ""
+
+#: kallithea/templates/base/base.html:301
+msgid "Show public gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
-msgid "Public journal"
+msgid "Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:306
+msgid "All Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:308
-msgid "Show public gists"
+msgid "My Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:309
-msgid "Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:313
-msgid "All Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:315
-msgid "My Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:316
 msgid "My Private Gists"
 msgstr ""
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr ""
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 msgid "My Pull Requests"
 msgstr ""
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr ""
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 msgid "Login to Your Account"
 msgstr ""
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 msgid "Forgot password?"
 msgstr ""
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 msgid "Don't have an account?"
 msgstr ""
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr ""
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-msgid "Inherit defaults"
+msgid "Create repositories"
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-#, fuzzy
-#| msgid "Updated permissions"
-msgid "default permissions"
-msgstr "Tilladelser opdateret"
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 
@@ -4739,7 +4732,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr ""
@@ -4751,7 +4744,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr ""
 
@@ -4803,7 +4796,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr ""
 
@@ -4931,8 +4924,8 @@
 msgstr ""
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr ""
 
@@ -4983,8 +4976,8 @@
 msgstr ""
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr ""
 
@@ -5290,9 +5283,9 @@
 msgid "File names"
 msgstr ""
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr ""
 
@@ -5302,20 +5295,20 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr ""
 
@@ -5324,12 +5317,12 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr ""
 
@@ -5370,94 +5363,118 @@
 msgid "%s Summary"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr ""
-
+#: kallithea/templates/summary/summary.html:54
+msgid "Clone URL"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+msgid "Use Name"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:101
-msgid "There are no downloads yet"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:103
-msgid "Downloads are disabled for this repository"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:109
+msgid "There are no downloads yet"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:111
+msgid "Downloads are disabled for this repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 msgid "With subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 msgid "Latest Changes"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 msgid "Quick Start"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:188
-msgid "Add or upload files directly via Kallithea"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:196
-msgid "Push new repository"
+msgid "Add or upload files directly via Kallithea"
 msgstr ""
 
 #: kallithea/templates/summary/summary.html:204
+msgid "Push new repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr ""
 
+#~ msgid "This repository has been locked by %s on %s"
+#~ msgstr "Dette repository er låst af %s den %s"
+
+#~ msgid "Repository has been locked"
+#~ msgstr "Repository er blevet låst"
+
+#~ msgid "Repository has been unlocked"
+#~ msgstr "Repository er blevet låst op"
+
+#~ msgid "An error occurred during unlocking"
+#~ msgstr "Der opstod en fejl ved oplåsning"
+
+#~ msgid "Invalid API key"
+#~ msgstr "Ugyldig API-nøgle"
+
+#, fuzzy
+#~| msgid "Updated permissions"
+#~ msgid "default permissions"
+#~ msgstr "Tilladelser opdateret"
+
 #~ msgid "There is no index to search in. Please run whoosh indexer"
 #~ msgstr "Der er intet indekseret til at søge i. Kør whoosh indexer"
 
--- a/kallithea/i18n/de/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/de/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,17 +1,14 @@
-# German translations for Kallithea.
 # Copyright (C) 2014 RhodeCode GmbH, and others.
 # This file is distributed under the same license as the Kallithea project.
-# Translators:
-# stephanj <info@stephan-jauernick.de>, 2013
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
-"PO-Revision-Date: 2019-05-08 20:48+0000\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\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/stable/"
-"de/>\n"
+"Language-Team: German <https://hosted.weblate.org/projects/kallithea/"
+"kallithea/de/>\n"
 "Language: de\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -20,14 +17,14 @@
 "X-Generator: Weblate 3.7-dev\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr "Es gibt noch keine Änderungssätze"
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -36,48 +33,48 @@
 msgid "None"
 msgstr "Keine"
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr "(geschlossen)"
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr "Zeige unsichtbare Zeichen"
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr "Ignoriere unsichtbare Zeichen"
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr "Erhöhe diff-Kontext auf %(num)s Zeilen"
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 #, fuzzy
 #| msgid "No permission to change pull request status"
 msgid "No permission to change status"
 msgstr "Keine Berechtigung zum Ändern des Status des Pull Requests"
 
-#: kallithea/controllers/changeset.py:214
+#: kallithea/controllers/changeset.py:212
 #, python-format
 msgid "Successfully deleted pull request %s"
 msgstr "Pull-Request %s erfolgreich gelöscht"
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr "Die angegebene Version existiert nicht in diesem Repository"
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, fuzzy, python-format
 #| msgid "Go to tip of repository"
 msgid "Could not find other repository %s"
 msgstr "Gehe zum Tip des Repositorys"
 
-#: kallithea/controllers/compare.py:72
+#: kallithea/controllers/compare.py:74
 #, fuzzy
 #| msgid "Cannot compare repositories without using common ancestor"
 msgid "Cannot compare repositories of different types"
@@ -85,52 +82,52 @@
 "Ohne einen gemeinsamen Vorfahren ist ein Vergleich der Repositories nicht "
 "möglich"
 
-#: kallithea/controllers/compare.py:244
+#: kallithea/controllers/compare.py:246
 msgid "Cannot show empty diff"
 msgstr "Kann leeren diff nicht anzeigen"
 
-#: kallithea/controllers/compare.py:246
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr "Es konnte kein Vorfahre für den merge diff gefunden werden"
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr "Es wurden mehrere merge Vorfahren für den merge Vergleich gefunden"
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr ""
 "Ohne einen gemeinsamen Vorfahren ist ein Vergleich der Repositories nicht "
 "möglich"
 
-#: kallithea/controllers/error.py:70
+#: kallithea/controllers/error.py:71
 msgid "No response"
 msgstr "Keine Rückmeldung"
 
-#: kallithea/controllers/error.py:71
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr "Unbekannter Fehler"
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr ""
 "Die Anfrage konnte wegen ungültiger Syntax vom Server nicht ausgewertet "
 "werden."
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr "Unauthorisierter Zugang zur Ressource"
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr "Du hast keine Rechte, um diese Seite zu betrachten"
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr "Die Ressource konnte nicht gefunden werden"
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
@@ -153,125 +150,119 @@
 msgid "Changeset was too big and was cut off..."
 msgstr "Der Änderungssatz war zu groß und wurde abgeschnitten..."
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr "%s %s Feed"
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
 msgstr "Änderungen im %s Repository"
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr "Hier klicken, um eine neue Datei hinzuzufügen"
 
-#: kallithea/controllers/files.py:93
+#: kallithea/controllers/files.py:86
 #, fuzzy
 #| msgid "There are no files yet. %s"
 msgid "There are no files yet."
 msgstr "Es gibt hier noch keine Dateien. %s"
 
-#: kallithea/controllers/files.py:193
+#: kallithea/controllers/files.py:186
 #, python-format
 msgid "%s at %s"
 msgstr "%s auf %s"
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr "Dieses Repository ist von %s am %s gesperrt worden"
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 #, fuzzy
 msgid "You can only delete files with revision being a valid branch"
 msgstr ""
 "Dateien können nur gelöscht werden, deren Revision ein gültiger Branch ist"
 
-#: kallithea/controllers/files.py:322
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr "Datei %s via Kallithea gelöscht"
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr "Datei %s erfolgreich gelöscht"
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr "Während des Commits trat ein Fehler auf"
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 #, fuzzy
 msgid "You can only edit files with revision being a valid branch"
 msgstr ""
 "Dateien können nur editiert werden, deren Revision ein gültiger Branch ist"
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr "Datei %s via Kallithea editiert"
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr "Keine Änderungen"
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr "Der Commit zu %s war erfolgreich"
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr "Datei via Kallithea hinzugefügt"
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr "Kein Inhalt"
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr "Kein Dateiname"
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr "Der Ort muss ein relativer Pfad sein und darf nicht .. enthalten"
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr "Downloads gesperrt"
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr "Unbekannte Revision %s"
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr "Leeres Repository"
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr "Unbekannter Archivtyp"
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr "Änderungssätze"
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
 msgstr "Entwicklungszweige"
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr "Tags"
 
@@ -280,11 +271,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr "Während des Forkens des Repositorys trat ein Fehler auf: %s"
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr "Gruppen"
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -292,188 +283,188 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr "Repositories"
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
 msgstr "Zweig"
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr "Geschlossene Branches"
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr "Marke"
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr "Lesezeichen"
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr "Öffentliches Logbuch"
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr "Logbuch"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
 msgstr "Falsches Captcha"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, 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:190
 msgid "A password reset confirmation code has been sent"
 msgstr "Ihr Link um das Passwort zurückzusetzen wurde versendet"
 
-#: kallithea/controllers/login.py:238
+#: 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:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Erfolgreich Kennwort geändert"
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr "Ungültigen Begutachter \"%s\" angegeben"
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr "%s (geschlossen)"
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr "Änderungssatz"
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr "Spezial"
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr "Branches anderer"
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr "Lesezeichen"
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr "Fehler beim Erstellen des Pull-Requests: %s"
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr "Während des Erstellens des Pull Requests trat ein Fehler auf"
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr "Es wurde erfolgreich ein neuer Pullrequest eröffnet"
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 #, fuzzy
 #| msgid "Pull request update created"
 msgid "New pull request iteration created"
 msgstr "Pull Request Update erstellt"
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr "Es wurden inzwischen folgende Begutachter hinzugefügt: %s"
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr "Es wurden inzwischen folgende Begutachter entfernt: %s"
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr "Keine Beschreibung"
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
 msgstr "Pull Request aktualisiert"
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr "Erfolgreich Pull-Request gelöscht"
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, python-format
 msgid "Revision %s not found in %s"
 msgstr "Die Revision %s konnte in %s nicht gefunden werden"
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, fuzzy, python-format
 #| msgid "No changesets found for updating this pull request."
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr "Keine Changesets gefunden, um den Pull Request zu aktualisieren."
 
-#: kallithea/controllers/pullrequests.py:522
+#: kallithea/controllers/pullrequests.py:520
 #, python-format
 msgid "This pull request has already been merged to %s."
 msgstr "Dieser Pull Request wurde bereits in %s integriert."
 
-#: kallithea/controllers/pullrequests.py:524
+#: kallithea/controllers/pullrequests.py:522
 msgid "This pull request has been closed and can not be updated."
 msgstr ""
 "Dieser Pull Request wurde geschlossen und kann daher nicht aktualisiert "
 "werden."
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, fuzzy, python-format
 #| msgid "The following changes are available on %s:"
 msgid "The following additional changes are available on %s:"
 msgstr "Die folgenden Änderungen sind verfügbar unter %s:"
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 #, fuzzy
 #| msgid "No changesets found for updating this pull request."
 msgid "No additional changesets found for iterating on this pull request."
 msgstr "Keine Changesets gefunden, um den Pull Request zu aktualisieren."
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr "Hinweis: Branch %s hat einen anderen Head: %s."
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 #, fuzzy
 #| msgid "Git pull requests don't support updates yet."
 msgid "Git pull requests don't support iterating yet."
 msgstr "Git Pull Request unterstützen bisher keine Updates."
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, fuzzy, python-format
 #| msgid "No changesets found for updating this pull request."
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
 msgstr "Keine Changesets gefunden, um den Pull Request zu aktualisieren."
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 "Der diff kann nicht angezeigt werden. Die Pull Request Revisionen konnten "
@@ -492,21 +483,21 @@
 msgid "An error occurred during search operation."
 msgstr "Während der Suchoperation trat ein Fehler auf."
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr "Es stehen noch keine Daten zur Verfügung"
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr "Statistiken sind deaktiviert für dieses Repository"
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr "Anmeldeeinstellungen erfolgreich geändert"
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr "Fehler bei der Änderung der Anmeldeeinstellungen aufgetreten"
 
@@ -518,125 +509,139 @@
 msgid "Error occurred during update of defaults"
 msgstr "Ein Fehler trat beim updaten der Standardeinstellungen auf"
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 msgid "Forever"
 msgstr "Immer"
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
 #: kallithea/controllers/admin/users.py:249
 msgid "5 minutes"
 msgstr "5 Minuten"
 
-#: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
 #: kallithea/controllers/admin/users.py:250
 msgid "1 hour"
 msgstr "1 Stunde"
 
-#: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
 #: kallithea/controllers/admin/users.py:251
 msgid "1 day"
 msgstr "1 Tag"
 
-#: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr "1 Monat"
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr "Lebenszeit"
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr "Ein fehler trat auf bei der Erstellung des gist"
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr "gist %s gelöscht"
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
 msgstr "Ungeändert"
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr "Erfolgreich Kerninhalt aktualisiert"
 
-#: kallithea/controllers/admin/gists.py:230
+#: kallithea/controllers/admin/gists.py:233
 msgid "Successfully updated gist data"
 msgstr "Erfolgreich Kerndaten aktualisiert"
 
-#: kallithea/controllers/admin/gists.py:233
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
 msgstr "Fehler beim Aktualisieren der Kerndaten %s"
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 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 "
 "Bedeutung für die ganze Applikation ist"
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr "Ihr Account wurde erfolgreich aktualisiert"
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr "Fehler beim Aktualisieren der Benutzer %s"
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr "Fehler bei der Änderung des Kennworts"
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr "Die EMail Addresse %s wurde zum Benutzer hinzugefügt"
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr "Währen der Speicherung der EMail Addresse trat ein Fehler auf"
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr "Die EMail Addresse wurde vom Benutzer entfernt"
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr "API Key wurde erfolgreich erstellt"
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr "API-Schlüssel erfolgreich zurückgesetzt"
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr "API-Schlüssel erfolgreich gelöscht"
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, fuzzy, python-format
+#| msgid "API key successfully created"
+msgid "SSH key %s successfully added"
+msgstr "API Key wurde erfolgreich erstellt"
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+#, fuzzy
+#| msgid "API key successfully deleted"
+msgid "SSH key successfully deleted"
+msgstr "API-Schlüssel erfolgreich gelöscht"
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -644,9 +649,9 @@
 msgid "Read"
 msgstr "Lesen"
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -654,9 +659,9 @@
 msgid "Write"
 msgstr "Schreiben"
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -679,258 +684,243 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr "Admin"
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:50
 msgid "Disabled"
 msgstr "Deaktiviert"
 
-#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:80
 msgid "Allowed with manual account activation"
 msgstr "Erlaubt mit manueller Kontoaktivierung"
 
-#: kallithea/controllers/admin/permissions.py:80
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr "Erlaubt mit automatischer Kontoaktivierung"
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr "Manuelle Aktivierung externen Kontos"
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr "Automatische Aktivierung externen Kontos"
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr "Aktiviert"
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr "Globale Berechtigungen erfolgreich geändert"
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr "Fehler bei der Änderung der globalen Berechtigungen"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, 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:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr "Repositoriumsgruppe %s erstellt"
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Repositoriumsgruppe %s aktualisiert"
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, 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:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, 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:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, 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:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Repositoriumsgruppe %s entfernt"
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, 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:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Als Administrator kann man sich keine Berechtigungen entziehen"
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr "Berechtigungen der Repositoriumsgruppe aktualisiert"
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr "Fehler beim Entzug der Berechtigungen"
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Fehler beim Erstellen des Repositoriums %s"
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Repositorium %s von %s erstellt"
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Aufgespaltenes Repositorium %s zu %s"
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr "Repositorium erzeugt %s"
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Repository %s wurde erfolgreich aktualisiert"
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "Fehler bei der Aktualisierung des Repositoriums %s"
 
-#: kallithea/controllers/admin/repos.py:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr "%s Spaltung abgetrennt"
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr "%s Spaltung gelöscht"
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Repositorium %s gelöscht"
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, 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:290
+#: kallithea/controllers/admin/repos.py:289
 #, 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:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr "Repositoriumsberechtigungen aktualisiert"
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr "Feldvalidierung fehlgeschlagen: %s"
 
-#: kallithea/controllers/admin/repos.py:390
+#: kallithea/controllers/admin/repos.py:391
 #, 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:401
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr "Fehler beim Entfernen des Feldes"
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr "-- Keine Abspaltung --"
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr "Sichtbarkeit des Repositorys im Öffentlichen Logbuch aktualisiert"
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 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:466
+#: kallithea/controllers/admin/repos.py:468
 msgid "Nothing"
 msgstr "Nichts"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:470
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "Markiere Repository %s als Abzweig von Repository %s"
 
-#: kallithea/controllers/admin/repos.py:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr "Während dieser operation trat ein Fehler auf"
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-msgid "Repository has been locked"
-msgstr "Repository wurde gesperrt"
+#: kallithea/controllers/admin/repos.py:490
+msgid "Cache invalidation successful"
+msgstr "Cache Entfernung war erfolgreich"
 
 #: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-msgid "Repository has been unlocked"
-msgstr "Repository nicht mehr gesperrt"
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr "Fehler beim Entsperren"
-
-#: kallithea/controllers/admin/repos.py:528
-msgid "Cache invalidation successful"
-msgstr "Cache Entfernung war erfolgreich"
-
-#: kallithea/controllers/admin/repos.py:532
 msgid "An error occurred during cache invalidation"
 msgstr "Währen der Cache Invalidierung trat ein Fehler auf"
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr "Von entferntem Ort übertragen"
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 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:579
+#: kallithea/controllers/admin/repos.py:541
 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:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr "VCS-Einstellungen aktualisiert"
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
@@ -938,121 +928,121 @@
 "hgsubversion-Unterstützung konnte nicht aktiviert werden. Die "
 "\"hgsubversion\"-Bibliothek fehlt"
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
 msgstr ""
 "Ein Fehler ist während der Aktualisierung der Applikationseinstellungen "
 "aufgetreten"
 
-#: kallithea/controllers/admin/settings.py:180
+#: kallithea/controllers/admin/settings.py:176
 #, 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:192
+#: kallithea/controllers/admin/settings.py:188
 #, fuzzy, python-format
 #| msgid "Invalidate Repository Cache"
 msgid "Invalidated %s repositories"
 msgstr "Ungültiger Repositorycache"
 
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr "Anwendungseinstellungen aktualisiert"
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr "Visualisierungseinstellungen aktualisiert"
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 "Es ist ein Fehler während der Aktualisierung der Layouteinstellung "
 "aufgetreten"
 
-#: kallithea/controllers/admin/settings.py:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr "Bitte gebe eine E-Mailadresse an"
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr "Task zum Versenden von E-Mails erstellt"
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "Es stehen noch keine Daten zur Verfügung"
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:357
 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:363
+#: kallithea/controllers/admin/settings.py:360
 msgid "Added new hook"
 msgstr "Neuer Hook hinzugefügt"
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr "Die Hooks wurden aktutalisiert"
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr "Während der Erzeugung des Hooks ist ein Fehler aufgetreten"
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr "Whoosh Reindizierungs Aufgabe wurde zur Ausführung geplant"
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr "Nutzergruppe %s erstellt"
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, 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:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr "Aktualisierte Nutzergruppe %s"
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, 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:217
+#: kallithea/controllers/admin/user_groups.py:212
 msgid "Successfully deleted user group"
 msgstr "Die Nutzergruppe wurde erfolgreich entfernt"
 
-#: kallithea/controllers/admin/user_groups.py:222
+#: kallithea/controllers/admin/user_groups.py:217
 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:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr "Zielgruppe kann nicht die gleiche Gruppe sein"
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr "Berechtigungen der Benutzergruppe wurden aktualisiert"
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr "Berechtigungen wurden aktualisiert"
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr ""
 "Es ist ein Fehler während des Speicherns der Berechtigungen aufgetreten"
@@ -1083,224 +1073,226 @@
 msgid "The default user cannot be edited"
 msgstr "Der Standard-Benutzer kann nicht bearbeitet werden"
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr "Die IP-Adresse %s wurde zur Nutzerwhitelist hinzugefügt"
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr "Während des Speicherns der IP-Adresse ist ein Fehler aufgetreten"
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr "IP-Adresse wurde von der Nutzerwhitelist entfernt"
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 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:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr "Sie müssen sich anmelden um diese Seite aufzurufen"
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr "Ungültiger API Key"
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 "Es wurde ein CSRF Leck entdeckt. Alle Formular Token sind abgelaufen"
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr "Das Repository konnte nicht im Filesystem gefunden werden"
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, fuzzy, python-format
 #| msgid "Changeset not found"
 msgid "Changeset for %s %s not found in %s"
 msgstr "Änderungssatz nicht gefunden"
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+#, fuzzy
+#| msgid "Your account is disabled"
+msgid "SSH access is disabled."
+msgstr "Ihr Account wurde Deaktiviert"
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr "Binäre Datei"
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 "Der Änderungssatz war zu groß und wurde abgeschnitten, benutzen sie das "
 "Diff Menü um die Unterschiede anzuzeigen"
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr "Keine Änderungen erkannt"
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "Branch %s gelöscht"
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr "Tag %s erstellt"
 
-#: kallithea/lib/helpers.py:625
+#: kallithea/lib/helpers.py:666
 #, fuzzy, python-format
 #| msgid "Changeset not found"
 msgid "Changeset %s not found"
 msgstr "Änderungssatz nicht gefunden"
 
-#: kallithea/lib/helpers.py:674
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "Zeige alle Kombinierten Änderungensätze %s->%s"
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 msgid "Compare view"
 msgstr "Vergleichsansicht"
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr "und"
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr "%s mehr"
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "revisionen"
 
-#: kallithea/lib/helpers.py:725
+#: kallithea/lib/helpers.py:766
 #, python-format
 msgid "Fork name %s"
 msgstr "Fork Name %s"
 
-#: kallithea/lib/helpers.py:746
+#: kallithea/lib/helpers.py:787
 #, python-format
 msgid "Pull request %s"
 msgstr "Pull Request %s"
 
-#: kallithea/lib/helpers.py:756
+#: kallithea/lib/helpers.py:797
 msgid "[deleted] repository"
 msgstr "[gelöscht] Repository"
 
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
 msgid "[created] repository"
 msgstr "[erstellt] Repository"
 
-#: kallithea/lib/helpers.py:760
+#: kallithea/lib/helpers.py:801
 msgid "[created] repository as fork"
 msgstr "[erstellt] Repository als Fork"
 
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
 msgid "[forked] repository"
 msgstr "[forked] Repository"
 
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
 msgid "[updated] repository"
 msgstr "[aktualisiert] Repository"
 
-#: kallithea/lib/helpers.py:766
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr "Archiv von Repository [heruntergeladen]"
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr "Repository [gelöscht]"
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr "Benutzer [erstellt]"
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr "Benutzer [akutalisiert]"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr "Benutzergruppe [erstellt]"
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr "Benutzergruppe [aktualisiert]"
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr "Revision [kommentiert] in Repository"
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr "Pull Request [kommentiert] für"
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr "Pull Request [geschlossen] für"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr "[Pushed] in"
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr "[via Kallithea] in Repository [committed]"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr "[Pulled von Remote] in Repository"
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr "[Pulled] von"
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr "[Following gestartet] für Repository"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr "[Following gestoppt] für Repository"
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr " und %s weitere"
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "Keine Dateien"
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr "neue Datei"
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr "mod"
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr "entf"
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr "umbenennen"
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1311,69 +1303,96 @@
 "es im Dateisystem erstellt oder umbenannt. Bitte starten sie die "
 "Applikation erneut um die Repositories neu zu Indizieren"
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] "%d Jahr"
 msgstr[1] "%d Jahre"
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] "%d Monat"
 msgstr[1] "%d Monate"
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] "%d Tag"
 msgstr[1] "%d Tage"
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] "%d Stunde"
 msgstr[1] "%d Stunden"
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] "%d Minute"
 msgstr[1] "%d Minuten"
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] "%d Sekunde"
 msgstr[1] "%d Sekunden"
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr "in %s"
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr "vor %s"
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr "in %s und %s"
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s und %s her"
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr "jetzt gerade"
 
@@ -1382,140 +1401,140 @@
 msgid "on line %s"
 msgstr "in Zeile %s"
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr "[Mention]"
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr "höchste Ebene"
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr "Kallithea Administrator"
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
 msgstr "Der Standard-Benutzer hat keinen Zugriff auf neue Repositories"
 
-#: kallithea/model/db.py:1706
+#: kallithea/model/db.py:1640
 msgid "Default user has read access to new repositories"
 msgstr "Der Standard-Benutzer hat Leserechte auf neuen Repositories"
 
-#: kallithea/model/db.py:1707
+#: kallithea/model/db.py:1641
 msgid "Default user has write access to new repositories"
 msgstr "Der Standard-Benutzer hat Schreibrechte auf neuen Repositories"
 
-#: kallithea/model/db.py:1708
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr "Der Standard-Benutzer hat Admin-Rechte auf neuen Repositories"
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 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:1711
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr "Der Standard-Benutzer hat Leserechte auf neuen Repository-Gruppen"
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr "Der Standard-Benutzer Schreibrechte auf neuen Repository-Gruppen"
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr "Der Standard-Benutzer Admin-Rechte auf neuen Repository-Gruppen"
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 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:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr "Der Standard-Benutzer hat Leserechte auf neuen Benutzer-Gruppen"
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr "Der Standard-Benutzer hat Schreibrechte auf neuen Benutzer-Gruppen"
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 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:1720
+#: kallithea/model/db.py:1654
 msgid "Only admins can create repository groups"
 msgstr "Nur Admins können Repository-Gruppen erstellen"
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 msgid "Non-admins can create repository groups"
 msgstr "Nicht-Admins können Repository-Gruppen erstellen"
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 msgid "Only admins can create user groups"
 msgstr "Nur Admins können Benutzer-Gruppen erstellen"
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 msgid "Non-admins can create user groups"
 msgstr "Nicht-Admins können Benutzer-Gruppen erstellen"
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr "Nur Admins können Repositories auf oberster Ebene erstellen"
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr "Nicht-Admins können Repositories oberster Ebene erstellen"
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 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:1730
+#: kallithea/model/db.py:1664
 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:1732
+#: kallithea/model/db.py:1666
 msgid "Only admins can fork repositories"
 msgstr "Nur Admins können Repositories forken"
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 msgid "Non-admins can fork repositories"
 msgstr "Nicht-Admins können Repositorys forken"
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr "Registrierung deaktiviert"
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr "Benutzerregistrierung mit manueller Kontoaktivierung"
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr "Benutzerregistrierung mit automatischer Kontoaktivierung"
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 msgid "Not reviewed"
 msgstr "Nicht Begutachtet"
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 msgid "Under review"
 msgstr "In Begutachtung"
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 #, fuzzy
 #| msgid "Approved"
 msgid "Not approved"
 msgstr "Akzeptiert"
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr "Akzeptiert"
 
@@ -1541,7 +1560,7 @@
 msgid "Name must not contain only digits"
 msgstr "Name darf nicht nur Ziffern enthalten"
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, fuzzy, python-format
 #| msgid "[Comment] %(repo_name)s changeset %(short_id)s on %(branch)s"
 msgid ""
@@ -1551,74 +1570,74 @@
 "Kommentar für %(repo_name)s Changeset %(short_id)s in %(branch)s erstellt "
 "von %(comment_username)s"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr "Neuer Benutzer %(new_username)s registriert"
 
-#: kallithea/model/notification.py:170
+#: kallithea/model/notification.py:169
 #, 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:171
+#: kallithea/model/notification.py:170
 #, 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:184
+#: kallithea/model/notification.py:183
 msgid "Closing"
 msgstr "Schließen"
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, fuzzy, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
 msgstr ""
 "%(user)s möchte ein Review des Pull Request #%(pr_id)s: %(pr_title)s"
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 #, fuzzy
 #| msgid "Error creating pull request: %s"
 msgid "Cannot create empty pull request"
 msgstr "Fehler beim Erstellen des Pull-Requests: %s"
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
-"Pull-Request kann nicht erstellt werden - Criss Cross Merge erkannt, bitte "
-"eine spätere %s-Revision in %s zusammenführen."
-
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+"Pull-Request kann nicht erstellt werden - Criss Cross Merge erkannt, "
+"bitte eine spätere %s-Revision in %s zusammenführen."
+
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 msgid "You are not authorized to create the pull request"
 msgstr "Sie sind nicht berechtigt, den Pull-Request anzulegen."
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 #, fuzzy
 #| msgid "Missing changesets since the previous pull request:"
 msgid "Missing changesets since the previous iteration:"
 msgstr "Fehlende Changesets seit letztem Pull Request:"
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, fuzzy, python-format
 #| msgid "New changesets on %s %s since the previous pull request:"
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr "Neue Changesets in %s %s seit dem letzten Pull Request:"
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 #, fuzzy
 #| msgid "Ancestor didn't change - show diff since previous version:"
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr "Vorgänger unverändert - zeige Diff zu lezter Version:"
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, fuzzy, python-format
 msgid ""
 "This iteration is based on another %s revision and there is no simple "
@@ -1627,26 +1646,42 @@
 "Dieser Pull Request basiert auf einer anderen %s Revision. Daher ist kein "
 "Simple Diff verfügbar."
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, fuzzy, python-format
 #| msgid "No changes found on %s %s since previous version."
 msgid "No changes found on %s %s since previous iteration."
 msgstr "Keine Änderungen seit der letzten Version gefunden in %s %s."
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr "Geschlossen, nächste Iteration: %s ."
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr "Letzter Tip"
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, fuzzy, python-format
+#| msgid "Changeset not found"
+msgid "SSH key %r not found"
+msgstr "Änderungssatz nicht gefunden"
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr "Neue Benutzerregistrierung"
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 #, fuzzy
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
@@ -1654,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:258
+#: kallithea/model/user.py:255
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
@@ -1664,7 +1699,7 @@
 "nicht entfernt werden. Entweder muss der Besitzer geändert oder das "
 "Repository entfernt werden: %s"
 
-#: kallithea/model/user.py:263
+#: kallithea/model/user.py:260
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
@@ -1674,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:270
+#: kallithea/model/user.py:267
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
@@ -1684,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:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr "Link zum Zurücksetzen des Passworts"
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 #, fuzzy
 msgid "Password reset notification"
 msgstr "Link zum Zurücksetzen des Passworts"
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
@@ -1702,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:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr "Eine leere Liste ist kein gültiger Wert"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:72
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "Benutezrname \"%(username)s\" existiert bereits"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:74
 #, fuzzy, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "Benutzername \"%(username)s\" ist ungültig"
 
-#: kallithea/model/validators.py:78
+#: kallithea/model/validators.py:76
 #, fuzzy
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
@@ -1726,25 +1761,25 @@
 "oder Bindestriche enthalten und muss mit einem alphanumerischen Zeichen "
 "oder einem Unterstrich beginnen"
 
-#: kallithea/model/validators.py:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr "Die Eingabe ist nicht gültig"
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr "Benutzername \"%(username)s\" ist ungültig"
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr "Ungültiger Benutzergruppenname"
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:132
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr "Benutzergruppe \"%(usergroup)s\" existiert bereits"
 
-#: kallithea/model/validators.py:136
+#: kallithea/model/validators.py:134
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
@@ -1753,68 +1788,64 @@
 "Unterstriche, Punkte oder Bindestriche enthalten und muss mit einem "
 "alphanumerischen Zeichen beginnen"
 
-#: kallithea/model/validators.py:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr "Kann diese Gruppe nicht als vorgesetzt setzen"
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:175
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr "Gruppe \"%(group_name)s\" existiert bereits"
 
-#: kallithea/model/validators.py:179
+#: kallithea/model/validators.py:177
 #, 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:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr "Üngültige(nicht ASCII) Zeichen im Passwort"
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr "Ungültiges altes Passwort"
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr "Die Passwörter stimmen nicht überein"
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 #, fuzzy
 msgid "Invalid username or password"
 msgstr "Ungültiges Passwort"
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr "Schlüssel stimmt nicht überein"
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, fuzzy, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr "Repository Name \"%(repo)s\" ist nicht erlaubt"
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr "Es gibt bereits ein Repository mit \"%(repo)s\""
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, 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:333
+#: kallithea/model/validators.py:318
 #, 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:419
+#: kallithea/model/validators.py:404
 msgid "Invalid repository URL"
 msgstr "Ungültige Repository-URL"
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
@@ -1822,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:445
+#: kallithea/model/validators.py:430
 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:460
+#: kallithea/model/validators.py:445
 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:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
 msgstr "keine Berechtigung, um ein Repository auf höchster Ebene anzulegen"
 
-#: kallithea/model/validators.py:512
+#: kallithea/model/validators.py:497
 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:552
+#: kallithea/model/validators.py:537
 msgid "This username or user group name is not valid"
 msgstr "Dieser Benutzername oder Benutzergruppenname ist nicht gültig"
 
-#: kallithea/model/validators.py:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr "Dies ist ein Ungültiger Pfad"
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 #, fuzzy
 msgid "This email address is already in use"
 msgstr "Diese E-Mailaddresse ist bereits in Benutzung"
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, fuzzy, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "E-MailAddresse \"%(email)s\" existiert nicht."
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
@@ -1867,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:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr "Bitte eine gültige IPv4- oder IPv6-Adresse angeben"
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
@@ -1879,17 +1910,17 @@
 "Die Größe (in Bits) des Netzwerks muss im Bereich 0-32 liegen (nicht "
 "%(bits)r)"
 
-#: kallithea/model/validators.py:765
+#: kallithea/model/validators.py:750
 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:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr "Dateiname darf kein Unterverzeichnis enthalten"
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1932,24 +1963,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr "Beschreibung"
 
@@ -1966,7 +2003,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1974,11 +2011,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr "Besitzer"
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr "Log In"
@@ -1993,7 +2030,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -2001,7 +2038,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr "Passwort"
@@ -2167,10 +2204,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr "Aktion"
@@ -2223,22 +2262,22 @@
 msgstr "Plugin"
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr "Speichern"
 
@@ -2256,14 +2295,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr "Privates Repository"
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2273,36 +2312,25 @@
 "sichtbar."
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr "Aktiviere Statistiken"
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr "Statistik-Fenster in der Zusammenfassungsseite aktivieren."
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr "Aktiviere Downloads"
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr "Download-Menü auf der Zusammenfassungsseite aktivieren."
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr "Locking aktivieren"
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr "Aktivieren Sie Lock-by-Pulling im Repository."
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2351,8 +2379,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 #, fuzzy
 msgid "Never"
 msgstr "nie"
@@ -2386,7 +2416,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr "Neuen Gist erstellen"
 
@@ -2424,23 +2454,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2468,7 +2500,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2528,7 +2560,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr "Mein Account"
 
@@ -2541,24 +2573,31 @@
 msgid "Email Addresses"
 msgstr "E-Mail-Adressen"
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
+#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/users/user_edit.html:32
+#, fuzzy
+#| msgid "API Keys"
+msgid "SSH Keys"
+msgstr "API Keys"
+
+#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
 msgid "API Keys"
 msgstr "API Keys"
 
-#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/my_account/my_account.html:32
 msgid "Owned Repositories"
 msgstr "Eigene Repositories"
 
-#: kallithea/templates/admin/my_account/my_account.html:30
+#: kallithea/templates/admin/my_account/my_account.html:33
 #: kallithea/templates/journal/journal.html:33
 msgid "Watched Repositories"
 msgstr "Beobachtete Repositories"
 
-#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 msgid "Show Permissions"
 msgstr "Berechtigungen anzeigen"
 
@@ -2585,7 +2624,9 @@
 msgstr "Entfernen des API-Schlüssels \"%s\" bestätigen"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 msgid "Remove"
 msgstr "Entfernen"
 
@@ -2601,12 +2642,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr "Hinzufügen"
 
@@ -2721,6 +2764,49 @@
 msgid "Name"
 msgstr "Name"
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+#, fuzzy
+#| msgid "Last Name"
+msgid "Last Used"
+msgstr "Nachname"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, fuzzy, python-format
+#| msgid "Confirm to remove this API key: %s"
+msgid "Confirm to remove this SSH key: %s"
+msgstr "Entfernen des API-Schlüssels \"%s\" bestätigen"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+#, fuzzy
+#| msgid "New API key"
+msgid "New SSH key"
+msgstr "Neuer API-Schlüssel"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+#, fuzzy
+#| msgid "Public Gist"
+msgid "Public key"
+msgstr "Öffentlicher Gist"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 msgid "Repositories You are Watching"
 msgstr "Repositories, denen Sie folgen"
@@ -2737,7 +2823,7 @@
 msgstr "Global"
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr "IP Whitelist"
 
@@ -2780,7 +2866,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2958,7 +3044,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr "Erweitert"
 
@@ -3070,19 +3156,11 @@
 "untergeordneten Elemente, einschließlich nicht-privater Repositories und "
 "anderer Gruppen, falls ausgewählt."
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-"Aktiviere die Sperre-bei-Pull für die Gruppe. Diese Option wird auf alle "
-"anderen enthaltenen Gruppen und Repositories angewandt"
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
 msgstr "Diese Gruppe löschen"
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Confirm to delete this group"
 msgstr "Löschen der Gruppe bestätigen"
 
@@ -3112,7 +3190,7 @@
 "Repository als Clon von dieser URL erstellt."
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
@@ -3121,7 +3199,7 @@
 "längere Beschreibungen."
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr ""
@@ -3133,7 +3211,7 @@
 msgstr "Repository Typ der erstellt werden soll."
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr "Start Revision"
@@ -3192,8 +3270,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr "Statistiken"
 
@@ -3230,73 +3308,32 @@
 "Alle Aktionen, die in diesem Repository ausgeführt wurden, sind im "
 "öffentlichen Logbuch für jeden einsehbar."
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-msgid "Change Locking"
-msgstr "Ändere die Sperrung"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-msgid "Confirm to unlock repository."
-msgstr "Entsperren des Repositorys bestätigen."
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-msgid "Unlock Repository"
-msgstr "Repository entsperren"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr "Gesperrt durch %s auf %s"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-msgid "Confirm to lock repository."
-msgstr "Sperren des Repositorys bestätigen."
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-msgid "Lock Repository"
-msgstr "Repository sperren"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr "Repository ist nicht gesperrt"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-"Erzwinge die Sperre dieses Repositories. Dies funktioniert nur, falls "
-"anonymer Zugang abgeschaltet ist. Ein Pull führt zur Sperre des "
-"Repositories. Der pullende Nutzer sperrt das Repository; nur dieser "
-"Nutzer kann die Sperre durch eine Push-Operation wieder aufheben."
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
 #: kallithea/templates/data_table/_dt_elements.html:68
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "Löschen des Repositorys bestätigen: %s"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
 msgid "Delete this Repository"
 msgstr "Dieses Repository löschen"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
 msgstr[0] "Dieses Repository hat %s Fork"
 msgstr[1] "Dieses Repository hat %s Forks"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr "Fork abtrennen"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr "Forks löschen"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3398,19 +3435,13 @@
 msgid "This repository does not have a remote repository URL."
 msgstr "Für dieses Repository ist keine nicht-lokale URL angegeben."
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "Permanent Repository ID"
+#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#, fuzzy
+#| msgid "Permanent Repository ID"
+msgid "Permanent URL"
 msgstr "Dauerhafte Repository-Kennung"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr "Was ist das?"
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr "URL nach Kennung"
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3426,15 +3457,15 @@
 "Dies ist insbesondere für CI-Systeme oder in Fällen nützlich, in denen "
 "die URL des Repositories bei Dritten dauerhaft eingetragen wird."
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 msgid "Remote repository"
 msgstr "Entferntes Repository"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 msgid "Repository URL"
 msgstr "Repository URL"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
@@ -3442,16 +3473,16 @@
 "Optional: URL eines entfernten Repositories. Falls gesetzt, dann kann das "
 "Repository von dieser URL bezogen werden."
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr "Standardrevision für Dateiseite, Downloads, Whoosh und Readme"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr "Typname des Benutzers"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr "Besitzer des Repositorys ändern."
 
@@ -3523,14 +3554,15 @@
 #: kallithea/templates/admin/settings/settings_global.html:7
 msgid "Set a custom title for your Kallithea Service."
 msgstr ""
+"Legen Sie einen benutzerdefinierten Titel für Ihren Kallithea-Dienst fest."
 
 #: kallithea/templates/admin/settings/settings_global.html:12
 msgid "HTTP authentication realm"
-msgstr ""
+msgstr "HTTP-Authentifizierungsrealm"
 
 #: kallithea/templates/admin/settings/settings_global.html:19
 msgid "HTML/JavaScript/CSS customization block"
-msgstr ""
+msgstr "HTML/JavaScript/CSS Anpassungsblock"
 
 #: kallithea/templates/admin/settings/settings_global.html:22
 msgid ""
@@ -3543,45 +3575,50 @@
 
 #: kallithea/templates/admin/settings/settings_global.html:32
 msgid "ReCaptcha public key"
-msgstr ""
+msgstr "ReCaptcha öffentlicher Schlüssel"
 
 #: kallithea/templates/admin/settings/settings_global.html:35
 msgid "Public key for reCaptcha system."
-msgstr ""
+msgstr "Öffentlicher Schlüssel für das reCaptcha-System."
 
 #: kallithea/templates/admin/settings/settings_global.html:40
 msgid "ReCaptcha private key"
-msgstr ""
+msgstr "ReCaptcha privater Schlüssel"
 
 #: kallithea/templates/admin/settings/settings_global.html:43
 msgid ""
 "Private key for reCaptcha system. Setting this value will enable captcha "
 "on registration."
 msgstr ""
+"Privater Schlüssel für das reCaptcha-System. Wenn Sie diesen Wert "
+"einstellen, wird das Captcha bei der Registrierung aktiviert."
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 msgid "Save Settings"
 msgstr "Einstellungen speichern"
 
 #: kallithea/templates/admin/settings/settings_hooks.html:3
 msgid "Built-in Mercurial Hooks (Read-Only)"
-msgstr ""
+msgstr "Eingebaute Mercurial Hooks (Read -Only)"
 
 #: kallithea/templates/admin/settings/settings_hooks.html:17
 msgid "Custom Hooks"
-msgstr ""
+msgstr "Benutzerdefinierte Hooks"
 
 #: kallithea/templates/admin/settings/settings_hooks.html:18
 msgid ""
 "Hooks can be used to trigger actions on certain events such as push / "
 "pull. They can trigger Python functions or external applications."
 msgstr ""
+"Mit Hilfe von Hooks können bei bestimmten Ereignissen, wie z.B. Push / "
+"Pull, Aktionen ausgelöst werden. Sie können Python-Funktionen oder "
+"externe Anwendungen auslösen."
 
 #: kallithea/templates/admin/settings/settings_hooks.html:60
 msgid "Failed to remove hook"
-msgstr ""
+msgstr "Hook konnte nicht entfernt werden"
 
 #: kallithea/templates/admin/settings/settings_mapping.html:4
 #, fuzzy
@@ -3591,35 +3628,43 @@
 
 #: kallithea/templates/admin/settings/settings_mapping.html:9
 msgid "Delete records of missing repositories"
-msgstr ""
+msgstr "Datensätze fehlender Repositories löschen"
 
 #: kallithea/templates/admin/settings/settings_mapping.html:12
 msgid ""
 "Check this option to remove all comments, pull requests and other records "
 "related to repositories that no longer exist in the filesystem."
 msgstr ""
+"Aktivieren Sie diese Option, um alle Kommentare, Pull-Requests und andere "
+"Datensätze zu entfernen, die sich auf Repositories beziehen, die nicht "
+"mehr im Dateisystem vorhanden sind."
 
 #: kallithea/templates/admin/settings/settings_mapping.html:17
 msgid "Invalidate cache for all repositories"
-msgstr ""
+msgstr "Cache für alle Repositories entwerten"
 
 #: kallithea/templates/admin/settings/settings_mapping.html:20
 msgid "Check this to reload data and clear cache keys for all repositories."
 msgstr ""
+"Aktivieren Sie dies, um Daten neu zu laden und Cache-Schlüssel für alle "
+"Repositories zu löschen."
 
 #: kallithea/templates/admin/settings/settings_mapping.html:25
 msgid "Install Git hooks"
-msgstr ""
+msgstr "Git-Hooks installieren"
 
 #: kallithea/templates/admin/settings/settings_mapping.html:28
 msgid ""
 "Verify if Kallithea's Git hooks are installed for each repository. "
 "Current hooks will be updated to the latest version."
 msgstr ""
+"Überprüfen Sie, ob die Git-Hooks von Kallithea für jedes Repository "
+"installiert sind. Aktuelle Hooks werden auf die neueste Version "
+"aktualisiert."
 
 #: kallithea/templates/admin/settings/settings_mapping.html:32
 msgid "Overwrite existing Git hooks"
-msgstr ""
+msgstr "Bestehende Git-Hooks überschreiben"
 
 #: kallithea/templates/admin/settings/settings_mapping.html:35
 msgid ""
@@ -3627,24 +3672,30 @@
 "not seem to come from Kallithea. WARNING: This operation will destroy any "
 "custom git hooks you may have deployed by hand!"
 msgstr ""
+"Wenn Sie Git-Hooks installieren, überschreiben Sie alle vorhandenen "
+"Hooks, auch wenn sie nicht von Kallithea zu kommen scheinen. WARNUNG: "
+"Diese Operation zerstört alle benutzerdefinierten Git-Hooks, die Sie "
+"möglicherweise von Hand bereitgestellt haben!"
 
 #: kallithea/templates/admin/settings/settings_mapping.html:41
 msgid "Rescan Repositories"
-msgstr ""
+msgstr "Repositories erneut scannen"
 
 #: kallithea/templates/admin/settings/settings_search.html:4
 msgid "Index build option"
-msgstr ""
+msgstr "Option zum Aufbau eines Index"
 
 #: kallithea/templates/admin/settings/settings_search.html:9
 msgid "Build from scratch"
-msgstr ""
+msgstr "Von Grund auf neu bauen"
 
 #: kallithea/templates/admin/settings/settings_search.html:12
 msgid ""
 "This option completely reindexeses all of the repositories for proper "
 "fulltext search capabilities."
 msgstr ""
+"Diese Option führt zu einer vollständigen Neuindizierung aller "
+"Repositories für eine korrekte Volltextsuche."
 
 #: kallithea/templates/admin/settings/settings_search.html:18
 msgid "Reindex"
@@ -3656,16 +3707,11 @@
 
 #: kallithea/templates/admin/settings/settings_system.html:7
 msgid "Kallithea version"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:7
-#, fuzzy
-msgid "Check for updates"
-msgstr "Auf Updates prüfen"
+msgstr "Kallithea-Version"
 
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
-msgstr ""
+msgstr "Kallithea Konfigurationsdatei"
 
 #: kallithea/templates/admin/settings/settings_system.html:9
 msgid "Python version"
@@ -3681,71 +3727,61 @@
 
 #: kallithea/templates/admin/settings/settings_system.html:12
 msgid "Git path"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-"Hinweis: Bitte stellen Sie sicher, dass der Server auf die URL zugreifen "
-"kann"
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+msgstr "Git-Pfad"
+
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
-msgstr ""
+msgstr "Python-Pakete"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:9
 msgid "Show repository size after push"
-msgstr ""
+msgstr "Zeigt die Größe des Repositories nach dem Push an"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
-msgstr ""
+msgid "Update repository after push (hg update)"
+msgstr "Repository nach dem Push aktualisieren (hg update)"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
-msgid "Update repository after push (hg update)"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:33
 msgid "Mercurial extensions"
 msgstr "Mercurial-Erweiterungen"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr "Erweiterung largefiles aktivieren"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr "Erweiterung hgsubversion aktivieren"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:47
+#: kallithea/templates/admin/settings/settings_vcs.html:35
 msgid ""
 "Requires hgsubversion library to be installed. Enables cloning of remote "
 "Subversion repositories while converting them to Mercurial."
 msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:59
+"Erfordert die Installation der hgsubversion-Bibliothek. Ermöglicht das "
+"Klonen von entfernten Subversion-Repositories während der Konvertierung "
+"zu Mercurial."
+
+#: kallithea/templates/admin/settings/settings_vcs.html:47
 msgid "Location of repositories"
 msgstr "Ort der Repositories"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
 msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+"Zum Entsperren klicken. Sie müssen Kallithea neu starten, damit diese "
+"Einstellung wirksam wird."
+
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
 msgstr ""
+"Dateisystem-Speicherort, an dem die Repositories gespeichert sind. Nach "
+"dem Ändern dieses Wertes sind sowohl ein Neustart als auch ein erneuter "
+"Scan des Repository-Ordners erforderlich."
 
 #: kallithea/templates/admin/settings/settings_visual.html:4
 msgid "General"
@@ -3753,11 +3789,13 @@
 
 #: kallithea/templates/admin/settings/settings_visual.html:9
 msgid "Use repository extra fields"
-msgstr ""
+msgstr "Zusätzliche Repository-Felder verwenden"
 
 #: kallithea/templates/admin/settings/settings_visual.html:12
 msgid "Allows storing additional customized fields per repository."
 msgstr ""
+"Ermöglicht die Speicherung zusätzlicher benutzerdefinierter Felder pro "
+"Repository."
 
 #: kallithea/templates/admin/settings/settings_visual.html:17
 msgid "Show Kallithea version"
@@ -3767,10 +3805,12 @@
 msgid ""
 "Shows or hides a version number of Kallithea displayed in the footer."
 msgstr ""
+"Zeigt oder verbirgt eine Versionsnummer von Kallithea, die in der "
+"Fußzeile angezeigt wird."
 
 #: kallithea/templates/admin/settings/settings_visual.html:25
 msgid "Show user Gravatars"
-msgstr ""
+msgstr "Benutzer Gravatare anzeigen"
 
 #: kallithea/templates/admin/settings/settings_visual.html:29
 msgid ""
@@ -3788,13 +3828,44 @@
 "                                                        {netloc}    "
 "network location/server host of running Kallithea server"
 msgstr ""
+"Gravatar URL ermöglicht es Ihnen, eine andere Avatar-Serveranwendung zu "
+"verwenden.\n"
+"                                                        Die folgenden "
+"Variablen der URL werden entsprechend ersetzt.\n"
+"                                                        {scheme}    "
+"'http' oder'https', die vom laufenden Kallithea-Server gesendet werden,\n"
+"                                                        {email}    "
+"Benutzer-E-Mail,\n"
+"                                                        {md5email}  md5 "
+"Hash der Benutzer-E-Mail (wie bei gravatar.com),\n"
+"                                                        {size}       "
+"Größe des Bildes, das von der Serveranwendung erwartet wird,\n"
+"                                                        {netloc}    "
+"Netzwerkstandort/Server-Host des laufenden Kallithea-Servers"
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-msgid "Clone URL"
+#, fuzzy
+#| msgid "Clone URL"
+msgid "HTTP Clone URL"
 msgstr "Clone-URL"
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
+#, fuzzy
+#| msgid ""
+#| "Schema of clone URL construction eg. '{scheme}://{user}@{netloc}/"
+#| "{repo}'.\n"
+#| "                                                    The following "
+#| "variables are available:\n"
+#| "                                                    {scheme} 'http' or "
+#| "'https' sent from running Kallithea server,\n"
+#| "                                                    {user}   current "
+#| "user username,\n"
+#| "                                                    {netloc} network "
+#| "location/server host of running Kallithea server,\n"
+#| "                                                    {repo}   full "
+#| "repository name,\n"
+#| "                                                    {repoid} ID of "
+#| "repository, can be used to construct clone-by-id"
 msgid ""
 "Schema of clone URL construction eg. '{scheme}://{user}@{netloc}/"
 "{repo}'.\n"
@@ -3809,61 +3880,99 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+"Schema der Klon-URL-Konstruktion z.B. '{scheme}://{user}@{netloc}/"
+"{repo}'.\n"
+"                                                    Die folgenden "
+"Variablen stehen zur Verfügung:\n"
+"                                                    {scheme}'http' "
+"oder'https', die vom laufenden Kallithea-Server gesendet werden,\n"
+"                                                    {user}   aktueller "
+"Benutzername des Benutzers,\n"
+"                                                    {netloc} "
+"Netzwerkstandort/Server-Host des laufenden Kallithea-Servers,\n"
+"                                                    {repo}   "
+"vollständiger Name des Repositories,\n"
+"                                                    {repoid} ID des "
+"Repositorys, kann verwendet werden, um einen Klon nach Id zu erstellen"
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+#, fuzzy
+#| msgid "Clone URL"
+msgid "SSH Clone URL"
+msgstr "Clone-URL"
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 #, fuzzy
 #| msgid "Repository Size"
 msgid "Repository page size"
 msgstr "Repository Größe"
 
-#: kallithea/templates/admin/settings/settings_visual.html:57
+#: kallithea/templates/admin/settings/settings_visual.html:68
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
 "shown."
 msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:62
+"Anzahl der Elemente, die auf den Repository-Seiten angezeigt werden, "
+"bevor der Seitenumbruch angezeigt wird."
+
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:65
+msgstr "Größe der Admin-Seite"
+
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:70
+"Anzahl der Elemente, die in den Gittern der Admin-Seiten angezeigt "
+"werden, bevor der Seitenumbruch angezeigt wird."
+
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr "Icons"
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:81
+msgstr "Öffentliches Repository-Symbol in Repositories anzeigen"
+
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:84
+msgstr "Privates Repository-Symbol in Repositories anzeigen"
+
+#: kallithea/templates/admin/settings/settings_visual.html:95
 msgid "Show public/private icons next to repository names."
 msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:89
+"Zeigt öffentliche/private Symbole neben den Namen der Repositories an."
+
+#: kallithea/templates/admin/settings/settings_visual.html:100
 #, fuzzy
 msgid "Meta Tagging"
 msgstr "Einstellungen"
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:98
+"Analysiert Meta-Tags aus dem Beschreibungsfeld des Repositorys und "
+"verwandelt sie in farbige Tags."
+
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
-msgstr ""
+msgstr "Erkannte Meta-Tags stilisieren:"
 
 #: kallithea/templates/admin/user_groups/user_group_add.html:5
 msgid "Add user group"
@@ -3912,7 +4021,7 @@
 #: kallithea/templates/data_table/_dt_elements.html:102
 #, python-format
 msgid "Confirm to delete this user group: %s"
-msgstr ""
+msgstr "Bestätigen, um diese Benutzergruppe zu löschen: %s"
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:21
 msgid "Delete this user group"
@@ -3952,7 +4061,7 @@
 
 #: kallithea/templates/admin/users/user_add.html:41
 msgid "Password confirmation"
-msgstr ""
+msgstr "Passwortbestätigung"
 
 #: kallithea/templates/admin/users/user_edit.html:5
 #, python-format
@@ -3961,7 +4070,7 @@
 
 #: kallithea/templates/admin/users/user_edit.html:30
 msgid "Emails"
-msgstr ""
+msgstr "E-Mails"
 
 #: kallithea/templates/admin/users/user_edit_advanced.html:1
 #, python-format
@@ -4023,12 +4132,12 @@
 msgstr "Support"
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr "Mercurial Repository"
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr "Git Repository"
 
@@ -4076,158 +4185,132 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr ""
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr ""
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr ""
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr ""
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr "Keine Übereinstimmungen gefunden"
 
+#: kallithea/templates/base/base.html:289
+msgid "Show recent activity"
+msgstr ""
+
+#: kallithea/templates/base/base.html:295
 #: kallithea/templates/base/base.html:296
-msgid "Show recent activity"
+msgid "Public journal"
+msgstr "Öffentliches Logbuch"
+
+#: kallithea/templates/base/base.html:301
+msgid "Show public gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
-msgid "Public journal"
-msgstr "Öffentliches Logbuch"
+msgid "Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:306
+msgid "All Public Gists"
+msgstr ""
 
 #: kallithea/templates/base/base.html:308
-msgid "Show public gists"
+msgid "My Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:309
-msgid "Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:313
-msgid "All Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:315
-msgid "My Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:316
 msgid "My Private Gists"
 msgstr ""
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr ""
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 msgid "My Pull Requests"
 msgstr "Meine Pull Requests"
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr "Nicht eingeloggt"
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 msgid "Login to Your Account"
 msgstr ""
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 #, fuzzy
 #| msgid "Forgot password ?"
 msgid "Forgot password?"
 msgstr "Passwort vergessen?"
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 #, fuzzy
 #| msgid "Don't have an account ?"
 msgid "Don't have an account?"
 msgstr "Kein Account?"
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr ""
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-#, fuzzy
-msgid "Inherit defaults"
-msgstr "Repositorystandards"
+msgid "Create repositories"
+msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-#, fuzzy
-#| msgid "Default permissions"
-msgid "default permissions"
-msgstr "Standart Rechte"
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 
@@ -4978,7 +5061,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr ""
@@ -4990,7 +5073,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr ""
 
@@ -5043,7 +5126,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr "Größe"
 
@@ -5173,8 +5256,8 @@
 msgstr ""
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr ""
 
@@ -5225,8 +5308,8 @@
 msgstr ""
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr ""
 
@@ -5539,9 +5622,9 @@
 msgid "File names"
 msgstr "Dateinamen"
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr "Zugriff verweigert"
 
@@ -5551,20 +5634,20 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr "Aktiviere"
 
@@ -5573,12 +5656,12 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr "Dateien"
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr "Mehr anzeigen"
 
@@ -5619,95 +5702,197 @@
 msgid "%s Summary"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr "Clone von"
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr ""
-
+#: kallithea/templates/summary/summary.html:54
+msgid "Clone URL"
+msgstr "Clone-URL"
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+#, fuzzy
+#| msgid "Last Name"
+msgid "Use Name"
+msgstr "Nachname"
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:101
-msgid "There are no downloads yet"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:103
-msgid "Downloads are disabled for this repository"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:109
+msgid "There are no downloads yet"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:111
+msgid "Downloads are disabled for this repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr "Herunterladen als zip"
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 msgid "With subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr "Feed"
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 msgid "Latest Changes"
 msgstr "Letzte Änderungen"
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 msgid "Quick Start"
 msgstr "Schnelleinstieg"
 
-#: kallithea/templates/summary/summary.html:188
+#: kallithea/templates/summary/summary.html:196
 msgid "Add or upload files directly via Kallithea"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:196
+#: kallithea/templates/summary/summary.html:204
 #, fuzzy
 msgid "Push new repository"
 msgstr "privates Repository"
 
-#: kallithea/templates/summary/summary.html:204
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr "Liesmich-Datei von Revision %s:%s"
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr "%s als %s herunterladen"
 
+#~ msgid "This repository has been locked by %s on %s"
+#~ msgstr "Dieses Repository ist von %s am %s gesperrt worden"
+
+#~ msgid "Repository has been locked"
+#~ msgstr "Repository wurde gesperrt"
+
+#~ msgid "Repository has been unlocked"
+#~ msgstr "Repository nicht mehr gesperrt"
+
+#~ msgid "An error occurred during unlocking"
+#~ msgstr "Fehler beim Entsperren"
+
+#~ msgid "Invalid API key"
+#~ msgstr "Ungültiger API Key"
+
+#~ msgid "Token mismatch"
+#~ msgstr "Schlüssel stimmt nicht überein"
+
+#~ msgid "Enable locking"
+#~ msgstr "Locking aktivieren"
+
+#~ msgid "Enable lock-by-pulling on repository."
+#~ msgstr "Aktivieren Sie Lock-by-Pulling im Repository."
+
+#~ msgid ""
+#~ "Enable lock-by-pulling on group. This option will be applied to all "
+#~ "other groups and repositories inside"
+#~ msgstr ""
+#~ "Aktiviere die Sperre-bei-Pull für die Gruppe. Diese Option wird auf "
+#~ "alle anderen enthaltenen Gruppen und Repositories angewandt"
+
+#~ msgid "Change Locking"
+#~ msgstr "Ändere die Sperrung"
+
+#~ msgid "Confirm to unlock repository."
+#~ msgstr "Entsperren des Repositorys bestätigen."
+
+#~ msgid "Unlock Repository"
+#~ msgstr "Repository entsperren"
+
+#~ msgid "Locked by %s on %s"
+#~ msgstr "Gesperrt durch %s auf %s"
+
+#~ msgid "Confirm to lock repository."
+#~ msgstr "Sperren des Repositorys bestätigen."
+
+#~ msgid "Lock Repository"
+#~ msgstr "Repository sperren"
+
+#~ msgid "Repository is not locked"
+#~ msgstr "Repository ist nicht gesperrt"
+
+#~ msgid ""
+#~ "Force locking on the repository. Works only when anonymous access is "
+#~ "disabled. Triggering a pull locks the repository.  The user who is "
+#~ "pulling locks the repository; only the user who pulled and locked it "
+#~ "can unlock it by doing a push."
+#~ msgstr ""
+#~ "Erzwinge die Sperre dieses Repositories. Dies funktioniert nur, falls "
+#~ "anonymer Zugang abgeschaltet ist. Ein Pull führt zur Sperre des "
+#~ "Repositories. Der pullende Nutzer sperrt das Repository; nur dieser "
+#~ "Nutzer kann die Sperre durch eine Push-Operation wieder aufheben."
+
+#~ msgid "What is that?"
+#~ msgstr "Was ist das?"
+
+#~ msgid "URL by id"
+#~ msgstr "URL nach Kennung"
+
+#, fuzzy
+#~ msgid "Check for updates"
+#~ msgstr "Auf Updates prüfen"
+
+#~ msgid "Upgrade info endpoint"
+#~ msgstr "Upgrade-Info-Endpunkt"
+
+#~ msgid "Note: please make sure this server can access this URL"
+#~ msgstr ""
+#~ "Hinweis: Bitte stellen Sie sicher, dass der Server auf die URL "
+#~ "zugreifen kann"
+
+#~ msgid "Log user push commands"
+#~ msgstr "Protokollieren der Push-Befehle der Benutzer"
+
+#~ msgid "Log user pull commands"
+#~ msgstr "Protokollieren der Pull-Befehle des Benutzers"
+
+#, fuzzy
+#~ msgid "Inherit defaults"
+#~ msgstr "Repositorystandards"
+
+#, fuzzy
+#~| msgid "Default permissions"
+#~ msgid "default permissions"
+#~ msgstr "Standart Rechte"
+
 #~ msgid "There is no index to search in. Please run whoosh indexer"
 #~ msgstr ""
 #~ "Es gibt keinen durchsuchbaren Index. Bitte den Whoosh Indizierer "
@@ -5881,9 +6066,6 @@
 #~ msgid "invalid user name"
 #~ msgstr "Ungültiger Benutzername"
 
-#~ msgid "Your account is disabled"
-#~ msgstr "Ihr Account wurde Deaktiviert"
-
 #~ msgid "invalid clone URL"
 #~ msgstr "ungültige Clone-URL"
 
--- a/kallithea/i18n/el/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/el/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,15 +1,12 @@
-# Greek translations for Kallithea.
 # Copyright (C) 2015 Various authors, licensing as GPLv3
 # This file is distributed under the same license as the Kallithea project.
-# Automatically generated, 2015.
-#
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
-"PO-Revision-Date: 2017-06-14 18:51+0000\n"
-"Last-Translator: Asterios Dimitriou <steve@pci.gr>\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\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/"
 "kallithea/el/>\n"
 "Language: el\n"
@@ -17,17 +14,17 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 2.15-dev\n"
+"X-Generator: Weblate 3.7.1-dev\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr "Δεν υπάρχουν σετ αλλαγών ακόμα"
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -36,48 +33,48 @@
 msgid "None"
 msgstr "Χωρίς"
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr "(κλειστό)"
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr "Εμφάνιση κενού"
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr "Αγνόηση κενού"
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr "Αύξηση του diff πλαισίου σε %(num)s γραμμές"
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 #, fuzzy
 #| msgid "No permission to change pull request status"
 msgid "No permission to change status"
 msgstr "Χωρίς δικαιώματα αλλαγής της κατάστασης του αιτήματος έλξης"
 
-#: kallithea/controllers/changeset.py:214
+#: kallithea/controllers/changeset.py:212
 #, python-format
 msgid "Successfully deleted pull request %s"
 msgstr "Επιτυχής διαγραφή αιτήματος έλξης %s"
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr "Δεν υπάρχει τέτοια αναθεώρηση για αυτό το αποθετήριο"
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, fuzzy, python-format
 #| msgid "Error creating repository %s"
 msgid "Could not find other repository %s"
 msgstr "Βλάβη κατά τη δημιουργία του αποθετηρίου %s"
 
-#: kallithea/controllers/compare.py:72
+#: kallithea/controllers/compare.py:74
 #, fuzzy
 #| msgid "Cannot compare repositories without using common ancestor"
 msgid "Cannot compare repositories of different types"
@@ -85,52 +82,52 @@
 "Δεν μπορεί να γίνει σύγκριση αποθετηρίων χωρίς να χρησιμοποιηθεί κοινός "
 "πρόγονος"
 
-#: kallithea/controllers/compare.py:244
+#: kallithea/controllers/compare.py:246
 msgid "Cannot show empty diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:246
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr ""
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr ""
 "Δεν μπορεί να γίνει σύγκριση αποθετηρίων χωρίς να χρησιμοποιηθεί κοινός "
 "πρόγονος"
 
-#: kallithea/controllers/error.py:70
+#: kallithea/controllers/error.py:71
 msgid "No response"
 msgstr "Χωρίς απόκριση"
 
-#: kallithea/controllers/error.py:71
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr "Άγνωστο λάθος"
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr ""
 "Η αίτηση δεν  μπόρεσε να ερμηνευτεί από τον εξυπηρετητή λόγω κακής "
 "διατύπωσης."
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr "Ανεξουσιοδοτημένη πρόσβαση στον πόρο"
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr "Δεν έχετε άδεια για να εμφανίσετε αυτή τη σελίδα"
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr "Ο πόρος δεν μπορεί να βρεθεί"
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
@@ -153,128 +150,122 @@
 msgid "Changeset was too big and was cut off..."
 msgstr "Το σετ αλλαγών ήταν πολύ μεγάλο και περικόπηκε..."
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr "%s %s τροφοδοσία"
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
 msgstr "Αλλαγές στο αποθετήριο %s"
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr "Κλικ εδώ για προθήκη νέου αρχείου"
 
-#: kallithea/controllers/files.py:93
+#: kallithea/controllers/files.py:86
 #, fuzzy
 #| msgid "There are no files yet. %s"
 msgid "There are no files yet."
 msgstr "Δεν υπάρχουν αρχεία ακόμα. %s"
 
-#: kallithea/controllers/files.py:193
+#: kallithea/controllers/files.py:186
 #, python-format
 msgid "%s at %s"
 msgstr "%s την %s"
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr "Το αποθετήριο κλειδώθηκε από %s την %s"
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 #, fuzzy
 msgid "You can only delete files with revision being a valid branch"
 msgstr ""
-"Μπορείτε να διαγράψετε μόνο αρχεία σε αναθεώρηση που βρίσκονται σε έγκυρη "
-"διακλάδωση "
-
-#: kallithea/controllers/files.py:322
+"Μπορείτε να διαγράψετε μόνο αρχεία με αναθεώρηση που βρίσκονται σε έγκυρη "
+"διακλάδωση"
+
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr "Διαγραφή αρχείου %s μέσω του Kallithea"
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr "Επιτυχής διαγραφή αρχείου %s"
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr "Συνέβη λάθος κατά το commit"
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 msgid "You can only edit files with revision being a valid branch"
 msgstr ""
 "Μπορείτε να επεξεργαστείτε μόνο αρχεία σε αναθεώρηση που βρίσκονται σε "
 "έγκυρη διακλάδωση"
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr "Επεξεργασία αρχείου %s μέσω του Kallithea"
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr "Καμία αλλαγή"
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr "Επιτυχής παράδοση σε %s"
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr "Προσθήκη αρχείου μέσω Kallithea"
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr "Χωρίς περιεχόμενο"
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr "Χωρίς όνομα αρχείου"
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr ""
 "Η τοποθεσία πρέπει να είναι σχετική διαδρομή και να μην περιέχει .. μέσα "
 "της"
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr "Οι μεταφορτώσεις απενεργοποιήθηκαν"
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr "Άγνωστη αναθεώρηση %s"
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr "Άδειο αποθετήριο"
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr "Άγνωστος τύπος αρχειοθέτησης"
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr "Σετ αλλαγών"
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
 msgstr "Κλάδοι"
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr "Ετικέτες"
 
@@ -283,11 +274,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr "Συνέβει ένα λάθος κατά την διακλάδωση του αποθετηρίου %s"
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr "Ομάδες"
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -295,186 +286,186 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr "Αποθετήρια"
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
 msgstr "Κλάδος"
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr "Κλειστοί Κλάδοι"
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr "Ετικέτα"
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr "Σελιδοδείκτης"
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr "Δημόσιο Ημερολόγιο"
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr "Ημερολόγιο"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
 msgstr "Λάθος captcha"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "Εγγραφήκατε επιτυχώς στο %s"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:190
 msgid "A password reset confirmation code has been sent"
 msgstr "Στάλθηκε ένας κωδικός επιβεβαίωσης επαναφοράς του συνθηματικού"
 
-#: kallithea/controllers/login.py:238
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Άκυρο τεκμήριο (token) επαναφοράς του συνθηματικού"
 
-#: kallithea/controllers/admin/my_account.py:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Το συνθηματικό ενημερώθηκε επιτυχώς"
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr "Καθορίστηκε άκυρος σχολιαστής \"%s\""
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr "%s (κλειστό)"
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr "Σετ αλλαγών"
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr "Ειδικός"
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr "Ομότιμοι κλάδοι"
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr "Σελιδοδείκτες"
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr "Λάθος στη δημιουργία αιτήματος έλξης - pull request: %s"
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr "Λάθος κατά τη δημιουργία αιτήματος έλξης (pull request)"
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr "Ένα νέο αίτημα έλξης (pull request) δημιουργήθηκε επιτυχώς"
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 #, fuzzy
 #| msgid "Pull request update created"
 msgid "New pull request iteration created"
 msgstr "Δημιουργήθηκε ενημέρωση αιτήματος έλξης"
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr "Χωρίς περιγραφή"
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
 msgstr "Ενημερώθηκε η αίτηση έλξης"
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr "Επιτυχής διαγραφή αιτήματος έλξης"
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, python-format
 msgid "Revision %s not found in %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, fuzzy, python-format
 #| msgid "No changesets found for updating this pull request."
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr "Δεν βρέθηκαν σετ αλλαγών για ενημέρωση αυτού του αιτήματος έλξης."
 
-#: kallithea/controllers/pullrequests.py:522
+#: kallithea/controllers/pullrequests.py:520
 #, python-format
 msgid "This pull request has already been merged to %s."
 msgstr "Το αίτημα έλξης έχει ήδη συγχωνευτεί με το %s."
 
-#: kallithea/controllers/pullrequests.py:524
+#: kallithea/controllers/pullrequests.py:522
 msgid "This pull request has been closed and can not be updated."
 msgstr "Αυτό το αίτημα έλξης έχει κλείσει και δεν μπορεί να ενημερωθεί."
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, fuzzy, python-format
 #| msgid "The following changes are available on %s:"
 msgid "The following additional changes are available on %s:"
 msgstr "Οι ακόλουθες αλλαγές είναι διαθέσιμες στο %s:"
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 #, fuzzy
 #| msgid "No changesets found for updating this pull request."
 msgid "No additional changesets found for iterating on this pull request."
 msgstr "Δεν βρέθηκαν σετ αλλαγών για ενημέρωση αυτού του αιτήματος έλξης."
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr "Σημείωση: Ο κλάδος %s έχει άλλη κεφαλή (head): %s."
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 #, fuzzy
 #| msgid "Git pull requests don't support updates yet."
 msgid "Git pull requests don't support iterating yet."
 msgstr "Αιτήματα έλξης του git δεν υποστηρίζουν ακόμα ενημερώσεις."
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, fuzzy, python-format
 #| msgid "No changesets found for updating this pull request."
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
 msgstr "Δεν βρέθηκαν σετ αλλαγών για ενημέρωση αυτού του αιτήματος έλξης."
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 
@@ -490,21 +481,21 @@
 msgid "An error occurred during search operation."
 msgstr "Ένα λάθος συνέβη κατά την διαδικασία αναζήτησης."
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr "Δεν υπάρχουν ακόμα έτοιμα δεδομένα"
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr "Τα στατιστικά είναι απενεργοποιημένα για αυτό το αποθετήριο"
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr "Οι ρυθμίσεις εξουσιοδότησης ενημερώθηκαν επιτυχώς"
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr "παρουσιάστηκε βλάβη κατά την ενημέρωση των ρυθμίσεων εξουσιοδότησης"
 
@@ -516,125 +507,139 @@
 msgid "Error occurred during update of defaults"
 msgstr "Συνέβη μία βλάβη κατά την ενημέρωση των προεπιλογών"
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 msgid "Forever"
 msgstr "Πάντα"
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
 #: kallithea/controllers/admin/users.py:249
 msgid "5 minutes"
 msgstr "5 λεπτά"
 
-#: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
 #: kallithea/controllers/admin/users.py:250
 msgid "1 hour"
 msgstr "1 ώρα"
 
-#: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
 #: kallithea/controllers/admin/users.py:251
 msgid "1 day"
 msgstr "1 ημέρα"
 
-#: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr "1 μήνας"
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr "Διάρκεια ζωής"
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr "Συνέβη μία βλάβη κατά τη δημιουργία του gist"
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr "Διαγράφηκε το gist %s"
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
 msgstr "Mη τροποποιημένo"
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr "Το περιεχόμενο του gist ενημερώθηκε επιτυχώς"
 
-#: kallithea/controllers/admin/gists.py:230
+#: kallithea/controllers/admin/gists.py:233
 msgid "Successfully updated gist data"
 msgstr "Τα δεδομένα του gist ενημερώθηκαν επιτυχώς"
 
-#: kallithea/controllers/admin/gists.py:233
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
 msgstr "Σφάλμα συνέβη κατά την ενημέρωση του gist %s"
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 "Δεν μπορείτε να επεξεργαστείτε αυτόν το χρήστη καθώς είναι κρίσιμος για "
 "όλη την εφαρμογή"
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr "Ο λογαριασμός σας ενημερώθηκε επιτυχώς"
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr "Συνέβη ένα σφάλμα κατά την ενημέρωση του χρήστη %s"
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr "Συνέβη ένα σφάλμα κατά την ενημέρωση του κωδικού του χρήστη"
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr "Προστέθηκε το email %s στον χρήστη"
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr "Συνέβη ένα σφάλμα κατά την αποθήκευση του email"
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr "Αφαιρέθηκε το email από τον χρήστη"
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr "Το API κλειδί δημιουργήθηκε επιτυχώς"
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr "Το API κλειδί επαναφέρθηκε επιτυχώς"
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr "Το API κλειδί διαγράφηκε επιτυχώς"
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, fuzzy, python-format
+#| msgid "API key successfully created"
+msgid "SSH key %s successfully added"
+msgstr "Το API κλειδί δημιουργήθηκε επιτυχώς"
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+#, fuzzy
+#| msgid "API key successfully deleted"
+msgid "SSH key successfully deleted"
+msgstr "Το API κλειδί διαγράφηκε επιτυχώς"
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -642,9 +647,9 @@
 msgid "Read"
 msgstr "Ανάγνωση"
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -652,9 +657,9 @@
 msgid "Write"
 msgstr "Εγγραφή"
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -677,366 +682,351 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr "Διαχειριστής"
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:50
 msgid "Disabled"
 msgstr "Απενεργοποιημένο"
 
-#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:80
 msgid "Allowed with manual account activation"
 msgstr "Επιτρέπεται με χειροποίητη ενεργοποίηση του λογαριασμού"
 
-#: kallithea/controllers/admin/permissions.py:80
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr "Επιτρέπεται με αυτόματη ενεργοποίηση του λογαριασμού"
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr "Χειροποίητη ενεργοποίηση εξωτερικού λογαριασμού"
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr "Αυτόματη ενεργοποίηση εξωτερικού λογαριασμού"
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr "Ενεργό"
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr "Τα καθολικά δικαιώματα ενημερώθηκαν επιτυχώς"
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr "Συνέβει μια βλάβη κατά την ενημέρωση των δικαιωμάτων"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr "Συνέβει μια βλάβη κατά την δημιουργία της ομάδας αποθετηρίου %s"
 
-#: kallithea/controllers/admin/repo_groups.py:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr "Δημιουργήθηκε η ομάδα αποθετηρίου %s"
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Ενημερώθηκε η ομάδα αποθετηρίου %s"
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr "Συνέβει μια βλάβη κατά την ενημέρωση της ομάδας αποθετηρίου %s"
 
-#: kallithea/controllers/admin/repo_groups.py:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "Αυτή η ομάδα περιέχει %s αποθετήρια και δε μπορεί να διαγραφεί"
 
-#: kallithea/controllers/admin/repo_groups.py:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr "Αυτή η ομάδα περιέχει %s υποομάδες και δε μπορεί να διαγραφεί"
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Αφαιρέθηκε η ομάδα αποθετηρίου %s"
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr "Συνέβει μια βλάβη κατά την διαγραφή της ομάδας αποθετηρίου %s"
 
-#: kallithea/controllers/admin/repo_groups.py:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Δεν μπορείτε να ανακαλέσετε την άδεια σας ως διαχειριστής"
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr "Τα δικαιώματα της ομάδας αποθετηρίου ενημερώθηκαν"
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr "Συνέβει μια βλάβη κατά την ανάκληση της άδειας"
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Βλάβη κατά τη δημιουργία του αποθετηρίου %s"
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Δημιουργήθηκε το αποθετήριο %s από το %s"
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Κλωνοποιήθηκε το αποθετηρίο %s ως %s"
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr "Δημιουργήθηκε το αποθετήριο %s"
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Το αποθετήριο %s ενημερώθηκε επιτυχώς"
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "Συνέβει μια βλάβη κατά την ενημέρωση του αποθετηρίου %s"
 
-#: kallithea/controllers/admin/repos.py:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr "Αποσυνδέθηκαν %s κλώνοι"
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr "Διαγράφηκαν %s κλώνοι"
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Διαγράφηκε το αποθετήριο %s"
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr "Δε μπορεί να διαγραφεί το αποθετήριο %s που ακόμα έχει κλώνους"
 
-#: kallithea/controllers/admin/repos.py:290
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "Συνέβει μια βλάβη κατά την διαγραφή του %s"
 
-#: kallithea/controllers/admin/repos.py:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr "Τα δικαιώματα του αποθετηρίου ενημερώθηκαν"
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:390
+#: kallithea/controllers/admin/repos.py:391
 #, 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:401
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr "Συνέβει μια βλάβη κατά την απομάκρυνση του πεδίου"
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr "-- Όχι κλώνος --"
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr "Ενημερώθηκε η ορατότητα του αποθετηρίου στο δημόσιο ημερολόγιο"
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 "Συνέβει μια βλάβη κατά την τοποθέτηση αυτού το αποθετηρίου στο δημόσιο "
 "ημερολόγιο"
 
-#: kallithea/controllers/admin/repos.py:466
+#: kallithea/controllers/admin/repos.py:468
 msgid "Nothing"
 msgstr "Χωρίς"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:470
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "Σημειώθηκε το αποθετήριο %s σαν κλώνος του %s"
 
-#: kallithea/controllers/admin/repos.py:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr "Παρουσιάστηκε ένα σφάλμα κατά τη διάρκεια αυτής της λειτουργίας"
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-msgid "Repository has been locked"
-msgstr "Το αποθετήριο έχει κλειδωθεί"
-
-#: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-msgid "Repository has been unlocked"
-msgstr "Το αποθετήριο έχει ξεκλειδωθεί"
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr "Παρουσιάστηκε ένα σφάλμα κατά το ξεκλείδωμα"
-
-#: kallithea/controllers/admin/repos.py:528
+#: kallithea/controllers/admin/repos.py:490
 msgid "Cache invalidation successful"
 msgstr "Η ακύρωση της cache ήταν επιτυχής"
 
-#: kallithea/controllers/admin/repos.py:532
+#: kallithea/controllers/admin/repos.py:494
 msgid "An error occurred during cache invalidation"
 msgstr "Παρουσιάστηκε ένα σφάλμα κατά τη διάρκεια ακύρωσης της cache"
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:579
+#: kallithea/controllers/admin/repos.py:541
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:180
+#: kallithea/controllers/admin/settings.py:176
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:192
+#: kallithea/controllers/admin/settings.py:188
 #, fuzzy, python-format
 #| msgid "Deleted repository %s"
 msgid "Invalidated %s repositories"
 msgstr "Διαγράφηκε το αποθετήριο %s"
 
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "Δεν υπάρχουν ακόμα έτοιμα δεδομένα"
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:357
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:363
+#: kallithea/controllers/admin/settings.py:360
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
+#: kallithea/controllers/admin/user_groups.py:212
+msgid "Successfully deleted user group"
+msgstr ""
+
 #: kallithea/controllers/admin/user_groups.py:217
-msgid "Successfully deleted user group"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:222
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr ""
 
@@ -1066,218 +1056,218 @@
 msgid "The default user cannot be edited"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr ""
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr ""
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr ""
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, python-format
 msgid "Changeset for %s %s not found in %s"
 msgstr ""
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+msgid "SSH access is disabled."
+msgstr ""
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr ""
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:625
+#: kallithea/lib/helpers.py:666
 #, python-format
 msgid "Changeset %s not found"
 msgstr ""
 
-#: kallithea/lib/helpers.py:674
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr ""
 
-#: kallithea/lib/helpers.py:725
-#, python-format
-msgid "Fork name %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:746
-#, python-format
-msgid "Pull request %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:756
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:760
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
-msgid "[updated] repository"
-msgstr ""
-
 #: kallithea/lib/helpers.py:766
+#, python-format
+msgid "Fork name %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:787
+#, python-format
+msgid "Pull request %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:797
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
+msgid "[created] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:801
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
+msgid "[updated] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr ""
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr ""
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr ""
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1285,69 +1275,96 @@
 "repositories"
 msgstr ""
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr ""
 
@@ -1356,133 +1373,133 @@
 msgid "on line %s"
 msgstr ""
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1706
+#: kallithea/model/db.py:1640
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1707
+#: kallithea/model/db.py:1641
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1708
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1711
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1730
+#: kallithea/model/db.py:1664
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1732
+#: kallithea/model/db.py:1666
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr ""
 
@@ -1497,7 +1514,7 @@
 
 #: kallithea/model/forms.py:67
 msgid "Please enter a password"
-msgstr ""
+msgstr "Παρακαλώ εισάγετε έναν κωδικό πρόσβασης"
 
 #: kallithea/model/forms.py:68
 #, python-format
@@ -1508,79 +1525,79 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:169
+#, 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:170
 #, 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:171
-#, 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:184
+#: kallithea/model/notification.py:183
 msgid "Closing"
 msgstr ""
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 #, fuzzy
 #| msgid "Error creating pull request: %s"
 msgid "Cannot create empty pull request"
 msgstr "Λάθος στη δημιουργία αιτήματος έλξης - pull request: %s"
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 msgid "You are not authorized to create the pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 #, fuzzy
 #| msgid "Missing changesets since the previous pull request:"
 msgid "Missing changesets since the previous iteration:"
 msgstr "Ελλιπή σετ αλλαγών από την προηγούμενη αίτηση έλξης:"
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, fuzzy, python-format
 #| msgid "New changesets on %s %s since the previous pull request:"
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr "Καινούρια σετ αλλαγών στα %s %s από την προηγούμενη αίτηση έλξης:"
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 #, fuzzy
 #| msgid "Ancestor didn't change - show diff since previous version:"
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 "Το γονικό δεν άλλαξε - εμφάνισε τις διαφορές από την προηγούμενη έκδοση:"
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, fuzzy, python-format
 #| msgid ""
 #| "This pull request is based on another %s revision and there is no "
@@ -1592,232 +1609,243 @@
 "Αυτή η αίτηση έλξης είναι βασισμένη σε μία άλλη %s αναθεώρηση και δεν "
 "υπάρχει ένα απλό diff."
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, fuzzy, python-format
 #| msgid "No changes found on %s %s since previous version."
 msgid "No changes found on %s %s since previous iteration."
 msgstr "Δεν βρέθηκαν αλλαγές στο %s %s από την προηγούμενη έκδοση."
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr ""
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, python-format
+msgid "SSH key %r not found"
+msgstr ""
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:255
 #, 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:263
+#: kallithea/model/user.py:260
 #, 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:270
+#: kallithea/model/user.py:267
 #, 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:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr ""
 
+#: kallithea/model/validators.py:72
+#, python-format
+msgid "Username \"%(username)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:74
 #, python-format
-msgid "Username \"%(username)s\" already exists"
+msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
 #: kallithea/model/validators.py:76
-#, python-format
-msgid "Username \"%(username)s\" cannot be used"
-msgstr ""
-
-#: kallithea/model/validators.py:78
 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:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr ""
 
+#: kallithea/model/validators.py:132
+#, python-format
+msgid "User group \"%(usergroup)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:134
-#, python-format
-msgid "User group \"%(usergroup)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:136
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr ""
 
+#: kallithea/model/validators.py:175
+#, python-format
+msgid "Group \"%(group_name)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:177
 #, python-format
-msgid "Group \"%(group_name)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:179
-#, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 msgid "Invalid username or password"
 msgstr ""
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr ""
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr ""
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
-#: kallithea/model/validators.py:333
+#: kallithea/model/validators.py:318
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:419
+#: kallithea/model/validators.py:404
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:430
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:460
+#: kallithea/model/validators.py:445
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:512
+#: kallithea/model/validators.py:497
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:552
+#: kallithea/model/validators.py:537
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 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:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:765
+#: kallithea/model/validators.py:750
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1858,24 +1886,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr ""
 
@@ -1892,7 +1926,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1900,11 +1934,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr ""
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr ""
@@ -1919,7 +1953,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1927,7 +1961,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr ""
@@ -2083,10 +2117,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr ""
@@ -2135,22 +2171,22 @@
 msgstr ""
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr ""
 
@@ -2168,14 +2204,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2183,36 +2219,25 @@
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr ""
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr ""
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr ""
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2259,8 +2284,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 msgid "Never"
 msgstr ""
 
@@ -2293,7 +2320,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr ""
 
@@ -2329,23 +2356,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2373,7 +2402,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2433,7 +2462,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr ""
 
@@ -2446,24 +2475,29 @@
 msgid "Email Addresses"
 msgstr ""
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
-msgid "API Keys"
-msgstr ""
-
 #: kallithea/templates/admin/my_account/my_account.html:29
-msgid "Owned Repositories"
-msgstr ""
-
-#: kallithea/templates/admin/my_account/my_account.html:30
-#: kallithea/templates/journal/journal.html:33
-msgid "Watched Repositories"
+#: kallithea/templates/admin/users/user_edit.html:32
+msgid "SSH Keys"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
+msgid "API Keys"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:32
+msgid "Owned Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:33
+#: kallithea/templates/journal/journal.html:33
+msgid "Watched Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 msgid "Show Permissions"
 msgstr ""
 
@@ -2490,7 +2524,9 @@
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 msgid "Remove"
 msgstr ""
 
@@ -2506,12 +2542,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr ""
 
@@ -2612,6 +2650,42 @@
 msgid "Name"
 msgstr ""
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+msgid "Last Used"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, python-format
+msgid "Confirm to remove this SSH key: %s"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+msgid "New SSH key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+msgid "Public key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 msgid "Repositories You are Watching"
 msgstr ""
@@ -2628,7 +2702,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr ""
 
@@ -2664,7 +2738,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2824,7 +2898,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr ""
 
@@ -2934,17 +3008,11 @@
 "private repositories and other groups if selected."
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Confirm to delete this group"
 msgstr ""
 
@@ -2973,14 +3041,14 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr ""
@@ -2990,7 +3058,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr ""
@@ -3042,8 +3110,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr ""
 
@@ -3077,69 +3145,32 @@
 "public journal."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-msgid "Change Locking"
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
+#: kallithea/templates/data_table/_dt_elements.html:68
+#, python-format
+msgid "Confirm to delete this repository: %s"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-msgid "Confirm to unlock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-msgid "Unlock Repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-msgid "Confirm to lock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-msgid "Lock Repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
-#: kallithea/templates/data_table/_dt_elements.html:68
-#, python-format
-msgid "Confirm to delete this repository: %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
 msgid "Delete this Repository"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3238,19 +3269,11 @@
 msgid "This repository does not have a remote repository URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "Permanent Repository ID"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_settings.html:10
+msgid "Permanent URL"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3260,30 +3283,30 @@
 "other cases that you need to hardcode the URL into a 3rd party service."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 msgid "Remote repository"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 msgid "Repository URL"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr ""
 
@@ -3392,8 +3415,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 msgid "Save Settings"
 msgstr ""
 
@@ -3488,10 +3511,6 @@
 msgid "Kallithea version"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr ""
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr ""
@@ -3512,15 +3531,7 @@
 msgid "Git path"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr ""
 
@@ -3529,46 +3540,38 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
+msgid "Update repository after push (hg update)"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
-msgid "Update repository after push (hg update)"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:33
 msgid "Mercurial extensions"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr ""
 
+#: kallithea/templates/admin/settings/settings_vcs.html:35
+msgid ""
+"Requires hgsubversion library to be installed. Enables cloning of remote "
+"Subversion repositories while converting them to Mercurial."
+msgstr ""
+
 #: kallithea/templates/admin/settings/settings_vcs.html:47
-msgid ""
-"Requires hgsubversion library to be installed. Enables cloning of remote "
-"Subversion repositories while converting them to Mercurial."
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:59
 msgid "Location of repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3617,8 +3620,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-msgid "Clone URL"
+msgid "HTTP Clone URL"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
@@ -3636,58 +3638,73 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+msgid "SSH Clone URL"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 #, fuzzy
 #| msgid "Repositories"
 msgid "Repository page size"
 msgstr "Αποθετήρια"
 
-#: kallithea/templates/admin/settings/settings_visual.html:57
+#: kallithea/templates/admin/settings/settings_visual.html:68
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:62
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:70
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:81
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 msgid "Show public/private icons next to repository names."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:89
+#: kallithea/templates/admin/settings/settings_visual.html:100
 msgid "Meta Tagging"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr ""
 
@@ -3848,12 +3865,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr ""
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr ""
 
@@ -3901,151 +3918,128 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr ""
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr ""
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr ""
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr ""
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr ""
 
+#: kallithea/templates/base/base.html:289
+msgid "Show recent activity"
+msgstr ""
+
+#: kallithea/templates/base/base.html:295
 #: kallithea/templates/base/base.html:296
-msgid "Show recent activity"
+msgid "Public journal"
+msgstr ""
+
+#: kallithea/templates/base/base.html:301
+msgid "Show public gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
-msgid "Public journal"
+msgid "Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:306
+msgid "All Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:308
-msgid "Show public gists"
+msgid "My Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:309
-msgid "Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:313
-msgid "All Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:315
-msgid "My Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:316
 msgid "My Private Gists"
 msgstr ""
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr ""
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 msgid "My Pull Requests"
 msgstr ""
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr ""
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 msgid "Login to Your Account"
 msgstr ""
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 msgid "Forgot password?"
 msgstr ""
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 msgid "Don't have an account?"
 msgstr ""
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr ""
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-msgid "Inherit defaults"
+msgid "Create repositories"
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-msgid "default permissions"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 
@@ -4770,7 +4764,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr ""
@@ -4782,7 +4776,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr ""
 
@@ -4835,7 +4829,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr ""
 
@@ -4963,8 +4957,8 @@
 msgstr ""
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr ""
 
@@ -5015,8 +5009,8 @@
 msgstr ""
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr ""
 
@@ -5322,9 +5316,9 @@
 msgid "File names"
 msgstr ""
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr ""
 
@@ -5334,20 +5328,20 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr ""
 
@@ -5356,12 +5350,12 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr ""
 
@@ -5402,94 +5396,110 @@
 msgid "%s Summary"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr ""
-
+#: kallithea/templates/summary/summary.html:54
+msgid "Clone URL"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+msgid "Use Name"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:101
-msgid "There are no downloads yet"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:103
-msgid "Downloads are disabled for this repository"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:109
+msgid "There are no downloads yet"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:111
+msgid "Downloads are disabled for this repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 msgid "With subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 msgid "Latest Changes"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 msgid "Quick Start"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:188
-msgid "Add or upload files directly via Kallithea"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:196
-msgid "Push new repository"
+msgid "Add or upload files directly via Kallithea"
 msgstr ""
 
 #: kallithea/templates/summary/summary.html:204
+msgid "Push new repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr ""
 
+#~ msgid "This repository has been locked by %s on %s"
+#~ msgstr "Το αποθετήριο κλειδώθηκε από %s την %s"
+
+#~ msgid "Repository has been locked"
+#~ msgstr "Το αποθετήριο έχει κλειδωθεί"
+
+#~ msgid "Repository has been unlocked"
+#~ msgstr "Το αποθετήριο έχει ξεκλειδωθεί"
+
+#~ msgid "An error occurred during unlocking"
+#~ msgstr "Παρουσιάστηκε ένα σφάλμα κατά το ξεκλείδωμα"
+
 #~ msgid "There is no index to search in. Please run whoosh indexer"
 #~ msgstr ""
 #~ "Δεν υπάρχει ευρετήριο για την αναζήτηση. Παρακαλώ τρέξτε τον whoosh "
--- a/kallithea/i18n/es/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/es/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,13 +1,10 @@
-# Spanish translations for Kallithea.
 # Copyright (C) 2016 Various authors, licensing as GPLv3
 # This file is distributed under the same license as the Kallithea project.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
-#
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\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/"
@@ -20,14 +17,14 @@
 "X-Generator: Weblate 3.0-dev\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr "Aún no hay cambios"
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -36,94 +33,94 @@
 msgid "None"
 msgstr "Ninguno"
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr "(cerrado)"
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr "Mostrar espacios en blanco"
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr "Ignorar espacios en blanco"
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr "Aumentar el contexto del diff a %(num)s lineas"
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 #, fuzzy
 #| msgid "No permission to change pull request status"
 msgid "No permission to change status"
 msgstr "No tene permiso para cambiar el estado de la petición pull"
 
-#: kallithea/controllers/changeset.py:214
+#: kallithea/controllers/changeset.py:212
 #, python-format
 msgid "Successfully deleted pull request %s"
 msgstr "Petición de pull %s eliminada correctamente"
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr "La revisión no existe en este repositorio"
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, python-format
 msgid "Could not find other repository %s"
 msgstr "No se puede encontrar otro repositorio %s"
 
-#: kallithea/controllers/compare.py:72
+#: kallithea/controllers/compare.py:74
 msgid "Cannot compare repositories of different types"
 msgstr "No se pueden comparar repositorios de diferentes tipos"
 
-#: kallithea/controllers/compare.py:244
-msgid "Cannot show empty diff"
-msgstr "No se puede mostrar diff vacio"
-
 #: kallithea/controllers/compare.py:246
+msgid "Cannot show empty diff"
+msgstr "No se puede mostrar diff vacio"
+
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr ""
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr "No se pueden comparar repositorios sin usar un ancestro común"
 
-#: kallithea/controllers/error.py:70
+#: kallithea/controllers/error.py:71
 msgid "No response"
 msgstr "No hay respuesta"
 
-#: kallithea/controllers/error.py:71
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr "Error desconocido"
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr ""
 "La petición no ha podido ser atendida por el servidor debido un error de "
 "sintaxis."
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr "Acceso no autorizado al recurso"
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr "No tiene permiso para ver esta página"
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr "No se ha encontrado el recurso"
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
@@ -146,124 +143,118 @@
 msgid "Changeset was too big and was cut off..."
 msgstr "El cambio era demasiado grande y se redució..."
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr "%s%s canal"
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, fuzzy, python-format
 msgid "Changes on %s repository"
 msgstr "Cambios en %s repositorio"
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr "Haga clic aquí para añadir un archivo nuevo"
 
-#: kallithea/controllers/files.py:93
+#: kallithea/controllers/files.py:86
 #, fuzzy
 #| msgid "There are no files yet. %s"
 msgid "There are no files yet."
 msgstr "Aún no hay archivos. %s"
 
-#: kallithea/controllers/files.py:193
+#: kallithea/controllers/files.py:186
 #, python-format
 msgid "%s at %s"
 msgstr "%s en %s"
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr "Este repositorio ha sido bloqueado por %s en %s"
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 msgid "You can only delete files with revision being a valid branch"
 msgstr ""
 "Sólo puede borrar archivos si la revisión pertenece a una rama válida"
 
-#: kallithea/controllers/files.py:322
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr "Archivo %s eliminado mediante Kallithea"
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr "El archivo %s se eliminó correctamente"
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr "Ocurrió un error al anotar los cambios"
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 msgid "You can only edit files with revision being a valid branch"
 msgstr ""
 "Sólo puede editar archivos si la revisión pertenece a una rama válida"
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr "Archivo %s editado mediante Kallithea"
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr "No hay cambios"
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr "Anotado correctamente a %s"
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr "Archivo añadido mediante Kallithea"
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr "Sin contenido"
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr "Sin nombre de archivo"
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 #, fuzzy
 msgid "Location must be relative path and must not contain .. in path"
 msgstr "La ruta debe ser relativa y no debe contener .. en la ruta"
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr "Descargas deshabilitadas"
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr "Revisión desconocida %s"
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr "Repositorio vacío"
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr "Tipo de archivo desconocido"
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr "Cambios"
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
 msgstr "Ramas"
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr "Etiquetas"
 
@@ -272,11 +263,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr "Ocurrió un error mientras se bifurcaba el repositorio %s"
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr "Grupos"
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -284,187 +275,187 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr "Repositorios"
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
 msgstr "Rama"
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr "Ramas cerradas"
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr "Etiqueta"
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr "Marcador"
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr "Registro público"
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr "Registro"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
 msgstr "CAPTCHA erróneo"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, 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:190
 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:238
+#: 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:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Contraseña actualizada correctamente"
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr "El validador \"%s\" no es correcto"
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr "%s (cerrado)"
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr "Cambio"
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr "Especial"
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 #, fuzzy
 msgid "Peer branches"
 msgstr "Ramas de los pares"
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr "Marcadores"
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr "Error al crear la petición de pull: %s"
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr "Ocurrió un error al crear la petición de pull"
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr "La petición de pull se ha creado correctamente"
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 #, fuzzy
 #| msgid "Pull request update created"
 msgid "New pull request iteration created"
 msgstr "Actualización de la petición pull creada"
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr "No hay descripción"
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
 msgstr "Petición pull actualizada"
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr "Petición pull eliminada correctamente"
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, python-format
 msgid "Revision %s not found in %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, fuzzy, python-format
 #| msgid "No changesets found for updating this pull request."
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr "No se encontraron cambios para actualizar la petición pull."
 
-#: kallithea/controllers/pullrequests.py:522
+#: kallithea/controllers/pullrequests.py:520
 #, python-format
 msgid "This pull request has already been merged to %s."
 msgstr "La petición pull ya ha sido incluida a %s."
 
-#: kallithea/controllers/pullrequests.py:524
+#: kallithea/controllers/pullrequests.py:522
 msgid "This pull request has been closed and can not be updated."
 msgstr "La petición pull esta cerrada y no se puede actualizar."
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, fuzzy, python-format
 #| msgid "The following changes are available on %s:"
 msgid "The following additional changes are available on %s:"
 msgstr "Los siguientes cambios están disponibles en %s:"
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 #, fuzzy
 #| msgid "No changesets found for updating this pull request."
 msgid "No additional changesets found for iterating on this pull request."
 msgstr "No se encontraron cambios para actualizar la petición pull."
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, fuzzy, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr "Nota: la rama %s tiene otro head: %s."
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 #, fuzzy
 #| msgid "Git pull requests don't support updates yet."
 msgid "Git pull requests don't support iterating yet."
 msgstr "La peticiones pull de Git aún no soportan actualizaciones."
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, fuzzy, python-format
 #| msgid "No changesets found for updating this pull request."
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
 msgstr "No se encontraron cambios para actualizar la petición pull."
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 
@@ -480,21 +471,21 @@
 msgid "An error occurred during search operation."
 msgstr "Ocurrió un error mientras se ejecutaba la búsqueda."
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr "Todavía no hay datos disponibles"
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr "Las estadísticas están deshabilitadas en este repositorio"
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr "Los ajustes de autentificación se han actualizado correctamente"
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr "ocurrió un error al actualizar los ajustes de autentificación"
 
@@ -506,123 +497,136 @@
 msgid "Error occurred during update of defaults"
 msgstr "Ocurrió un error al actualizar los ajustes predeterminados"
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 msgid "Forever"
 msgstr "Para siempre"
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
 #: kallithea/controllers/admin/users.py:249
 msgid "5 minutes"
 msgstr "5 minutos"
 
-#: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
 #: kallithea/controllers/admin/users.py:250
 msgid "1 hour"
 msgstr "1 hora"
 
-#: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
 #: kallithea/controllers/admin/users.py:251
 msgid "1 day"
 msgstr "1 día"
 
-#: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr "1 mes"
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr "Tiempo de vida"
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr "Ocurrió un error mientras se creaba el gist"
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr "Gist %s eliminado"
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
 msgstr "Sin modificar"
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr "Gist actualizado correctamente"
 
-#: kallithea/controllers/admin/gists.py:230
-msgid "Successfully updated gist data"
-msgstr ""
-
 #: kallithea/controllers/admin/gists.py:233
+msgid "Successfully updated gist data"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, python-format
+msgid "SSH key %s successfully added"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+#, fuzzy
+#| msgid "Successfully deleted file %s"
+msgid "SSH key successfully deleted"
+msgstr "El archivo %s se eliminó correctamente"
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -630,9 +634,9 @@
 msgid "Read"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -640,9 +644,9 @@
 msgid "Write"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -665,363 +669,348 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
-#: kallithea/templates/admin/auth/auth_settings.html:42
-#: kallithea/templates/base/root.html:50
-msgid "Disabled"
-msgstr ""
-
 #: kallithea/controllers/admin/permissions.py:78
-msgid "Allowed with manual account activation"
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
+#: kallithea/templates/admin/auth/auth_settings.html:42
+#: kallithea/templates/base/root.html:50
+msgid "Disabled"
 msgstr ""
 
 #: kallithea/controllers/admin/permissions.py:80
+msgid "Allowed with manual account activation"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:290
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:390
+#: kallithea/controllers/admin/repos.py:391
 #, 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:401
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:466
-msgid "Nothing"
-msgstr ""
-
 #: kallithea/controllers/admin/repos.py:468
+msgid "Nothing"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:470
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-msgid "Repository has been locked"
+#: kallithea/controllers/admin/repos.py:490
+msgid "Cache invalidation successful"
 msgstr ""
 
 #: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-msgid "Repository has been unlocked"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:528
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:532
 msgid "An error occurred during cache invalidation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:579
+#: kallithea/controllers/admin/repos.py:541
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:180
+#: kallithea/controllers/admin/settings.py:176
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:192
+#: kallithea/controllers/admin/settings.py:188
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "Todavía no hay datos disponibles"
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:357
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:363
+#: kallithea/controllers/admin/settings.py:360
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
+#: kallithea/controllers/admin/user_groups.py:212
+msgid "Successfully deleted user group"
+msgstr ""
+
 #: kallithea/controllers/admin/user_groups.py:217
-msgid "Successfully deleted user group"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:222
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr ""
 
@@ -1051,218 +1040,218 @@
 msgid "The default user cannot be edited"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr ""
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr ""
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr ""
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, python-format
 msgid "Changeset for %s %s not found in %s"
 msgstr ""
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+msgid "SSH access is disabled."
+msgstr ""
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr ""
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:625
+#: kallithea/lib/helpers.py:666
 #, python-format
 msgid "Changeset %s not found"
 msgstr ""
 
-#: kallithea/lib/helpers.py:674
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr ""
 
-#: kallithea/lib/helpers.py:725
-#, python-format
-msgid "Fork name %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:746
-#, python-format
-msgid "Pull request %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:756
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:760
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
-msgid "[updated] repository"
-msgstr ""
-
 #: kallithea/lib/helpers.py:766
+#, python-format
+msgid "Fork name %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:787
+#, python-format
+msgid "Pull request %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:797
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
+msgid "[created] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:801
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
+msgid "[updated] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr ""
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr ""
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr ""
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1270,69 +1259,96 @@
 "repositories"
 msgstr ""
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr ""
 
@@ -1341,133 +1357,133 @@
 msgid "on line %s"
 msgstr ""
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1706
+#: kallithea/model/db.py:1640
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1707
+#: kallithea/model/db.py:1641
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1708
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1711
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1730
+#: kallithea/model/db.py:1664
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1732
+#: kallithea/model/db.py:1666
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr ""
 
@@ -1493,79 +1509,79 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:169
+#, 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:170
 #, 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:171
-#, 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:184
+#: kallithea/model/notification.py:183
 msgid "Closing"
 msgstr ""
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 #, fuzzy
 #| msgid "Error creating pull request: %s"
 msgid "Cannot create empty pull request"
 msgstr "Error al crear la petición de pull: %s"
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 msgid "You are not authorized to create the pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 #, fuzzy
 #| msgid "Missing changesets since the previous pull request:"
 msgid "Missing changesets since the previous iteration:"
 msgstr "Cambios que faltan desde la ultima petición de pull:"
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, fuzzy, python-format
 #| msgid "New changesets on %s %s since the previous pull request:"
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr "Cambios nuevos en %s %s desde la ultima petición pull:"
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 #, fuzzy
 #| msgid "Ancestor didn't change - show diff since previous version:"
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 "El ascendente no ha cambiado - ver diferencias desde la versión anterior:"
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, fuzzy, python-format
 msgid ""
 "This iteration is based on another %s revision and there is no simple "
@@ -1574,232 +1590,243 @@
 "La petición de pull está basada en otra %s revisión y no hay un diff "
 "simple."
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, fuzzy, python-format
 #| msgid "No changes found on %s %s since previous version."
 msgid "No changes found on %s %s since previous iteration."
 msgstr "No se encontró ningún cambio en %s %s desde la versión anterior."
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr ""
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, python-format
+msgid "SSH key %r not found"
+msgstr ""
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:255
 #, 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:263
+#: kallithea/model/user.py:260
 #, 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:270
+#: kallithea/model/user.py:267
 #, 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:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr ""
 
+#: kallithea/model/validators.py:72
+#, python-format
+msgid "Username \"%(username)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:74
 #, python-format
-msgid "Username \"%(username)s\" already exists"
+msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
 #: kallithea/model/validators.py:76
-#, python-format
-msgid "Username \"%(username)s\" cannot be used"
-msgstr ""
-
-#: kallithea/model/validators.py:78
 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:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr ""
 
+#: kallithea/model/validators.py:132
+#, python-format
+msgid "User group \"%(usergroup)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:134
-#, python-format
-msgid "User group \"%(usergroup)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:136
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr ""
 
+#: kallithea/model/validators.py:175
+#, python-format
+msgid "Group \"%(group_name)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:177
 #, python-format
-msgid "Group \"%(group_name)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:179
-#, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 msgid "Invalid username or password"
 msgstr ""
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr ""
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr ""
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
-#: kallithea/model/validators.py:333
+#: kallithea/model/validators.py:318
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:419
+#: kallithea/model/validators.py:404
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:430
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:460
+#: kallithea/model/validators.py:445
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:512
+#: kallithea/model/validators.py:497
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:552
+#: kallithea/model/validators.py:537
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 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:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:765
+#: kallithea/model/validators.py:750
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1840,24 +1867,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr ""
 
@@ -1874,7 +1907,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1882,11 +1915,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr ""
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr ""
@@ -1901,7 +1934,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1909,7 +1942,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr ""
@@ -2065,10 +2098,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr ""
@@ -2117,22 +2152,22 @@
 msgstr ""
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr ""
 
@@ -2150,14 +2185,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2165,36 +2200,25 @@
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr ""
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr ""
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr ""
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2241,8 +2265,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 msgid "Never"
 msgstr ""
 
@@ -2275,7 +2301,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr ""
 
@@ -2311,23 +2337,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2355,7 +2383,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2415,7 +2443,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr ""
 
@@ -2428,24 +2456,29 @@
 msgid "Email Addresses"
 msgstr ""
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
-msgid "API Keys"
-msgstr ""
-
 #: kallithea/templates/admin/my_account/my_account.html:29
-msgid "Owned Repositories"
-msgstr ""
-
-#: kallithea/templates/admin/my_account/my_account.html:30
-#: kallithea/templates/journal/journal.html:33
-msgid "Watched Repositories"
+#: kallithea/templates/admin/users/user_edit.html:32
+msgid "SSH Keys"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
+msgid "API Keys"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:32
+msgid "Owned Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:33
+#: kallithea/templates/journal/journal.html:33
+msgid "Watched Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 msgid "Show Permissions"
 msgstr ""
 
@@ -2472,7 +2505,9 @@
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 msgid "Remove"
 msgstr ""
 
@@ -2488,12 +2523,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr ""
 
@@ -2594,6 +2631,42 @@
 msgid "Name"
 msgstr ""
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+msgid "Last Used"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, python-format
+msgid "Confirm to remove this SSH key: %s"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+msgid "New SSH key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+msgid "Public key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 msgid "Repositories You are Watching"
 msgstr ""
@@ -2610,7 +2683,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr ""
 
@@ -2646,7 +2719,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2806,7 +2879,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr ""
 
@@ -2914,17 +2987,11 @@
 "private repositories and other groups if selected."
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Confirm to delete this group"
 msgstr ""
 
@@ -2952,14 +3019,14 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr ""
@@ -2969,7 +3036,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr ""
@@ -3021,8 +3088,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr ""
 
@@ -3056,69 +3123,32 @@
 "public journal."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-msgid "Change Locking"
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
+#: kallithea/templates/data_table/_dt_elements.html:68
+#, python-format
+msgid "Confirm to delete this repository: %s"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-msgid "Confirm to unlock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-msgid "Unlock Repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-msgid "Confirm to lock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-msgid "Lock Repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
-#: kallithea/templates/data_table/_dt_elements.html:68
-#, python-format
-msgid "Confirm to delete this repository: %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
 msgid "Delete this Repository"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3217,19 +3247,11 @@
 msgid "This repository does not have a remote repository URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "Permanent Repository ID"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_settings.html:10
+msgid "Permanent URL"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3239,30 +3261,30 @@
 "other cases that you need to hardcode the URL into a 3rd party service."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 msgid "Remote repository"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 msgid "Repository URL"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr ""
 
@@ -3371,8 +3393,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 msgid "Save Settings"
 msgstr ""
 
@@ -3467,10 +3489,6 @@
 msgid "Kallithea version"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr ""
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr ""
@@ -3491,15 +3509,7 @@
 msgid "Git path"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr ""
 
@@ -3508,46 +3518,38 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
+msgid "Update repository after push (hg update)"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
-msgid "Update repository after push (hg update)"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:33
 msgid "Mercurial extensions"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr ""
 
+#: kallithea/templates/admin/settings/settings_vcs.html:35
+msgid ""
+"Requires hgsubversion library to be installed. Enables cloning of remote "
+"Subversion repositories while converting them to Mercurial."
+msgstr ""
+
 #: kallithea/templates/admin/settings/settings_vcs.html:47
-msgid ""
-"Requires hgsubversion library to be installed. Enables cloning of remote "
-"Subversion repositories while converting them to Mercurial."
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:59
 msgid "Location of repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3596,8 +3598,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-msgid "Clone URL"
+msgid "HTTP Clone URL"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
@@ -3615,58 +3616,73 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+msgid "SSH Clone URL"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 #, fuzzy
 #| msgid "Repositories"
 msgid "Repository page size"
 msgstr "Repositorios"
 
-#: kallithea/templates/admin/settings/settings_visual.html:57
+#: kallithea/templates/admin/settings/settings_visual.html:68
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:62
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:70
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:81
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 msgid "Show public/private icons next to repository names."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:89
+#: kallithea/templates/admin/settings/settings_visual.html:100
 msgid "Meta Tagging"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr ""
 
@@ -3827,12 +3843,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr ""
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr ""
 
@@ -3880,151 +3896,128 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr ""
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr ""
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr ""
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr ""
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr ""
 
+#: kallithea/templates/base/base.html:289
+msgid "Show recent activity"
+msgstr ""
+
+#: kallithea/templates/base/base.html:295
 #: kallithea/templates/base/base.html:296
-msgid "Show recent activity"
+msgid "Public journal"
+msgstr ""
+
+#: kallithea/templates/base/base.html:301
+msgid "Show public gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
-msgid "Public journal"
+msgid "Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:306
+msgid "All Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:308
-msgid "Show public gists"
+msgid "My Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:309
-msgid "Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:313
-msgid "All Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:315
-msgid "My Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:316
 msgid "My Private Gists"
 msgstr ""
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr ""
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 msgid "My Pull Requests"
 msgstr ""
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr ""
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 msgid "Login to Your Account"
 msgstr ""
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 msgid "Forgot password?"
 msgstr ""
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 msgid "Don't have an account?"
 msgstr ""
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr ""
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-msgid "Inherit defaults"
+msgid "Create repositories"
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-msgid "default permissions"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 
@@ -4746,7 +4739,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr ""
@@ -4758,7 +4751,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr ""
 
@@ -4810,7 +4803,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr ""
 
@@ -4938,8 +4931,8 @@
 msgstr ""
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr ""
 
@@ -4990,8 +4983,8 @@
 msgstr ""
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr ""
 
@@ -5297,9 +5290,9 @@
 msgid "File names"
 msgstr ""
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr ""
 
@@ -5309,20 +5302,20 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr ""
 
@@ -5331,12 +5324,12 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr ""
 
@@ -5377,94 +5370,101 @@
 msgid "%s Summary"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr ""
-
+#: kallithea/templates/summary/summary.html:54
+msgid "Clone URL"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+msgid "Use Name"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:101
-msgid "There are no downloads yet"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:103
-msgid "Downloads are disabled for this repository"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:109
+msgid "There are no downloads yet"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:111
+msgid "Downloads are disabled for this repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 msgid "With subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 msgid "Latest Changes"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 msgid "Quick Start"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:188
-msgid "Add or upload files directly via Kallithea"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:196
-msgid "Push new repository"
+msgid "Add or upload files directly via Kallithea"
 msgstr ""
 
 #: kallithea/templates/summary/summary.html:204
+msgid "Push new repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr ""
 
+#~ msgid "This repository has been locked by %s on %s"
+#~ msgstr "Este repositorio ha sido bloqueado por %s en %s"
+
 #~ msgid "There is no index to search in. Please run whoosh indexer"
 #~ msgstr ""
 #~ "No hay ningún indice para buscar. Por favor, ejecute el indexador "
--- a/kallithea/i18n/fr/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/fr/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,33 +1,30 @@
-# French translations for Kallithea.
 # Copyright (C) 2014 RhodeCode GmbH, and others.
 # This file is distributed under the same license as the Kallithea project.
-# Translators:
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2011
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
-"PO-Revision-Date: 2019-05-06 08:48+0000\n"
-"Last-Translator: Étienne Gilli <etienne.gilli@gmail.com>\n"
-"Language-Team: French <https://hosted.weblate.org/projects/kallithea/stable/"
-"fr/>\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\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/"
+"kallithea/fr/>\n"
 "Language: fr\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 3.7-dev\n"
+"X-Generator: Weblate 3.9-dev\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr "Il n’y a aucun changement pour le moment"
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -36,92 +33,92 @@
 msgid "None"
 msgstr "Aucun"
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr "(fermé)"
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr "Afficher les espaces et tabulations"
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr "Ignorer les espaces et tabulations"
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr "Augmenter le contexte du diff à %(num)s lignes"
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 msgid "No permission to change status"
 msgstr "Permission manquante pour changer le statut"
 
-#: kallithea/controllers/changeset.py:214
+#: kallithea/controllers/changeset.py:212
 #, python-format
 msgid "Successfully deleted pull request %s"
 msgstr "La requête de pull %s a été supprimée avec succès"
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr "Une telle révision n'existe pas pour ce dépôt"
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, python-format
 msgid "Could not find other repository %s"
 msgstr "Impossible de trouver l'autre dépôt %s"
 
-#: kallithea/controllers/compare.py:72
+#: kallithea/controllers/compare.py:74
 msgid "Cannot compare repositories of different types"
 msgstr "Impossible de comparer des dépôts de types différents"
 
-#: kallithea/controllers/compare.py:244
+#: kallithea/controllers/compare.py:246
 msgid "Cannot show empty diff"
 msgstr "Impossible d'afficher un diff vide"
 
-#: kallithea/controllers/compare.py:246
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr "Aucun ancêtre trouvé pour le diff de fusion"
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr "Plusieurs ancêtres de fusion trouvés pour la comparaison de fusion"
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr "Impossible de comparer des dépôts sans utiliser un ancêtre commun"
 
-#: kallithea/controllers/error.py:70
+#: kallithea/controllers/error.py:71
 msgid "No response"
 msgstr "Pas de réponse"
 
-#: kallithea/controllers/error.py:71
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr "Erreur inconnue"
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr ""
 "Le serveur n’a pas pu interpréter la requête à cause d’une erreur de "
 "syntaxe."
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr "Accès interdit à cette ressource"
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr "Vous n’avez pas la permission de voir cette page"
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr "Ressource introuvable"
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
@@ -144,125 +141,119 @@
 msgid "Changeset was too big and was cut off..."
 msgstr "Cet ensemble de changements était trop important et a été découpé…"
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr "Flux %s de %s"
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
 msgstr "Changements sur le dépôt %s"
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr "Ajouter un nouveau fichier"
 
-#: kallithea/controllers/files.py:93
+#: kallithea/controllers/files.py:86
 msgid "There are no files yet."
 msgstr "Il n'y a pas encore de fichier."
 
-#: kallithea/controllers/files.py:193
+#: kallithea/controllers/files.py:186
 #, python-format
 msgid "%s at %s"
 msgstr "%s à %s"
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr "Ce dépôt a été verrouillé par %s sur %s"
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 msgid "You can only delete files with revision being a valid branch"
 msgstr ""
 "Vous ne pouvez supprimer les fichiers que si la révision est une branche "
 "valide"
 
-#: kallithea/controllers/files.py:322
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr "Le fichier %s a été supprimé via Kallithea"
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr "Suppression du fichier %s effectuée avec succès"
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr "Une erreur est survenue durant le commit"
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 msgid "You can only edit files with revision being a valid branch"
 msgstr ""
 "Vous ne pouvez modifier les fichiers que si la révision est une branche "
 "valide"
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr "%s édité via Kallithea"
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr "Aucun changement"
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr "Commit réalisé avec succès sur %s"
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr "%s ajouté par Kallithea"
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr "Aucun contenu"
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr "Aucun nom de fichier"
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr ""
 "Le chemin doit être un chemin relatif et ne doit pas contenir .. dans le "
 "chemin"
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr "Les téléchargements sont désactivés"
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr "Révision %s inconnue"
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr "Dépôt vide"
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr "Type d’archive inconnu"
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr "Changesets"
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
 msgstr "Branches"
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr "Tags"
 
@@ -271,11 +262,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr "Une erreur est survenue durant le fork du dépôt %s"
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr "Groupes"
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -283,176 +274,176 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr "Dépôts"
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
 msgstr "Branche"
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr "Branches fermées"
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr "Étiquette"
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr "Signet"
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr "Journal public"
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr "Historique"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
 msgstr "Mauvais captcha"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, 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:190
 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:238
+#: 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:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Mot de passe mis à jour avec succès"
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr "Reviewer spécifié \"%s\" non valide"
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr "%s (fermé)"
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr "Changements"
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr "Spécial"
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr "Branches appairées"
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr "Signets"
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr "Erreur de création de la demande de pull : %s"
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr "Une erreur est survenue durant la création de la pull request"
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr "La requête de pull a été ouverte avec succès"
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 msgid "New pull request iteration created"
 msgstr "Nouvelle itération de requête de pull créée"
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr "Entretemps, les relecteurs suivants on été ajoutés : %s"
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr "Entretemps, les relecteurs suivants ont été supprimés : %s"
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr "Aucune description"
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
 msgstr "Pull request mise à jour"
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr "La requête de pull a été supprimée avec succès"
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, python-format
 msgid "Revision %s not found in %s"
 msgstr "Révision %s non trouvée dans %s"
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, python-format
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr ""
 "Erreur : Pas de changeset trouvé lors de l'affichage la requête de pull "
 "de %s."
 
-#: kallithea/controllers/pullrequests.py:522
+#: kallithea/controllers/pullrequests.py:520
 #, python-format
 msgid "This pull request has already been merged to %s."
 msgstr "Cette pull request a déjà été fusionnée à %s."
 
-#: kallithea/controllers/pullrequests.py:524
+#: kallithea/controllers/pullrequests.py:522
 msgid "This pull request has been closed and can not be updated."
 msgstr "Cette pull request a été fermée et ne peut pas être mise à jour."
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, python-format
 msgid "The following additional changes are available on %s:"
 msgstr ""
 "Les modifications additionnelles suivantes sont disponibles sur %s :"
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 msgid "No additional changesets found for iterating on this pull request."
 msgstr "Pas de changeset additionnel trouvé pour cette requête de pull."
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
-msgstr "Note: La branche %s a une autre tête : %s."
-
-#: kallithea/controllers/pullrequests.py:564
+msgstr "Note : La branche %s a une autre tête : %s."
+
+#: kallithea/controllers/pullrequests.py:567
 msgid "Git pull requests don't support iterating yet."
 msgstr ""
 "Les itérations des requêtes de pull Git ne sont pas encore supportées."
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, python-format
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
@@ -460,7 +451,7 @@
 "Erreur : certains changesets n'ont pas été trouvés lors de l'affichage la "
 "requête de pull depuis %s."
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 "Le diff ne peut pas être affiché : révisions des requêtes de pull "
@@ -478,21 +469,21 @@
 msgid "An error occurred during search operation."
 msgstr "Une erreur est survenue pendant la recherche."
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr "Aucune donnée actuellement disponible"
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 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:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr "Mise à jour des paramètres d'authentification effectuée avec succès"
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr ""
 "une erreur est survenue pendant la mise à jour des réglages "
@@ -507,127 +498,141 @@
 msgstr ""
 "Une erreur est survenue durant la mise à jour des réglages par défaut"
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 msgid "Forever"
 msgstr "Pour toujours"
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
 #: kallithea/controllers/admin/users.py:249
 msgid "5 minutes"
 msgstr "5 minute"
 
-#: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
 #: kallithea/controllers/admin/users.py:250
 msgid "1 hour"
 msgstr "1 heure"
 
-#: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
 #: kallithea/controllers/admin/users.py:251
 msgid "1 day"
 msgstr "1 jour"
 
-#: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr "1 mois"
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr "Toujours"
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr "Une erreur est survenue lors de la création du gist"
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr "Gist %s supprimé"
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
 msgstr "Non modifié"
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr "Le contenu du gist a été mis à jour avec succès"
 
-#: kallithea/controllers/admin/gists.py:230
+#: kallithea/controllers/admin/gists.py:233
 msgid "Successfully updated gist data"
 msgstr "Les données du gist on été mises à jour avec succès"
 
-#: kallithea/controllers/admin/gists.py:233
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 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:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 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 "
 "fonctionnement de l’application"
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr "Votre compte a été mis à jour avec succès"
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr "Une erreur est survenue durant la mise à jour de l'utilisateur %s"
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr ""
 "Une erreur est survenue durant la mise à jour du mot de passe de "
 "l'utilisateur"
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr "L’e-mail « %s » a été ajouté à l’utilisateur"
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr "Une erreur est survenue durant l’enregistrement de l’e-mail"
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr "L’e-mail a été enlevé de l’utilisateur"
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr "Clé d'API créée avec succès"
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr "Clé d'API remise à zéro avec succès"
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr "Clé d'API supprimée avec succès"
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, fuzzy, python-format
+#| msgid "API key successfully created"
+msgid "SSH key %s successfully added"
+msgstr "Clé d'API créée avec succès"
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+#, fuzzy
+#| msgid "API key successfully deleted"
+msgid "SSH key successfully deleted"
+msgstr "Clé d'API supprimée avec succès"
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -635,9 +640,9 @@
 msgid "Read"
 msgstr "Lire"
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -645,9 +650,9 @@
 msgid "Write"
 msgstr "Écrire"
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -670,258 +675,243 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr "Administration"
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:50
 msgid "Disabled"
 msgstr "Interdite"
 
-#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:80
 msgid "Allowed with manual account activation"
 msgstr "Autorisé avec activation de compte manuelle"
 
-#: kallithea/controllers/admin/permissions.py:80
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr "Autorisé avec activation de compte automatique"
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr "Activation manuelle du compte externe"
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr "Activation automatique du compte externe"
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr "Autorisée"
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr "Permissions globales mises à jour avec succès"
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr "Une erreur est survenue durant la mise à jour des permissions"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, 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:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr "Groupe de dépôts %s créé"
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Groupe de dépôts %s mis à jour"
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, 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:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, 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:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, 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:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Groupe de dépôts %s supprimé"
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, 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:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Impossible de révoquer votre permission d'administrateur"
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr "Permissions du groupe de dépôts mises à jour"
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 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:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Erreur de création du dépôt %s"
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Dépôt %s créé depuis %s"
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "dépôt %s forké en tant que %s"
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr "Dépôt %s créé"
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Dépôt %s mis à jour avec succès"
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, 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:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr "%s forks détachés"
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr "%s forks supprimés"
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Dépôt %s supprimé"
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, 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:290
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "Erreur pendant la suppression de %s"
 
-#: kallithea/controllers/admin/repos.py:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr "Permissions du dépôt mises à jour"
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr "Erreur de validation du champ : %s"
 
-#: kallithea/controllers/admin/repos.py:390
+#: kallithea/controllers/admin/repos.py:391
 #, 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:401
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr "Une erreur est survenue durant la suppression du champ"
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr "-- Pas un fork --"
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 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:450
+#: kallithea/controllers/admin/repos.py:452
 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:466
+#: kallithea/controllers/admin/repos.py:468
 msgid "Nothing"
 msgstr "[Aucun dépôt]"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:470
 #, 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:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr "Une erreur est survenue durant cette opération"
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-msgid "Repository has been locked"
-msgstr "Ce dépôt a été verrouillé"
+#: 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
-#: kallithea/controllers/admin/repos.py:509
-msgid "Repository has been unlocked"
-msgstr "Ce dépôt a été déverrouillé"
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr "Une erreur est survenue durant le déverrouillage"
-
-#: kallithea/controllers/admin/repos.py:528
-msgid "Cache invalidation successful"
-msgstr "Invalidation du cache réalisée avec succès"
-
-#: kallithea/controllers/admin/repos.py:532
 msgid "An error occurred during cache invalidation"
 msgstr "Une erreur est survenue durant l’invalidation du cache"
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr "Les changements distants ont été récupérés"
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 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:579
+#: kallithea/controllers/admin/repos.py:541
 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:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr "Réglages des gestionnaires de versions mis à jour"
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
@@ -929,117 +919,117 @@
 "Impossible d'activer la prise en charge de hgsubversion. La bibliothèque "
 "« hgsubversion » est manquante"
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 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:180
+#: kallithea/controllers/admin/settings.py:176
 #, 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:192
+#: kallithea/controllers/admin/settings.py:188
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr "%s dépôts invalidés"
 
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr "Réglages mis à jour"
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr "Réglages d’affichage mis à jour"
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 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:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr "Veuillez entrer votre adresse e-mail"
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr "Tâche d'envoi d'e-mail créée"
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 msgid "Hook already exists"
 msgstr "Le hook existe déjà"
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:357
 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:363
+#: kallithea/controllers/admin/settings.py:360
 msgid "Added new hook"
 msgstr "Le nouveau hook a été ajouté"
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr "Hooks mis à jour"
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr "Une erreur est survenue durant la création du hook"
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr "La tâche de réindexation Whoosh a été planifiée"
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr "Groupe d'utilisateurs %s créé"
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, 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:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr "Groupe d'utilisateurs %s mis à jour"
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, 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:217
+#: kallithea/controllers/admin/user_groups.py:212
 msgid "Successfully deleted user group"
 msgstr "Groupe d'utilisateurs supprimé avec succès"
 
-#: kallithea/controllers/admin/user_groups.py:222
+#: kallithea/controllers/admin/user_groups.py:217
 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:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr "Le groupe cible ne peut pas être le même"
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr "Permissions du groupe d'utilisateurs mises à jour"
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr "Permissions mises à jour"
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr "Une erreur est survenue durant l’enregistrement des permissions"
 
@@ -1069,223 +1059,225 @@
 msgid "The default user cannot be edited"
 msgstr "L'utilisateur par défaut ne peut pas être modifié"
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr "L'adresse IP %s a été ajoutée à la liste blanche"
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr "Une erreur est survenue durant la sauvegarde d'IP"
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr "L'adresse IP a été supprimée de la liste blanche"
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 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:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr "Vous devez être connecté pour visualiser cette page"
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr "Clé d'API invalide"
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 "Une fuite de jeton CSRF a été détectée - tous les jetons de formulaire "
 "sont considérés comme expirés"
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr "Dépôt non trouvé sur le système de fichiers"
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, python-format
 msgid "Changeset for %s %s not found in %s"
 msgstr "Ensemble de changements pour %s %s non trouvé dans %s"
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+#, fuzzy
+#| msgid "Your account is disabled"
+msgid "SSH access is disabled."
+msgstr "Votre compte est désactivé"
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr "Fichier binaire"
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 "Cet ensemble de changements était trop gros pour être affiché et a été "
 "découpé, utilisez le menu « diff » pour afficher les différences"
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr "Aucun changement détecté"
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "Branche supprimée : %s"
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr "Étiquette créée : %s"
 
-#: kallithea/lib/helpers.py:625
+#: kallithea/lib/helpers.py:666
 #, python-format
 msgid "Changeset %s not found"
 msgstr "Ensemble de changements %s non trouvé"
 
-#: kallithea/lib/helpers.py:674
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "Afficher les changements combinés %s->%s"
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 msgid "Compare view"
 msgstr "Vue de comparaison"
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr "et"
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr "%s de plus"
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "révisions"
 
-#: kallithea/lib/helpers.py:725
+#: kallithea/lib/helpers.py:766
 #, python-format
 msgid "Fork name %s"
 msgstr "Nom du fork %s"
 
-#: kallithea/lib/helpers.py:746
+#: kallithea/lib/helpers.py:787
 #, python-format
 msgid "Pull request %s"
 msgstr "Requête de pull %s"
 
-#: kallithea/lib/helpers.py:756
+#: kallithea/lib/helpers.py:797
 msgid "[deleted] repository"
 msgstr "[a supprimé] le dépôt"
 
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
 msgid "[created] repository"
 msgstr "[a créé] le dépôt"
 
-#: kallithea/lib/helpers.py:760
+#: kallithea/lib/helpers.py:801
 msgid "[created] repository as fork"
 msgstr "[a créé] le dépôt en tant que fork"
 
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
 msgid "[forked] repository"
 msgstr "[a forké] le dépôt"
 
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
 msgid "[updated] repository"
 msgstr "[a mis à jour] le dépôt"
 
-#: kallithea/lib/helpers.py:766
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr "[téléchargée] archive depuis le dépôt"
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr "[a supprimé] le dépôt"
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr "[a créé] l’utilisateur"
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr "[a mis à jour] l’utilisateur"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr "[créé] groupe d'utilisateurs"
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr "[mis à jour] groupe d'utilisateurs"
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr "[a commenté] une révision du dépôt"
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr "[a commenté] la requête de pull pour"
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr "[a fermé] la requête de pull de"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr "[a pushé] dans"
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr "[a commité via Kallithea] dans le dépôt"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr "[a pullé depuis un site distant] dans le dépôt"
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr "[a pullé] depuis"
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr "[suit maintenant] le dépôt"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr "[ne suit plus] le dépôt"
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr " et %s de plus"
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "Aucun fichier"
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr "nouveau fichier"
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr "mod"
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr "suppr."
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr "renommer"
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1296,69 +1288,96 @@
 "probablement été créé ou renommé manuellement. Veuillez relancer "
 "l’application pour rescanner les dépôts"
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] "%d an"
 msgstr[1] "%d ans"
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] "%d mois"
 msgstr[1] "%d mois"
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] "%d jour"
 msgstr[1] "%d jours"
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] "%d heure"
 msgstr[1] "%d heures"
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] "%d minute"
 msgstr[1] "%d minutes"
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] "%d seconde"
 msgstr[1] "%d secondes"
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr "dans %s"
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr "Il y a %s"
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr "dans %s et %s"
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr "Il y a %s et %s"
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr "à l’instant"
 
@@ -1367,158 +1386,158 @@
 msgid "on line %s"
 msgstr "à la ligne %s"
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr "[Mention]"
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr "niveau supérieur"
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr "Administrateur Kallithea"
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 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:1706
+#: kallithea/model/db.py:1640
 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:1707
+#: kallithea/model/db.py:1641
 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:1708
+#: kallithea/model/db.py:1642
 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:1710
+#: kallithea/model/db.py:1644
 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:1711
+#: kallithea/model/db.py:1645
 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:1712
+#: kallithea/model/db.py:1646
 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:1713
+#: kallithea/model/db.py:1647
 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:1715
+#: kallithea/model/db.py:1649
 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:1716
+#: kallithea/model/db.py:1650
 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:1717
+#: kallithea/model/db.py:1651
 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:1718
+#: kallithea/model/db.py:1652
 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:1720
+#: kallithea/model/db.py:1654
 msgid "Only admins can create repository groups"
 msgstr "Seul un administrateur peut créer un groupe de dépôts"
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 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:1723
+#: kallithea/model/db.py:1657
 msgid "Only admins can create user groups"
 msgstr "Seul un administrateur peut créer des groupes d'utilisateurs"
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 msgid "Non-admins can create user groups"
 msgstr ""
 "Les utilisateurs non-administrateurs peuvent créer des groupes "
 "d'utilisateurs"
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 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:1727
+#: kallithea/model/db.py:1661
 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:1729
+#: kallithea/model/db.py:1663
 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:1730
+#: kallithea/model/db.py:1664
 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:1732
+#: kallithea/model/db.py:1666
 msgid "Only admins can fork repositories"
 msgstr "Seul un administrateur peut faire un fork de dépôt"
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 msgid "Non-admins can fork repositories"
 msgstr "Les utilisateurs non-administrateurs peuvent faire un fork de dépôt"
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr "Enregistrement désactivé"
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr "Enregistrement des utilisateurs avec activation de compte manuelle"
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr ""
 "Enregistrement des utilisateurs avec activation de compte automatique"
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 msgid "Not reviewed"
 msgstr "Pas encore relue"
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 msgid "Under review"
 msgstr "En cours de relecture"
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 msgid "Not approved"
 msgstr "Non approuvée"
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr "Approuvée"
 
@@ -1544,7 +1563,7 @@
 msgid "Name must not contain only digits"
 msgstr "Le nom ne doit pas contenir seulement des chiffres"
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
@@ -1553,12 +1572,12 @@
 "[Commentaire] Changeset %(short_id)s « %(message_short)s » de "
 "%(repo_name)s dans %(branch)s"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr "Nouvel utilisateur %(new_username)s enregistré"
 
-#: kallithea/model/notification.py:170
+#: kallithea/model/notification.py:169
 #, python-format
 msgid ""
 "[Review] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
@@ -1567,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:171
+#: kallithea/model/notification.py:170
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s PR %(pr_nice_id)s \"%(pr_title_short)s\" from "
@@ -1576,11 +1595,11 @@
 "[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:184
+#: kallithea/model/notification.py:183
 msgid "Closing"
 msgstr "Fermeture"
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
@@ -1588,11 +1607,11 @@
 "%(user)s veut que vous regardiez la demande de pull %(pr_nice_id)s : "
 "%(pr_title)s"
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 msgid "Cannot create empty pull request"
 msgstr "Impossible de créer une requête de pull vide"
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
@@ -1601,24 +1620,24 @@
 "Impossible de créer la requête de pull : fusion croisée détectée, merci "
 "de fusionner une révision plus vieille de %s vers %s"
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 msgid "You are not authorized to create the pull request"
 msgstr "Vous n'êtes pas autorisé à créer cette requête de pull"
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 msgid "Missing changesets since the previous iteration:"
 msgstr "Changeset manquant depuis la précédente itération :"
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, python-format
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr "Nouveau changeset sur %s %s depuis la précédente itération :"
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr "L'ancêtre n'a pas changé - diff depuis l'itération précédente :"
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, python-format
 msgid ""
 "This iteration is based on another %s revision and there is no simple "
@@ -1627,32 +1646,48 @@
 "Cette itération est basée sur une autre révision %s et il n'y a pas de "
 "diff simple."
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, python-format
 msgid "No changes found on %s %s since previous iteration."
 msgstr "Aucun changement constaté sur %s %s depuis l'itération précédente."
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr "Fermé, itération suivante : %s."
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr "Dernier sommet"
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, fuzzy, python-format
+#| msgid "Changeset %s not found"
+msgid "SSH key %r not found"
+msgstr "Ensemble de changements %s non trouvé"
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr "Nouveau enregistrement d'utilisateur"
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 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:258
+#: kallithea/model/user.py:255
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
@@ -1661,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:263
+#: kallithea/model/user.py:260
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
@@ -1670,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:270
+#: kallithea/model/user.py:267
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
@@ -1680,15 +1715,15 @@
 "être supprimé. Changez les propriétaires de ces groupes d'utilisateurs ou "
 "supprimez-les : %s"
 
-#: kallithea/model/user.py:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr "Lien de remise à zéro du mot de passe"
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 msgid "Password reset notification"
 msgstr "Notification de réinitialisation du mot de passe"
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
@@ -1697,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:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr "Cette valeur ne peut être une liste vide"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:72
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "Le nom d’utilisateur « %(username)s » existe déjà"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:74
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "Le nom d’utilisateur « %(username)s » n’est pas valide"
 
-#: kallithea/model/validators.py:78
+#: kallithea/model/validators.py:76
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
@@ -1720,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:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr "L'entrée n'est pas valide"
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr "Le nom d’utilisateur « %(username)s » n’est pas valide"
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr "Nom de groupe d'utilisateurs invalide"
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:132
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr "Le groupe d'utilisateurs « %(usergroup)s » existe déjà"
 
-#: kallithea/model/validators.py:136
+#: kallithea/model/validators.py:134
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
@@ -1747,65 +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:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr "Impossible d’assigner ce groupe en tant que parent"
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:175
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr "Le groupe « %(group_name)s » existe déjà"
 
-#: kallithea/model/validators.py:179
+#: kallithea/model/validators.py:177
 #, 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:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr "Caractères incorrects (non-ASCII) dans le mot de passe"
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr "Ancien mot de passe invalide"
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr "Les mots de passe ne correspondent pas"
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 msgid "Invalid username or password"
 msgstr "Nom d'utilisateur ou mot de passe invalide"
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr "Jeton d’authentification incorrect"
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, 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:330
+#: kallithea/model/validators.py:315
 #, 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:331
+#: kallithea/model/validators.py:316
 #, 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:333
+#: kallithea/model/validators.py:318
 #, 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:419
+#: kallithea/model/validators.py:404
 msgid "Invalid repository URL"
 msgstr "URL de dépôt invalide"
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
@@ -1813,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:445
+#: kallithea/model/validators.py:430
 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:460
+#: kallithea/model/validators.py:445
 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:462
+#: kallithea/model/validators.py:447
 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:512
+#: kallithea/model/validators.py:497
 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:552
+#: kallithea/model/validators.py:537
 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:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr "Ceci n’est pas un chemin valide"
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 msgid "This email address is already in use"
 msgstr "Cette adresse e-mail est déjà enregistrée"
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "L’adresse e-mail « %(email)s » n’existe pas"
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
@@ -1856,28 +1887,28 @@
 "L’attribut Login du CN doit être spécifié. Cet attribut correspond au nom "
 "d’utilisateur"
 
-#: kallithea/model/validators.py:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr "Veuillez entrer une adresse IPv4 ou IPv6 valide"
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, 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:765
+#: kallithea/model/validators.py:750
 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:779
+#: kallithea/model/validators.py:764
 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:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1921,24 +1952,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr "Description"
 
@@ -1955,7 +1992,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1963,11 +2000,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr "Propriétaire"
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr "Connexion"
@@ -1982,7 +2019,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1990,7 +2027,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr "Mot de passe"
@@ -2154,10 +2191,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr "Action"
@@ -2209,22 +2248,22 @@
 msgstr "Greffon"
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr "Enregistrer"
 
@@ -2242,14 +2281,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr "Dépôt privé"
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2259,36 +2298,25 @@
 "comme collaborateurs."
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr "Activer les statistiques"
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr "Afficher les statistiques sur la page du dépôt."
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr "Activer les téléchargements"
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr "Afficher le menu de téléchargements sur la page du dépôt."
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr "Activer le verrouillage"
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr "Activer le verrouillage lors d’un pull sur le dépôt."
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2337,8 +2365,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 msgid "Never"
 msgstr "Jamais"
 
@@ -2371,7 +2401,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr "Créer un nouveau gist"
 
@@ -2407,23 +2437,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2451,7 +2483,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2511,7 +2543,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr "Mon compte"
 
@@ -2524,24 +2556,31 @@
 msgid "Email Addresses"
 msgstr "Adresses e-mail"
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
+#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/users/user_edit.html:32
+#, fuzzy
+#| msgid "API Keys"
+msgid "SSH Keys"
+msgstr "Clés de l'API"
+
+#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
 msgid "API Keys"
 msgstr "Clés de l'API"
 
-#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/my_account/my_account.html:32
 msgid "Owned Repositories"
 msgstr "Dépôts possédés"
 
-#: kallithea/templates/admin/my_account/my_account.html:30
+#: kallithea/templates/admin/my_account/my_account.html:33
 #: kallithea/templates/journal/journal.html:33
 msgid "Watched Repositories"
 msgstr "Dépôts surveillés"
 
-#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 msgid "Show Permissions"
 msgstr "Afficher les permissions"
 
@@ -2568,7 +2607,9 @@
 msgstr "Confirmer la suppression de cette clé d'API : %s"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 msgid "Remove"
 msgstr "Supprimer"
 
@@ -2584,12 +2625,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr "Ajouter"
 
@@ -2701,6 +2744,49 @@
 msgid "Name"
 msgstr "Nom"
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+#, fuzzy
+#| msgid "Last Name"
+msgid "Last Used"
+msgstr "Nom"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, fuzzy, python-format
+#| msgid "Confirm to remove this API key: %s"
+msgid "Confirm to remove this SSH key: %s"
+msgstr "Confirmer la suppression de cette clé d'API : %s"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+#, fuzzy
+#| msgid "New API key"
+msgid "New SSH key"
+msgstr "Nouvelle clé d'API"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+#, fuzzy
+#| msgid "Public Gist"
+msgid "Public key"
+msgstr "Gist public"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 msgid "Repositories You are Watching"
 msgstr "Dépôts que vous surveillez"
@@ -2717,7 +2803,7 @@
 msgstr "Global"
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr "Liste blanche d'adresses IP"
 
@@ -2758,7 +2844,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2940,7 +3026,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr "Avancé"
 
@@ -3048,19 +3134,11 @@
 "Ajouter ou révoquer la permission pour tous les enfants de ce groupe, y "
 "compris les dépôts non-privés et les autres groupes si sélectionné."
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-"Activer le verrou lors d’un pull sur le groupe. Cette option sera "
-"appliquée à tous les sous-groupes et dépôts de ce groupe"
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
 msgstr "Supprimer ce groupe"
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Confirm to delete this group"
 msgstr "Confirmer la suppression de ce groupe"
 
@@ -3090,7 +3168,7 @@
 "comme un clone à partir de cette URL."
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
@@ -3099,7 +3177,7 @@
 "pour des descriptions plus détaillées."
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr "Sélectionnez un groupe (optionel) dans lequel sera placé le dépôt."
@@ -3109,7 +3187,7 @@
 msgstr "Type de dépôt à créer."
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr "Révision d’arrivée"
@@ -3168,8 +3246,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr "Statistiques"
 
@@ -3206,73 +3284,32 @@
 "Les actions réalisées sur ce dépôt seront visibles à tous depuis le "
 "journal public."
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-msgid "Change Locking"
-msgstr "Changer le verrouillage"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-msgid "Confirm to unlock repository."
-msgstr "Veuillez confirmer le déverrouillage de ce dépôt."
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-msgid "Unlock Repository"
-msgstr "Déverrouiller le dépôt"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr "Verrouillé par %s sur %s"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-msgid "Confirm to lock repository."
-msgstr "Veuillez confirmer le verrouillage de ce dépôt."
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-msgid "Lock Repository"
-msgstr "Verrouiller le dépôt"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr "Ce dépôt n’est pas verrouillé"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-"Forcer le verrouillage du dépôt. Ne fonctionne que lorsque l'accès "
-"anonyme est désactivé. Déclencher un pull verrouille le dépôt. "
-"L'utilisateur qui fait le pull verrouille le dépôt ; seul l'utilisateur "
-"qui a fait le pull et a verrouillé peut déverrouiller en faisant un push."
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
 #: kallithea/templates/data_table/_dt_elements.html:68
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "Voulez-vous vraiment supprimer le dépôt %s ?"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
 msgid "Delete this Repository"
 msgstr "Supprimer ce dépôt"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
 msgstr[0] "Ce dépôt a %s fork"
 msgstr[1] "Ce dépôt a %s forks"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr "Détacher les forks"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr "Supprimer les forks"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3375,19 +3412,13 @@
 msgid "This repository does not have a remote repository URL."
 msgstr "Ce dépôt n'a pas d'URL de dépôt distant."
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "Permanent Repository ID"
+#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#, fuzzy
+#| msgid "Permanent Repository ID"
+msgid "Permanent URL"
 msgstr "ID permanent du dépôt"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr "Qu'est-ce que c'est ?"
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr "URL par id"
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3404,15 +3435,15 @@
 "d'intégration continue, ou dans tous les cas où vous devez saisir l'URL "
 "« en dur » dans un service tiers."
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 msgid "Remote repository"
 msgstr "Dépôt distant"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 msgid "Repository URL"
 msgstr "URL du dépôt"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
@@ -3420,18 +3451,18 @@
 "Optionel : URL d'un dépôt distant. Si renseigné, le dépôt sera pullé à "
 "partir de cette URL."
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr ""
 "Révision par défaut pour les pages de fichiers, de téléchargements, de "
 "recherche et de documentation"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr "Saisir le nom de l'utilisateur"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr "Changer le propriétaire de ce dépôt."
 
@@ -3547,8 +3578,8 @@
 "captcha à l'enregistrement."
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 msgid "Save Settings"
 msgstr "Enregistrer les options"
 
@@ -3657,10 +3688,6 @@
 msgid "Kallithea version"
 msgstr "Version de Kallithea"
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr "Vérifier les mises à jour"
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr "Fichier de configuration de Kallithea"
@@ -3681,15 +3708,7 @@
 msgid "Git path"
 msgstr "Chemin de Git"
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr "Point d'accès aux informations de mise à jour"
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr "Note : vérifiez que le serveur peut accéder cette URL"
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr "Paquets Python"
 
@@ -3698,30 +3717,22 @@
 msgstr "Afficher la taille du dépôt après un push"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
-msgstr "Journaliser les commandes de push"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr "Journaliser les commandes de pull"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
 msgid "Update repository after push (hg update)"
 msgstr "Mettre à jour les dépôts après un push (hg update)"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:33
+#: kallithea/templates/admin/settings/settings_vcs.html:21
 msgid "Mercurial extensions"
 msgstr "Extensions Mercurial"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr "Activer l'extension largefiles"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr "Activer l'extension hgsubversion"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:47
+#: kallithea/templates/admin/settings/settings_vcs.html:35
 msgid ""
 "Requires hgsubversion library to be installed. Enables cloning of remote "
 "Subversion repositories while converting them to Mercurial."
@@ -3729,11 +3740,11 @@
 "La bibliothèque hgsubversion doit être installée. Elle permet de cloner "
 "des dépôts SVN distants et de les migrer vers Mercurial."
 
-#: kallithea/templates/admin/settings/settings_vcs.html:59
+#: kallithea/templates/admin/settings/settings_vcs.html:47
 msgid "Location of repositories"
 msgstr "Emplacement des dépôts"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
@@ -3741,7 +3752,7 @@
 "Cliquez pour déverrouiller. Vous devez redémarrer Kallithea pour ce que "
 "réglage prenne effet."
 
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3810,11 +3821,28 @@
 "emplacement réseau/hôte du serveur Kallithea en cours d'utilisation."
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-msgid "Clone URL"
+#, fuzzy
+#| msgid "Clone URL"
+msgid "HTTP Clone URL"
 msgstr "URL de clone"
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
+#, fuzzy
+#| msgid ""
+#| "Schema of clone URL construction eg. '{scheme}://{user}@{netloc}/"
+#| "{repo}'.\n"
+#| "                                                    The following "
+#| "variables are available:\n"
+#| "                                                    {scheme} 'http' or "
+#| "'https' sent from running Kallithea server,\n"
+#| "                                                    {user}   current "
+#| "user username,\n"
+#| "                                                    {netloc} network "
+#| "location/server host of running Kallithea server,\n"
+#| "                                                    {repo}   full "
+#| "repository name,\n"
+#| "                                                    {repoid} ID of "
+#| "repository, can be used to construct clone-by-id"
 msgid ""
 "Schema of clone URL construction eg. '{scheme}://{user}@{netloc}/"
 "{repo}'.\n"
@@ -3829,7 +3857,12 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
 msgstr ""
 "Modèle de construction d'URL de clone. Par exemple : '{scheme}://{user}"
 "@{netloc}/{repo}'.\n"
@@ -3847,11 +3880,23 @@
 "                                                        {repoid}    ID du "
 "dépôt, peut être utilisé pour cloner par ID."
 
-#: kallithea/templates/admin/settings/settings_visual.html:54
+#: kallithea/templates/admin/settings/settings_visual.html:56
+#, fuzzy
+#| msgid "Clone URL"
+msgid "SSH Clone URL"
+msgstr "URL de clone"
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 msgid "Repository page size"
 msgstr "Taille de la page du dépôt"
 
-#: kallithea/templates/admin/settings/settings_visual.html:57
+#: kallithea/templates/admin/settings/settings_visual.html:68
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
 "shown."
@@ -3859,11 +3904,11 @@
 "Nombre d'éléments affichés dans les pages des dépôts avant d'afficher la "
 "pagination."
 
-#: kallithea/templates/admin/settings/settings_visual.html:62
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
 msgstr "Taille de la page d'admin"
 
-#: kallithea/templates/admin/settings/settings_visual.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
@@ -3871,27 +3916,27 @@
 "Nombre d'éléments affichés dans les grilles des pages admin avant "
 "d'afficher la pagination."
 
-#: kallithea/templates/admin/settings/settings_visual.html:70
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr "Icônes"
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
 msgstr "Afficher l’icône de dépôt public sur les dépôts"
 
-#: kallithea/templates/admin/settings/settings_visual.html:81
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr "Afficher l’icône de dépôt privé sur les dépôts"
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 msgid "Show public/private icons next to repository names."
 msgstr "Afficher l’icône « public/privé » à côté du nom des dépôts."
 
-#: kallithea/templates/admin/settings/settings_visual.html:89
+#: kallithea/templates/admin/settings/settings_visual.html:100
 msgid "Meta Tagging"
 msgstr "Meta-tagging"
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
@@ -3899,7 +3944,7 @@
 "Analyser les méta-tags dans le champ de description du dépôt et les "
 "transformer en tags colorés."
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr "Styliser les méta-tags reconnus :"
 
@@ -4060,12 +4105,12 @@
 msgstr "Support"
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr "Dépôt Mercurial"
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr "Dépôt Git"
 
@@ -4113,157 +4158,132 @@
 msgstr "Comparer"
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr "Rechercher"
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr "Déverrouiller"
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr "Verrouiller"
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr "Suivre"
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr "Arrêter de suivre"
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr "Fork"
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr "Créer une requête de pull"
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr "Basculer vers"
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr "Aucune correspondance trouvée"
 
-#: kallithea/templates/base/base.html:296
+#: kallithea/templates/base/base.html:289
 msgid "Show recent activity"
 msgstr "Afficher l'activité récente"
 
-#: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
+#: kallithea/templates/base/base.html:295
+#: kallithea/templates/base/base.html:296
 msgid "Public journal"
 msgstr "Journal public"
 
-#: kallithea/templates/base/base.html:308
+#: kallithea/templates/base/base.html:301
 msgid "Show public gists"
 msgstr "Afficher les gists publics"
 
-#: kallithea/templates/base/base.html:309
+#: kallithea/templates/base/base.html:302
 msgid "Gists"
 msgstr "Gists"
 
-#: kallithea/templates/base/base.html:313
+#: kallithea/templates/base/base.html:306
 msgid "All Public Gists"
 msgstr "Tous les Gists publics"
 
-#: kallithea/templates/base/base.html:315
+#: kallithea/templates/base/base.html:308
 msgid "My Public Gists"
 msgstr "Mes Gists publics"
 
-#: kallithea/templates/base/base.html:316
+#: kallithea/templates/base/base.html:309
 msgid "My Private Gists"
 msgstr "Mes Gist privés"
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr "Recherche dans les dépôts"
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 msgid "My Pull Requests"
 msgstr "Mes requêtes de pull"
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr "Non connecté"
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 msgid "Login to Your Account"
 msgstr "Connexion à votre compte"
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 msgid "Forgot password?"
 msgstr "Mot de passe oublié ?"
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 msgid "Don't have an account?"
 msgstr "Vous n’avez pas de compte ?"
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr "Se déconnecter"
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr "Révision parente"
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr "Révision fille"
 
 #: kallithea/templates/base/default_perms_box.html:11
-msgid "Inherit defaults"
-msgstr "Hériter des réglages par défaut"
+msgid "Create repositories"
+msgstr "Création de dépôts"
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-"Sélectionner pour hériter des réglages généraux, de la liste blanche d'IP "
-"et des permissions depuis les %s."
-
-#: kallithea/templates/base/default_perms_box.html:16
-msgid "default permissions"
-msgstr "permissions par défaut"
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr "Création de dépôts"
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 "Sélectionner cette option pour autoriser cet utilisateur à créer des "
 "dépôts"
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr "Créer des groupes d'utilisateurs"
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 "Sélectionner cette option pour autoriser cet utilisateur à créer des "
 "groupes d'utilisateurs"
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr "Forker les dépôts"
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 "Sélectionner cette option pour autoriser cet utilisateur à forker des "
@@ -4984,7 +5004,7 @@
 msgstr "Diff de fichier pour %s"
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr "Fichiers de %s"
@@ -4996,7 +5016,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr "Ajouter un nouveau fichier"
 
@@ -5048,7 +5068,7 @@
 msgstr "Chargement de la liste des fichiers…"
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr "Taille"
 
@@ -5180,8 +5200,8 @@
 msgstr "Followers de %s"
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr "Followers"
 
@@ -5234,8 +5254,8 @@
 msgstr "Forks de %s"
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr "Forks"
 
@@ -5552,9 +5572,9 @@
 msgid "File names"
 msgstr "Les noms de fichiers"
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr "Permission refusée"
 
@@ -5564,20 +5584,20 @@
 msgstr "Statistiques pour %s"
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr "Flux ATOM pour %s"
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr "Flux RSS pour %s"
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr "Activer"
 
@@ -5586,12 +5606,12 @@
 msgstr "Statistiques obtenues : "
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr "Fichiers"
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr "Afficher plus"
 
@@ -5632,95 +5652,217 @@
 msgid "%s Summary"
 msgstr "Résumé de %s"
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr "Dépôt verrouillé par %s"
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr "Dépôt déverrouillé"
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr "Fork de"
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr "Cloner depuis"
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr "Afficher par ID"
-
+#: kallithea/templates/summary/summary.html:54
+msgid "Clone URL"
+msgstr "URL de clone"
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr "Afficher par nom"
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+#, fuzzy
+#| msgid "Last Name"
+msgid "Use Name"
+msgstr "Nom"
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr "Populaires"
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr "Téléchargements"
 
-#: kallithea/templates/summary/summary.html:101
+#: kallithea/templates/summary/summary.html:109
 msgid "There are no downloads yet"
 msgstr "Il n’y a pas encore de téléchargements proposés"
 
-#: kallithea/templates/summary/summary.html:103
+#: kallithea/templates/summary/summary.html:111
 msgid "Downloads are disabled for this repository"
 msgstr "Les téléchargements sont désactivés pour ce dépôt"
 
-#: kallithea/templates/summary/summary.html:109
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr "Télécharger en ZIP"
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr ""
 "Télécharger une archive contenant également les sous-dépôts éventuels"
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 msgid "With subrepos"
 msgstr "Avec les sous-dépôts"
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr "Flux"
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 msgid "Latest Changes"
 msgstr "Derniers changements"
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 msgid "Quick Start"
 msgstr "Démarrage rapide"
 
-#: kallithea/templates/summary/summary.html:188
-msgid "Add or upload files directly via Kallithea"
-msgstr "Ajouter ou téléverser des fichiers directement via Kallithea"
-
 #: kallithea/templates/summary/summary.html:196
-msgid "Push new repository"
-msgstr "Pusher le nouveau dépôt"
+msgid "Add or upload files directly via Kallithea"
+msgstr "Ajouter ou téléverser des fichiers directement via Kallithea"
 
 #: kallithea/templates/summary/summary.html:204
+msgid "Push new repository"
+msgstr "Pusher le nouveau dépôt"
+
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr "Le dépôt existe déjà ?"
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr "Fichier Lisez-moi de la revision %s:%s"
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr "Télécharge %s comme %s"
 
+#~ msgid "This repository has been locked by %s on %s"
+#~ msgstr "Ce dépôt a été verrouillé par %s sur %s"
+
+#~ msgid "Repository has been locked"
+#~ msgstr "Ce dépôt a été verrouillé"
+
+#~ msgid "Repository has been unlocked"
+#~ msgstr "Ce dépôt a été déverrouillé"
+
+#~ msgid "An error occurred during unlocking"
+#~ msgstr "Une erreur est survenue durant le déverrouillage"
+
+#~ msgid "Invalid API key"
+#~ msgstr "Clé d'API invalide"
+
+#~ msgid "Token mismatch"
+#~ msgstr "Jeton d’authentification incorrect"
+
+#~ msgid "Enable locking"
+#~ msgstr "Activer le verrouillage"
+
+#~ msgid "Enable lock-by-pulling on repository."
+#~ msgstr "Activer le verrouillage lors d’un pull sur le dépôt."
+
+#~ msgid ""
+#~ "Enable lock-by-pulling on group. This option will be applied to all "
+#~ "other groups and repositories inside"
+#~ msgstr ""
+#~ "Activer le verrou lors d’un pull sur le groupe. Cette option sera "
+#~ "appliquée à tous les sous-groupes et dépôts de ce groupe"
+
+#~ msgid "Change Locking"
+#~ msgstr "Changer le verrouillage"
+
+#~ msgid "Confirm to unlock repository."
+#~ msgstr "Veuillez confirmer le déverrouillage de ce dépôt."
+
+#~ msgid "Unlock Repository"
+#~ msgstr "Déverrouiller le dépôt"
+
+#~ msgid "Locked by %s on %s"
+#~ msgstr "Verrouillé par %s sur %s"
+
+#~ msgid "Confirm to lock repository."
+#~ msgstr "Veuillez confirmer le verrouillage de ce dépôt."
+
+#~ msgid "Lock Repository"
+#~ msgstr "Verrouiller le dépôt"
+
+#~ msgid "Repository is not locked"
+#~ msgstr "Ce dépôt n’est pas verrouillé"
+
+#~ msgid ""
+#~ "Force locking on the repository. Works only when anonymous access is "
+#~ "disabled. Triggering a pull locks the repository.  The user who is "
+#~ "pulling locks the repository; only the user who pulled and locked it "
+#~ "can unlock it by doing a push."
+#~ msgstr ""
+#~ "Forcer le verrouillage du dépôt. Ne fonctionne que lorsque l'accès "
+#~ "anonyme est désactivé. Déclencher un pull verrouille le dépôt. "
+#~ "L'utilisateur qui fait le pull verrouille le dépôt ; seul "
+#~ "l'utilisateur qui a fait le pull et a verrouillé peut déverrouiller en "
+#~ "faisant un push."
+
+#~ msgid "What is that?"
+#~ msgstr "Qu'est-ce que c'est ?"
+
+#~ msgid "URL by id"
+#~ msgstr "URL par id"
+
+#~ msgid "Check for updates"
+#~ msgstr "Vérifier les mises à jour"
+
+#~ msgid "Upgrade info endpoint"
+#~ msgstr "Point d'accès aux informations de mise à jour"
+
+#~ msgid "Note: please make sure this server can access this URL"
+#~ msgstr "Note : vérifiez que le serveur peut accéder cette URL"
+
+#~ msgid "Log user push commands"
+#~ msgstr "Journaliser les commandes de push"
+
+#~ msgid "Log user pull commands"
+#~ msgstr "Journaliser les commandes de pull"
+
+#~ msgid "Unlock"
+#~ msgstr "Déverrouiller"
+
+#~ msgid "Lock"
+#~ msgstr "Verrouiller"
+
+#~ msgid "Inherit defaults"
+#~ msgstr "Hériter des réglages par défaut"
+
+#~ msgid ""
+#~ "Select to inherit global settings, IP whitelist and permissions from "
+#~ "the %s."
+#~ msgstr ""
+#~ "Sélectionner pour hériter des réglages généraux, de la liste blanche "
+#~ "d'IP et des permissions depuis les %s."
+
+#~ msgid "default permissions"
+#~ msgstr "permissions par défaut"
+
+#~ msgid "Repository locked by %s"
+#~ msgstr "Dépôt verrouillé par %s"
+
+#~ msgid "Repository unlocked"
+#~ msgstr "Dépôt déverrouillé"
+
+#~ msgid "Show by ID"
+#~ msgstr "Afficher par ID"
+
+#~ msgid "Show by Name"
+#~ msgstr "Afficher par nom"
+
 #~ msgid ""
 #~ "Changing status on a changeset associated with a closed pull request "
 #~ "is not allowed"
@@ -6152,9 +6294,6 @@
 #~ msgid "invalid user name"
 #~ msgstr "nom d’utilisateur invalide"
 
-#~ msgid "Your account is disabled"
-#~ msgstr "Votre compte est désactivé"
-
 #~ msgid "invalid clone URL"
 #~ msgstr "URL de clonage invalide"
 
--- a/kallithea/i18n/how_to	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/how_to	Sun Jan 05 04:07:51 2020 +0100
@@ -7,7 +7,7 @@
     https://hosted.weblate.org/projects/kallithea/kallithea/
 
 Registered users may contribute to the existing languages, or request a new
-language translations.
+language translation.
 
 
 Translating using Weblate
@@ -45,8 +45,8 @@
 using its administrative interface.
 
 
-Regenerating translatations after source code changes (admin-only)
-------------------------------------------------------------------
+Regenerating translations after source code changes (admin-only)
+----------------------------------------------------------------
 
 When the Kallithea source code changes, both the location as the content of
 translation strings can change. It is therefore necessary to regularly
--- a/kallithea/i18n/hu/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/hu/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,13 +1,11 @@
-# Hungarian translations for Kallithea.
 # Copyright (C) 2014 Various authors, licensing as GPLv3
 # This file is distributed under the same license as the Kallithea project.
-# Automatically generated, 2014.
 # #, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\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/"
@@ -20,14 +18,14 @@
 "X-Generator: Weblate 2.3-dev\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -36,90 +34,90 @@
 msgid "None"
 msgstr ""
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 msgid "No permission to change status"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:214
+#: kallithea/controllers/changeset.py:212
 #, python-format
 msgid "Successfully deleted pull request %s"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr ""
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, python-format
 msgid "Could not find other repository %s"
 msgstr ""
 
-#: kallithea/controllers/compare.py:72
+#: kallithea/controllers/compare.py:74
 msgid "Cannot compare repositories of different types"
 msgstr ""
 
-#: kallithea/controllers/compare.py:244
-msgid "Cannot show empty diff"
-msgstr ""
-
 #: kallithea/controllers/compare.py:246
+msgid "Cannot show empty diff"
+msgstr ""
+
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr ""
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr ""
 
-#: kallithea/controllers/error.py:70
-msgid "No response"
-msgstr ""
-
 #: kallithea/controllers/error.py:71
+msgid "No response"
+msgstr ""
+
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr ""
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr ""
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr ""
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr ""
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr ""
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
@@ -140,119 +138,113 @@
 msgid "Changeset was too big and was cut off..."
 msgstr ""
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr ""
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
 msgstr ""
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr ""
 
-#: kallithea/controllers/files.py:93
+#: kallithea/controllers/files.py:86
 msgid "There are no files yet."
 msgstr ""
 
-#: kallithea/controllers/files.py:193
+#: kallithea/controllers/files.py:186
 #, python-format
 msgid "%s at %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr ""
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 msgid "You can only delete files with revision being a valid branch"
 msgstr ""
 
-#: kallithea/controllers/files.py:322
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr ""
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr ""
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 msgid "You can only edit files with revision being a valid branch"
 msgstr ""
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr ""
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr ""
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr ""
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr ""
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr ""
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr ""
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr ""
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr ""
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr ""
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr ""
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
 msgstr ""
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr ""
 
@@ -261,11 +253,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr ""
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr ""
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -273,177 +265,177 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr ""
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
 msgstr ""
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr ""
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr ""
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr ""
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr ""
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr ""
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
 msgstr ""
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr ""
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:190
 msgid "A password reset confirmation code has been sent"
 msgstr ""
 
-#: kallithea/controllers/login.py:238
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 msgid "New pull request iteration created"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, python-format
 msgid "Revision %s not found in %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, python-format
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr ""
 
+#: kallithea/controllers/pullrequests.py:520
+#, python-format
+msgid "This pull request has already been merged to %s."
+msgstr ""
+
 #: kallithea/controllers/pullrequests.py:522
-#, python-format
-msgid "This pull request has already been merged to %s."
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:524
 msgid "This pull request has been closed and can not be updated."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, python-format
 msgid "The following additional changes are available on %s:"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 msgid "No additional changesets found for iterating on this pull request."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 msgid "Git pull requests don't support iterating yet."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, python-format
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 
@@ -459,21 +451,21 @@
 msgid "An error occurred during search operation."
 msgstr ""
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr ""
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -485,123 +477,134 @@
 msgid "Error occurred during update of defaults"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 msgid "Forever"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
-#: kallithea/controllers/admin/users.py:249
-msgid "5 minutes"
-msgstr ""
-
 #: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
-#: kallithea/controllers/admin/users.py:250
-msgid "1 hour"
+#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/users.py:249
+msgid "5 minutes"
 msgstr ""
 
 #: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
-#: kallithea/controllers/admin/users.py:251
-msgid "1 day"
+#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/users.py:250
+msgid "1 hour"
 msgstr ""
 
 #: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/my_account.py:235
+#: kallithea/controllers/admin/users.py:251
+msgid "1 day"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:230
-msgid "Successfully updated gist data"
-msgstr ""
-
 #: kallithea/controllers/admin/gists.py:233
+msgid "Successfully updated gist data"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, python-format
+msgid "SSH key %s successfully added"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+msgid "SSH key successfully deleted"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -609,9 +612,9 @@
 msgid "Read"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -619,9 +622,9 @@
 msgid "Write"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -644,363 +647,346 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
-#: kallithea/templates/admin/auth/auth_settings.html:42
-#: kallithea/templates/base/root.html:50
-msgid "Disabled"
-msgstr ""
-
 #: kallithea/controllers/admin/permissions.py:78
-msgid "Allowed with manual account activation"
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
+#: kallithea/templates/admin/auth/auth_settings.html:42
+#: kallithea/templates/base/root.html:50
+msgid "Disabled"
 msgstr ""
 
 #: kallithea/controllers/admin/permissions.py:80
+msgid "Allowed with manual account activation"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:290
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:390
+#: kallithea/controllers/admin/repos.py:391
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:401
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:466
-msgid "Nothing"
-msgstr ""
-
 #: kallithea/controllers/admin/repos.py:468
+msgid "Nothing"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:470
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-#, fuzzy
-msgid "Repository has been locked"
-msgstr "Ennek a tárolónak %s elágazása van"
+#: kallithea/controllers/admin/repos.py:490
+msgid "Cache invalidation successful"
+msgstr ""
 
 #: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-#, fuzzy
-msgid "Repository has been unlocked"
-msgstr "Ennek a tárolónak %s elágazása van"
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:528
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:532
 msgid "An error occurred during cache invalidation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:579
+#: kallithea/controllers/admin/repos.py:541
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:180
+#: kallithea/controllers/admin/settings.py:176
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:192
+#: kallithea/controllers/admin/settings.py:188
 #, fuzzy, python-format
 #| msgid "Private Repository"
 msgid "Invalidated %s repositories"
 msgstr "Tároló törlése"
 
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 msgid "Hook already exists"
 msgstr ""
 
+#: kallithea/controllers/admin/settings.py:357
+msgid "Builtin hooks are read-only. Please use another hook name."
+msgstr ""
+
 #: kallithea/controllers/admin/settings.py:360
-msgid "Builtin hooks are read-only. Please use another hook name."
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:363
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
+#: kallithea/controllers/admin/user_groups.py:212
+msgid "Successfully deleted user group"
+msgstr ""
+
 #: kallithea/controllers/admin/user_groups.py:217
-msgid "Successfully deleted user group"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:222
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr ""
 
@@ -1030,218 +1016,218 @@
 msgid "The default user cannot be edited"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr ""
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr ""
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr ""
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, python-format
 msgid "Changeset for %s %s not found in %s"
 msgstr ""
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+msgid "SSH access is disabled."
+msgstr ""
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr ""
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:625
+#: kallithea/lib/helpers.py:666
 #, python-format
 msgid "Changeset %s not found"
 msgstr ""
 
-#: kallithea/lib/helpers.py:674
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr ""
 
-#: kallithea/lib/helpers.py:725
-#, python-format
-msgid "Fork name %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:746
-#, python-format
-msgid "Pull request %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:756
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:760
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
-msgid "[updated] repository"
-msgstr ""
-
 #: kallithea/lib/helpers.py:766
+#, python-format
+msgid "Fork name %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:787
+#, python-format
+msgid "Pull request %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:797
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
+msgid "[created] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:801
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
+msgid "[updated] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr ""
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr ""
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr ""
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1249,69 +1235,96 @@
 "repositories"
 msgstr ""
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr ""
 
@@ -1320,133 +1333,133 @@
 msgid "on line %s"
 msgstr ""
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1706
+#: kallithea/model/db.py:1640
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1707
+#: kallithea/model/db.py:1641
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1708
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1711
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1730
+#: kallithea/model/db.py:1664
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1732
+#: kallithea/model/db.py:1666
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr ""
 
@@ -1472,302 +1485,313 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:169
+#, 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:170
 #, 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:171
-#, 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:184
+#: kallithea/model/notification.py:183
 msgid "Closing"
 msgstr ""
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 msgid "Cannot create empty pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 msgid "You are not authorized to create the pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 msgid "Missing changesets since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, python-format
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, python-format
 msgid ""
 "This iteration is based on another %s revision and there is no simple "
 "diff."
 msgstr ""
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, python-format
 msgid "No changes found on %s %s since previous iteration."
 msgstr ""
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr ""
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, python-format
+msgid "SSH key %r not found"
+msgstr ""
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:255
 #, 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:263
+#: kallithea/model/user.py:260
 #, 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:270
+#: kallithea/model/user.py:267
 #, 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:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr ""
 
+#: kallithea/model/validators.py:72
+#, python-format
+msgid "Username \"%(username)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:74
 #, python-format
-msgid "Username \"%(username)s\" already exists"
+msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
 #: kallithea/model/validators.py:76
-#, python-format
-msgid "Username \"%(username)s\" cannot be used"
-msgstr ""
-
-#: kallithea/model/validators.py:78
 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:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr ""
 
+#: kallithea/model/validators.py:132
+#, python-format
+msgid "User group \"%(usergroup)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:134
-#, python-format
-msgid "User group \"%(usergroup)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:136
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr ""
 
+#: kallithea/model/validators.py:175
+#, python-format
+msgid "Group \"%(group_name)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:177
 #, python-format
-msgid "Group \"%(group_name)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:179
-#, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 msgid "Invalid username or password"
 msgstr ""
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr ""
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr ""
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
-#: kallithea/model/validators.py:333
+#: kallithea/model/validators.py:318
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:419
+#: kallithea/model/validators.py:404
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:430
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:460
+#: kallithea/model/validators.py:445
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:512
+#: kallithea/model/validators.py:497
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:552
+#: kallithea/model/validators.py:537
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 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:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:765
+#: kallithea/model/validators.py:750
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1808,24 +1832,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr ""
 
@@ -1842,7 +1872,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1850,11 +1880,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr ""
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr ""
@@ -1869,7 +1899,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1877,7 +1907,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr ""
@@ -2033,10 +2063,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr ""
@@ -2085,22 +2117,22 @@
 msgstr ""
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr ""
 
@@ -2118,14 +2150,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2133,36 +2165,25 @@
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr ""
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr ""
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr ""
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2209,8 +2230,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 msgid "Never"
 msgstr ""
 
@@ -2243,7 +2266,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr ""
 
@@ -2279,23 +2302,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2323,7 +2348,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2383,7 +2408,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr ""
 
@@ -2396,24 +2421,29 @@
 msgid "Email Addresses"
 msgstr ""
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
-msgid "API Keys"
-msgstr ""
-
 #: kallithea/templates/admin/my_account/my_account.html:29
-msgid "Owned Repositories"
-msgstr ""
-
-#: kallithea/templates/admin/my_account/my_account.html:30
-#: kallithea/templates/journal/journal.html:33
-msgid "Watched Repositories"
+#: kallithea/templates/admin/users/user_edit.html:32
+msgid "SSH Keys"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
+msgid "API Keys"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:32
+msgid "Owned Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:33
+#: kallithea/templates/journal/journal.html:33
+msgid "Watched Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 msgid "Show Permissions"
 msgstr ""
 
@@ -2440,7 +2470,9 @@
 msgstr "A csoport törlésének megerősítése"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 msgid "Remove"
 msgstr ""
 
@@ -2456,12 +2488,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr ""
 
@@ -2562,6 +2596,42 @@
 msgid "Name"
 msgstr ""
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+msgid "Last Used"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, fuzzy, python-format
+msgid "Confirm to remove this SSH key: %s"
+msgstr "A csoport törlésének megerősítése"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+msgid "New SSH key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+msgid "Public key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 msgid "Repositories You are Watching"
 msgstr ""
@@ -2578,7 +2648,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr ""
 
@@ -2614,7 +2684,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2774,7 +2844,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr ""
 
@@ -2880,17 +2950,11 @@
 "private repositories and other groups if selected."
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Confirm to delete this group"
 msgstr "A csoport törlésének megerősítése"
 
@@ -2921,14 +2985,14 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr ""
@@ -2938,7 +3002,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr ""
@@ -2990,8 +3054,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr ""
 
@@ -3025,69 +3089,32 @@
 "public journal."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-msgid "Change Locking"
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
+#: kallithea/templates/data_table/_dt_elements.html:68
+#, python-format
+msgid "Confirm to delete this repository: %s"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-msgid "Confirm to unlock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-msgid "Unlock Repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-msgid "Confirm to lock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-msgid "Lock Repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
-#: kallithea/templates/data_table/_dt_elements.html:68
-#, python-format
-msgid "Confirm to delete this repository: %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
 msgid "Delete this Repository"
 msgstr "Tároló törlése"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
 msgstr[0] "Ennek a tárolónak %s elágazása van"
 msgstr[1] "Ennek a tárolónak %s elágazása van"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3188,19 +3215,11 @@
 msgid "This repository does not have a remote repository URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "Permanent Repository ID"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_settings.html:10
+msgid "Permanent URL"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3210,31 +3229,31 @@
 "other cases that you need to hardcode the URL into a 3rd party service."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 #, fuzzy
 msgid "Remote repository"
 msgstr "Tároló törlése"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 msgid "Repository URL"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr ""
 
@@ -3343,8 +3362,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 msgid "Save Settings"
 msgstr ""
 
@@ -3439,10 +3458,6 @@
 msgid "Kallithea version"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr ""
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr ""
@@ -3463,15 +3478,7 @@
 msgid "Git path"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr ""
 
@@ -3480,46 +3487,38 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
+msgid "Update repository after push (hg update)"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
-msgid "Update repository after push (hg update)"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:33
 msgid "Mercurial extensions"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr ""
 
+#: kallithea/templates/admin/settings/settings_vcs.html:35
+msgid ""
+"Requires hgsubversion library to be installed. Enables cloning of remote "
+"Subversion repositories while converting them to Mercurial."
+msgstr ""
+
 #: kallithea/templates/admin/settings/settings_vcs.html:47
-msgid ""
-"Requires hgsubversion library to be installed. Enables cloning of remote "
-"Subversion repositories while converting them to Mercurial."
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:59
 msgid "Location of repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3568,8 +3567,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-msgid "Clone URL"
+msgid "HTTP Clone URL"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
@@ -3587,56 +3585,71 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+msgid "SSH Clone URL"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 msgid "Repository page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:57
+#: kallithea/templates/admin/settings/settings_visual.html:68
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:62
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:70
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:81
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 msgid "Show public/private icons next to repository names."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:89
+#: kallithea/templates/admin/settings/settings_visual.html:100
 msgid "Meta Tagging"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr ""
 
@@ -3797,12 +3810,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr ""
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr ""
 
@@ -3850,151 +3863,128 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr ""
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr ""
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr ""
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr ""
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr ""
 
+#: kallithea/templates/base/base.html:289
+msgid "Show recent activity"
+msgstr ""
+
+#: kallithea/templates/base/base.html:295
 #: kallithea/templates/base/base.html:296
-msgid "Show recent activity"
+msgid "Public journal"
+msgstr ""
+
+#: kallithea/templates/base/base.html:301
+msgid "Show public gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
-msgid "Public journal"
+msgid "Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:306
+msgid "All Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:308
-msgid "Show public gists"
+msgid "My Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:309
-msgid "Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:313
-msgid "All Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:315
-msgid "My Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:316
 msgid "My Private Gists"
 msgstr ""
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr ""
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 msgid "My Pull Requests"
 msgstr ""
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr ""
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 msgid "Login to Your Account"
 msgstr ""
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 msgid "Forgot password?"
 msgstr ""
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 msgid "Don't have an account?"
 msgstr ""
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr ""
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-msgid "Inherit defaults"
+msgid "Create repositories"
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-msgid "default permissions"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 
@@ -4709,7 +4699,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr ""
@@ -4721,7 +4711,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr ""
 
@@ -4773,7 +4763,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr ""
 
@@ -4901,8 +4891,8 @@
 msgstr ""
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr ""
 
@@ -4953,8 +4943,8 @@
 msgstr ""
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr ""
 
@@ -5262,9 +5252,9 @@
 msgid "File names"
 msgstr ""
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr ""
 
@@ -5274,20 +5264,20 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr ""
 
@@ -5296,12 +5286,12 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr ""
 
@@ -5342,95 +5332,107 @@
 msgid "%s Summary"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr ""
-
+#: kallithea/templates/summary/summary.html:54
+msgid "Clone URL"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+msgid "Use Name"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:101
-msgid "There are no downloads yet"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:103
-msgid "Downloads are disabled for this repository"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:109
+msgid "There are no downloads yet"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:111
+msgid "Downloads are disabled for this repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 msgid "With subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 msgid "Latest Changes"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 msgid "Quick Start"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:188
-msgid "Add or upload files directly via Kallithea"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:196
-msgid "Push new repository"
+msgid "Add or upload files directly via Kallithea"
 msgstr ""
 
 #: kallithea/templates/summary/summary.html:204
+msgid "Push new repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr ""
 
 #, fuzzy
+#~ msgid "Repository has been locked"
+#~ msgstr "Ennek a tárolónak %s elágazása van"
+
+#, fuzzy
+#~ msgid "Repository has been unlocked"
+#~ msgstr "Ennek a tárolónak %s elágazása van"
+
+#, fuzzy
 #~| msgid "Remote repository"
 #~ msgid "Repository Group"
 #~ msgstr "Tároló törlése"
--- a/kallithea/i18n/ja/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/ja/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,20 +1,12 @@
-# Japanese translations for Kallithea.
 # Copyright (C) 2014 RhodeCode GmbH, and others.
 # This file is distributed under the same license as the Kallithea project.
-# Translators:
-# しろう, 2013
-# shirou - しろう, 2013
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2011
-# こいんとす <tkondou@gmail.com>, 2013
-# Takumi IINO <trot.thunder@gmail.com>, 2013
-# whosaysni <whosaysni@gmail.com>, 2014
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
-"PO-Revision-Date: 2016-01-07 01:53+0000\n"
-"Last-Translator: Takumi IINO <trot.thunder@gmail.com>\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\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/"
 "kallithea/ja/>\n"
 "Language: ja\n"
@@ -22,17 +14,17 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 2.5-dev\n"
+"X-Generator: Weblate 3.9-dev\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr "まだチェンジセットがありません"
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -41,96 +33,96 @@
 msgid "None"
 msgstr "なし"
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr "(閉鎖済み)"
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr "空白を表示"
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr "空白を無視"
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr "diff コンテキストを %(num)s 行増やす"
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 #, fuzzy
 #| msgid "No permission to change pull request status"
 msgid "No permission to change status"
 msgstr "プルリクエストステータスを変更する権限がありません"
 
-#: kallithea/controllers/changeset.py:214
+#: kallithea/controllers/changeset.py:212
 #, fuzzy, python-format
 msgid "Successfully deleted pull request %s"
 msgstr "プルリクエストの削除に成功しました"
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr "お探しのリビジョンはこのリポジトリにはありません"
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, fuzzy, python-format
 #| msgid "Go to tip of repository"
 msgid "Could not find other repository %s"
 msgstr "リポジトリの最新のリビジョン(tip)に移動"
 
-#: kallithea/controllers/compare.py:72
+#: kallithea/controllers/compare.py:74
 #, fuzzy
 #| msgid "Cannot compare repositories without using common ancestor"
 msgid "Cannot compare repositories of different types"
 msgstr "共通の祖先を持たないのでリポジトリを比較できません"
 
-#: kallithea/controllers/compare.py:244
+#: kallithea/controllers/compare.py:246
 msgid "Cannot show empty diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:246
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr ""
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr "共通の祖先を持たないのでリポジトリを比較できません"
 
-#: kallithea/controllers/error.py:70
+#: kallithea/controllers/error.py:71
 msgid "No response"
 msgstr "応答がありません"
 
-#: kallithea/controllers/error.py:71
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr "不明なエラー"
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr ""
 "形式が間違っているため、サーバーはリクエストを処理できませんでした。"
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr "リソースにアクセスする権限がありません"
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr "このページを閲覧する権限がありません"
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr "リソースが見つかりません"
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
@@ -153,123 +145,117 @@
 msgid "Changeset was too big and was cut off..."
 msgstr "チェンジセットが大きすぎるため、省略しました..."
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr "%s %s フィード"
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
 msgstr "%s リポジトリでの変更"
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr "新しいファイルを追加"
 
-#: kallithea/controllers/files.py:93
+#: kallithea/controllers/files.py:86
 #, fuzzy
 #| msgid "There are no files yet. %s"
 msgid "There are no files yet."
 msgstr "まだファイルがありません。 %s"
 
-#: kallithea/controllers/files.py:193
+#: kallithea/controllers/files.py:186
 #, fuzzy, python-format
 msgid "%s at %s"
 msgstr "%s と %s の間"
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr "このリポジトリは %s によって %s にロックされました"
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 #, fuzzy
 msgid "You can only delete files with revision being a valid branch"
 msgstr "有効なブランチ上のリビジョンからしかファイルを削除できません"
 
-#: kallithea/controllers/files.py:322
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr "Kallithea経由で %s を削除"
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr "%s ファイルの削除に成功しました"
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr "コミット中にエラーが発生しました"
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 #, fuzzy
 msgid "You can only edit files with revision being a valid branch"
 msgstr "有効なブランチを示すリビジョンでのみファイルを編集できます "
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr "Kallithea経由で %s を変更"
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr "変更点なし"
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr "%s へのコミットが成功しました"
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr "Kallithea経由でファイルを追加"
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr "内容がありません"
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr "ファイル名がありません"
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr "場所には相対パスかつ .. を含まないパスを入力してください"
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr "ダウンロードは無効化されています"
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr "%s は未知のリビジョンです"
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr "空のリポジトリ"
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr "未知のアーカイブ種別です"
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr "チェンジセット"
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
 msgstr "ブランチ"
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr "タグ"
 
@@ -278,11 +264,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr "リポジトリ %s のフォーク中にエラーが発生しました"
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr "グループ"
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -290,186 +276,186 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr "リポジトリ"
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
 msgstr "ブランチ"
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr "閉鎖済みブランチ"
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr "タグ"
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr "ブックマーク"
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr "公開ジャーナル"
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr "ジャーナル"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
 msgstr "キャプチャが一致しません"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "%sへの登録を受け付けました"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:190
 msgid "A password reset confirmation code has been sent"
 msgstr "パスワードリセットの確認コードが送信されました"
 
-#: kallithea/controllers/login.py:238
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "無効なパスワードリセットトークン"
 
-#: kallithea/controllers/admin/my_account.py:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "パスワードを更新しました"
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr "%s (閉鎖済み)"
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr "チェンジセット"
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr "スペシャル"
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr "相手のブランチ"
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr "ブックマーク"
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr "プルリクエスト作成中にエラーが発生しました: %s"
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr "プルリクエストの作成中にエラーが発生しました"
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr "新しいプルリクエストの作成に成功しました"
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 #, fuzzy
 #| msgid "Pull request update created"
 msgid "New pull request iteration created"
 msgstr "プルリクエストレビュアー"
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr "説明がありません"
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
 msgstr "プルリクエストを更新しました"
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr "プルリクエストの削除に成功しました"
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, python-format
 msgid "Revision %s not found in %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, fuzzy, python-format
 #| msgid "No changesets found for updating this pull request."
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr "プルリクエストを更新するためのチェンジセットが見つかりません。"
 
-#: kallithea/controllers/pullrequests.py:522
+#: kallithea/controllers/pullrequests.py:520
 #, python-format
 msgid "This pull request has already been merged to %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:524
+#: kallithea/controllers/pullrequests.py:522
 msgid "This pull request has been closed and can not be updated."
 msgstr ""
 "このプルリクエストはすでにクローズされていて、更新することはできません。"
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, python-format
 msgid "The following additional changes are available on %s:"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 #, fuzzy
 #| msgid "No changesets found for updating this pull request."
 msgid "No additional changesets found for iterating on this pull request."
 msgstr "プルリクエストを更新するためのチェンジセットが見つかりません。"
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr "ノート: ブランチ%sには別のヘッド%sがあります。"
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 #, fuzzy
 #| msgid "Git pull requests don't support updates yet."
 msgid "Git pull requests don't support iterating yet."
 msgstr "Gitのプルリクエストはまだ更新をサポートしていません。"
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, fuzzy, python-format
 #| msgid "No changesets found for updating this pull request."
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
 msgstr "プルリクエストを更新するためのチェンジセットが見つかりません。"
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 
@@ -485,21 +471,21 @@
 msgid "An error occurred during search operation."
 msgstr "検索を実行する際にエラーが発生しました。"
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr "まだデータの準備ができていません"
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr "このリポジトリの統計は無効化されています"
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr "認証設定の更新に成功しました"
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr "認証設定の更新中にエラーが発生しました"
 
@@ -511,123 +497,137 @@
 msgid "Error occurred during update of defaults"
 msgstr "デフォルト設定の更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 msgid "Forever"
 msgstr "永久"
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
 #: kallithea/controllers/admin/users.py:249
 msgid "5 minutes"
 msgstr "5 分"
 
-#: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
 #: kallithea/controllers/admin/users.py:250
 msgid "1 hour"
 msgstr "1 時間"
 
-#: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
 #: kallithea/controllers/admin/users.py:251
 msgid "1 day"
 msgstr "1 日"
 
-#: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr "1 ヶ月"
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr "有効期間"
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr "gist の作成中にエラーが発生しました"
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr "gist %s を削除しました"
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
 msgstr "変更しない"
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr "Gist の内容を更新しました"
 
-#: kallithea/controllers/admin/gists.py:230
+#: kallithea/controllers/admin/gists.py:233
 msgid "Successfully updated gist data"
 msgstr "Gist データを更新しました"
 
-#: kallithea/controllers/admin/gists.py:233
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
 msgstr "Gist %s の更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr "このユーザーはアプリケーション全体で非常に重要なので編集できません"
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr "アカウントの更新に成功しました"
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr "ユーザー %s の更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr "パスワードの更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr "ユーザーにメールアドレス %s を追加しました"
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr "メールの保存時にエラーが発生しました"
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr "ユーザーからメールアドレスを削除しました"
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr "APIキーの作成に成功しました"
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr "APIキーのリセットに成功しました"
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr "APIキーの削除に成功しました"
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, fuzzy, python-format
+#| msgid "API key successfully created"
+msgid "SSH key %s successfully added"
+msgstr "APIキーの作成に成功しました"
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+#, fuzzy
+#| msgid "API key successfully deleted"
+msgid "SSH key successfully deleted"
+msgstr "APIキーの削除に成功しました"
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -635,9 +635,9 @@
 msgid "Read"
 msgstr "読込"
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -645,9 +645,9 @@
 msgid "Write"
 msgstr "書込"
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -670,255 +670,240 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr "管理"
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:50
 msgid "Disabled"
 msgstr "無効"
 
-#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:80
 msgid "Allowed with manual account activation"
 msgstr "手動でアカウントをアクティベートする"
 
-#: kallithea/controllers/admin/permissions.py:80
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr "自動でアカウントをアクティベートする"
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr "外部アカウントを手動でアクティベートする"
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr "外部アカウントを自動でアクティベートする"
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr "有効"
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr "全般の権限の更新に成功しました"
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr "権限の更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr "リポジトリグループ %s の作成中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repo_groups.py:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr "リポジトリグループ %s を作成しました"
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr "リポジトリグループ %s を更新しました"
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr "リポジトリグループ %s の更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repo_groups.py:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "このグループは %s 個のリポジトリを含んでいるため削除できません"
 
-#: kallithea/controllers/admin/repo_groups.py:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr "このグループは %s 個のサブグループを含んでいるため削除できません"
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr "リポジトリグループ %s を削除しました"
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr "リポジトリグループ %s の削除中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repo_groups.py:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "自分自身の管理者としての権限を取り消すことはできません"
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr "リポジトリグループ権限を更新しました"
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr "権限の取消中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr "リポジトリ %s の作成中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "リポジトリ %s を %s から作成しました"
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "リポジトリ %s を %s としてフォークしました"
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr "リポジトリ %s を作成しました"
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "リポジトリ %s の更新に成功しました"
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "リポジトリ %s の更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr "%s 個のフォークを切り離しました"
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr "%s 個のフォークを削除しました"
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr "リポジトリ %s を削除しました"
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 "フォークしたリポジトリが存在するため、 リポジトリ %s は削除できません"
 
-#: kallithea/controllers/admin/repos.py:290
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "%s の削除中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr "リポジトリ権限を更新しました"
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:390
+#: kallithea/controllers/admin/repos.py:391
 #, 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:401
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr "フィールドの削除中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr "-- フォークではありません --"
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr "公開ジャーナルでのリポジトリの可視性を更新しました"
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 msgid "An error occurred during setting this repository in public journal"
 msgstr "このリポジトリの公開ジャーナルの設定中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:466
+#: kallithea/controllers/admin/repos.py:468
 msgid "Nothing"
 msgstr "ありません"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:470
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "%s リポジトリを %s のフォークとする"
 
-#: kallithea/controllers/admin/repos.py:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr "操作中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-msgid "Repository has been locked"
-msgstr "リポジトリがロックされました"
-
-#: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-msgid "Repository has been unlocked"
-msgstr "リポジトリのロックが解除されました"
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr "アンロック中にエラーが発生しました"
-
-#: kallithea/controllers/admin/repos.py:528
+#: kallithea/controllers/admin/repos.py:490
 msgid "Cache invalidation successful"
 msgstr "キャッシュの無効化に成功しました"
 
-#: kallithea/controllers/admin/repos.py:532
+#: kallithea/controllers/admin/repos.py:494
 msgid "An error occurred during cache invalidation"
 msgstr "キャッシュの無効化中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr "リモートから取得"
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 msgid "An error occurred during pull from remote location"
 msgstr "リモートから取得中にエラーが発生しました"
 
-#: kallithea/controllers/admin/repos.py:579
+#: kallithea/controllers/admin/repos.py:541
 msgid "An error occurred during deletion of repository stats"
 msgstr "リポジトリステートの削除中にエラーが発生しました"
 
-#: kallithea/controllers/admin/settings.py:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr "VCS設定を更新しました"
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
@@ -926,111 +911,111 @@
 "\"hgsubversion\"ライブラリが見つからないため、hgsubversionサポートを有効に"
 "出来ません"
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
 msgstr "アプリケーション設定の更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/settings.py:180
+#: kallithea/controllers/admin/settings.py:176
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr "リポジトリの再スキャンに成功しました。 追加: %s 削除: %s。"
 
-#: kallithea/controllers/admin/settings.py:192
+#: kallithea/controllers/admin/settings.py:188
 #, fuzzy, python-format
 #| msgid "Invalidate cache for all repositories"
 msgid "Invalidated %s repositories"
 msgstr "すべてのリポジトリのキャッシュを無効化する"
 
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr "アプリケーション設定を更新しました"
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr "表示設定を更新しました"
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
 msgstr "表示設定の更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/settings.py:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr "メールアドレスを入力してください"
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr "メール送信タスクを作成しました"
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "まだデータの準備ができていません"
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:357
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:363
+#: kallithea/controllers/admin/settings.py:360
 msgid "Added new hook"
 msgstr "新しいフックを追加しました"
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr "フックを更新しました"
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr "フックの作成中にエラーが発生しました"
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr "Whooshの再インデックスタスクを予定に入れました"
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr "ユーザーグループ %s を作成しました"
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr "ユーザーグループ %s の作成中にエラーが発生しました"
 
-#: kallithea/controllers/admin/user_groups.py:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr "ユーザーグループ %s を更新しました"
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr "ユーザーグループ %s の更新中にエラーが発生しました"
 
-#: kallithea/controllers/admin/user_groups.py:217
+#: kallithea/controllers/admin/user_groups.py:212
 msgid "Successfully deleted user group"
 msgstr "ユーザーグループの削除に成功しました"
 
-#: kallithea/controllers/admin/user_groups.py:222
+#: kallithea/controllers/admin/user_groups.py:217
 msgid "An error occurred during deletion of user group"
 msgstr "ユーザーグループの削除中にエラーが発生しました"
 
-#: kallithea/controllers/admin/user_groups.py:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr "対象に同じ物を選ぶことはできません"
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr "ユーザーグループ権限を更新しました"
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr "権限を更新しました"
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr "権限の保存時にエラーが発生しました"
 
@@ -1060,223 +1045,225 @@
 msgid "The default user cannot be edited"
 msgstr "デフォルト ユーザーを編集できません"
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr "ユーザーホワイトリストにIP %s を追加しました"
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr "IPアドレスの保存中にエラーが発生しました"
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr "ユーザーホワイトリストからIPアドレスを削除しました"
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 "このアクションを実行するためには登録済みのユーザーである必要があります"
 
-#: kallithea/lib/auth.py:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr "このページを閲覧するためにはサインインが必要です"
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr "APIキーが無効です"
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr "ファイルシステム内にリポジトリが見つかりません"
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, fuzzy, python-format
 #| msgid "Changeset not found"
 msgid "Changeset for %s %s not found in %s"
 msgstr "リビジョンが見つかりません"
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+#, fuzzy
+#| msgid "Your account is disabled"
+msgid "SSH access is disabled."
+msgstr "アカウントは無効です"
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr "バイナリファイル"
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 "チェンジセットが大きすぎるため省略しました。差分を表示する場合は差分メ"
 "ニューを使用してください"
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr "検出された変更はありません"
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "削除されたブランチ: %s"
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr "作成したタグ: %s"
 
-#: kallithea/lib/helpers.py:625
+#: kallithea/lib/helpers.py:666
 #, fuzzy, python-format
 #| msgid "Changeset not found"
 msgid "Changeset %s not found"
 msgstr "リビジョンが見つかりません"
 
-#: kallithea/lib/helpers.py:674
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "%s から %s までのすべてのチェンジセットを表示"
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 msgid "Compare view"
 msgstr "比較ビュー"
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr "と"
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr "%s 以上"
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "リビジョン"
 
-#: kallithea/lib/helpers.py:725
+#: kallithea/lib/helpers.py:766
 #, python-format
 msgid "Fork name %s"
 msgstr "フォーク名 %s"
 
-#: kallithea/lib/helpers.py:746
+#: kallithea/lib/helpers.py:787
 #, python-format
 msgid "Pull request %s"
 msgstr "プルリクエスト #%s"
 
-#: kallithea/lib/helpers.py:756
+#: kallithea/lib/helpers.py:797
 msgid "[deleted] repository"
 msgstr "リポジトリを[削除]"
 
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
 msgid "[created] repository"
 msgstr "リポジトリを[作成]"
 
-#: kallithea/lib/helpers.py:760
+#: kallithea/lib/helpers.py:801
 msgid "[created] repository as fork"
 msgstr "フォークしてリポジトリを[作成]"
 
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
 msgid "[forked] repository"
 msgstr "リポジトリを[フォーク]"
 
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
 msgid "[updated] repository"
 msgstr "リポジトリを[更新]"
 
-#: kallithea/lib/helpers.py:766
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr "リポジトリからアーカイブを[ダウンロード]"
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr "リポジトリを[削除]"
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr "ユーザーを[作成]"
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr "ユーザーを[更新]"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr "ユーザーグループを[作成]"
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr "ユーザーグループを[更新]"
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr "リポジトリのリビジョンに[コメント]"
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr "プルリクエストに[コメント]"
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr "プルリクエストを[クローズ]"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr "[プッシュ]"
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr "リポジトリに[Kallithea経由でコミット]"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr "リポジトリに[リモートからプル]"
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr "[プル]"
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr "リポジトリの[フォローを開始]"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr "リポジトリの[フォローを停止]"
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr " と %s 以上"
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "ファイルはありません"
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr "新しいファイル"
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr "変更"
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr "削除"
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr "リネーム"
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1287,63 +1274,90 @@
 "られたか名前が変更されたためです。リポジトリをもう一度チェックするためにア"
 "プリケーションを再起動してください"
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] "%d 年"
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] "%d ヶ月"
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] "%d 日"
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] "%d 時間"
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] "%d 分"
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] "%d 秒"
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr "%s 以内"
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr "%s 前"
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr "%s と %s の間"
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s と %s 前"
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr "たったいま"
 
@@ -1352,140 +1366,140 @@
 msgid "on line %s"
 msgstr "%s 行目"
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr "[Mention]"
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr "top level"
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr "Kallithea 管理者"
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
 msgstr "デフォルトユーザーは新しいリポジトリにアクセスできません"
 
-#: kallithea/model/db.py:1706
+#: kallithea/model/db.py:1640
 msgid "Default user has read access to new repositories"
 msgstr ""
 "デフォルトユーザーは新しいリポジトリに読み取りアクセスする権限があります"
 
-#: kallithea/model/db.py:1707
+#: kallithea/model/db.py:1641
 msgid "Default user has write access to new repositories"
 msgstr ""
 "デフォルトユーザーは新しいリポジトリに書き込みアクセスする権限があります"
 
-#: kallithea/model/db.py:1708
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1711
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 msgid "Only admins can create repository groups"
 msgstr "管理者のみがリポジトリのグループを作成できます"
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 msgid "Non-admins can create repository groups"
 msgstr "非管理者がリポジトリのグループを作成できます"
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 msgid "Only admins can create user groups"
 msgstr "管理者だけがユーザー グループを作成することができます"
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 msgid "Non-admins can create user groups"
 msgstr "非管理者ユーザーがグループを作成することができます"
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr "管理者だけがトップレベルにリポジトリを作成することができます"
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr "非管理者がトップレベルにリポジトリを作成することができます"
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 "リポジトリグループの書き込みパーミッションを使ったリポジトリ作成が有効です"
 
-#: kallithea/model/db.py:1730
+#: kallithea/model/db.py:1664
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 "リポジトリグループの書き込みパーミッションを使ったリポジトリ作成は無効です"
 
-#: kallithea/model/db.py:1732
+#: kallithea/model/db.py:1666
 msgid "Only admins can fork repositories"
 msgstr "管理者のみがリポジトリをフォークすることができます"
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 #, fuzzy
 msgid "Non-admins can fork repositories"
 msgstr "非管理者がリポジトリをフォークすることができます"
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr "新規登録を無効にする"
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr "ユーザーの新規登録時に手動でアカウントをアクティベートする"
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr "ユーザーの新規登録時に自動でアカウントをアクティベートする"
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 msgid "Not reviewed"
 msgstr "未レビュー"
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 msgid "Under review"
 msgstr "レビュー中"
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 #, fuzzy
 #| msgid "Approved"
 msgid "Not approved"
 msgstr "承認"
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr "承認"
 
@@ -1511,7 +1525,7 @@
 msgid "Name must not contain only digits"
 msgstr "数字だけの名前は使えません"
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, fuzzy, python-format
 #| msgid "[Comment] %(repo_name)s pull request %(pr_nice_id)s from %(ref)s"
 msgid ""
@@ -1519,30 +1533,30 @@
 "%(branch)s"
 msgstr "プルリクエストに[コメント]"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr "新しいユーザー %(new_username)s が登録されました"
 
-#: kallithea/model/notification.py:170
+#: kallithea/model/notification.py:169
 #, 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:171
+#: kallithea/model/notification.py:170
 #, 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:184
+#: kallithea/model/notification.py:183
 msgid "Closing"
 msgstr "クローズ"
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
@@ -1550,64 +1564,80 @@
 "%(user)s がプリリクエスト #%(pr_nice_id)s: %(pr_title)s のレビューを求めて"
 "います"
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 #, fuzzy
 #| msgid "Error creating pull request: %s"
 msgid "Cannot create empty pull request"
 msgstr "プルリクエスト作成中にエラーが発生しました: %s"
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 #, fuzzy
 #| msgid "Confirm to delete this pull request"
 msgid "You are not authorized to create the pull request"
 msgstr "このプルリクエストを削除してもよろしいですか?"
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 msgid "Missing changesets since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, python-format
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, python-format
 msgid ""
 "This iteration is based on another %s revision and there is no simple "
 "diff."
 msgstr ""
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, python-format
 msgid "No changes found on %s %s since previous iteration."
 msgstr ""
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr "最新のtip"
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, fuzzy, python-format
+#| msgid "Changeset not found"
+msgid "SSH key %r not found"
+msgstr "リビジョンが見つかりません"
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr "新規ユーザー登録"
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 #, fuzzy
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
@@ -1615,7 +1645,7 @@
 "このユーザーを削除できません。このユーザーはアプリケーションにとって必要不"
 "可欠です。"
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:255
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
@@ -1624,7 +1654,7 @@
 "ユーザー \"%s\" はまだ %s 個のリポジトリの所有者のため削除することはできま"
 "せん。リポジトリの所有者を変更するか削除してください: %s"
 
-#: kallithea/model/user.py:263
+#: kallithea/model/user.py:260
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
@@ -1633,7 +1663,7 @@
 "ユーザー \"%s\" はまだ %s 個のリポジトリグループの所有者のため削除すること"
 "はできません。リポジトリグループの所有者を変更するか削除してください: %s"
 
-#: kallithea/model/user.py:270
+#: kallithea/model/user.py:267
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
@@ -1642,36 +1672,36 @@
 "ユーザー \"%s\" はまだ %s 個のユーザーグループの所有者のため削除することは"
 "できません。ユーザーグループの所有者を変更するか削除してください。 %s"
 
-#: kallithea/model/user.py:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr "パスワードリセットのリンク"
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 msgid "Password reset notification"
 msgstr "パスワードの再設定通知"
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr "空のリストにはできません"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:72
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "ユーザー名 \"%(username)s\" はすでに使われています"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:74
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "ユーザー名 %(username)s は使用できません"
 
-#: kallithea/model/validators.py:78
+#: kallithea/model/validators.py:76
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
@@ -1680,25 +1710,25 @@
 "か使えません。また、アルファベットまたはアンダースコア(_)から始まる必要が"
 "あります"
 
-#: kallithea/model/validators.py:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr "入力が正しくありません"
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr "ユーザー名 %(username)s は不正です"
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr "不正なユーザーグループ名です"
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:132
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr "ユーザーグループ \"%(usergroup)s\" はすでに存在します"
 
-#: kallithea/model/validators.py:136
+#: kallithea/model/validators.py:134
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
@@ -1706,105 +1736,101 @@
 "ユーザーグループ名はアルファベット、アンダースコア(_)、ピリオド(.)、ダッ"
 "シュ(-)しか使えません。また、アルファベットから始まる必要があります"
 
-#: kallithea/model/validators.py:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr "このグループは親にできません"
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:175
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr "グループ \"%(group_name)s\" はすでに存在します"
 
-#: kallithea/model/validators.py:179
+#: kallithea/model/validators.py:177
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr "グループ名 \"%(group_name)s\" を持つリポジトリはすでに存在します"
 
-#: kallithea/model/validators.py:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr "パスワードに利用出来ない文字列(non-ascii)です"
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr "古いpasswordが間違っています"
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr "パスワードが一致しません"
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 msgid "Invalid username or password"
 msgstr "ユーザー名とパスワードの組み合わせが無効です"
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr "トークンが一致しません"
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr "リポジトリ名 %(repo)s は許可されていません"
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr "リポジトリ %(repo)s はすでに存在します"
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 "リポジトリ \"%(repo)s\" は グループ \"%(group)s\" にすでに存在します"
 
-#: kallithea/model/validators.py:333
+#: kallithea/model/validators.py:318
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr "リポジトリグループ名 \"%(repo)s\" はすでに存在します"
 
-#: kallithea/model/validators.py:419
+#: kallithea/model/validators.py:404
 msgid "Invalid repository URL"
 msgstr "無効なリポジトリのURL"
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:430
 msgid "Fork has to be the same type as parent"
 msgstr "フォークは親と同じ種別の必要があります"
 
-#: kallithea/model/validators.py:460
+#: kallithea/model/validators.py:445
 msgid "You don't have permissions to create repository in this group"
 msgstr "このグループにリポジトリを作成する権限がありません"
 
-#: kallithea/model/validators.py:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
 msgstr "ルートにリポジトリを作成する権限がありません"
 
-#: kallithea/model/validators.py:512
+#: kallithea/model/validators.py:497
 msgid "You don't have permissions to create a group in this location"
 msgstr "この場所にグループを作成する権限がありません"
 
-#: kallithea/model/validators.py:552
+#: kallithea/model/validators.py:537
 msgid "This username or user group name is not valid"
 msgstr "ユーザー名かユーザーグループが不正です"
 
-#: kallithea/model/validators.py:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr "不正なパスです"
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 msgid "This email address is already in use"
 msgstr "このメールアドレスはすでに取得されています"
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "メールアドレス \"%(email)s\" がみつかりません"
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
@@ -1812,11 +1838,11 @@
 "LDAPのこのCNに対するログイン属性は必須です。 - これは \"ユーザー名\" と同"
 "じです"
 
-#: kallithea/model/validators.py:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr "有効なIPv4かIPv6のアドレスを入力してください"
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
@@ -1824,17 +1850,17 @@
 "ネットワークサイズ (bits) は0-32の範囲にする必要があります ( %(bits)r は不"
 "正です)"
 
-#: kallithea/model/validators.py:765
+#: kallithea/model/validators.py:750
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 "キー名にはアルファベット、アンダースコア(_)、ピリオド(.)、ダッシュ(-)、数"
 "字が使えます"
 
-#: kallithea/model/validators.py:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr "ファイル名はディレクトリ内にすることはできません"
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1877,24 +1903,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr "説明"
 
@@ -1911,7 +1943,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1919,11 +1951,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr "所有者"
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr "ログイン"
@@ -1938,7 +1970,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1946,7 +1978,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr "パスワード"
@@ -2103,10 +2135,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr "アクション"
@@ -2157,22 +2191,22 @@
 msgstr "プラグイン"
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr "保存"
 
@@ -2190,14 +2224,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr "非公開リポジトリ"
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2207,36 +2241,25 @@
 "す。"
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr "統計を有効にする"
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr "概要ページの統計ウィンドウを有効にします。"
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr "ダウンロードを有効にする"
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr "概要ページのダウンロードメニューを有効にします。"
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr "ロックを有効にする"
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr "リポジトリのpullのロックを有効にします。"
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2285,8 +2308,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 msgid "Never"
 msgstr "しない"
 
@@ -2319,7 +2344,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr "新しい Gist を作成"
 
@@ -2357,23 +2382,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2401,7 +2428,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2461,7 +2488,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr "アカウント"
 
@@ -2474,24 +2501,31 @@
 msgid "Email Addresses"
 msgstr "メールアドレス"
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
+#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/users/user_edit.html:32
+#, fuzzy
+#| msgid "API Keys"
+msgid "SSH Keys"
+msgstr "APIキー"
+
+#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
 msgid "API Keys"
 msgstr "APIキー"
 
-#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/my_account/my_account.html:32
 msgid "Owned Repositories"
 msgstr "所有しているリポジトリ"
 
-#: kallithea/templates/admin/my_account/my_account.html:30
+#: kallithea/templates/admin/my_account/my_account.html:33
 #: kallithea/templates/journal/journal.html:33
 msgid "Watched Repositories"
 msgstr "ウォッチ中のリポジトリ"
 
-#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 msgid "Show Permissions"
 msgstr "権限の表示"
 
@@ -2518,7 +2552,9 @@
 msgstr "このAPIキーを削除してもよろしいですか?: %s"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 msgid "Remove"
 msgstr "削除"
 
@@ -2534,12 +2570,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr "追加"
 
@@ -2641,6 +2679,49 @@
 msgid "Name"
 msgstr "名前"
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+#, fuzzy
+#| msgid "Last Name"
+msgid "Last Used"
+msgstr "名字"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, fuzzy, python-format
+#| msgid "Confirm to remove this API key: %s"
+msgid "Confirm to remove this SSH key: %s"
+msgstr "このAPIキーを削除してもよろしいですか?: %s"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+#, fuzzy
+#| msgid "New API key"
+msgid "New SSH key"
+msgstr "新しいAPIキー"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+#, fuzzy
+#| msgid "Public Gist"
+msgid "Public key"
+msgstr "公開 Gist"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 msgid "Repositories You are Watching"
 msgstr "あなたがウォッチしているリポジトリ"
@@ -2657,7 +2738,7 @@
 msgstr "全般"
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr "IPアドレスのホワイトリスト"
 
@@ -2701,7 +2782,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2875,7 +2956,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr "高度な設定"
 
@@ -2989,19 +3070,11 @@
 "このグループに属する全ての子要素のパーミッションを設定または無効化します。"
 "選択されていれば、非公開でないリポジトリや他のリポジトリも対象に含みます。"
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-"グループに対してpullのロックを有効にします。このオプションはグループに含ま"
-"れる全てのグループとリポジトリに適用されます。"
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
 msgstr "このグループを削除"
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Confirm to delete this group"
 msgstr "このグループを削除してもよろしいですか?: %s"
 
@@ -3030,7 +3103,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
@@ -3038,7 +3111,7 @@
 "短く要点を絞ってください。長い説明にはREADMEファイルを利用してください。"
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr "オプション:このリポジトリが属するグループを選択します"
@@ -3048,7 +3121,7 @@
 msgstr "作成するリポジトリの種別を指定します"
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr "ランディングリビジョン"
@@ -3106,8 +3179,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr "統計"
 
@@ -3142,68 +3215,31 @@
 msgstr ""
 "公開ジャーナルでは、このリポジトリに対して行った操作のすべてが公開されます"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-msgid "Change Locking"
-msgstr "ロック"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-msgid "Confirm to unlock repository."
-msgstr "このリポジトリのロックを解除しますか?"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-msgid "Unlock Repository"
-msgstr "リポジトリのロックを解除"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-msgid "Confirm to lock repository."
-msgstr "このリポジトリをロックしますか?"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-msgid "Lock Repository"
-msgstr "リポジトリをロック"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr "リポジトリはロックされていません"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
 #: kallithea/templates/data_table/_dt_elements.html:68
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "このリポジトリを削除してもよろしいですか? : %s"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
 msgid "Delete this Repository"
 msgstr "このリポジトリを削除"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
 msgstr[0] "このリポジトリには %s 個のフォークがあります"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr "フォークの切り離し"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr "フォークも削除"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3304,19 +3340,13 @@
 msgid "This repository does not have a remote repository URL."
 msgstr "このリポジトリにリモートURLは設定されていません"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "Permanent Repository ID"
+#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#, fuzzy
+#| msgid "Permanent Repository ID"
+msgid "Permanent URL"
 msgstr "リポジトリID"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr "これは何?"
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr "id を使ってURLを表現"
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3331,15 +3361,15 @@
 "この機能は、CIを使っている場合や、3rd pirtyのサービス向けにURLを固定化した"
 "いときに便利です。"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 msgid "Remote repository"
 msgstr "リモートリポジトリ"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 msgid "Repository URL"
 msgstr "リポジトリURL"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
@@ -3347,20 +3377,20 @@
 "オプション: リモートリポジトリのURLです。設定した場合、このURLから変更を取"
 "得することができます。"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr ""
 "ファイルページ、ダウンロード、検索、READMEのデフォルトのリビジョンを指定し"
 "ます"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 #, fuzzy
 #| msgid "Type name of reviewer to add"
 msgid "Type name of user"
 msgstr "追加するレビュアーの名前を入力"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr "リポジトリの所有者を変更"
 
@@ -3471,8 +3501,8 @@
 "す。"
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 msgid "Save Settings"
 msgstr "設定を保存"
 
@@ -3580,10 +3610,6 @@
 msgid "Kallithea version"
 msgstr "Kallithea バージョン"
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr "更新を確認"
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr "Kallithea の設定ファイル"
@@ -3604,15 +3630,7 @@
 msgid "Git path"
 msgstr "Git パス"
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr "更新情報のエンドポイント"
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr "ノート: サーバーがこのURLにアクセスできることを確認して下さい"
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr "Python パッケージ"
 
@@ -3621,30 +3639,22 @@
 msgstr "プッシュ後にリポジトリのサイズを表示する"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
-msgstr "ユーザーのプッシュコマンドを記録する"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr "ユーザーのプルコマンドを記録する"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
 msgid "Update repository after push (hg update)"
 msgstr "プッシュ後にリポジトリを更新する (hg update)"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:33
+#: kallithea/templates/admin/settings/settings_vcs.html:21
 msgid "Mercurial extensions"
 msgstr "Mercurialエクステンション"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr "largefilesエクステンションを有効にする"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr "hgsubversionエクステンションを有効にする"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:47
+#: kallithea/templates/admin/settings/settings_vcs.html:35
 msgid ""
 "Requires hgsubversion library to be installed. Enables cloning of remote "
 "Subversion repositories while converting them to Mercurial."
@@ -3652,18 +3662,18 @@
 "hgsubversion ライブラリのインストールが必要です。リモートのSVNリポジトリを"
 "クローンしてMercurialリポジトリに変換するすることが可能です。"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:59
+#: kallithea/templates/admin/settings/settings_vcs.html:47
 msgid "Location of repositories"
 msgstr "リポジトリの場所"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
 msgstr ""
 "アンロックする。この設定を有効にするためにはKallitheaの再起動が必要です。"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3726,8 +3736,9 @@
 "{netloc} Kallithea サーバーのアドレスまたはホスト名"
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-msgid "Clone URL"
+#, fuzzy
+#| msgid "Clone URL"
+msgid "HTTP Clone URL"
 msgstr "クローンURL"
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
@@ -3755,7 +3766,12 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
 msgstr ""
 "クローン URL のスキーマは、 '{scheme}://{user}@{netloc}/{repo}' のような形"
 "式にします。使える変数は下記の通りです:\n"
@@ -3771,13 +3787,25 @@
 "                                                        {repoid} リポジト"
 "リの ID。 clone-by-id に使います。"
 
-#: kallithea/templates/admin/settings/settings_visual.html:54
+#: kallithea/templates/admin/settings/settings_visual.html:56
+#, fuzzy
+#| msgid "Clone URL"
+msgid "SSH Clone URL"
+msgstr "クローンURL"
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 #, fuzzy
 #| msgid "Repository Size"
 msgid "Repository page size"
 msgstr "リポジトリサイズ"
 
-#: kallithea/templates/admin/settings/settings_visual.html:57
+#: kallithea/templates/admin/settings/settings_visual.html:68
 #, fuzzy
 #| msgid ""
 #| "Number of items displayed in the admin pages grids before pagination "
@@ -3787,45 +3815,45 @@
 "shown."
 msgstr "管理ページで、ページ分割しないでグリッドに表示する項目の数"
 
-#: kallithea/templates/admin/settings/settings_visual.html:62
+#: kallithea/templates/admin/settings/settings_visual.html:73
 #, fuzzy
 #| msgid "Admin pages items"
 msgid "Admin page size"
 msgstr "管理ページの項目"
 
-#: kallithea/templates/admin/settings/settings_visual.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr "管理ページで、ページ分割しないでグリッドに表示する項目の数"
 
-#: kallithea/templates/admin/settings/settings_visual.html:70
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr "アイコン"
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
 msgstr "公開リポジトリのアイコンを表示する"
 
-#: kallithea/templates/admin/settings/settings_visual.html:81
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr "非公開リポジトリのアイコンを表示する"
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 msgid "Show public/private icons next to repository names."
 msgstr "リポジトリ名の隣に公開/非公開アイコンを表示します。"
 
-#: kallithea/templates/admin/settings/settings_visual.html:89
+#: kallithea/templates/admin/settings/settings_visual.html:100
 msgid "Meta Tagging"
 msgstr "メタタグ"
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr "リポジトリの説明のメタタグを解析して色つきのタグに変換します。"
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr "次のメタタグを変換する:"
 
@@ -3986,12 +4014,12 @@
 msgstr "サポート"
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr "Mercurialリポジトリ"
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr "Gitリポジトリ"
 
@@ -4039,160 +4067,135 @@
 msgstr "比較"
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr "検索"
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr "アンロック"
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr "ロック"
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr "フォロー"
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr "アンフォロー"
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr "フォーク"
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr "プルリクエストを作成"
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr "ブランチの切り替え"
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr "一致するものが見つかりません"
 
-#: kallithea/templates/base/base.html:296
+#: kallithea/templates/base/base.html:289
 msgid "Show recent activity"
 msgstr "最近の活動を表示"
 
-#: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
+#: kallithea/templates/base/base.html:295
+#: kallithea/templates/base/base.html:296
 msgid "Public journal"
 msgstr "公開ジャーナル"
 
-#: kallithea/templates/base/base.html:308
+#: kallithea/templates/base/base.html:301
 msgid "Show public gists"
 msgstr "公開 gists を表示"
 
-#: kallithea/templates/base/base.html:309
+#: kallithea/templates/base/base.html:302
 msgid "Gists"
 msgstr "Gists"
 
-#: kallithea/templates/base/base.html:313
+#: kallithea/templates/base/base.html:306
 msgid "All Public Gists"
 msgstr "すべての公開 Gists"
 
-#: kallithea/templates/base/base.html:315
+#: kallithea/templates/base/base.html:308
 msgid "My Public Gists"
 msgstr "公開 Gists"
 
-#: kallithea/templates/base/base.html:316
+#: kallithea/templates/base/base.html:309
 msgid "My Private Gists"
 msgstr "非公開 Gists"
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr "リポジトリから検索"
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 msgid "My Pull Requests"
 msgstr "私のプルリクエスト"
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr "ログインしていません"
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 msgid "Login to Your Account"
 msgstr "あなたのアカウントにログイン"
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 #, fuzzy
 #| msgid "Forgot password ?"
 msgid "Forgot password?"
 msgstr "パスワードを忘れた?"
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 #, fuzzy
 #| msgid "Don't have an account ?"
 msgid "Don't have an account?"
 msgstr "アカウントを持っていない?"
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr "ログアウト"
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr "親リビジョン"
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr "子リビジョン"
 
 #: kallithea/templates/base/default_perms_box.html:11
-msgid "Inherit defaults"
-msgstr "デフォルト権限を継承"
+msgid "Create repositories"
+msgstr "リポジトリを作成する"
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-#, fuzzy
-#| msgid "Default permissions"
-msgid "default permissions"
-msgstr "デフォルトの権限"
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr "リポジトリを作成する"
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 "ユーザーにリポジトリ作成を許可する場合はこのオプションを選んでください"
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr "ユーザーグループを作成"
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 "ユーザーにユーザーグループの作成を許可する場合はこのオプションを選んでくだ"
 "さい"
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr "リポジトリをフォークする"
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 "ユーザーにリポジトリのフォークを許可する場合はこのオプションを選んでくださ"
@@ -4941,7 +4944,7 @@
 msgstr "%s ファイル差分"
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr "%s ファイル"
@@ -4953,7 +4956,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr "新しいファイルを追加"
 
@@ -5006,7 +5009,7 @@
 msgstr "ファイル一覧を読み込み中..."
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr "サイズ"
 
@@ -5137,8 +5140,8 @@
 msgstr "%s フォロワー"
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr "フォロワー"
 
@@ -5191,8 +5194,8 @@
 msgstr "%s フォーク"
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr "フォーク"
 
@@ -5511,9 +5514,9 @@
 msgid "File names"
 msgstr "ファイル名"
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr "権限がありません"
 
@@ -5523,20 +5526,20 @@
 msgstr "%s 統計情報"
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr "%s ATOM フィード"
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr "%s RSS フィード"
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr "有効にする"
 
@@ -5545,12 +5548,12 @@
 msgstr "収集した統計情報: "
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr "ファイル"
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr "もっと表示"
 
@@ -5591,94 +5594,196 @@
 msgid "%s Summary"
 msgstr "%s 要約"
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr "リポジトリは %s によってロックされました"
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr "リポジトリはロックされていません"
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr "フォーク元"
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr "クローン元"
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr "IDで表示"
-
+#: kallithea/templates/summary/summary.html:54
+msgid "Clone URL"
+msgstr "クローンURL"
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr "名前で表示"
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+#, fuzzy
+#| msgid "Last Name"
+msgid "Use Name"
+msgstr "名字"
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr "トレンドファイル"
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr "ダウンロード"
 
-#: kallithea/templates/summary/summary.html:101
+#: kallithea/templates/summary/summary.html:109
 msgid "There are no downloads yet"
 msgstr "まだダウンロードがありません"
 
-#: kallithea/templates/summary/summary.html:103
+#: kallithea/templates/summary/summary.html:111
 msgid "Downloads are disabled for this repository"
 msgstr "このリポジトリのダウンロードは無効化されています"
 
-#: kallithea/templates/summary/summary.html:109
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr "ZIPでダウンロード"
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr "チェックするとダウンロードアーカイブにサブリポジトリが含まれます"
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 msgid "With subrepos"
 msgstr "サブリポジトリを含める"
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr "フィード"
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 msgid "Latest Changes"
 msgstr "最近の変更"
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 msgid "Quick Start"
 msgstr "クイックスタート"
 
-#: kallithea/templates/summary/summary.html:188
+#: kallithea/templates/summary/summary.html:196
 msgid "Add or upload files directly via Kallithea"
 msgstr "Kallithea経由で直接ファイルを追加またはアップロード"
 
-#: kallithea/templates/summary/summary.html:196
+#: kallithea/templates/summary/summary.html:204
 msgid "Push new repository"
 msgstr "新しいリポジトリをプッシュ"
 
-#: kallithea/templates/summary/summary.html:204
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr "存在するリポジトリをプッシュ"
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr "リビジョン %s:%s の README ファイル"
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr "%s を %s でダウンロード"
 
+#~ msgid "This repository has been locked by %s on %s"
+#~ msgstr "このリポジトリは %s によって %s にロックされました"
+
+#~ msgid "Repository has been locked"
+#~ msgstr "リポジトリがロックされました"
+
+#~ msgid "Repository has been unlocked"
+#~ msgstr "リポジトリのロックが解除されました"
+
+#~ msgid "An error occurred during unlocking"
+#~ msgstr "アンロック中にエラーが発生しました"
+
+#~ msgid "Invalid API key"
+#~ msgstr "APIキーが無効です"
+
+#~ msgid "Token mismatch"
+#~ msgstr "トークンが一致しません"
+
+#~ msgid "Enable locking"
+#~ msgstr "ロックを有効にする"
+
+#~ msgid "Enable lock-by-pulling on repository."
+#~ msgstr "リポジトリのpullのロックを有効にします。"
+
+#~ msgid ""
+#~ "Enable lock-by-pulling on group. This option will be applied to all "
+#~ "other groups and repositories inside"
+#~ msgstr ""
+#~ "グループに対してpullのロックを有効にします。このオプションはグループに"
+#~ "含まれる全てのグループとリポジトリに適用されます。"
+
+#~ msgid "Change Locking"
+#~ msgstr "ロック"
+
+#~ msgid "Confirm to unlock repository."
+#~ msgstr "このリポジトリのロックを解除しますか."
+
+#~ msgid "Unlock Repository"
+#~ msgstr "リポジトリのロックを解除"
+
+#~ msgid "Confirm to lock repository."
+#~ msgstr "このリポジトリをロックしますか."
+
+#~ msgid "Lock Repository"
+#~ msgstr "リポジトリをロック"
+
+#~ msgid "Repository is not locked"
+#~ msgstr "リポジトリはロックされていません"
+
+#~ msgid "What is that?"
+#~ msgstr "これは何?"
+
+#~ msgid "URL by id"
+#~ msgstr "id を使ってURLを表現"
+
+#~ msgid "Check for updates"
+#~ msgstr "更新を確認"
+
+#~ msgid "Upgrade info endpoint"
+#~ msgstr "更新情報のエンドポイント"
+
+#~ msgid "Note: please make sure this server can access this URL"
+#~ msgstr "ノート: サーバーがこのURLにアクセスできることを確認して下さい"
+
+#~ msgid "Log user push commands"
+#~ msgstr "ユーザーのプッシュコマンドを記録する"
+
+#~ msgid "Log user pull commands"
+#~ msgstr "ユーザーのプルコマンドを記録する"
+
+#~ msgid "Unlock"
+#~ msgstr "アンロック"
+
+#~ msgid "Lock"
+#~ msgstr "ロック"
+
+#~ msgid "Inherit defaults"
+#~ msgstr "デフォルト権限を継承"
+
+#, fuzzy
+#~| msgid "Default permissions"
+#~ msgid "default permissions"
+#~ msgstr "デフォルトの権限"
+
+#~ msgid "Repository locked by %s"
+#~ msgstr "リポジトリは %s によってロックされました"
+
+#~ msgid "Repository unlocked"
+#~ msgstr "リポジトリはロックされていません"
+
+#~ msgid "Show by ID"
+#~ msgstr "IDで表示"
+
+#~ msgid "Show by Name"
+#~ msgstr "名前で表示"
+
 #~ msgid "There is no index to search in. Please run whoosh indexer"
 #~ msgstr ""
 #~ "検索するためのインデックスがありません。whooshでインデックスを作成して"
@@ -6003,9 +6108,6 @@
 #~ msgid "invalid user name"
 #~ msgstr "不正なユーザー名です"
 
-#~ msgid "Your account is disabled"
-#~ msgstr "アカウントは無効です"
-
 #~ msgid "invalid clone URL"
 #~ msgstr "無効なクローンURIです"
 
--- a/kallithea/i18n/kallithea.pot	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/kallithea.pot	Sun Jan 05 04:07:51 2020 +0100
@@ -6,26 +6,26 @@
 #, fuzzy
 msgid ""
 msgstr ""
-"Project-Id-Version: Kallithea 0.4.0\n"
+"Project-Id-Version: Kallithea 0.4.99\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\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.6.0\n"
+"Generated-By: Babel 2.7.0\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -34,89 +34,91 @@
 msgid "None"
 msgstr ""
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:90 kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88 kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 msgid "No permission to change status"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:214
+#: kallithea/controllers/changeset.py:212
 #, python-format
 msgid "Successfully deleted pull request %s"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr ""
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, python-format
 msgid "Could not find other repository %s"
 msgstr ""
 
-#: kallithea/controllers/compare.py:72
+#: kallithea/controllers/compare.py:74
 msgid "Cannot compare repositories of different types"
 msgstr ""
 
-#: kallithea/controllers/compare.py:244
-msgid "Cannot show empty diff"
-msgstr ""
-
 #: kallithea/controllers/compare.py:246
+msgid "Cannot show empty diff"
+msgstr ""
+
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr ""
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr ""
 
-#: kallithea/controllers/error.py:70
-msgid "No response"
-msgstr ""
-
 #: kallithea/controllers/error.py:71
+msgid "No response"
+msgstr ""
+
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr ""
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid "The request could not be understood by the server due to malformed syntax."
 msgstr ""
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr ""
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr ""
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr ""
 
-#: kallithea/controllers/error.py:93
-msgid "The server encountered an unexpected condition which prevented it from fulfilling the request."
+#: kallithea/controllers/error.py:94
+msgid ""
+"The server encountered an unexpected condition which prevented it from "
+"fulfilling the request."
 msgstr ""
 
 #: kallithea/controllers/feed.py:63
@@ -134,119 +136,113 @@
 msgid "Changeset was too big and was cut off..."
 msgstr ""
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr ""
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
 msgstr ""
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr ""
 
-#: kallithea/controllers/files.py:93
+#: kallithea/controllers/files.py:86
 msgid "There are no files yet."
 msgstr ""
 
-#: kallithea/controllers/files.py:193
+#: kallithea/controllers/files.py:186
 #, python-format
 msgid "%s at %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr ""
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 msgid "You can only delete files with revision being a valid branch"
 msgstr ""
 
-#: kallithea/controllers/files.py:322
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr ""
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr ""
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 msgid "You can only edit files with revision being a valid branch"
 msgstr ""
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr ""
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr ""
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr ""
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr ""
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr ""
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr ""
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr ""
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr ""
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr ""
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr ""
 
-#: kallithea/controllers/files.py:756 kallithea/controllers/pullrequests.py:184
-#: kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730 kallithea/controllers/pullrequests.py:182
+#: kallithea/model/scm.py:676
 msgid "Branches"
 msgstr ""
 
-#: kallithea/controllers/files.py:757 kallithea/controllers/pullrequests.py:185
-#: kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731 kallithea/controllers/pullrequests.py:183
+#: kallithea/model/scm.py:687
 msgid "Tags"
 msgstr ""
 
@@ -255,187 +251,187 @@
 msgid "An error occurred during repository forking %s"
 msgstr ""
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr ""
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
 #: kallithea/templates/admin/repos/repos.html:9
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56 kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr ""
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
 msgstr ""
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr ""
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr ""
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr ""
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr ""
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr ""
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
 msgstr ""
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr ""
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:190
 msgid "A password reset confirmation code has been sent"
 msgstr ""
 
-#: kallithea/controllers/login.py:238
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 msgid "New pull request iteration created"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, python-format
 msgid "Revision %s not found in %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, python-format
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr ""
 
+#: kallithea/controllers/pullrequests.py:520
+#, python-format
+msgid "This pull request has already been merged to %s."
+msgstr ""
+
 #: kallithea/controllers/pullrequests.py:522
-#, python-format
-msgid "This pull request has already been merged to %s."
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:524
 msgid "This pull request has been closed and can not be updated."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, python-format
 msgid "The following additional changes are available on %s:"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 msgid "No additional changesets found for iterating on this pull request."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 msgid "Git pull requests don't support iterating yet."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, python-format
 msgid "Error: some changesets not found when displaying pull request from %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 
@@ -451,21 +447,21 @@
 msgid "An error occurred during search operation."
 msgstr ""
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr ""
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -477,123 +473,134 @@
 msgid "Error occurred during update of defaults"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 msgid "Forever"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
-#: kallithea/controllers/admin/users.py:249
-msgid "5 minutes"
-msgstr ""
-
 #: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
-#: kallithea/controllers/admin/users.py:250
-msgid "1 hour"
+#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/users.py:249
+msgid "5 minutes"
 msgstr ""
 
 #: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
-#: kallithea/controllers/admin/users.py:251
-msgid "1 day"
+#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/users.py:250
+msgid "1 hour"
 msgstr ""
 
 #: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/my_account.py:235
+#: kallithea/controllers/admin/users.py:251
+msgid "1 day"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:230
-msgid "Successfully updated gist data"
-msgstr ""
-
 #: kallithea/controllers/admin/gists.py:233
+msgid "Successfully updated gist data"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, python-format
+msgid "SSH key %s successfully added"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+msgid "SSH key successfully deleted"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -601,9 +608,9 @@
 msgid "Read"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -611,9 +618,9 @@
 msgid "Write"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -636,358 +643,345 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
-#: kallithea/templates/admin/auth/auth_settings.html:42
-#: kallithea/templates/base/root.html:50
-msgid "Disabled"
-msgstr ""
-
 #: kallithea/controllers/admin/permissions.py:78
-msgid "Allowed with manual account activation"
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
+#: kallithea/templates/admin/auth/auth_settings.html:42
+#: kallithea/templates/base/root.html:50
+msgid "Disabled"
 msgstr ""
 
 #: kallithea/controllers/admin/permissions.py:80
+msgid "Allowed with manual account activation"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:290
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:390
+#: kallithea/controllers/admin/repos.py:391
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:401
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:466
-msgid "Nothing"
-msgstr ""
-
 #: kallithea/controllers/admin/repos.py:468
+msgid "Nothing"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:470
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-msgid "Repository has been locked"
+#: kallithea/controllers/admin/repos.py:490
+msgid "Cache invalidation successful"
 msgstr ""
 
 #: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-msgid "Repository has been unlocked"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:528
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:532
 msgid "An error occurred during cache invalidation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:579
+#: kallithea/controllers/admin/repos.py:541
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
-msgid "Unable to activate hgsubversion support. The \"hgsubversion\" library is missing"
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
+msgid ""
+"Unable to activate hgsubversion support. The \"hgsubversion\" library is "
+"missing"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:180
+#: kallithea/controllers/admin/settings.py:176
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:192
+#: kallithea/controllers/admin/settings.py:188
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 msgid "Hook already exists"
 msgstr ""
 
+#: kallithea/controllers/admin/settings.py:357
+msgid "Builtin hooks are read-only. Please use another hook name."
+msgstr ""
+
 #: kallithea/controllers/admin/settings.py:360
-msgid "Builtin hooks are read-only. Please use another hook name."
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:363
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
+#: kallithea/controllers/admin/user_groups.py:212
+msgid "Successfully deleted user group"
+msgstr ""
+
 #: kallithea/controllers/admin/user_groups.py:217
-msgid "Successfully deleted user group"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:222
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr ""
 
@@ -1017,282 +1011,312 @@
 msgid "The default user cannot be edited"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr ""
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr ""
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr ""
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, python-format
 msgid "Changeset for %s %s not found in %s"
 msgstr ""
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+msgid "SSH access is disabled."
+msgstr ""
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr ""
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:625
+#: kallithea/lib/helpers.py:666
 #, python-format
 msgid "Changeset %s not found"
 msgstr ""
 
-#: kallithea/lib/helpers.py:674
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:701 kallithea/templates/changelog/changelog.html:43
+#: kallithea/lib/helpers.py:742 kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr ""
 
-#: kallithea/lib/helpers.py:725
-#, python-format
-msgid "Fork name %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:746
-#, python-format
-msgid "Pull request %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:756
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:760
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
-msgid "[updated] repository"
-msgstr ""
-
 #: kallithea/lib/helpers.py:766
+#, python-format
+msgid "Fork name %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:787
+#, python-format
+msgid "Pull request %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:797
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
+msgid "[created] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:801
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
+msgid "[updated] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr ""
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr ""
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr ""
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1264
-#, python-format
-msgid "%s repository is not mapped to db perhaps it was created or renamed from the filesystem please run the application again in order to rescan repositories"
-msgstr ""
-
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/helpers.py:1297
+#, python-format
+msgid ""
+"%s repository is not mapped to db perhaps it was created or renamed from "
+"the filesystem please run the application again in order to rescan "
+"repositories"
+msgstr ""
+
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr ""
 
@@ -1301,131 +1325,131 @@
 msgid "on line %s"
 msgstr ""
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1706
+#: kallithea/model/db.py:1640
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1707
+#: kallithea/model/db.py:1641
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1708
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1711
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 msgid "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1730
+#: kallithea/model/db.py:1664
 msgid "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1732
+#: kallithea/model/db.py:1666
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr ""
 
@@ -1451,273 +1475,310 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:165
-#, python-format
-msgid "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on %(branch)s"
-msgstr ""
-
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:164
+#, python-format
+msgid ""
+"[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
+"%(branch)s"
+msgstr ""
+
+#: kallithea/model/notification.py:167
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:169
+#, 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:170
 #, 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:171
-#, 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:184
+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:183
 msgid "Closing"
 msgstr ""
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, python-format
 msgid "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 msgid "Cannot create empty pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:219
-#, python-format
-msgid "Cannot create pull request - criss cross merge detected, please merge a later %s revision to %s"
-msgstr ""
-
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:217
+#, python-format
+msgid ""
+"Cannot create pull request - criss cross merge detected, please merge a "
+"later %s revision to %s"
+msgstr ""
+
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 msgid "You are not authorized to create the pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 msgid "Missing changesets since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, python-format
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 
+#: kallithea/model/pull_request.py:360
+#, python-format
+msgid ""
+"This iteration is based on another %s revision and there is no simple "
+"diff."
+msgstr ""
+
 #: kallithea/model/pull_request.py:362
 #, python-format
-msgid "This iteration is based on another %s revision and there is no simple diff."
-msgstr ""
-
-#: kallithea/model/pull_request.py:364
-#, python-format
 msgid "No changes found on %s %s since previous iteration."
 msgstr ""
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr ""
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, python-format
+msgid "SSH key %r not found"
+msgstr ""
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 msgid "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:258
-#, 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:263
-#, 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:270
-#, 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:364
+#: kallithea/model/user.py:255
+#, 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:260
+#, 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:267
+#, 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:361
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:414
-#, python-format
-msgid "The password to your account %s has been changed using password reset form."
-msgstr ""
-
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/user.py:409
+#, 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
 msgid "Value cannot be an empty list"
 msgstr ""
 
+#: kallithea/model/validators.py:72
+#, python-format
+msgid "Username \"%(username)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:74
 #, python-format
-msgid "Username \"%(username)s\" already exists"
+msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
 #: kallithea/model/validators.py:76
-#, python-format
-msgid "Username \"%(username)s\" cannot be used"
-msgstr ""
-
-#: kallithea/model/validators.py:78
-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:105
+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
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr ""
 
+#: kallithea/model/validators.py:132
+#, python-format
+msgid "User group \"%(usergroup)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:134
-#, python-format
-msgid "User group \"%(usergroup)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:136
-msgid "user group name may only contain alphanumeric characters underscores, periods or dashes and must begin with alphanumeric character"
-msgstr ""
-
-#: kallithea/model/validators.py:176
+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
+#, python-format
+msgid "Group \"%(group_name)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:177
 #, python-format
-msgid "Group \"%(group_name)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:179
-#, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 msgid "Invalid username or password"
 msgstr ""
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr ""
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr ""
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
-#: kallithea/model/validators.py:333
+#: kallithea/model/validators.py:318
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:419
+#: kallithea/model/validators.py:404
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:420
-msgid "Invalid repository URL. It must be a valid http, https, ssh, svn+http or svn+https URL"
+#: kallithea/model/validators.py:405
+msgid ""
+"Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
+"svn+https URL"
+msgstr ""
+
+#: kallithea/model/validators.py:430
+msgid "Fork has to be the same type as parent"
 msgstr ""
 
 #: kallithea/model/validators.py:445
-msgid "Fork has to be the same type as parent"
-msgstr ""
-
-#: kallithea/model/validators.py:460
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:512
+#: kallithea/model/validators.py:497
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:552
+#: kallithea/model/validators.py:537
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:719
-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:731
+#: kallithea/model/validators.py:704
+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
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, python-format
 msgid "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:765
+#: kallithea/model/validators.py:750
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1758,24 +1819,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr ""
 
@@ -1792,7 +1859,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1800,11 +1867,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr ""
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr ""
@@ -1819,7 +1886,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1827,7 +1894,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr ""
@@ -1878,7 +1945,9 @@
 msgstr ""
 
 #: kallithea/templates/password_reset.html:52
-msgid "A password reset link will be sent to the specified email address if it is registered in the system."
+msgid ""
+"A password reset link will be sent to the specified email address if it "
+"is registered in the system."
 msgstr ""
 
 #: kallithea/templates/password_reset_confirmation.html:23
@@ -1887,7 +1956,9 @@
 msgstr ""
 
 #: kallithea/templates/password_reset_confirmation.html:24
-msgid "Note that you must use the same browser session for this as the one used to request the password reset."
+msgid ""
+"Note that you must use the same browser session for this as the one used "
+"to request the password reset."
 msgstr ""
 
 #: kallithea/templates/password_reset_confirmation.html:29
@@ -1979,10 +2050,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr ""
@@ -2017,7 +2090,9 @@
 msgstr ""
 
 #: kallithea/templates/admin/auth/auth_settings.html:32
-msgid "Comma-separated list of plugins; Kallithea will try user authentication in plugin order"
+msgid ""
+"Comma-separated list of plugins; Kallithea will try user authentication "
+"in plugin order"
 msgstr ""
 
 #: kallithea/templates/admin/auth/auth_settings.html:36
@@ -2029,22 +2104,22 @@
 msgstr ""
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr ""
 
@@ -2062,49 +2137,40 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
-msgid "Private repositories are only visible to people explicitly added as collaborators."
+msgid ""
+"Private repositories are only visible to people explicitly added as "
+"collaborators."
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr ""
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr ""
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr ""
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2112,7 +2178,9 @@
 
 #: kallithea/templates/admin/gists/edit.html:35
 #, python-format
-msgid "Gist was updated since you started editing. Copy your changes and click %(here)s to reload new version."
+msgid ""
+"Gist was updated since you started editing. Copy your changes and click "
+"%(here)s to reload new version."
 msgstr ""
 
 #: kallithea/templates/admin/gists/edit.html:36
@@ -2149,8 +2217,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 msgid "Never"
 msgstr ""
 
@@ -2183,7 +2253,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr ""
 
@@ -2219,23 +2289,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2263,7 +2335,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2323,7 +2395,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr ""
 
@@ -2336,24 +2408,29 @@
 msgid "Email Addresses"
 msgstr ""
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
-msgid "API Keys"
-msgstr ""
-
 #: kallithea/templates/admin/my_account/my_account.html:29
-msgid "Owned Repositories"
-msgstr ""
-
-#: kallithea/templates/admin/my_account/my_account.html:30
-#: kallithea/templates/journal/journal.html:33
-msgid "Watched Repositories"
+#: kallithea/templates/admin/users/user_edit.html:32
+msgid "SSH Keys"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
+msgid "API Keys"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:32
+msgid "Owned Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:33
+#: kallithea/templates/journal/journal.html:33
+msgid "Watched Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 msgid "Show Permissions"
 msgstr ""
 
@@ -2380,7 +2457,9 @@
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 msgid "Remove"
 msgstr ""
 
@@ -2396,12 +2475,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr ""
 
@@ -2501,6 +2582,42 @@
 msgid "Name"
 msgstr ""
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+msgid "Last Used"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, python-format
+msgid "Confirm to remove this SSH key: %s"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+msgid "New SSH key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+msgid "Public key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 msgid "Repositories You are Watching"
 msgstr ""
@@ -2517,7 +2634,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr ""
 
@@ -2531,11 +2648,16 @@
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:10
 #, python-format
-msgid "Allow access to Kallithea without needing to log in. Anonymous users use %s user permissions."
+msgid ""
+"Allow access to Kallithea without needing to log in. Anonymous users use "
+"%s user permissions."
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:19
-msgid "All default permissions on each repository will be reset to chosen permission, note that all custom default permission on repositories will be lost"
+msgid ""
+"All default permissions on each repository will be reset to chosen "
+"permission, note that all custom default permission on repositories will "
+"be lost"
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:20
@@ -2548,14 +2670,17 @@
 
 #: 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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:32
-msgid "All default permissions on each repository group will be reset to chosen permission, note that all custom default permission on repository groups will be lost"
+msgid ""
+"All default permissions on each repository group will be reset to chosen "
+"permission, note that all custom default permission on repository groups "
+"will be lost"
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:33
@@ -2572,7 +2697,10 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:45
-msgid "All default permissions on each user group will be reset to chosen permission, note that all custom default permission on user groups will be lost"
+msgid ""
+"All default permissions on each user group will be reset to chosen "
+"permission, note that all custom default permission on user groups will "
+"be lost"
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:46
@@ -2592,7 +2720,9 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:57
-msgid "Note: This will also give all users API access to create repositories everywhere. That might change in future versions."
+msgid ""
+"Note: This will also give all users API access to create repositories "
+"everywhere. That might change in future versions."
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:61
@@ -2600,7 +2730,10 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:64
-msgid "With this, write permission to a repository group allows creating repositories inside that group. Without this, group write permissions mean nothing."
+msgid ""
+"With this, write permission to a repository group allows creating "
+"repositories inside that group. Without this, group write permissions "
+"mean nothing."
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:68
@@ -2694,7 +2827,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr ""
 
@@ -2795,18 +2928,16 @@
 msgstr ""
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:92
-msgid "Set or revoke permission to all children of that group, including non-private repositories and other groups if selected."
-msgstr ""
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid "Enable lock-by-pulling on group. This option will be applied to all other groups and repositories inside"
-msgstr ""
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+msgid ""
+"Set or revoke permission to all children of that group, including non-"
+"private repositories and other groups if selected."
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Confirm to delete this group"
 msgstr ""
 
@@ -2828,17 +2959,19 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:16
-msgid "Optional: URL of a remote repository. If set, the repository will be created as a clone from this URL."
+msgid ""
+"Optional: URL of a remote repository. If set, the repository will be "
+"created as a clone from this URL."
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid "Keep it short and to the point. Use a README file for longer descriptions."
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr ""
@@ -2848,13 +2981,15 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:52
-msgid "Default revision for files page, downloads, full text search index and readme generation"
+msgid ""
+"Default revision for files page, downloads, full text search index and "
+"readme generation"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_creating.html:9
@@ -2868,11 +3003,15 @@
 
 #: kallithea/templates/admin/repos/repo_creating.html:27
 #, python-format
-msgid "Repository \"%(repo_name)s\" is being created, you will be redirected when this process is finished.repo_name"
+msgid ""
+"Repository \"%(repo_name)s\" is being created, you will be redirected "
+"when this process is finished.repo_name"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_creating.html:39
-msgid "We're sorry but error occurred during this operation. Please check your Kallithea server logs, or contact administrator."
+msgid ""
+"We're sorry but error occurred during this operation. Please check your "
+"Kallithea server logs, or contact administrator."
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit.html:8
@@ -2894,8 +3033,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr ""
 
@@ -2924,69 +3063,41 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:37
-msgid "All actions done in this repository will be visible to everyone in the public journal."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-msgid "Change Locking"
+msgid ""
+"All actions done in this repository will be visible to everyone in the "
+"public journal."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
+#: kallithea/templates/data_table/_dt_elements.html:68
+#, python-format
+msgid "Confirm to delete this repository: %s"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-msgid "Confirm to unlock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-msgid "Unlock Repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-msgid "Confirm to lock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-msgid "Lock Repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid "Force locking on the repository. Works only when anonymous access is disabled. Triggering a pull locks the repository.  The user who is pulling locks the repository; only the user who pulled and locked it can unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
-#: kallithea/templates/data_table/_dt_elements.html:68
-#, python-format
-msgid "Confirm to delete this repository: %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
 msgid "Delete this Repository"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
-msgid "The deleted repository will be moved away and hidden until the administrator expires it. The administrator can both permanently delete it or restore it."
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
+msgid ""
+"The deleted repository will be moved away and hidden until the "
+"administrator expires it. The administrator can both permanently delete "
+"it or restore it."
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_caches.html:4
@@ -2994,7 +3105,9 @@
 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."
+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
@@ -3077,47 +3190,44 @@
 msgid "This repository does not have a remote repository URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "Permanent Repository ID"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_settings.html:10
+msgid "Permanent URL"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
-"In case this repository is renamed or moved into another group the repository URL changes.\n"
-"                               Using the above permanent URL guarantees that this repository always will be accessible on that URL.\n"
-"                               This is useful for CI systems, or any other cases that you need to hardcode the URL into a 3rd party service."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+"In case this repository is renamed or moved into another group the "
+"repository URL changes.\n"
+"                               Using the above permanent URL guarantees "
+"that this repository always will be accessible on that URL.\n"
+"                               This is useful for CI systems, or any "
+"other cases that you need to hardcode the URL into a 3rd party service."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 msgid "Remote repository"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 msgid "Repository URL"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
-msgid "Optional: URL of a remote repository. If set, the repository can be pulled from this URL."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
+msgid ""
+"Optional: URL of a remote repository. If set, the repository can be "
+"pulled from this URL."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr ""
 
@@ -3199,7 +3309,12 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:22
-msgid "HTML (possibly with                         JavaScript and/or CSS) that will be added to the bottom                         of every page. This can be used for web analytics                         systems, but also to                         perform instance-specific customizations like adding a                         project banner at the top of every page."
+msgid ""
+"HTML (possibly with                         JavaScript and/or CSS) that "
+"will be added to the bottom                         of every page. This "
+"can be used for web analytics                         systems, but also "
+"to                         perform instance-specific customizations like "
+"adding a                         project banner at the top of every page."
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:32
@@ -3215,12 +3330,14 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:43
-msgid "Private key for reCaptcha system. Setting this value will enable captcha on registration."
+msgid ""
+"Private key for reCaptcha system. Setting this value will enable captcha "
+"on registration."
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 msgid "Save Settings"
 msgstr ""
 
@@ -3233,7 +3350,9 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_hooks.html:18
-msgid "Hooks can be used to trigger actions on certain events such as push / pull. They can trigger Python functions or external applications."
+msgid ""
+"Hooks can be used to trigger actions on certain events such as push / "
+"pull. They can trigger Python functions or external applications."
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_hooks.html:60
@@ -3249,7 +3368,9 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_mapping.html:12
-msgid "Check this option to remove all comments, pull requests and other records related to repositories that no longer exist in the filesystem."
+msgid ""
+"Check this option to remove all comments, pull requests and other records"
+" related to repositories that no longer exist in the filesystem."
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_mapping.html:17
@@ -3265,7 +3386,9 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_mapping.html:28
-msgid "Verify if Kallithea's Git hooks are installed for each repository. Current hooks will be updated to the latest version."
+msgid ""
+"Verify if Kallithea's Git hooks are installed for each repository. "
+"Current hooks will be updated to the latest version."
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_mapping.html:32
@@ -3273,7 +3396,10 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_mapping.html:35
-msgid "If installing Git hooks, overwrite any existing hooks, even if they do not seem to come from Kallithea. WARNING: This operation will destroy any custom git hooks you may have deployed by hand!"
+msgid ""
+"If installing Git hooks, overwrite any existing hooks, even if they do "
+"not seem to come from Kallithea. WARNING: This operation will destroy any"
+" custom git hooks you may have deployed by hand!"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_mapping.html:41
@@ -3289,7 +3415,9 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_search.html:12
-msgid "This option completely reindexeses all of the repositories for proper fulltext search capabilities."
+msgid ""
+"This option completely reindexeses all of the repositories for proper "
+"fulltext search capabilities."
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_search.html:18
@@ -3304,10 +3432,6 @@
 msgid "Kallithea version"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr ""
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr ""
@@ -3328,15 +3452,7 @@
 msgid "Git path"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr ""
 
@@ -3345,43 +3461,41 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
+msgid "Update repository after push (hg update)"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
-msgid "Update repository after push (hg update)"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:33
 msgid "Mercurial extensions"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr ""
 
+#: kallithea/templates/admin/settings/settings_vcs.html:35
+msgid ""
+"Requires hgsubversion library to be installed. Enables cloning of remote "
+"Subversion repositories while converting them to Mercurial."
+msgstr ""
+
 #: kallithea/templates/admin/settings/settings_vcs.html:47
-msgid "Requires hgsubversion library to be installed. Enables cloning of remote Subversion repositories while converting them to Mercurial."
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:59
 msgid "Location of repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
-msgid "Click to unlock. You must restart Kallithea in order to make this setting take effect."
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:68
-msgid "Filesystem location where repositories are stored. After changing this value, a restart and rescan of the repository folder are both required."
+#: kallithea/templates/admin/settings/settings_vcs.html:52
+msgid ""
+"Click to unlock. You must restart Kallithea in order to make this setting"
+" take effect."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:56
+msgid ""
+"Filesystem location where repositories are stored. After changing this "
+"value, a restart and rescan of the repository folder are both required."
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:4
@@ -3411,71 +3525,104 @@
 #: kallithea/templates/admin/settings/settings_visual.html:29
 msgid ""
 "Gravatar URL allows you to use another avatar server application.\n"
-"                                                        The following variables of the URL will be replaced accordingly.\n"
-"                                                        {scheme}    'http' or 'https' sent from running Kallithea server,\n"
-"                                                        {email}     user email,\n"
-"                                                        {md5email}  md5 hash of the user email (like at gravatar.com),\n"
-"                                                        {size}      size of the image that is expected from the server application,\n"
-"                                                        {netloc}    network location/server host of running Kallithea server"
+"                                                        The following "
+"variables of the URL will be replaced accordingly.\n"
+"                                                        {scheme}    "
+"'http' or 'https' sent from running Kallithea server,\n"
+"                                                        {email}     user "
+"email,\n"
+"                                                        {md5email}  md5 "
+"hash of the user email (like at gravatar.com),\n"
+"                                                        {size}      size "
+"of the image that is expected from the server application,\n"
+"                                                        {netloc}    "
+"network location/server host of running Kallithea server"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-msgid "Clone URL"
+msgid "HTTP Clone URL"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
 msgid ""
-"Schema of clone URL construction eg. '{scheme}://{user}@{netloc}/{repo}'.\n"
-"                                                    The following variables are available:\n"
-"                                                    {scheme} 'http' or 'https' sent from running Kallithea server,\n"
-"                                                    {user}   current user username,\n"
-"                                                    {netloc} network location/server host of running Kallithea server,\n"
-"                                                    {repo}   full repository name,\n"
-"                                                    {repoid} ID of repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
-msgid "Repository page size"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:57
-msgid "Number of items displayed in the repository pages before pagination is shown."
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:62
-msgid "Admin page size"
+"Schema of clone URL construction eg. '{scheme}://{user}@{netloc}/{repo}'."
+"\n"
+"                                                    The following "
+"variables are available:\n"
+"                                                    {scheme} 'http' or "
+"'https' sent from running Kallithea server,\n"
+"                                                    {user}   current user"
+" username,\n"
+"                                                    {netloc} network "
+"location/server host of running Kallithea server,\n"
+"                                                    {repo}   full "
+"repository name,\n"
+"                                                    {repoid} ID of "
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+msgid "SSH Clone URL"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. "
+"'ssh://{system_user}@{hostname}/{repo}'."
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:65
-msgid "Number of items displayed in the admin pages grids before pagination is shown."
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:70
-msgid "Icons"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:75
-msgid "Show public repository icon on repositories"
+msgid "Repository page size"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:68
+msgid ""
+"Number of items displayed in the repository pages before pagination is "
+"shown."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:73
+msgid "Admin page size"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:76
+msgid ""
+"Number of items displayed in the admin pages grids before pagination is "
+"shown."
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:81
+msgid "Icons"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:86
+msgid "Show public repository icon on repositories"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 msgid "Show public/private icons next to repository names."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:89
+#: kallithea/templates/admin/settings/settings_visual.html:100
 msgid "Meta Tagging"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
-msgid "Parses meta tags from the repository description field and turns them into colored tags."
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:105
+msgid ""
+"Parses meta tags from the repository description field and turns them "
+"into colored tags."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr ""
 
@@ -3634,11 +3781,11 @@
 msgid "Support"
 msgstr ""
 
-#: kallithea/templates/base/base.html:86 kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:86 kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr ""
 
-#: kallithea/templates/base/base.html:89 kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:89 kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr ""
 
@@ -3686,148 +3833,127 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr ""
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:178 kallithea/templates/forks/fork.html:9
+#: kallithea/templates/base/base.html:171 kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr ""
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr ""
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr ""
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr ""
 
+#: kallithea/templates/base/base.html:289
+msgid "Show recent activity"
+msgstr ""
+
+#: kallithea/templates/base/base.html:295
 #: kallithea/templates/base/base.html:296
-msgid "Show recent activity"
+msgid "Public journal"
+msgstr ""
+
+#: kallithea/templates/base/base.html:301
+msgid "Show public gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
-msgid "Public journal"
+msgid "Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:306
+msgid "All Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:308
-msgid "Show public gists"
+msgid "My Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:309
-msgid "Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:313
-msgid "All Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:315
-msgid "My Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:316
 msgid "My Private Gists"
 msgstr ""
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr ""
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 msgid "My Pull Requests"
 msgstr ""
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr ""
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 msgid "Login to Your Account"
 msgstr ""
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 msgid "Forgot password?"
 msgstr ""
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 msgid "Don't have an account?"
 msgstr ""
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr ""
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-msgid "Inherit defaults"
+msgid "Create repositories"
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid "Select to inherit global settings, IP whitelist and permissions from the %s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-msgid "default permissions"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 
@@ -4319,7 +4445,9 @@
 msgstr ""
 
 #: kallithea/templates/compare/compare_cs.html:15
-msgid "Please merge the target branch to your branch before creating a pull request."
+msgid ""
+"Please merge the target branch to your branch before creating a pull "
+"request."
 msgstr ""
 
 #: kallithea/templates/compare/compare_cs.html:19
@@ -4448,7 +4576,9 @@
 msgstr ""
 
 #: kallithea/templates/email_templates/password_reset.html:25
-msgid "This account is however managed outside this system and the password cannot be changed here."
+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
@@ -4456,11 +4586,15 @@
 msgstr ""
 
 #: kallithea/templates/email_templates/password_reset.html:33
-msgid "Should you not be able to use the link above, please type the following code into the password reset form"
+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
-msgid "If it weren't you who requested the password reset, just disregard this message."
+msgid ""
+"If it weren't you who requested the password reset, just disregard this "
+"message."
 msgstr ""
 
 #: kallithea/templates/email_templates/pull_request.html:4
@@ -4523,7 +4657,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr ""
@@ -4535,7 +4669,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr ""
 
@@ -4587,7 +4721,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr ""
 
@@ -4715,8 +4849,8 @@
 msgstr ""
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr ""
 
@@ -4767,8 +4901,8 @@
 msgstr ""
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr ""
 
@@ -4930,7 +5064,9 @@
 msgstr ""
 
 #: kallithea/templates/pullrequests/pullrequest_show.html:95
-msgid "This is just a range of changesets and doesn't have a target or a real merge ancestor."
+msgid ""
+"This is just a range of changesets and doesn't have a target or a real "
+"merge ancestor."
 msgstr ""
 
 #: kallithea/templates/pullrequests/pullrequest_show.html:103
@@ -4946,7 +5082,9 @@
 msgstr ""
 
 #: kallithea/templates/pullrequests/pullrequest_show.html:177
-msgid "Pull request iterations do not change content once created. Select a revision to create a new iteration."
+msgid ""
+"Pull request iterations do not change content once created. Select a "
+"revision to create a new iteration."
 msgstr ""
 
 #: kallithea/templates/pullrequests/pullrequest_show.html:187
@@ -5070,9 +5208,9 @@
 msgid "File names"
 msgstr ""
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr ""
 
@@ -5082,20 +5220,20 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr ""
 
@@ -5104,12 +5242,12 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr ""
 
@@ -5150,90 +5288,94 @@
 msgid "%s Summary"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr ""
-
+#: kallithea/templates/summary/summary.html:54
+msgid "Clone URL"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+msgid "Use Name"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:101
-msgid "There are no downloads yet"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:103
-msgid "Downloads are disabled for this repository"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:109
+msgid "There are no downloads yet"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:111
+msgid "Downloads are disabled for this repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 msgid "With subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 msgid "Latest Changes"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 msgid "Quick Start"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:188
-msgid "Add or upload files directly via Kallithea"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:196
-msgid "Push new repository"
+msgid "Add or upload files directly via Kallithea"
 msgstr ""
 
 #: kallithea/templates/summary/summary.html:204
+msgid "Push new repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr ""
--- a/kallithea/i18n/nb_NO/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/nb_NO/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,13 +1,10 @@
-# Translations template for Kallithea.
 # Copyright (C) 2017 Various authors, licensing as GPLv3
 # This file is distributed under the same license as the Kallithea project.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2017.
-#
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3.99\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\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/"
@@ -20,14 +17,14 @@
 "X-Generator: Weblate 3.6.1\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr "Ingen endringssett enda"
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -36,95 +33,95 @@
 msgid "None"
 msgstr "Ingen"
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr "(lukket)"
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr "Vis blanktegn"
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr "Ignorer blanktegn"
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr "Øk diff-bindeleddsinformasjon til %(num)s linjer"
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 #, fuzzy
 #| msgid "No permission to change pull request status"
 msgid "No permission to change status"
 msgstr "Ingen tilgang til endring av innsendingsforespørselsstatus"
 
-#: kallithea/controllers/changeset.py:214
+#: kallithea/controllers/changeset.py:212
 #, python-format
 msgid "Successfully deleted pull request %s"
 msgstr "Slettet flettingsforespørsel %s"
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr "En slik revisjon funnes ikke for denne pakkebrønnen"
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, python-format
 msgid "Could not find other repository %s"
 msgstr "Fant ikke annen pakkebrønn %s"
 
-#: kallithea/controllers/compare.py:72
+#: kallithea/controllers/compare.py:74
 msgid "Cannot compare repositories of different types"
 msgstr "Kan ikke sammenligne pakkebrønner av forskjellige typer"
 
-#: kallithea/controllers/compare.py:244
+#: kallithea/controllers/compare.py:246
 #, fuzzy
 msgid "Cannot show empty diff"
 msgstr "Kan ikke vise tom diff"
 
-#: kallithea/controllers/compare.py:246
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr ""
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr "Kan ikke sammenligne pakkebrønner uten bruk av felles opphav"
 
-#: kallithea/controllers/error.py:70
+#: kallithea/controllers/error.py:71
 msgid "No response"
 msgstr "Ingen respons"
 
-#: kallithea/controllers/error.py:71
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr "Ukjent feil"
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr ""
 "Forespørselen kunne ikke forstås av tjeneren som følge av feilaktig "
 "syntaks."
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr "Uautorisert tilgang til ressurs"
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr "Du har ikke tilgang til å se denne siden"
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr "Kunne ikke finne ressursen"
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
@@ -147,125 +144,119 @@
 msgid "Changeset was too big and was cut off..."
 msgstr "Endringsettet var for stort og har blitt avskåret…"
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, fuzzy, python-format
 msgid "%s %s feed"
 msgstr "%s %s kilde"
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, fuzzy, python-format
 msgid "Changes on %s repository"
 msgstr "Endringer i %s-pakkebrønn"
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr "Klikk her for å legge til ny fil"
 
-#: kallithea/controllers/files.py:93
+#: kallithea/controllers/files.py:86
 #, fuzzy
 #| msgid "There are no files yet. %s"
 msgid "There are no files yet."
 msgstr "Ingen filer enda. %s"
 
-#: kallithea/controllers/files.py:193
+#: kallithea/controllers/files.py:186
 #, fuzzy, python-format
 msgid "%s at %s"
 msgstr "%s den %s"
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr "Denne pakkebrønnen har blitt påst av %s den %s"
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 #, fuzzy
 msgid "You can only delete files with revision being a valid branch"
 msgstr ""
 "Du kan bare slette filer med en revisjon som er en gyldig forgrening"
 
-#: kallithea/controllers/files.py:322
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr "Slettet filen %s via Kallithea"
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr "Filen %s ble slettet"
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr "Feil inntraff under innsendelse"
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 msgid "You can only edit files with revision being a valid branch"
 msgstr ""
 "Du kan bare redigere filer med en revisjon som er en gyldig avgrening"
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr "Filen %s ble endret via Kallithea"
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr "Ingen endringer"
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr "Innsendt til %s"
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr "Fil lagt til via Kallithea"
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr "Inget innhold"
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr "Inget filnavn"
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr ""
 "Plasseringen må være en relativ sti, og kan ikke inneholde .. i stien"
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr "Nedlastinger avskrudd"
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr "Ukjent revisjon %s"
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr "Tom pakkebrønn"
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr "Ukjent arkivtype"
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr "Endringssett"
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
 msgstr "Forgreninger"
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr "Etiketter"
 
@@ -274,11 +265,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr "En uventet feil inntraff under forgrening av pakkebrønnen %s"
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr "Grupper"
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -286,11 +277,11 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr "Pakkebrønner"
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
@@ -298,169 +289,169 @@
 msgid "Branch"
 msgstr "Forgrening"
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr "Lukkede forgreninger"
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr "Etikett"
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr "Bokmerke"
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr "Offentlig loggbok"
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr "Loggbok"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 #, fuzzy
 msgid "Bad captcha"
 msgstr "Feilaktig CAPTCHA"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, 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:190
 msgid "A password reset confirmation code has been sent"
 msgstr "Passordbekreftelseskode sendt"
 
-#: kallithea/controllers/login.py:238
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Ugyldig passordtilbakestillingssymbol"
 
-#: kallithea/controllers/admin/my_account.py:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Passord oppdatert"
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, fuzzy, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr "Ugyldig analytiker \"%s\" angitt"
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr "%s (lukket)"
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr "Endringssett"
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 #, fuzzy
 msgid "Special"
 msgstr "Spesiell"
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr "Likemennsforgreninger"
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr "Bokmerker"
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr "Feil ved opprettelse av ny innsendelsesforespørsel: %s"
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr "Feil inntraff under opprettelse av innsendelsesforespørsel"
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr "Åpnet en ny innsendelsesforespørsel"
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 msgid "New pull request iteration created"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr "Ingen beskrivelse"
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
 msgstr "Innsendingsforespørsel oppdatert"
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr "Slettet innsendingsforespørsel"
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, python-format
 msgid "Revision %s not found in %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, python-format
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:522
+#: kallithea/controllers/pullrequests.py:520
 #, python-format
 msgid "This pull request has already been merged to %s."
 msgstr "Denne innsendingsforespørselen har allerede blitt flettet inn i %s."
 
-#: kallithea/controllers/pullrequests.py:524
+#: kallithea/controllers/pullrequests.py:522
 msgid "This pull request has been closed and can not be updated."
 msgstr ""
 "Denne innsendingsforespørselen har blitt lukket, og kan ikke oppdateres."
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, python-format
 msgid "The following additional changes are available on %s:"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 msgid "No additional changesets found for iterating on this pull request."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr "Merk: Forgreningen %s har et annet hode: %s."
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 msgid "Git pull requests don't support iterating yet."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, python-format
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 
@@ -476,21 +467,21 @@
 msgid "An error occurred during search operation."
 msgstr "Feil inntraff under søkeoperasjon."
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr "Ingen data klar enda"
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr "Statistikk er avskrudd for denne pakkebrønnen"
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr "Autentiseringsinnstillinger oppdatert"
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr "feil inntraff under oppdatering av autentiseringsinnstillinger"
 
@@ -502,127 +493,141 @@
 msgid "Error occurred during update of defaults"
 msgstr "Feil inntraff under oppdatering av forvalg"
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 msgid "Forever"
 msgstr "For alltid"
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
 #: kallithea/controllers/admin/users.py:249
 msgid "5 minutes"
 msgstr "Fem minutter"
 
-#: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
 #: kallithea/controllers/admin/users.py:250
 msgid "1 hour"
 msgstr "Én time"
 
-#: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
 #: kallithea/controllers/admin/users.py:251
 msgid "1 day"
 msgstr "Én dag"
 
-#: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr "Én måned"
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr "Livstid"
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr "Feil inntraff under gist-opprettelse"
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr "Slettet gist-en %s"
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
 msgstr "Uendret"
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr "Oppdaterte gist-innhold"
 
-#: kallithea/controllers/admin/gists.py:230
+#: kallithea/controllers/admin/gists.py:233
 msgid "Successfully updated gist data"
 msgstr "Oppdaterte gist-data"
 
-#: kallithea/controllers/admin/gists.py:233
+#: kallithea/controllers/admin/gists.py:236
 #, fuzzy, python-format
 msgid "Error occurred during update of gist %s"
 msgstr "Feil inntraff under oppdatering av gist-en %s"
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 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 "
 "programmet"
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr "Kontoen din ble oppdatert"
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, fuzzy, python-format
 msgid "Error occurred during update of user %s"
 msgstr "Feil inntraff under oppdatering av brukeren %s"
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr "Feil inntraff under oppdatering av brukerpassord"
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, fuzzy, python-format
 msgid "Added email %s to user"
 msgstr "La til e-postadressen %s for bruker"
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 #, fuzzy
 msgid "An error occurred during email saving"
 msgstr "Feil inntraff under lagring av e-postadresse"
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 #, fuzzy
 msgid "Removed email from user"
 msgstr "Fjernet e-postadresse fra bruker"
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr "API-nøkkel opprettet"
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr "API-nøkkel tilbakestilt"
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr "API-nøkkel slettet"
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, fuzzy, python-format
+#| msgid "API key successfully created"
+msgid "SSH key %s successfully added"
+msgstr "API-nøkkel opprettet"
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+#, fuzzy
+#| msgid "API key successfully deleted"
+msgid "SSH key successfully deleted"
+msgstr "API-nøkkel slettet"
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -630,9 +635,9 @@
 msgid "Read"
 msgstr "LEs"
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -640,9 +645,9 @@
 msgid "Write"
 msgstr "Skriv"
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -665,368 +670,353 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr "Admin"
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:50
 msgid "Disabled"
 msgstr "Avskrudd"
 
-#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:80
 msgid "Allowed with manual account activation"
 msgstr "Tillatt med manuell kontoaktivering"
 
-#: kallithea/controllers/admin/permissions.py:80
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr "Tillatt med automatisk kontoaktivering"
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr "Manuell aktivering av ekstern konto"
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr "Automatisk aktivering av ekstern konto"
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr "Påskrudd"
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 #, fuzzy
 msgid "Global permissions updated successfully"
 msgstr "Globale tilganger oppdatert"
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr "Feil inntraff under oppdatering av tilganger"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, 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:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr "Opprettet pakkebrønnsgruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Oppdaterte pakkebrønnsgruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, 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:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, 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:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, 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:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Fjernet pakkebrønnsgruppen %s"
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, 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:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 #, fuzzy
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Kan ikke tilbakekalle egen administratortilgang"
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr "Pakkebrønnsgruppetilganger oppdatert"
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr "En feil inntraff under tilbakekalling av tilgang"
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Feil under opprettelse av pakkebrønnen %s"
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Opprettet pakkebrønnen %s fra %s"
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Forgrenet pakkebrønnen %s som %s"
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr "Opprettet pakkebrønnen %s"
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Pakkebrønnen %s ble oppdatert"
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "Feil under oppdatering av pakkebrønnen %s"
 
-#: kallithea/controllers/admin/repos.py:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr "Avhektet %s forgreninger"
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr "Slettet %s forgreninger"
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Slettet pakkebrønnen %s"
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, 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:290
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "En feil inntraff under sletting av %s"
 
-#: kallithea/controllers/admin/repos.py:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr "Pakkebrønnstilganger oppdatert"
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:390
+#: kallithea/controllers/admin/repos.py:391
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:401
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr "Feil inntraff under fjerning av felt"
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr "-- Ikke en forgrening --"
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr "Oppdaterte pakkebrønnssynlighet i offentlig loggbok"
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 #, 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:466
+#: kallithea/controllers/admin/repos.py:468
 msgid "Nothing"
 msgstr "Ingenting"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:470
 #, 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:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr "En feil inntraff under denne operasjonen"
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-msgid "Repository has been locked"
-msgstr "Pakkebrønnen har blitt låst"
+#: kallithea/controllers/admin/repos.py:490
+msgid "Cache invalidation successful"
+msgstr ""
 
 #: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-msgid "Repository has been unlocked"
-msgstr "Pakkebrønnen har blitt låst opp"
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr "En feil inntraff under opplåsning"
-
-#: kallithea/controllers/admin/repos.py:528
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:532
 msgid "An error occurred during cache invalidation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:579
+#: kallithea/controllers/admin/repos.py:541
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr "Oppdaterte VCS-innstillinger"
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:180
+#: kallithea/controllers/admin/settings.py:176
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:192
+#: kallithea/controllers/admin/settings.py:188
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr "Skriv inn e-postadresse"
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "Ingen data klar enda"
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:357
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:363
+#: kallithea/controllers/admin/settings.py:360
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr "Opprettet brukergruppe %s"
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr "Oppdaterte brukergruppe %s"
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:217
+#: kallithea/controllers/admin/user_groups.py:212
 #, fuzzy
 msgid "Successfully deleted user group"
 msgstr "Brukergruppe slettet"
 
-#: kallithea/controllers/admin/user_groups.py:222
+#: kallithea/controllers/admin/user_groups.py:217
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr ""
 
@@ -1056,226 +1046,226 @@
 msgid "The default user cannot be edited"
 msgstr "Forvalgt bruker kan ikke redigeres"
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr "La til IP-adressen %s i brukerhvitlisten"
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr "Kunne ikke legge til IP-adresse"
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr "Fjernet IP-adressen fra brukerhvitlisten"
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr ""
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr "Ugyldig API-nøkkel"
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr ""
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, python-format
 msgid "Changeset for %s %s not found in %s"
 msgstr ""
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+msgid "SSH access is disabled."
+msgstr ""
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr "Binærfil"
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:625
+#: kallithea/lib/helpers.py:666
 #, python-format
 msgid "Changeset %s not found"
 msgstr ""
 
-#: kallithea/lib/helpers.py:674
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr ""
 
-#: kallithea/lib/helpers.py:725
+#: kallithea/lib/helpers.py:766
 #, python-format
 msgid "Fork name %s"
 msgstr "Forgreningsnavn %s"
 
-#: kallithea/lib/helpers.py:746
+#: kallithea/lib/helpers.py:787
 #, python-format
 msgid "Pull request %s"
 msgstr "Flettingsforespørsel %s"
 
-#: kallithea/lib/helpers.py:756
+#: kallithea/lib/helpers.py:797
 #, fuzzy
 msgid "[deleted] repository"
 msgstr "[slettet] pakkebrønn"
 
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
 #, fuzzy
 msgid "[created] repository"
 msgstr "[opprettet] pakkebrønn"
 
-#: kallithea/lib/helpers.py:760
+#: kallithea/lib/helpers.py:801
 msgid "[created] repository as fork"
 msgstr "[opprettet] pakkebrønn som forgrening"
 
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
 #, fuzzy
 msgid "[forked] repository"
 msgstr "[forgrenet] pakkebrønn"
 
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
 #, fuzzy
 msgid "[updated] repository"
 msgstr "[oppdaterte] pakkebrønn"
 
-#: kallithea/lib/helpers.py:766
+#: kallithea/lib/helpers.py:807
 #, fuzzy
 msgid "[downloaded] archive from repository"
 msgstr "[lastet ned] arkiv fra pakkebrønn"
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 #, fuzzy
 msgid "[delete] repository"
 msgstr "[slett] pakkebrønn"
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr "[opprettet] bruker"
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr "[oppdaterte] bruker"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr "[opprettet] brukergruppe"
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr "[oppdaterte] brukergruppe"
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 #, fuzzy
 msgid "[commented] on revision in repository"
 msgstr "[kommenterte] en revisjon i pakkebrønn"
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr "[kommenterte] flettingsforespørsel for"
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr "[lukket] flettingsforespørsel for"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr "[dyttet] til"
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 #, fuzzy
 msgid "[committed via Kallithea] into repository"
 msgstr "[innsendt via Kallithea] inn i pakkebrønn"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr ""
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "Ingen filer"
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr "ny fil"
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1283,69 +1273,96 @@
 "repositories"
 msgstr ""
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] "%d år"
 msgstr[1] "%d år"
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] "%d måned"
 msgstr[1] "%d måneder"
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] "%d dag"
-msgstr[1] "%ed dager"
-
-#: kallithea/lib/utils2.py:336
+msgstr[1] "%d dager"
+
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] "%d time"
 msgstr[1] "%d timer"
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] "%d minutt"
 msgstr[1] "%d minutter"
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] "%d sekund"
 msgstr[1] "%d sekunder"
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr "om %s"
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr "for %s siden"
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr "om %s og %s"
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s og %s siden"
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr "akkurat nå"
 
@@ -1354,134 +1371,134 @@
 msgid "on line %s"
 msgstr "på linje %s"
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr "toppnivå"
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr "Kallithea-administrator"
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 #, fuzzy
 msgid "Default user has no access to new repositories"
 msgstr "Forvalgt bruker har ingen tilgang til nye pakkebrønner"
 
-#: kallithea/model/db.py:1706
+#: kallithea/model/db.py:1640
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1707
+#: kallithea/model/db.py:1641
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1708
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1711
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1730
+#: kallithea/model/db.py:1664
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1732
+#: kallithea/model/db.py:1666
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 msgid "Not approved"
 msgstr "Ikke godkjent"
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr "Godkjent"
 
@@ -1507,302 +1524,313 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:169
+#, 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:170
 #, 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:171
-#, 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:184
+#: kallithea/model/notification.py:183
 msgid "Closing"
 msgstr "Lukker"
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 msgid "Cannot create empty pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 msgid "You are not authorized to create the pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 msgid "Missing changesets since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, python-format
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, python-format
 msgid ""
 "This iteration is based on another %s revision and there is no simple "
 "diff."
 msgstr ""
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, python-format
 msgid "No changes found on %s %s since previous iteration."
 msgstr ""
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr ""
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, python-format
+msgid "SSH key %r not found"
+msgstr ""
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:255
 #, 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:263
+#: kallithea/model/user.py:260
 #, 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:270
+#: kallithea/model/user.py:267
 #, 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:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr ""
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:72
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "Brukernavnet \"%(username)s\" finnes allerede"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:74
 #, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "Brukernavnet \"%(username)s\" kan ikke brukes"
 
-#: kallithea/model/validators.py:78
+#: kallithea/model/validators.py:76
 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:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr "Ugyldig brukergruppenavn"
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:132
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr "Brukergruppen \"%(usergroup)s\" finnes allerede"
 
-#: kallithea/model/validators.py:136
+#: kallithea/model/validators.py:134
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr ""
 
+#: kallithea/model/validators.py:175
+#, python-format
+msgid "Group \"%(group_name)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:177
 #, python-format
-msgid "Group \"%(group_name)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:179
-#, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr "Ugyldig gammelt passord"
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr "Passordene samsvarer ikke"
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 msgid "Invalid username or password"
 msgstr "Ugyldig brukernavn eller passord"
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr "Symbol stemmer ikke overens"
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr ""
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
-#: kallithea/model/validators.py:333
+#: kallithea/model/validators.py:318
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:419
+#: kallithea/model/validators.py:404
 msgid "Invalid repository URL"
 msgstr "Ugyldig pakkebrønnsnettadresse"
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:430
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:460
+#: kallithea/model/validators.py:445
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:512
+#: kallithea/model/validators.py:497
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:552
+#: kallithea/model/validators.py:537
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr "Dette er ikke en gyldig sti"
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 msgid "This email address is already in use"
 msgstr "E-postadressen er allerede i bruk"
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, fuzzy, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "Fant ikke e-postadressen \"%(email)s\""
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 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:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr "Skriv inn en gyldig IPv4- eller IPv6-adresse"
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:765
+#: kallithea/model/validators.py:750
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1844,24 +1872,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr "Beskrivelse"
 
@@ -1878,7 +1912,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1886,11 +1920,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr "Eier"
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr "Logg inn"
@@ -1905,7 +1939,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1913,7 +1947,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr "Passord"
@@ -2075,10 +2109,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr "Handling"
@@ -2128,22 +2164,22 @@
 msgstr "Programtillegg"
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr "Lagre"
 
@@ -2161,14 +2197,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr "Privat pakkebrønn"
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2176,36 +2212,25 @@
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr "Skru på statistikk"
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr "Skru på nedlastinger"
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr "Skru på nedlastingsmeny på sammendragsside."
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr "Skru på låsing"
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr ""
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2252,8 +2277,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 msgid "Never"
 msgstr "Aldri"
 
@@ -2286,7 +2313,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr ""
 
@@ -2322,23 +2349,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2366,7 +2395,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2426,7 +2455,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr "Min konto"
 
@@ -2439,24 +2468,31 @@
 msgid "Email Addresses"
 msgstr "E-postadresser"
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
+#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/users/user_edit.html:32
+#, fuzzy
+#| msgid "API Keys"
+msgid "SSH Keys"
+msgstr "API-nøkler"
+
+#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
 msgid "API Keys"
 msgstr "API-nøkler"
 
-#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/my_account/my_account.html:32
 msgid "Owned Repositories"
 msgstr "Eide pakkebrønner"
 
-#: kallithea/templates/admin/my_account/my_account.html:30
+#: kallithea/templates/admin/my_account/my_account.html:33
 #: kallithea/templates/journal/journal.html:33
 msgid "Watched Repositories"
 msgstr ""
 
-#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 msgid "Show Permissions"
 msgstr ""
 
@@ -2483,7 +2519,9 @@
 msgstr "Bekreft fjerning av denne API-nøklen: %s"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 msgid "Remove"
 msgstr "Fjern"
 
@@ -2499,12 +2537,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr "Legg til"
 
@@ -2605,6 +2645,47 @@
 msgid "Name"
 msgstr "Navn"
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+#, fuzzy
+#| msgid "Last Name"
+msgid "Last Used"
+msgstr "Etternavn"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, fuzzy, python-format
+#| msgid "Confirm to remove this API key: %s"
+msgid "Confirm to remove this SSH key: %s"
+msgstr "Bekreft fjerning av denne API-nøklen: %s"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+#, fuzzy
+#| msgid "New API key"
+msgid "New SSH key"
+msgstr "Ny API-nøkkel"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+msgid "Public key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 msgid "Repositories You are Watching"
 msgstr "Pakkebrønner du holder oppsyn med"
@@ -2621,7 +2702,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr "IP-hvitliste"
 
@@ -2657,7 +2738,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2817,7 +2898,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr "Avansert"
 
@@ -2923,17 +3004,11 @@
 "private repositories and other groups if selected."
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
 msgstr "Fjern denne gruppen"
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Confirm to delete this group"
 msgstr "Bekreft sletting av denne gruppen"
 
@@ -2961,14 +3036,14 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr ""
@@ -2978,7 +3053,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr ""
@@ -3030,8 +3105,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr "Statistikk"
 
@@ -3065,69 +3140,32 @@
 "public journal."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-msgid "Change Locking"
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
+#: kallithea/templates/data_table/_dt_elements.html:68
+#, python-format
+msgid "Confirm to delete this repository: %s"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-msgid "Confirm to unlock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-msgid "Unlock Repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-msgid "Confirm to lock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-msgid "Lock Repository"
-msgstr "Lås pakkebrønn"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr "Pakkebrønnen er ikke låst"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
-#: kallithea/templates/data_table/_dt_elements.html:68
-#, python-format
-msgid "Confirm to delete this repository: %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
 msgid "Delete this Repository"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
 msgstr[0] "Denne pakkebrønnen har %s forgrening"
 msgstr[1] "Denne pakkebrønnen har %s forgreninger"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr "Slett forgreninger"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3224,20 +3262,11 @@
 msgid "This repository does not have a remote repository URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "Permanent Repository ID"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-#, fuzzy
-msgid "URL by id"
-msgstr "Nettadresse etter ID"
-
 #: kallithea/templates/admin/repos/repo_edit_settings.html:10
+msgid "Permanent URL"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3247,30 +3276,30 @@
 "other cases that you need to hardcode the URL into a 3rd party service."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 msgid "Remote repository"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 msgid "Repository URL"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr "Skriv inn brukerens navn"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr ""
 
@@ -3380,8 +3409,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 msgid "Save Settings"
 msgstr "Lagre innstillinger"
 
@@ -3476,10 +3505,6 @@
 msgid "Kallithea version"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr ""
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr ""
@@ -3500,15 +3525,7 @@
 msgid "Git path"
 msgstr "Git-sti"
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr "Python-pakker"
 
@@ -3517,46 +3534,38 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
+msgid "Update repository after push (hg update)"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
-msgid "Update repository after push (hg update)"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:33
 msgid "Mercurial extensions"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr ""
 
+#: kallithea/templates/admin/settings/settings_vcs.html:35
+msgid ""
+"Requires hgsubversion library to be installed. Enables cloning of remote "
+"Subversion repositories while converting them to Mercurial."
+msgstr ""
+
 #: kallithea/templates/admin/settings/settings_vcs.html:47
-msgid ""
-"Requires hgsubversion library to be installed. Enables cloning of remote "
-"Subversion repositories while converting them to Mercurial."
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:59
 msgid "Location of repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3605,9 +3614,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
 #, fuzzy
-msgid "Clone URL"
+msgid "HTTP Clone URL"
 msgstr "Kloningsnettadresse"
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
@@ -3625,56 +3633,72 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+#, fuzzy
+msgid "SSH Clone URL"
+msgstr "Kloningsnettadresse"
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 msgid "Repository page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:57
+#: kallithea/templates/admin/settings/settings_visual.html:68
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:62
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:70
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:81
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 msgid "Show public/private icons next to repository names."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:89
+#: kallithea/templates/admin/settings/settings_visual.html:100
 msgid "Meta Tagging"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr ""
 
@@ -3835,12 +3859,12 @@
 msgstr "Støtte"
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr "Merkurial-pakkebrønn"
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr "Git-pakkebrønn"
 
@@ -3890,160 +3914,135 @@
 msgstr "Sammenlign"
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr "Søk"
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr "Lås opp"
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr "Lås"
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr "Følg"
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr "Forgren"
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 #, fuzzy
 msgid "Create Pull Request"
 msgstr "Opprett flettingsorespørsel"
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr "Bytt til"
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr ""
 
-#: kallithea/templates/base/base.html:296
+#: kallithea/templates/base/base.html:289
 msgid "Show recent activity"
 msgstr "Vis nylig aktivitet"
 
-#: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
+#: kallithea/templates/base/base.html:295
+#: kallithea/templates/base/base.html:296
 msgid "Public journal"
 msgstr ""
 
-#: kallithea/templates/base/base.html:308
+#: kallithea/templates/base/base.html:301
 #, fuzzy
 msgid "Show public gists"
 msgstr "Vis offentlige Gist-er"
 
-#: kallithea/templates/base/base.html:309
+#: kallithea/templates/base/base.html:302
 #, fuzzy
 msgid "Gists"
 msgstr "Gist-er"
 
-#: kallithea/templates/base/base.html:313
+#: kallithea/templates/base/base.html:306
 msgid "All Public Gists"
 msgstr "Alle offentlige Gist-er"
 
-#: kallithea/templates/base/base.html:315
+#: kallithea/templates/base/base.html:308
 msgid "My Public Gists"
 msgstr "Mine offentlige Gist-er"
 
-#: kallithea/templates/base/base.html:316
+#: kallithea/templates/base/base.html:309
 msgid "My Private Gists"
 msgstr "Mine private Gist-er"
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 #, fuzzy
 msgid "Search in repositories"
 msgstr "Søk i pakkebrønner"
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 #, fuzzy
 msgid "My Pull Requests"
 msgstr "Mine flettingsforespørsler"
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr "Ikke innlogget"
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 #, fuzzy
 msgid "Login to Your Account"
 msgstr "Logg in på kontoen din"
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 msgid "Forgot password?"
 msgstr "Glemt passordet?"
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 msgid "Don't have an account?"
 msgstr "Mangler du konto?"
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr "Logg ut"
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-msgid "Inherit defaults"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-#, fuzzy
-#| msgid "Default Permissions"
-msgid "default permissions"
-msgstr "Forvalgte tilganger"
-
-#: kallithea/templates/base/default_perms_box.html:23
 #, fuzzy
 msgid "Create repositories"
 msgstr "Opprett pakkebrønner"
 
-#: kallithea/templates/base/default_perms_box.html:27
+#: kallithea/templates/base/default_perms_box.html:15
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 
@@ -4756,7 +4755,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr ""
@@ -4768,7 +4767,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr ""
 
@@ -4820,7 +4819,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr ""
 
@@ -4948,8 +4947,8 @@
 msgstr ""
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr ""
 
@@ -5000,8 +4999,8 @@
 msgstr ""
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr ""
 
@@ -5307,9 +5306,9 @@
 msgid "File names"
 msgstr ""
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr ""
 
@@ -5319,20 +5318,20 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr ""
 
@@ -5341,12 +5340,12 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr ""
 
@@ -5387,94 +5386,143 @@
 msgid "%s Summary"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr ""
-
+#: kallithea/templates/summary/summary.html:54
+#, fuzzy
+msgid "Clone URL"
+msgstr "Kloningsnettadresse"
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+#, fuzzy
+#| msgid "Last Name"
+msgid "Use Name"
+msgstr "Etternavn"
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:101
-msgid "There are no downloads yet"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:103
-msgid "Downloads are disabled for this repository"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:109
+msgid "There are no downloads yet"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:111
+msgid "Downloads are disabled for this repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 msgid "With subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 msgid "Latest Changes"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 msgid "Quick Start"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:188
-msgid "Add or upload files directly via Kallithea"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:196
-msgid "Push new repository"
+msgid "Add or upload files directly via Kallithea"
 msgstr ""
 
 #: kallithea/templates/summary/summary.html:204
+msgid "Push new repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr ""
 
+#~ msgid "This repository has been locked by %s on %s"
+#~ msgstr "Denne pakkebrønnen har blitt påst av %s den %s"
+
+#~ msgid "Repository has been locked"
+#~ msgstr "Pakkebrønnen har blitt låst"
+
+#~ msgid "Repository has been unlocked"
+#~ msgstr "Pakkebrønnen har blitt låst opp"
+
+#~ msgid "An error occurred during unlocking"
+#~ msgstr "En feil inntraff under opplåsning"
+
+#~ msgid "Invalid API key"
+#~ msgstr "Ugyldig API-nøkkel"
+
+#~ msgid "Token mismatch"
+#~ msgstr "Symbol stemmer ikke overens"
+
+#~ msgid "Enable locking"
+#~ msgstr "Skru på låsing"
+
+#~ msgid "Lock Repository"
+#~ msgstr "Lås pakkebrønn"
+
+#~ msgid "Repository is not locked"
+#~ msgstr "Pakkebrønnen er ikke låst"
+
+#, fuzzy
+#~ msgid "URL by id"
+#~ msgstr "Nettadresse etter ID"
+
+#~ msgid "Unlock"
+#~ msgstr "Lås opp"
+
+#~ msgid "Lock"
+#~ msgstr "Lås"
+
+#, fuzzy
+#~| msgid "Default Permissions"
+#~ msgid "default permissions"
+#~ msgstr "Forvalgte tilganger"
+
 #~ msgid "There is no index to search in. Please run whoosh indexer"
 #~ msgstr "Det er ingen indeks å søke i. Kjør en annen whoosh-indekserer"
 
--- a/kallithea/i18n/nl_BE/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/nl_BE/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,33 +1,31 @@
-# Dutch (Belgium) translations for Kallithea.
 # Copyright (C) 2014 Various authors, licensing as GPLv3
 # This file is distributed under the same license as the Kallithea project.
-# Automatically generated, 2014.
 # #, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
-"PO-Revision-Date: 2017-06-18 16:22+0000\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\n"
+"PO-Revision-Date: 2019-10-05 19:28+0000\n"
 "Last-Translator: Thomas De Schampheleire <patrickdepinguin@gmail.com>\n"
-"Language-Team: Dutch (Belgium) <https://hosted.weblate.org/projects/"
-"kallithea/kallithea/nl_BE/>\n"
+"Language-Team: Flemish <https://hosted.weblate.org/projects/kallithea/"
+"kallithea/nl_BE/>\n"
 "Language: nl_BE\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 2.15-dev\n"
+"X-Generator: Weblate 3.9-dev\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr "Er zijn nog geen changesets"
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -36,100 +34,95 @@
 msgid "None"
 msgstr "Geen"
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr "(gesloten)"
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr "Toon witruimtes"
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 #, fuzzy
 msgid "Ignore whitespace"
 msgstr "Negeer witruimtes"
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr "Vergroot de diff context tot %(num)s lijnen"
 
-#: kallithea/controllers/changeset.py:203
-#, fuzzy
+#: kallithea/controllers/changeset.py:201
 msgid "No permission to change status"
-msgstr "Selecteer de changeset"
-
-#: kallithea/controllers/changeset.py:214
+msgstr "Geen toestemming om de status te veranderen"
+
+#: kallithea/controllers/changeset.py:212
 #, python-format
 msgid "Successfully deleted pull request %s"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr "Deze revisie bestaat niet in deze repository"
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, python-format
 msgid "Could not find other repository %s"
 msgstr ""
 
-#: kallithea/controllers/compare.py:72
-#, fuzzy
-#| msgid "Cannot compare repositories without using common ancestor"
+#: kallithea/controllers/compare.py:74
 msgid "Cannot compare repositories of different types"
-msgstr ""
-"Kan geen repositories vergelijken zonder een gemeenschappelijke voorouder "
-"te gebruiken"
-
-#: kallithea/controllers/compare.py:244
-msgid "Cannot show empty diff"
-msgstr ""
+msgstr "Kan geen repositories van verschillende types vergelijken"
 
 #: kallithea/controllers/compare.py:246
+msgid "Cannot show empty diff"
+msgstr "Kan geen lege diff tonen"
+
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr ""
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr ""
 "Kan geen repositories vergelijken zonder een gemeenschappelijke voorouder "
 "te gebruiken"
 
-#: kallithea/controllers/error.py:70
+#: kallithea/controllers/error.py:71
 msgid "No response"
 msgstr "Geen antwoord"
 
-#: kallithea/controllers/error.py:71
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr "Ongekende fout"
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr ""
 "De aanvraag kon niet door de server begrepen worden wegens incorrecte "
 "syntax."
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr "Ongeautoriseerde toegang tot resource"
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr "U hebt geen permissie om deze pagina te bekijken"
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr "De resource kon niet gevonden worden"
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
@@ -151,123 +144,115 @@
 msgid "Changeset was too big and was cut off..."
 msgstr "De changeset was te groot en werd afgekort..."
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr "%s %s feed"
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
 msgstr "Veranderingen in repository %s"
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr "Klik hier om een nieuw bestand toe te voegen"
 
-#: kallithea/controllers/files.py:93
-#, fuzzy
-#| msgid "There are no files yet. %s"
+#: kallithea/controllers/files.py:86
 msgid "There are no files yet."
-msgstr "Er zijn nog geen bestanden. %s"
-
-#: kallithea/controllers/files.py:193
+msgstr "Er zijn nog geen bestanden."
+
+#: kallithea/controllers/files.py:186
 #, python-format
 msgid "%s at %s"
 msgstr "%s op %s"
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr "Deze repository is gelocket door %s op %s"
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 msgid "You can only delete files with revision being a valid branch"
 msgstr ""
 "Men kan enkel bestanden verwijderen als de revisie een geldige branch is"
 
-#: kallithea/controllers/files.py:322
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr "Bestand %s verwijderd via Kallithea"
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr "Bestand %s succesvol verwijderd"
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr "Er trad een fout op tijdens het committeren"
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 msgid "You can only edit files with revision being a valid branch"
 msgstr ""
 "Men kan enkel bestanden wijzigen als de revisie een geldige branch is"
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr "Bestand %s gewijzigd via Kallithea"
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr "Geen wijzigingen"
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr "Succesvol gecommitteerd naar %s"
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr "Bestand toegevoegd via Kallithea"
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr "Geen inhoud"
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr "Geen bestandsnaam"
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr "De locatie moet een relatief pad zijn en mag geen .. bevatten"
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr "Downloads uitgeschakeld"
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr "Ongekende revisie %s"
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr "Lege repository"
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr "Ongekende archieftype"
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr "Changesets"
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
 msgstr "Branches"
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr "Tags"
 
@@ -276,11 +261,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr "Er is een fout opgetreden tijdens het forken van de repository %s"
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr "Groepen"
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -288,177 +273,177 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr "Repositories"
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
 msgstr "Branch"
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr "Gesloten branches"
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr "Tag"
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr "Bladwijzer"
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr "Publiek logboek"
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr "Logboek"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
 msgstr "Incorrecte captcha"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, 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:190
 msgid "A password reset confirmation code has been sent"
 msgstr "Een paswoordherstel bevestigingscode is verzonden"
 
-#: kallithea/controllers/login.py:238
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Ongeldig paswoordherstel token"
 
-#: kallithea/controllers/admin/my_account.py:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Paswoord succesvol aangepast"
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr "Changeset"
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr "Bijzonder"
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 msgid "New pull request iteration created"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, python-format
 msgid "Revision %s not found in %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, python-format
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr ""
 
+#: kallithea/controllers/pullrequests.py:520
+#, python-format
+msgid "This pull request has already been merged to %s."
+msgstr ""
+
 #: kallithea/controllers/pullrequests.py:522
-#, python-format
-msgid "This pull request has already been merged to %s."
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:524
 msgid "This pull request has been closed and can not be updated."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, python-format
 msgid "The following additional changes are available on %s:"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 msgid "No additional changesets found for iterating on this pull request."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 msgid "Git pull requests don't support iterating yet."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, python-format
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 
@@ -474,21 +459,21 @@
 msgid "An error occurred during search operation."
 msgstr ""
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr ""
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -500,123 +485,134 @@
 msgid "Error occurred during update of defaults"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 msgid "Forever"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
-#: kallithea/controllers/admin/users.py:249
-msgid "5 minutes"
-msgstr ""
-
 #: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
-#: kallithea/controllers/admin/users.py:250
-msgid "1 hour"
+#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/users.py:249
+msgid "5 minutes"
 msgstr ""
 
 #: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
-#: kallithea/controllers/admin/users.py:251
-msgid "1 day"
+#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/users.py:250
+msgid "1 hour"
 msgstr ""
 
 #: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/my_account.py:235
+#: kallithea/controllers/admin/users.py:251
+msgid "1 day"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:230
-msgid "Successfully updated gist data"
-msgstr ""
-
 #: kallithea/controllers/admin/gists.py:233
+msgid "Successfully updated gist data"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, python-format
+msgid "SSH key %s successfully added"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+msgid "SSH key successfully deleted"
+msgstr "SSH key succesvol verwijderd"
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -624,9 +620,9 @@
 msgid "Read"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -634,9 +630,9 @@
 msgid "Write"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -659,361 +655,345 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
-#: kallithea/templates/admin/auth/auth_settings.html:42
-#: kallithea/templates/base/root.html:50
-msgid "Disabled"
-msgstr ""
-
 #: kallithea/controllers/admin/permissions.py:78
-msgid "Allowed with manual account activation"
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
+#: kallithea/templates/admin/auth/auth_settings.html:42
+#: kallithea/templates/base/root.html:50
+msgid "Disabled"
 msgstr ""
 
 #: kallithea/controllers/admin/permissions.py:80
+msgid "Allowed with manual account activation"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:290
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:390
-#, fuzzy, python-format
-#| msgid "An error occurred during repository forking %s"
+#: kallithea/controllers/admin/repos.py:391
+#, python-format
 msgid "An error occurred during creation of field: %r"
-msgstr "Er is een fout opgetreden tijdens het forken van de repository %s"
-
-#: kallithea/controllers/admin/repos.py:401
+msgstr "Er is een fout opgetreden tijdens het aanmaken van veld: %r"
+
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:466
-msgid "Nothing"
-msgstr ""
-
 #: kallithea/controllers/admin/repos.py:468
+msgid "Nothing"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:470
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-msgid "Repository has been locked"
+#: kallithea/controllers/admin/repos.py:490
+msgid "Cache invalidation successful"
 msgstr ""
 
 #: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-msgid "Repository has been unlocked"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:528
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:532
 msgid "An error occurred during cache invalidation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:579
+#: kallithea/controllers/admin/repos.py:541
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:180
+#: kallithea/controllers/admin/settings.py:176
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:192
+#: kallithea/controllers/admin/settings.py:188
 #, python-format
 msgid "Invalidated %s repositories"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 msgid "Hook already exists"
 msgstr ""
 
+#: kallithea/controllers/admin/settings.py:357
+msgid "Builtin hooks are read-only. Please use another hook name."
+msgstr ""
+
 #: kallithea/controllers/admin/settings.py:360
-msgid "Builtin hooks are read-only. Please use another hook name."
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:363
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
+#: kallithea/controllers/admin/user_groups.py:212
+msgid "Successfully deleted user group"
+msgstr ""
+
 #: kallithea/controllers/admin/user_groups.py:217
-msgid "Successfully deleted user group"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:222
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr ""
 
@@ -1043,219 +1023,218 @@
 msgid "The default user cannot be edited"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr ""
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr ""
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr ""
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, python-format
 msgid "Changeset for %s %s not found in %s"
 msgstr ""
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+msgid "SSH access is disabled."
+msgstr ""
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr ""
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:625
-#, fuzzy, python-format
-#| msgid "Set changeset status"
+#: kallithea/lib/helpers.py:666
+#, python-format
 msgid "Changeset %s not found"
-msgstr "Selecteer de changeset"
-
-#: kallithea/lib/helpers.py:674
+msgstr "Changeset %s werd niet gevonden"
+
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr ""
 
-#: kallithea/lib/helpers.py:725
-#, python-format
-msgid "Fork name %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:746
-#, python-format
-msgid "Pull request %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:756
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:760
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
-msgid "[updated] repository"
-msgstr ""
-
 #: kallithea/lib/helpers.py:766
+#, python-format
+msgid "Fork name %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:787
+#, python-format
+msgid "Pull request %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:797
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
+msgid "[created] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:801
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
+msgid "[updated] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr ""
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr ""
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr ""
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1263,69 +1242,96 @@
 "repositories"
 msgstr ""
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr ""
 
@@ -1334,133 +1340,133 @@
 msgid "on line %s"
 msgstr ""
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1706
+#: kallithea/model/db.py:1640
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1707
+#: kallithea/model/db.py:1641
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1708
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1711
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1730
+#: kallithea/model/db.py:1664
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1732
+#: kallithea/model/db.py:1666
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr ""
 
@@ -1486,302 +1492,313 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:169
+#, 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:170
 #, 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:171
-#, 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:184
+#: kallithea/model/notification.py:183
 msgid "Closing"
 msgstr ""
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 msgid "Cannot create empty pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 msgid "You are not authorized to create the pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 msgid "Missing changesets since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, python-format
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, python-format
 msgid ""
 "This iteration is based on another %s revision and there is no simple "
 "diff."
 msgstr ""
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, python-format
 msgid "No changes found on %s %s since previous iteration."
 msgstr ""
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr ""
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, python-format
+msgid "SSH key %r not found"
+msgstr "SSH key %r werd niet gevonden"
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:255
 #, 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:263
+#: kallithea/model/user.py:260
 #, 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:270
+#: kallithea/model/user.py:267
 #, 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:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr ""
 
+#: kallithea/model/validators.py:72
+#, python-format
+msgid "Username \"%(username)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:74
 #, python-format
-msgid "Username \"%(username)s\" already exists"
+msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
 #: kallithea/model/validators.py:76
-#, python-format
-msgid "Username \"%(username)s\" cannot be used"
-msgstr ""
-
-#: kallithea/model/validators.py:78
 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:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr ""
 
+#: kallithea/model/validators.py:132
+#, python-format
+msgid "User group \"%(usergroup)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:134
-#, python-format
-msgid "User group \"%(usergroup)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:136
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr ""
 
+#: kallithea/model/validators.py:175
+#, python-format
+msgid "Group \"%(group_name)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:177
 #, python-format
-msgid "Group \"%(group_name)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:179
-#, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 msgid "Invalid username or password"
 msgstr ""
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr ""
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr ""
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
-#: kallithea/model/validators.py:333
+#: kallithea/model/validators.py:318
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:419
+#: kallithea/model/validators.py:404
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:430
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:460
+#: kallithea/model/validators.py:445
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:512
+#: kallithea/model/validators.py:497
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:552
+#: kallithea/model/validators.py:537
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 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:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:765
+#: kallithea/model/validators.py:750
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1822,24 +1839,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr ""
 
@@ -1856,7 +1879,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1864,11 +1887,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr ""
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr ""
@@ -1883,7 +1906,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1891,7 +1914,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr ""
@@ -2047,10 +2070,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr ""
@@ -2099,22 +2124,22 @@
 msgstr ""
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr ""
 
@@ -2132,14 +2157,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2147,36 +2172,25 @@
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr ""
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr ""
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr ""
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2223,8 +2237,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 msgid "Never"
 msgstr ""
 
@@ -2257,7 +2273,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr ""
 
@@ -2293,23 +2309,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2337,7 +2355,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2397,7 +2415,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr ""
 
@@ -2410,24 +2428,29 @@
 msgid "Email Addresses"
 msgstr ""
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
-msgid "API Keys"
-msgstr ""
-
 #: kallithea/templates/admin/my_account/my_account.html:29
-msgid "Owned Repositories"
-msgstr ""
-
-#: kallithea/templates/admin/my_account/my_account.html:30
-#: kallithea/templates/journal/journal.html:33
-msgid "Watched Repositories"
+#: kallithea/templates/admin/users/user_edit.html:32
+msgid "SSH Keys"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
+msgid "API Keys"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:32
+msgid "Owned Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:33
+#: kallithea/templates/journal/journal.html:33
+msgid "Watched Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 msgid "Show Permissions"
 msgstr ""
 
@@ -2454,7 +2477,9 @@
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 msgid "Remove"
 msgstr ""
 
@@ -2470,12 +2495,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr ""
 
@@ -2576,6 +2603,42 @@
 msgid "Name"
 msgstr ""
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+msgid "Last Used"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, python-format
+msgid "Confirm to remove this SSH key: %s"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+msgid "New SSH key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+msgid "Public key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 msgid "Repositories You are Watching"
 msgstr ""
@@ -2592,7 +2655,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr ""
 
@@ -2628,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2788,7 +2851,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr ""
 
@@ -2843,10 +2906,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
-#, fuzzy
-#| msgid "No response"
 msgid "Add repos"
-msgstr "Geen antwoord"
+msgstr "Repositories toevoegen"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10
 msgid "Add/Edit groups"
@@ -2896,17 +2957,11 @@
 "private repositories and other groups if selected."
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Confirm to delete this group"
 msgstr ""
 
@@ -2934,14 +2989,14 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr ""
@@ -2951,7 +3006,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr ""
@@ -3003,8 +3058,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr ""
 
@@ -3038,69 +3093,32 @@
 "public journal."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-msgid "Change Locking"
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
+#: kallithea/templates/data_table/_dt_elements.html:68
+#, python-format
+msgid "Confirm to delete this repository: %s"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-msgid "Confirm to unlock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-msgid "Unlock Repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-msgid "Confirm to lock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-msgid "Lock Repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
-#: kallithea/templates/data_table/_dt_elements.html:68
-#, python-format
-msgid "Confirm to delete this repository: %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
 msgid "Delete this Repository"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
 msgstr[0] ""
 msgstr[1] ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3178,10 +3196,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_remote.html:4
-#, fuzzy
-#| msgid "Empty repository"
 msgid "Fork of repository"
-msgstr "Lege repository"
+msgstr "Fork van repository"
 
 #: kallithea/templates/admin/repos/repo_edit_remote.html:7
 msgid "Remote repository URL"
@@ -3199,19 +3215,11 @@
 msgid "This repository does not have a remote repository URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "Permanent Repository ID"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_settings.html:10
+msgid "Permanent URL"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3221,30 +3229,30 @@
 "other cases that you need to hardcode the URL into a 3rd party service."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 msgid "Remote repository"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 msgid "Repository URL"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr ""
 
@@ -3353,8 +3361,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 msgid "Save Settings"
 msgstr ""
 
@@ -3449,10 +3457,6 @@
 msgid "Kallithea version"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr ""
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr ""
@@ -3473,15 +3477,7 @@
 msgid "Git path"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr ""
 
@@ -3490,46 +3486,38 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
+msgid "Update repository after push (hg update)"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
-msgid "Update repository after push (hg update)"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:33
 msgid "Mercurial extensions"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr ""
 
+#: kallithea/templates/admin/settings/settings_vcs.html:35
+msgid ""
+"Requires hgsubversion library to be installed. Enables cloning of remote "
+"Subversion repositories while converting them to Mercurial."
+msgstr ""
+
 #: kallithea/templates/admin/settings/settings_vcs.html:47
-msgid ""
-"Requires hgsubversion library to be installed. Enables cloning of remote "
-"Subversion repositories while converting them to Mercurial."
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:59
 msgid "Location of repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3578,8 +3566,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-msgid "Clone URL"
+msgid "HTTP Clone URL"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
@@ -3597,58 +3584,71 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
-#, fuzzy
-#| msgid "Repositories"
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+msgid "SSH Clone URL"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 msgid "Repository page size"
-msgstr "Repositories"
-
-#: kallithea/templates/admin/settings/settings_visual.html:57
+msgstr "Repository paginagrootte"
+
+#: kallithea/templates/admin/settings/settings_visual.html:68
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:62
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:70
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:81
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 msgid "Show public/private icons next to repository names."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:89
+#: kallithea/templates/admin/settings/settings_visual.html:100
 msgid "Meta Tagging"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr ""
 
@@ -3809,12 +3809,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr ""
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr ""
 
@@ -3862,151 +3862,128 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr ""
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr ""
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr ""
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr ""
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr ""
 
+#: kallithea/templates/base/base.html:289
+msgid "Show recent activity"
+msgstr ""
+
+#: kallithea/templates/base/base.html:295
 #: kallithea/templates/base/base.html:296
-msgid "Show recent activity"
+msgid "Public journal"
+msgstr ""
+
+#: kallithea/templates/base/base.html:301
+msgid "Show public gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
-msgid "Public journal"
+msgid "Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:306
+msgid "All Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:308
-msgid "Show public gists"
+msgid "My Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:309
-msgid "Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:313
-msgid "All Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:315
-msgid "My Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:316
 msgid "My Private Gists"
 msgstr ""
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr ""
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 msgid "My Pull Requests"
 msgstr ""
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr ""
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 msgid "Login to Your Account"
 msgstr ""
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 msgid "Forgot password?"
 msgstr ""
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 msgid "Don't have an account?"
 msgstr ""
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr ""
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-msgid "Inherit defaults"
+msgid "Create repositories"
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-msgid "default permissions"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 
@@ -4079,18 +4056,16 @@
 msgstr ""
 
 #: kallithea/templates/base/root.html:39
-#, fuzzy
 msgid "Open New Pull Request from {0}"
-msgstr "Statuswijziging -> %s"
+msgstr "Open nieuwe pull request vanaf {0}"
 
 #: kallithea/templates/base/root.html:40
 msgid "Open New Pull Request for {0} &rarr; {1}"
 msgstr ""
 
 #: kallithea/templates/base/root.html:41
-#, fuzzy
 msgid "Show Selected Changesets {0} &rarr; {1}"
-msgstr "Selecteer de changeset"
+msgstr "Toon geselecteerde changesets {0} &rarr; {1}"
 
 #: kallithea/templates/base/root.html:42
 msgid "Selection Link"
@@ -4127,9 +4102,8 @@
 msgstr "Selecteer een changeset"
 
 #: kallithea/templates/base/root.html:52
-#, fuzzy
 msgid "Specify changeset"
-msgstr "Selecteer de changeset"
+msgstr "Specifieer een changeset"
 
 #: kallithea/templates/base/root.html:53
 msgid "Click to sort ascending"
@@ -4237,19 +4211,18 @@
 msgstr ""
 
 #: kallithea/templates/changelog/changelog_table.html:41
-#, fuzzy, python-format
+#, python-format
 msgid "Changeset status: %s by %s"
-msgstr "Selecteer de changeset"
+msgstr "Changeset status: %s door %s"
 
 #: kallithea/templates/changelog/changelog_table.html:60
 msgid "Expand commit message"
 msgstr ""
 
 #: kallithea/templates/changelog/changelog_table.html:76
-#, fuzzy, python-format
-#| msgid "No comments."
+#, python-format
 msgid "%s comments"
-msgstr "Geen kommentaar."
+msgstr "%s opmerkingen"
 
 #: kallithea/templates/changelog/changelog_table.html:80
 #: kallithea/templates/changeset/changeset.html:63
@@ -4346,24 +4319,20 @@
 msgstr ""
 
 #: kallithea/templates/changeset/changeset_file_comment.html:20
-#, fuzzy
-#| msgid "No comments."
 msgid "comment"
-msgstr "Geen kommentaar."
+msgstr "opmerking"
 
 #: kallithea/templates/changeset/changeset_file_comment.html:21
-#, fuzzy
 msgid "on pull request"
-msgstr "Statuswijziging -> %s"
+msgstr "op pull request"
 
 #: kallithea/templates/changeset/changeset_file_comment.html:22
 msgid "No title"
 msgstr ""
 
 #: kallithea/templates/changeset/changeset_file_comment.html:24
-#, fuzzy
 msgid "on this changeset"
-msgstr "Selecteer de changeset"
+msgstr "op deze changeset"
 
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 msgid "Delete comment?"
@@ -4371,18 +4340,16 @@
 
 #: kallithea/templates/changeset/changeset_file_comment.html:38
 #: kallithea/templates/changeset/changeset_file_comment.html:71
-#, fuzzy
 msgid "Status change"
-msgstr "Statuswijziging -> %s"
+msgstr "Statuswijziging"
 
 #: kallithea/templates/changeset/changeset_file_comment.html:87
 msgid "Comments are in plain text. Use @username to notify another user."
 msgstr ""
 
 #: kallithea/templates/changeset/changeset_file_comment.html:93
-#, fuzzy
 msgid "Set changeset status"
-msgstr "Selecteer de changeset"
+msgstr "Zet changeset status"
 
 #: kallithea/templates/changeset/changeset_file_comment.html:95
 msgid "Vote for pull request status"
@@ -4394,14 +4361,12 @@
 msgstr ""
 
 #: kallithea/templates/changeset/changeset_file_comment.html:114
-#, fuzzy
 msgid "Finish pull request"
-msgstr "Statuswijziging -> %s"
+msgstr "Werk pull request af"
 
 #: kallithea/templates/changeset/changeset_file_comment.html:117
-#, fuzzy
 msgid "Close"
-msgstr "(gesloten)"
+msgstr "Sluit"
 
 #: kallithea/templates/changeset/changeset_file_comment.html:129
 msgid "Comment"
@@ -4475,16 +4440,13 @@
 msgstr ""
 
 #: kallithea/templates/changeset/diff_block.html:48
-#, fuzzy, python-format
-#| msgid "Unknown revision %s"
+#, python-format
 msgid "Unknown operation: %r"
-msgstr "Ongekende revisie %s"
+msgstr "Ongekende operatie: %r"
 
 #: kallithea/templates/changeset/diff_block.html:52
-#, fuzzy
-#| msgid "No filename"
 msgid "No file after"
-msgstr "Geen bestandsnaam"
+msgstr "Geen bestand hierna"
 
 #: kallithea/templates/changeset/diff_block.html:55
 msgid "File after"
@@ -4604,26 +4566,21 @@
 msgstr ""
 
 #: kallithea/templates/email_templates/changeset_comment.html:4
-#, fuzzy, python-format
-#| msgid "Set changeset status"
+#, python-format
 msgid "Comment on Changeset \"%s\""
-msgstr "Selecteer de changeset"
+msgstr "Opmerking op changeset \"%s\""
 
 #: kallithea/templates/email_templates/changeset_comment.html:20
-#, fuzzy
-#| msgid "Changeset"
 msgid "Changeset on"
-msgstr "Changeset"
+msgstr "Changeset in"
 
 #: kallithea/templates/email_templates/changeset_comment.html:23
 #: kallithea/templates/email_templates/pull_request.html:22
 #: kallithea/templates/email_templates/pull_request.html:28
 #: kallithea/templates/email_templates/pull_request_comment.html:30
 #: kallithea/templates/email_templates/pull_request_comment.html:36
-#, fuzzy
-#| msgid "Branch"
 msgid "branch"
-msgstr "Branch"
+msgstr "branch"
 
 #: kallithea/templates/email_templates/changeset_comment.html:29
 #: kallithea/templates/email_templates/pull_request.html:15
@@ -4632,10 +4589,8 @@
 msgstr ""
 
 #: kallithea/templates/email_templates/comment.html:27
-#, fuzzy
-#| msgid "Status change"
 msgid "Status change:"
-msgstr "Statuswijziging -> %s"
+msgstr "Statuswijziging:"
 
 #: kallithea/templates/email_templates/comment.html:33
 msgid "The pull request has been closed."
@@ -4684,10 +4639,8 @@
 
 #: kallithea/templates/email_templates/pull_request.html:12
 #: kallithea/templates/email_templates/pull_request_comment.html:20
-#, fuzzy
-#| msgid "on pull request"
 msgid "Pull request"
-msgstr "Statuswijziging -> %s"
+msgstr "Pull request"
 
 #: kallithea/templates/email_templates/pull_request.html:19
 #: kallithea/templates/email_templates/pull_request_comment.html:27
@@ -4710,10 +4663,9 @@
 msgstr ""
 
 #: kallithea/templates/email_templates/pull_request_comment.html:4
-#, fuzzy, python-format
-#| msgid "on pull request"
+#, python-format
 msgid "Comment on Pull Request %s \"%s\""
-msgstr "Statuswijziging -> %s"
+msgstr "Opmerking bij pull request %s \"%s\""
 
 #: kallithea/templates/email_templates/registration.html:22
 msgid "Full Name"
@@ -4735,7 +4687,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr ""
@@ -4747,7 +4699,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr ""
 
@@ -4787,9 +4739,8 @@
 #: kallithea/templates/files/files_add.html:68
 #: kallithea/templates/files/files_delete.html:40
 #: kallithea/templates/files/files_edit.html:71
-#, fuzzy
 msgid "Commit Changes"
-msgstr "Selecteer de changeset"
+msgstr "Committeer wijzigingen"
 
 #: kallithea/templates/files/files_browser.html:40
 msgid "Search File List"
@@ -4800,7 +4751,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr ""
 
@@ -4928,8 +4879,8 @@
 msgstr ""
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr ""
 
@@ -4980,8 +4931,8 @@
 msgstr ""
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr ""
 
@@ -5175,9 +5126,8 @@
 msgstr ""
 
 #: kallithea/templates/pullrequests/pullrequest_show.html:189
-#, fuzzy
 msgid "Cancel Changes"
-msgstr "Selecteer de changeset"
+msgstr "Annuleer wijzigingen"
 
 #: kallithea/templates/pullrequests/pullrequest_show.html:197
 msgid "Reviewers"
@@ -5213,9 +5163,9 @@
 msgstr ""
 
 #: kallithea/templates/pullrequests/pullrequest_show_all.html:11
-#, fuzzy, python-format
+#, python-format
 msgid "Pull Requests from '%s'"
-msgstr "Statuswijziging -> %s"
+msgstr "Pull requests vanaf '%s'"
 
 #: kallithea/templates/pullrequests/pullrequest_show_all.html:13
 #, python-format
@@ -5288,9 +5238,9 @@
 msgid "File names"
 msgstr ""
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr ""
 
@@ -5300,20 +5250,20 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr ""
 
@@ -5322,12 +5272,12 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr ""
 
@@ -5368,95 +5318,101 @@
 msgid "%s Summary"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr ""
-
+#: kallithea/templates/summary/summary.html:54
+msgid "Clone URL"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+msgid "Use Name"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:101
-msgid "There are no downloads yet"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:103
-msgid "Downloads are disabled for this repository"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:109
+msgid "There are no downloads yet"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:111
+msgid "Downloads are disabled for this repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 msgid "With subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:175
-#, fuzzy
+#: kallithea/templates/summary/summary.html:183
 msgid "Latest Changes"
-msgstr "Statuswijziging -> %s"
-
-#: kallithea/templates/summary/summary.html:177
+msgstr "Laatste wijzigingen"
+
+#: kallithea/templates/summary/summary.html:185
 msgid "Quick Start"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:188
-msgid "Add or upload files directly via Kallithea"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:196
-msgid "Push new repository"
+msgid "Add or upload files directly via Kallithea"
 msgstr ""
 
 #: kallithea/templates/summary/summary.html:204
+msgid "Push new repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr ""
 
+#~ msgid "This repository has been locked by %s on %s"
+#~ msgstr "Deze repository is gelocket door %s op %s"
+
 #, fuzzy
 #~| msgid "Empty repository"
 #~ msgid "Repository Group"
--- a/kallithea/i18n/pl/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/pl/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,19 +1,12 @@
-# Polish translations for Kallithea.
 # Copyright (C) 2014 RhodeCode GmbH, and others.
 # This file is distributed under the same license as the Kallithea project.
-# Translators:
-# Nemcio <areczek01@gmail.com>, 2013
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2010
-# marcinkuzminski <marcin@python-blog.com>, 2013
-# Nemcio <bogdan114@g.pl>, 2012
-# Nemcio <areczek01@gmail.com>, 2012-2013
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
-"PO-Revision-Date: 2015-04-04 09:08+0200\n"
-"Last-Translator: Andrej Shadura <andrew@shadura.me>\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\n"
+"PO-Revision-Date: 2019-08-17 19:53+0000\n"
+"Last-Translator: Mateusz Mendel <mendelm9@gmail.com>\n"
 "Language-Team: Polish <https://hosted.weblate.org/projects/kallithea/"
 "kallithea/pl/>\n"
 "Language: pl\n"
@@ -22,17 +15,17 @@
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n"
 "%100<10 || n%100>=20) ? 1 : 2;\n"
-"X-Generator: Weblate 2.3-dev\n"
+"X-Generator: Weblate 3.8\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr "Brak zestawienia zmian"
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -41,100 +34,99 @@
 msgid "None"
 msgstr "Brak"
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr "(zamknięty)"
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr "pokazuj spacje"
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr "Ignoruj pokazywanie spacji"
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 #, fuzzy
 msgid "No permission to change status"
-msgstr "Zagłosuj na żądanie na grupę zmian"
-
-#: kallithea/controllers/changeset.py:214
-#, fuzzy, python-format
+msgstr "Brak uprawnień do zmiany statusu"
+
+#: kallithea/controllers/changeset.py:212
+#, python-format
 msgid "Successfully deleted pull request %s"
-msgstr "Prośba o skasowanie połączenia gałęzi została wykonana prawidłowo"
-
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+msgstr ""
+"Prośba o skasowanie połączenia gałęzi %s została wykonana prawidłowo"
+
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr ""
 
-#: kallithea/controllers/compare.py:66
-#, fuzzy, python-format
-#| msgid "Go to tip of repository"
+#: kallithea/controllers/compare.py:68
+#, python-format
 msgid "Could not find other repository %s"
-msgstr "Potwierdź blokowanie repozytorium"
-
-#: kallithea/controllers/compare.py:72
+msgstr "Nie można znaleźć innego repozytorium %s"
+
+#: kallithea/controllers/compare.py:74
 msgid "Cannot compare repositories of different types"
 msgstr ""
 
-#: kallithea/controllers/compare.py:244
-msgid "Cannot show empty diff"
-msgstr ""
-
 #: kallithea/controllers/compare.py:246
+msgid "Cannot show empty diff"
+msgstr ""
+
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr ""
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr ""
 
-#: kallithea/controllers/error.py:70
-#, fuzzy
-msgid "No response"
-msgstr "rewizja"
-
 #: kallithea/controllers/error.py:71
+msgid "No response"
+msgstr "Brak odpowiedzi"
+
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr ""
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr ""
-"Wniosek nie może być rozumiany przez serwer z powodu zniekształconej "
+"Żądanie nie może być rozumiane przez serwer z powodu zniekształconej "
 "składni."
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr "Nieautoryzowany dostęp do zasobów"
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr "Nie masz uprawnień do przeglądania tej strony"
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr "Zasób nie został znaleziony"
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
 msgstr ""
-"Serwer napotkał niespodziewany warunek, który uniemożliwia jej spełnienie "
+"Serwer napotkał niespodziewany warunek, który uniemożliwia spełnienie "
 "żądania."
 
 #: kallithea/controllers/feed.py:63
@@ -152,124 +144,116 @@
 msgid "Changeset was too big and was cut off..."
 msgstr "Lista zmian była zbyt duża i została ucięta..."
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr "%s %s zasilać"
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
 msgstr "Zmiany w %s repozytorium"
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr "Kliknij tutaj, by dodać nowy plik"
 
-#: kallithea/controllers/files.py:93
-#, fuzzy
-#| msgid "There are no forks yet"
+#: kallithea/controllers/files.py:86
 msgid "There are no files yet."
-msgstr "Nie ma jeszcze gałęzi"
-
-#: kallithea/controllers/files.py:193
+msgstr "Nie ma jeszcze gałęzi."
+
+#: kallithea/controllers/files.py:186
 #, fuzzy, python-format
 msgid "%s at %s"
 msgstr "w %s i %s"
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr "Repozytorium zostało zablokowane przez %s na %s"
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 #, fuzzy
 msgid "You can only delete files with revision being a valid branch"
-msgstr "Można tylko edytować pliki z rewizji obecnej gałęzi "
-
-#: kallithea/controllers/files.py:322
+msgstr "Można tylko usuwać pliki po sprawdzeniu obecnej gałęzi"
+
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr ""
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr "Wystąpił błąd w trakcie zatwierdzania"
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 #, fuzzy
 msgid "You can only edit files with revision being a valid branch"
-msgstr "Można tylko edytować pliki z rewizji obecnej gałęzi "
-
-#: kallithea/controllers/files.py:385
+msgstr "Można tylko edytować pliki z rewizji obecnej gałęzi"
+
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr "Edytowanie %s w Kallithea"
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr "Bez zmian"
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr "Committ wykonany do %s"
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr "Dodano %s poprzez Kallithea"
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr "Brak treści"
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr "Brak nazwy pliku"
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr ""
 "Lokalizacja musi być ścieżką względną i nie może zawierać .. ścieżki"
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr "Pobieranie wyłączone"
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr "Nieznana wersja %s"
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr "Puste repozytorium"
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr "Nieznany typ archiwum"
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr "Różnice"
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
 msgstr "Gałęzie"
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr "Etykiety"
 
@@ -278,11 +262,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr "Wystąpił błąd podczas rozgałęzienia %s repozytorium"
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr ""
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -290,188 +274,185 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr "Repozytoria"
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
 msgstr "gałąź"
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr "Zamknięte Gałęzie"
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr "Tag"
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
-msgstr "Bookmark"
-
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+msgstr "Zakładka"
+
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr "Dziennik Publiczny"
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr "Dziennik"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
 msgstr ""
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "Udało Ci się zarejestrować w %s"
 
-#: kallithea/controllers/login.py:189
-#, fuzzy
+#: kallithea/controllers/login.py:190
 msgid "A password reset confirmation code has been sent"
 msgstr "Twój link zresetowania hasła został wysłany"
 
-#: kallithea/controllers/login.py:238
-#, fuzzy
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
-msgstr "łącze resetowania hasła"
-
-#: kallithea/controllers/admin/my_account.py:155
-#: kallithea/controllers/login.py:243
+msgstr "Nieprawidłowy token resetowania hasła"
+
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr "%s (zamknięty)"
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr "Grupy zmian"
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr "Specjalne"
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr "gałęzie"
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr "Zakładki"
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr "Wystąpił błąd podczas prośby o połączenie gałęzi"
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr "Prośba o wykonanie połączenia gałęzi została wykonana prawidłowo"
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 #, fuzzy
 #| msgid "Pull request update created"
 msgid "New pull request iteration created"
 msgstr "Recenzje wniosków połączenia gałęzi"
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr "Brak opisu"
 
-#: kallithea/controllers/pullrequests.py:432
-#, fuzzy
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
-msgstr "Połączone gałęzie"
-
-#: kallithea/controllers/pullrequests.py:445
+msgstr "Połączone gałęzie zaktualizowane"
+
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr "Prośba o skasowanie połączenia gałęzi została wykonana prawidłowo"
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, python-format
 msgid "Revision %s not found in %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, python-format
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr ""
 
+#: kallithea/controllers/pullrequests.py:520
+#, python-format
+msgid "This pull request has already been merged to %s."
+msgstr ""
+
 #: kallithea/controllers/pullrequests.py:522
-#, python-format
-msgid "This pull request has already been merged to %s."
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:524
 msgid "This pull request has been closed and can not be updated."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, python-format
 msgid "The following additional changes are available on %s:"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 msgid "No additional changesets found for iterating on this pull request."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 msgid "Git pull requests don't support iterating yet."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, python-format
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 
 #: kallithea/controllers/search.py:136
 msgid "Invalid search query. Try quoting it."
-msgstr "Nieprawidłowe zapytania. Spróbuj zacytować go."
+msgstr "Nieprawidłowe zapytanie. Spróbuj zacytować je."
 
 #: kallithea/controllers/search.py:140
 msgid "The server has no search index."
@@ -481,24 +462,23 @@
 msgid "An error occurred during search operation."
 msgstr "Wystąpił błąd podczas operacji wyszukiwania."
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
-#, fuzzy
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr "Żadne dane nie zostały załadowane"
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr "Statystyki są wyłączone dla tego repozytorium"
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr "Ustawienia autentykacji poprawnie zaktualizowane"
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
-msgstr "wystapił błąd podczas uaktualniania ustawień autentykacji"
+msgstr "wystąpił błąd podczas uaktualniania ustawień autentykacji"
 
 #: kallithea/controllers/admin/defaults.py:75
 msgid "Default settings updated successfully"
@@ -508,127 +488,138 @@
 msgid "Error occurred during update of defaults"
 msgstr "wystąpił błąd podczas aktualizacji wartości domyślnych"
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
-#, fuzzy
 msgid "Forever"
 msgstr "na zawsze"
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
 #: kallithea/controllers/admin/users.py:249
 msgid "5 minutes"
 msgstr "5 minut"
 
-#: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
 #: kallithea/controllers/admin/users.py:250
 msgid "1 hour"
 msgstr "1 godzina"
 
-#: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
 #: kallithea/controllers/admin/users.py:251
 msgid "1 day"
 msgstr "1 dzień"
 
-#: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr "1 miesiąc"
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr "Czas życia"
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
-msgstr "Wystąpił błąd podczas tworzenia git"
-
-#: kallithea/controllers/admin/gists.py:156
+msgstr "Wystąpił błąd podczas tworzenia gist"
+
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr "Usuń gist %s"
 
-#: kallithea/controllers/admin/gists.py:196
-#, fuzzy
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
-msgstr "Ostatnio modyfikowany"
-
-#: kallithea/controllers/admin/gists.py:225
+msgstr "Niemodyfikowany"
+
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:230
-msgid "Successfully updated gist data"
-msgstr ""
-
 #: kallithea/controllers/admin/gists.py:233
+msgid "Successfully updated gist data"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 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 "
 "aplikacji"
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr "Twoje konto zostało pomyślnie zaktualizowane"
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr "wystąpił błąd podczas aktualizacji użytkownika %s"
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr "Dodano e-mail %s do użytkownika"
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr "Wystąpił błąd podczas zapisywania e-maila"
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr "Usunięto e-mail użytkownikowi"
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, python-format
+msgid "SSH key %s successfully added"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+#, fuzzy
+#| msgid "Successfully deleted user"
+msgid "SSH key successfully deleted"
+msgstr "Użytkownik został usunięty"
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -636,9 +627,9 @@
 msgid "Read"
 msgstr "Odczyt"
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -646,9 +637,9 @@
 msgid "Write"
 msgstr "Zapis"
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -671,368 +662,349 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr "Administracja"
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:50
 msgid "Disabled"
 msgstr "Wyłączone"
 
-#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:80
 msgid "Allowed with manual account activation"
 msgstr "Dozwolona z ręczną aktywacją konta"
 
-#: kallithea/controllers/admin/permissions.py:80
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr "Dozwolona z automatyczną aktywacją konta"
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr "Ręczna aktywacja nowego konta"
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr "Automatyczna aktywacja nowego konta"
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr "Włączone"
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr "Globalne uprawnienia zaktualizowane poprawnie"
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr "Wystąpił błąd podczas aktualizacji uprawnień"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, 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:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr "Utworzono grupę repo %s"
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Zaktualizowano grupę repo %s"
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, 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:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, 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:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, 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:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Usunięto grupę repo %s"
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, 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:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Nie można cofnąć zezwolenia dla admina jako admin"
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr "Aktualizacja uprawnień grup repozytorium"
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr "Wystąpił błąd podczas cofania zezwolenia"
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
-msgstr "utworzone repozytorium %s"
-
-#: kallithea/controllers/admin/repos.py:195
+msgstr "Błąd podczas tworzenia repozytorium %s"
+
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "utworzone repozytorium %s z %s"
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Gałęzi %s w repozytorium %s"
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr "Utworzone repozytorium %s"
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Repozytorium %s zostało pomyślnie zaktualizowane"
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "Wystąpił błąd podczas aktualizacji repozytorium %s"
 
-#: kallithea/controllers/admin/repos.py:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr "Oderwane rozgałęzienie %s"
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
-msgstr "Usunięte repozytorium %s"
-
-#: kallithea/controllers/admin/repos.py:282
+msgstr "Usunięte rozgałęzienia %s"
+
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Usunięte repozytorium %s"
 
-#: kallithea/controllers/admin/repos.py:285
-#, fuzzy, python-format
+#: kallithea/controllers/admin/repos.py:284
+#, python-format
 msgid "Cannot delete repository %s which still has forks"
-msgstr "Nie można usunąć %s nadal zawiera załączniki rozgałęzienia"
-
-#: kallithea/controllers/admin/repos.py:290
+msgstr ""
+"Nie można usunąć repozytorium %s nadal zawiera załączniki rozgałęzienia"
+
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "Wystąpił błąd podczas usuwania %s"
 
-#: kallithea/controllers/admin/repos.py:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr "Uprawnienia repozytorium zostały zaktualizowane"
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:390
-#, fuzzy, python-format
-#| msgid "An error occurred during creation of field"
+#: kallithea/controllers/admin/repos.py:391
+#, python-format
 msgid "An error occurred during creation of field: %r"
-msgstr "Wystąpił błąd podczas tworzenia użytkownika %s"
-
-#: kallithea/controllers/admin/repos.py:401
+msgstr "Wystąpił błąd podczas tworzenia pola: %r"
+
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
-msgstr "Wystąpił błąd podczas zapisywania e-maila"
-
-#: kallithea/controllers/admin/repos.py:415
+msgstr "Wystąpił błąd podczas usuwania pola"
+
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
-msgstr "-- Brak rozgalezienia --"
-
-#: kallithea/controllers/admin/repos.py:446
+msgstr "-- Brak rozgałęzienia --"
+
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr "Zaktualizowano widoczność stron w publicznym dzienniku"
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 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:466
+#: kallithea/controllers/admin/repos.py:468
 msgid "Nothing"
 msgstr "Brak"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:470
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "Oznaczono %s repo jako rozwidlenie %s"
 
-#: kallithea/controllers/admin/repos.py:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr "Wystąpił błąd podczas tej operacji"
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-#, fuzzy
-msgid "Repository has been locked"
-msgstr "Repozytorium nie jest zablokowane"
+#: kallithea/controllers/admin/repos.py:490
+msgid "Cache invalidation successful"
+msgstr "Cache wyczyszczony poprawnie"
 
 #: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-#, fuzzy
-msgid "Repository has been unlocked"
-msgstr "Repozytorium nie jest zablokowane"
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr "Wystąpił błąd podczas odblokowywania"
-
-#: kallithea/controllers/admin/repos.py:528
-msgid "Cache invalidation successful"
-msgstr "Cache wyczyszczony poprawnie"
-
-#: kallithea/controllers/admin/repos.py:532
 msgid "An error occurred during cache invalidation"
 msgstr "Wystąpił błąd podczas unieważniania cache"
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr "Pobieranie z lokalizacji zdalnej"
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 msgid "An error occurred during pull from remote location"
 msgstr "Wystąpił błąd podczas pobierania z lokalizacji zdalnej"
 
-#: kallithea/controllers/admin/repos.py:579
+#: kallithea/controllers/admin/repos.py:541
 msgid "An error occurred during deletion of repository stats"
 msgstr "Wystąpił błąd podczas usuwania z repozytorium statystyk"
 
-#: kallithea/controllers/admin/settings.py:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr "Aktualizacja ustawień VCS"
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
 msgstr "Wystąpił błąd podczas aktualizacji ustawień aplikacji"
 
-#: kallithea/controllers/admin/settings.py:180
+#: kallithea/controllers/admin/settings.py:176
 #, 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:192
-#, fuzzy, python-format
-#| msgid "Invalidate cache for all repositories"
+#: kallithea/controllers/admin/settings.py:188
+#, python-format
 msgid "Invalidated %s repositories"
-msgstr "Unieważnia cache dla wszystkich repozytoriów"
-
-#: kallithea/controllers/admin/settings.py:233
+msgstr "Unieważnione %s repozytoria"
+
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr "Aktualizacja ustawień aplikacji"
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr "Aktualizacja ustawień wizualizacji"
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
 msgstr "Wystąpił błąd podczas aktualizacji ustawień wizualizacji"
 
-#: kallithea/controllers/admin/settings.py:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr "Proszę podać adres email"
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:358
-#, fuzzy
+#: kallithea/controllers/admin/settings.py:355
 msgid "Hook already exists"
-msgstr "Żadne dane nie zostały załadowane"
+msgstr "Hook już istnieje"
+
+#: kallithea/controllers/admin/settings.py:357
+msgid "Builtin hooks are read-only. Please use another hook name."
+msgstr ""
 
 #: kallithea/controllers/admin/settings.py:360
-msgid "Builtin hooks are read-only. Please use another hook name."
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:363
 msgid "Added new hook"
 msgstr "Dodano nowy hook"
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr "Aktualizacja hooku"
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr "Wystąpił błąd podczas tworzenia hooku"
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr "Zadanie ponownej indeksacji whoosh zostało zaplanowane"
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr "Utworzono grupę użytkowników %s"
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, 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:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr "Zaktualizowano grupę użytkowników %s"
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, 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:217
+#: kallithea/controllers/admin/user_groups.py:212
 msgid "Successfully deleted user group"
 msgstr "Grupa użytkowników została usunięta z powodzeniem"
 
-#: kallithea/controllers/admin/user_groups.py:222
+#: kallithea/controllers/admin/user_groups.py:217
 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:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr "Grupa docelowa nie może być taka sama"
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr "Aktualizacja uprawnień grupy użytkowników"
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr "Aktualizacja uprawnień"
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr "Wystąpił błąd podczas zapisywania uprawnień"
 
@@ -1062,223 +1034,223 @@
 msgid "The default user cannot be edited"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
-msgstr "Dodano ip %s do listy dozwolonych adresów użytkownia"
-
-#: kallithea/controllers/admin/users.py:418
+msgstr "Dodano ip %s do listy dozwolonych adresów użytkownika"
+
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
-msgstr "Wystąpił błąd podczas zapisywania e-maila"
-
-#: kallithea/controllers/admin/users.py:430
+msgstr "Wystąpił błąd podczas zapisywania adresu IP"
+
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr "Usunięto adres ip z listy dozwolonych adresów dla użytkownika"
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 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:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr "Musisz być zalogowany, żeby oglądać stronę"
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr ""
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr ""
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, fuzzy, python-format
 #| msgid "Changeset not found"
 msgid "Changeset for %s %s not found in %s"
-msgstr "Nie znaleziono changeset"
-
-#: kallithea/lib/diffs.py:193
+msgstr "Nie znaleziono changeset dla %s%s w %s"
+
+#: kallithea/lib/base.py:647
+#, fuzzy
+#| msgid "Your account is disabled"
+msgid "SSH access is disabled."
+msgstr "Twoje konto jest wyłączone"
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr "Plik binarny"
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 "Lista zmian była zbyt duża i została obcięta, użyj menu porównań żeby "
 "wyświetlić różnice"
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr "Nie wykryto zmian"
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "Usunięta gałąź: %s"
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr "Utworzony tag: %s"
 
-#: kallithea/lib/helpers.py:625
-#, fuzzy, python-format
-#| msgid "Changeset not found"
+#: kallithea/lib/helpers.py:666
+#, python-format
 msgid "Changeset %s not found"
-msgstr "Nie znaleziono changeset"
-
-#: kallithea/lib/helpers.py:674
+msgstr "Nie znaleziono changeset %s"
+
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "Pokaż wszystkie zestawienia zmian changesets %s->%s"
 
-#: kallithea/lib/helpers.py:680
-#, fuzzy
+#: kallithea/lib/helpers.py:721
 msgid "Compare view"
 msgstr "Wyświetl porównanie"
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr "i"
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr "%s więcej"
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "rewizja"
 
-#: kallithea/lib/helpers.py:725
-#, fuzzy, python-format
+#: kallithea/lib/helpers.py:766
+#, python-format
 msgid "Fork name %s"
 msgstr "nazwa rozgałęzienia %s"
 
-#: kallithea/lib/helpers.py:746
+#: kallithea/lib/helpers.py:787
 #, fuzzy, python-format
 msgid "Pull request %s"
 msgstr "Połączonych gałęzi #%s"
 
-#: kallithea/lib/helpers.py:756
+#: kallithea/lib/helpers.py:797
 msgid "[deleted] repository"
 msgstr "[usunięte] repozytorium"
 
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
 msgid "[created] repository"
 msgstr "[utworzone] repozytorium"
 
-#: kallithea/lib/helpers.py:760
+#: kallithea/lib/helpers.py:801
 msgid "[created] repository as fork"
 msgstr "[utworzone] repozytorium jako rozgałęzienie"
 
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
 msgid "[forked] repository"
 msgstr "[rozgałęzione] repozytorium"
 
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
 msgid "[updated] repository"
 msgstr "[zaktualizowane] repozytorium"
 
-#: kallithea/lib/helpers.py:766
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr "[pobierz] archiwum z repozytorium"
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr "[skasowane] repozytorium"
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr "[utworzony] użytkownik"
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr "[zaktualizowany] użytkownik"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr "[utworzona] grupa użytkowników"
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr "[zaktualizowana] grupa użytkowników"
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr "[komentarz] do zmiany w repozytorium"
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr "[komentarz] wniosek o połączenie gałęzi"
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr "[zamknięty] wniosek o połączenie gałęzi"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr "[wysłane zmiany] w"
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr "[synchronizacja przez Kallithea] z repozytorium"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr "[pobieranie z zdalnego] do repozytorium"
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr "[pobrano]"
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr "[start następnego] repozytorium"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr "[zatrzymany po] repozytorium"
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr " i %s więcej"
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: 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:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr "nowy plik"
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr "modyfikuj"
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr "kasuj"
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr "zmień nazwę"
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1289,7 +1261,34 @@
 "zmienione z systemie plików proszę uruchomić aplikację ponownie, aby "
 "ponownie przeskanować repozytoria"
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
@@ -1297,7 +1296,7 @@
 msgstr[1] "%d lata"
 msgstr[2] "%d lat"
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
@@ -1305,7 +1304,7 @@
 msgstr[1] "%d miesięcy"
 msgstr[2] "%d miesięcy"
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
@@ -1313,7 +1312,7 @@
 msgstr[1] "%d dni"
 msgstr[2] "%d dni"
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
@@ -1321,7 +1320,7 @@
 msgstr[1] "%d godziny"
 msgstr[2] "%d godzin"
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
@@ -1329,7 +1328,7 @@
 msgstr[1] "%d minuty"
 msgstr[2] "%d minut"
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
@@ -1337,27 +1336,27 @@
 msgstr[1] "%d sekund"
 msgstr[2] "%d sekund"
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr "w %s"
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr "%s temu"
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr "w %s i %s"
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s i %s temu"
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr "przed chwilą"
 
@@ -1366,147 +1365,144 @@
 msgid "on line %s"
 msgstr "widziany %s"
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr "[Wymieniony]"
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr "najwyższy poziom"
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
-msgstr "Administrator Repo"
-
-#: kallithea/model/db.py:1705
+msgstr "Administrator Kallithea"
+
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1706
-#, fuzzy
+#: kallithea/model/db.py:1640
 msgid "Default user has read access to new repositories"
-msgstr "Nieautoryzowany dostęp do zasobów"
-
-#: kallithea/model/db.py:1707
-#, fuzzy
+msgstr "Użytkownik domyślny ma dostęp do odczytu nowych repozytoriów"
+
+#: kallithea/model/db.py:1641
 msgid "Default user has write access to new repositories"
-msgstr "Nieautoryzowany dostęp do zasobów"
-
-#: kallithea/model/db.py:1708
+msgstr "Użytkownik domyślny ma dostęp do zapisu nowych repozytoriów"
+
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1711
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 #, fuzzy
 msgid "Only admins can create repository groups"
-msgstr "Utworzono grupę repo %s"
-
-#: kallithea/model/db.py:1721
+msgstr "Tylko admini mogą tworzyć grupy repozytoriów"
+
+#: kallithea/model/db.py:1655
 #, fuzzy
 msgid "Non-admins can create repository groups"
-msgstr "Utworzono grupę repo %s"
-
-#: kallithea/model/db.py:1723
+msgstr ""
+"Użytkownicy bez uprawnień administratora mogą tworzyć grupy repozytoriów"
+
+#: kallithea/model/db.py:1657
 #, fuzzy
 msgid "Only admins can create user groups"
-msgstr "Tworzenie grup użytkowników"
-
-#: kallithea/model/db.py:1724
+msgstr "Tylko admini mogą tworzyć grupy użytkowników"
+
+#: kallithea/model/db.py:1658
 #, fuzzy
 msgid "Non-admins can create user groups"
-msgstr "Tworzenie grup użytkowników"
-
-#: kallithea/model/db.py:1726
+msgstr ""
+"Użytkownicy bez uprawnień administratora mogą tworzyć grupy użytkowników"
+
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1730
+#: kallithea/model/db.py:1664
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1732
+#: kallithea/model/db.py:1666
 #, fuzzy
 msgid "Only admins can fork repositories"
-msgstr "Ogólna liczba repozytoriów"
-
-#: kallithea/model/db.py:1733
+msgstr "Tylko admini mogą rozgałęziać repozytoria"
+
+#: kallithea/model/db.py:1667
 #, fuzzy
 msgid "Non-admins can fork repositories"
-msgstr "Unieważnia cache dla wszystkich repozytoriów"
-
-#: kallithea/model/db.py:1735
+msgstr ""
+"Użytkownicy bez uprawnień administratora mogą rozgałęziać repozytoria"
+
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr "Rejestracja wyłączona"
 
-#: kallithea/model/db.py:1736
-#, fuzzy
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr "Rejestracja użytkownika z ręczną aktywacją konta"
 
-#: kallithea/model/db.py:1737
-#, fuzzy
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr "Rejestracja użytkownika z automatyczną aktywacją konta"
 
-#: kallithea/model/db.py:2263
-#, fuzzy
+#: kallithea/model/db.py:2206
 msgid "Not reviewed"
 msgstr "Brak Korekty"
 
-#: kallithea/model/db.py:2264
-#, fuzzy
+#: kallithea/model/db.py:2207
 msgid "Under review"
 msgstr "Objęty Przeglądem"
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 #, fuzzy
 #| msgid "Approved"
 msgid "Not approved"
-msgstr "Zaakceptowano"
-
-#: kallithea/model/db.py:2266
+msgstr "Niezaakceptowano"
+
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr "Zaakceptowano"
 
@@ -1532,7 +1528,7 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, fuzzy, python-format
 #| msgid "[Comment] %(repo_name)s pull request %(pr_nice_id)s from %(ref)s"
 msgid ""
@@ -1540,187 +1536,203 @@
 "%(branch)s"
 msgstr "[komentarz] wniosek o połączenie gałęzi"
 
-#: kallithea/model/notification.py:168
-#, fuzzy, python-format
+#: kallithea/model/notification.py:167
+#, python-format
 msgid "New user %(new_username)s registered"
-msgstr "Użytkownik %(new_username)s zarejestrował"
-
-#: kallithea/model/notification.py:170
+msgstr "Użytkownik %(new_username)s zarejestrował się"
+
+#: kallithea/model/notification.py:169
 #, 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:171
+#: kallithea/model/notification.py:170
 #, 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:184
+#: kallithea/model/notification.py:183
 #, fuzzy
 msgid "Closing"
-msgstr "Używa:"
-
-#: kallithea/model/pull_request.py:76
+msgstr "Zamykanie"
+
+#: kallithea/model/pull_request.py:73
 #, fuzzy, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
-msgstr "%(user)s chce żeby przejrzeć nowe gałęzie #%(pr_id)s: %(pr_title)s"
-
-#: kallithea/model/pull_request.py:211
+msgstr ""
+"%(user)s chce żeby przejrzeć nowe gałęzie %(pr_nice_id)s: %(pr_title)s"
+
+#: kallithea/model/pull_request.py:209
 #, fuzzy
 #| msgid "Create Pull Request"
 msgid "Cannot create empty pull request"
-msgstr "Stwórz nowe żądanie połączenia gałęzi"
-
-#: kallithea/model/pull_request.py:219
+msgstr "Nie można stworzyć pustego żądania połączenia gałęzi"
+
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 #, fuzzy
 #| msgid "Confirm to delete this pull request"
 msgid "You are not authorized to create the pull request"
-msgstr "Potwierdź usunięcie połączenia gałęzi"
-
-#: kallithea/model/pull_request.py:341
+msgstr "Nie masz uprawnień, aby stworzyć żądanie połączenia gałęzi"
+
+#: kallithea/model/pull_request.py:339
 msgid "Missing changesets since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, python-format
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, python-format
 msgid ""
 "This iteration is based on another %s revision and there is no simple "
 "diff."
 msgstr ""
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, python-format
 msgid "No changes found on %s %s since previous iteration."
 msgstr ""
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr "ostatni tip"
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, fuzzy, python-format
+#| msgid "Changeset %s not found"
+msgid "SSH key %r not found"
+msgstr "Nie znaleziono changeset %s"
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr "nowy użytkownik się zarejestrował"
 
-#: kallithea/model/user.py:253
-#, fuzzy
+#: kallithea/model/user.py:250
 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:258
+#: kallithea/model/user.py:255
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
 "owners or remove those repositories: %s"
 msgstr ""
 "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:263
+"zostać usunięty. Zmień właściciela lub usuń te repozytoria: %s"
+
+#: kallithea/model/user.py:260
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
 "owners or remove those repository groups: %s"
 msgstr ""
 "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:270
+"zostać usunięty. Zmień właściciela lub usuń te repozytoria: %s"
+
+#: kallithea/model/user.py:267
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
 "owners or remove those user groups: %s"
 msgstr ""
 "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:364
+"zostać usunięty. Zmień właściciela lub usuń te grupy użytkowników: %s"
+
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr "łącze resetowania hasła"
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 #, fuzzy
 msgid "Password reset notification"
-msgstr "łącze resetowania hasła"
-
-#: kallithea/model/user.py:414
+msgstr "Powiadomienie o resetowaniu hasła"
+
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr "Wartość listy nie może być pusta"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:72
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "Użytkownik \"%(username)s\" już istnieje"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:74
 #, fuzzy, python-format
 msgid "Username \"%(username)s\" cannot be used"
-msgstr "Nazwa użytkownika %(username)s jest nieprawidłowa"
-
-#: kallithea/model/validators.py:78
+msgstr "Nazwa użytkownika \"%(username)s\" nie może być użyta"
+
+#: kallithea/model/validators.py:76
 #, fuzzy
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
 "dashes and must begin with an alphanumeric character or underscore"
 msgstr ""
 "Nazwa użytkownika może zawierać tylko znaki alfanumeryczne, podkreślenia, "
-"kropki lub myślniki i muszą zaczynać się znakiem alfanumerycznym lub "
+"kropki lub myślniki i musi zaczynać się znakiem alfanumerycznym lub "
 "podkreśleniem"
 
-#: kallithea/model/validators.py:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr "Nazwa użytkownika %(username)s jest nieprawidłowa"
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr "Niewłaściwa nazwa grupy"
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:132
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr "Nazwa grupy \"%(usergroup)s\" już istnieje"
 
-#: kallithea/model/validators.py:136
+#: kallithea/model/validators.py:134
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
@@ -1728,107 +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:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr "Nie można przypisać do tej grupy jako rodzic"
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:175
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr "Nazwa grupy \"%(group_name)s\" już istnieje"
 
-#: kallithea/model/validators.py:179
+#: kallithea/model/validators.py:177
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr "Repozytorium o nazwie \"%(group_name)s\" już istnieje"
 
-#: kallithea/model/validators.py:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr "Nieprawidłowe znaki (nie-ascii) w haśle"
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr "Hasła różnią się"
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 #, fuzzy
 msgid "Invalid username or password"
-msgstr "nieprawidłowe hasło"
-
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr "Niezgodność tokenu"
-
-#: kallithea/model/validators.py:328
+msgstr "nieprawidłowa nazwa użytkownika lub hasło"
+
+#: kallithea/model/validators.py:313
 #, fuzzy, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr "Nazwa repozytorium  %(repo)s jest zabroniona"
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr "Repozytorium o nazwie %(repo)s już istnieje"
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, 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:333
+#: kallithea/model/validators.py:318
 #, 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:419
+#: kallithea/model/validators.py:404
 #, fuzzy
 msgid "Invalid repository URL"
-msgstr "prywatne repozytorium"
-
-#: kallithea/model/validators.py:420
+msgstr "Nieprawidłowy URL repozytorium"
+
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:430
 msgid "Fork has to be the same type as parent"
 msgstr "Fork musi być tego samego typu, jak rodzic"
 
-#: kallithea/model/validators.py:460
+#: kallithea/model/validators.py:445
 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:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
-msgstr "nie masz uprawnień do tworzenia repozytorium w tej grupie"
-
-#: kallithea/model/validators.py:512
+msgstr "nie masz uprawnień do tworzenia repozytorium w tej lokacji roota"
+
+#: kallithea/model/validators.py:497
 msgid "You don't have permissions to create a group in this location"
-msgstr "Nie masz uprawnień do tworzenia repozytorium w tej grupie"
-
-#: kallithea/model/validators.py:552
+msgstr "Nie masz uprawnień do tworzenia grupy w tym miejscu"
+
+#: kallithea/model/validators.py:537
 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:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr "To nie jest prawidłowa ścieżka"
 
-#: kallithea/model/validators.py:662
-#, fuzzy
+#: kallithea/model/validators.py:647
 msgid "This email address is already in use"
 msgstr "Ten adres e-mail jest już zajęty"
 
-#: kallithea/model/validators.py:682
-#, fuzzy, python-format
+#: kallithea/model/validators.py:667
+#, python-format
 msgid "Email address \"%(email)s\" not found"
-msgstr "e-mail \"%(email)s\" nie istnieje."
-
-#: kallithea/model/validators.py:719
+msgstr "e-mail \"%(email)s\" nie istnieje"
+
+#: kallithea/model/validators.py:704
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
@@ -1836,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:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr "Proszę podać poprawny adres IPv4 lub IPv6"
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, 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:765
+#: kallithea/model/validators.py:750
 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:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr "Nazwa pliku nie może znajdować się w katalogu"
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1898,30 +1905,36 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr "Opis"
 
 #: kallithea/templates/index_base.html:60
 msgid "Last Change"
-msgstr "Ostatnia akytwność"
+msgstr "Ostatnia aktywność"
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:15
 #: kallithea/templates/admin/my_account/my_account_watched.html:15
@@ -1932,7 +1945,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1940,11 +1953,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr "Właściciel"
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr "Zaloguj się"
@@ -1959,7 +1972,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1967,7 +1980,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr "Hasło"
@@ -1994,16 +2007,15 @@
 
 #: kallithea/templates/password_reset.html:21
 #: kallithea/templates/password_reset_confirmation.html:16
-#, fuzzy, python-format
+#, python-format
 msgid "Reset Your Password to %s"
-msgstr "Zapomniałeś hasła do %s?"
+msgstr "Zresetować hasło do %s"
 
 #: kallithea/templates/password_reset.html:23
 #: kallithea/templates/password_reset_confirmation.html:5
 #: kallithea/templates/password_reset_confirmation.html:18
-#, fuzzy
 msgid "Reset Your Password"
-msgstr "Zapomniałeś hasła?"
+msgstr "Zresetuj hasło"
 
 #: kallithea/templates/password_reset.html:30
 msgid "Email Address"
@@ -2015,16 +2027,17 @@
 msgstr ""
 
 #: kallithea/templates/password_reset.html:47
-#, fuzzy
 msgid "Send Password Reset Email"
-msgstr "łącze resetowania hasła"
+msgstr "Wyślij email z resetowaniem hasła"
 
 #: kallithea/templates/password_reset.html:52
 #, fuzzy
 msgid ""
 "A password reset link will be sent to the specified email address if it "
 "is registered in the system."
-msgstr "Link do zresetowania hasła zostanie wysłany na adres e-mail"
+msgstr ""
+"Link do zresetowania hasła zostanie wysłany na adres e-mail znajdujący "
+"się w systemie."
 
 #: kallithea/templates/password_reset_confirmation.html:23
 #, python-format
@@ -2042,14 +2055,12 @@
 msgstr ""
 
 #: kallithea/templates/password_reset_confirmation.html:36
-#, fuzzy
 msgid "New Password"
 msgstr "Nowe hasło"
 
 #: kallithea/templates/password_reset_confirmation.html:43
-#, fuzzy
 msgid "Confirm New Password"
-msgstr "Nowe hasło"
+msgstr "Potwierdź nowe hasło"
 
 #: kallithea/templates/password_reset_confirmation.html:51
 msgid "Confirm"
@@ -2105,24 +2116,22 @@
 #: kallithea/templates/admin/admin.html:5
 #: kallithea/templates/admin/admin.html:13
 #: kallithea/templates/base/base.html:55
-#, fuzzy
 msgid "Admin Journal"
 msgstr "Dziennik administratora"
 
 #: kallithea/templates/admin/admin.html:10
 #: kallithea/templates/journal/journal.html:10
 msgid "journal filter..."
-msgstr "szybkie wyszukiwanie..."
+msgstr "filtr dziennika..."
 
 #: kallithea/templates/admin/admin.html:12
 #: kallithea/templates/journal/journal.html:12
-#, fuzzy
 msgid "Filter"
 msgstr "filtr"
 
 #: kallithea/templates/admin/admin.html:13
 #: kallithea/templates/journal/journal.html:13
-#, fuzzy, python-format
+#, python-format
 msgid "%s Entry"
 msgid_plural "%s Entries"
 msgstr[0] "%s wejście"
@@ -2131,10 +2140,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr "Działanie"
@@ -2183,29 +2194,28 @@
 msgstr "Wtyczka"
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr "Zapisz"
 
 #: kallithea/templates/admin/defaults/defaults.html:5
 #: kallithea/templates/admin/defaults/defaults.html:11
 #: kallithea/templates/base/base.html:62
-#, fuzzy
 msgid "Repository Defaults"
 msgstr "Repozytoria domyślne"
 
@@ -2217,14 +2227,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr "Prywatne repozytorium"
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2234,36 +2244,25 @@
 "jako współpracownicy."
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr "Włącz statystyki"
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr "Włącz okno statystyk na stronie podsumowania."
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr "Włącz pobieranie"
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr "Włącz menu pobierania na stronie podsumowania."
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr "Włącz blokowanie"
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr "Włącz blokowanie pobierania w repozytorium."
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2310,9 +2309,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
-#, fuzzy
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 msgid "Never"
 msgstr "nigdy"
 
@@ -2328,13 +2328,13 @@
 
 #: kallithea/templates/admin/gists/index.html:6
 #: kallithea/templates/admin/gists/index.html:16
-#, fuzzy, python-format
+#, python-format
 msgid "Private Gists for User %s"
 msgstr "Prywatne Gists użytkownika %s"
 
 #: kallithea/templates/admin/gists/index.html:8
 #: kallithea/templates/admin/gists/index.html:18
-#, fuzzy, python-format
+#, python-format
 msgid "Public Gists for User %s"
 msgstr "Publiczne Gists użytkownika %s"
 
@@ -2345,7 +2345,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr "Utwórz Nowy Gist"
 
@@ -2381,23 +2381,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2425,7 +2427,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2485,7 +2487,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr "Moje konto"
 
@@ -2495,33 +2497,35 @@
 msgstr "Profil"
 
 #: kallithea/templates/admin/my_account/my_account.html:26
-#, fuzzy
 msgid "Email Addresses"
-msgstr "Nowy adres e-mail"
-
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
-msgid "API Keys"
-msgstr ""
+msgstr "Adresy e-mail"
 
 #: kallithea/templates/admin/my_account/my_account.html:29
-#, fuzzy
-msgid "Owned Repositories"
-msgstr "repozytoria"
-
-#: kallithea/templates/admin/my_account/my_account.html:30
-#: kallithea/templates/journal/journal.html:33
-#, fuzzy
-msgid "Watched Repositories"
-msgstr "Utwórz repozytorium"
+#: kallithea/templates/admin/users/user_edit.html:32
+msgid "SSH Keys"
+msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
+msgid "API Keys"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:32
+msgid "Owned Repositories"
+msgstr "Posiadane repozytoria"
+
+#: kallithea/templates/admin/my_account/my_account.html:33
+#: kallithea/templates/journal/journal.html:33
+msgid "Watched Repositories"
+msgstr "Obserwowane repozytoria"
+
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 #, fuzzy
 msgid "Show Permissions"
-msgstr "Skopiuj uprawnienia"
+msgstr "Pokaż uprawnienia"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:5
 #: kallithea/templates/admin/users/user_edit_api_keys.html:5
@@ -2536,9 +2540,8 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:29
 #: kallithea/templates/admin/users/user_edit_api_keys.html:29
-#, fuzzy
 msgid "Expired"
-msgstr "Wygasa"
+msgstr "Wygasło"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:39
@@ -2547,10 +2550,11 @@
 msgstr "Potwierdź, aby usunąć to ip: %s"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
-#, fuzzy
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 msgid "Remove"
-msgstr "Usunięto"
+msgstr "Usuń"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:48
 #: kallithea/templates/admin/users/user_edit_api_keys.html:48
@@ -2562,16 +2566,18 @@
 #: kallithea/templates/admin/users/user_edit_api_keys.html:56
 #, fuzzy
 msgid "New API key"
-msgstr "Nowe pole klucza"
+msgstr "Nowe pole klucza API"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr "Dodaj"
 
@@ -2605,9 +2611,8 @@
 
 #: kallithea/templates/admin/my_account/my_account_emails.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:30
-#, fuzzy
 msgid "No additional emails specified."
-msgstr "Brak dodatkowych emaili"
+msgstr "Brak dodatkowych emaili."
 
 #: kallithea/templates/admin/my_account/my_account_emails.html:39
 #: kallithea/templates/admin/users/user_edit_emails.html:39
@@ -2615,9 +2620,8 @@
 msgstr "Nowy adres e-mail"
 
 #: kallithea/templates/admin/my_account/my_account_password.html:1
-#, fuzzy
 msgid "Change Your Account Password"
-msgstr "Nowe hasło"
+msgstr "Zmień hasło"
 
 #: kallithea/templates/admin/my_account/my_account_password.html:8
 msgid "Current password"
@@ -2649,10 +2653,9 @@
 
 #: kallithea/templates/admin/my_account/my_account_profile.html:10
 #: kallithea/templates/admin/users/user_edit_profile.html:10
-#, fuzzy, python-format
-#| msgid "Change your avatar at"
+#, python-format
 msgid "Change %s avatar at"
-msgstr "Zmiana awataru na"
+msgstr "Zmiana awataru %s na"
 
 #: kallithea/templates/admin/my_account/my_account_profile.html:12
 #: kallithea/templates/admin/users/user_edit_profile.html:12
@@ -2660,9 +2663,8 @@
 msgstr "Avatary są wyłączone"
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:1
-#, fuzzy
 msgid "Repositories You Own"
-msgstr "Nie znaleziono repozytorium."
+msgstr "Twoje repozytoria"
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:13
 #: kallithea/templates/admin/my_account/my_account_watched.html:13
@@ -2676,15 +2678,54 @@
 msgid "Name"
 msgstr "Nazwa"
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+#, fuzzy
+#| msgid "Last Name"
+msgid "Last Used"
+msgstr "Nazwisko"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, fuzzy, python-format
+msgid "Confirm to remove this SSH key: %s"
+msgstr "Potwierdź, aby usunąć to ip: %s"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+#, fuzzy
+msgid "New SSH key"
+msgstr "Nowe pole klucza API"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+#, fuzzy
+#| msgid "Public Gist"
+msgid "Public key"
+msgstr "Publiczny Gist"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
-#, fuzzy
 msgid "Repositories You are Watching"
-msgstr "Położenie repozytorium"
+msgstr "Repozytoria które obserwujesz"
 
 #: kallithea/templates/admin/permissions/permissions.html:5
 #: kallithea/templates/admin/permissions/permissions.html:11
 #: kallithea/templates/base/base.html:60
-#, fuzzy
 msgid "Default Permissions"
 msgstr "Domyślne uprawnienia"
 
@@ -2694,8 +2735,7 @@
 msgstr "Globalne"
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
-#, fuzzy
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr "Lista dozwolonych adresów IP"
 
@@ -2704,10 +2744,8 @@
 msgstr "Dostęp anonimowy"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:8
-#, fuzzy
-#| msgid "Anonymous access"
 msgid "Allow anonymous access"
-msgstr "Dostęp anonimowy"
+msgstr "Zezwalaj na dostęp anonimowy"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:10
 #, python-format
@@ -2727,9 +2765,8 @@
 "niestandardowe uprawnienia w repozytoriach zostaną utracone"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:20
-#, fuzzy
 msgid "Apply to all existing repositories"
-msgstr "Istniejące repozytorium?"
+msgstr "Zastosuj do wszystkich Istniejących repozytoriów"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:23
 msgid "Permissions for the Default user on new repositories."
@@ -2737,7 +2774,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2754,9 +2791,8 @@
 "niestandardowe uprawnienia w repozytoriach zostaną utracone"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:33
-#, fuzzy
 msgid "Apply to all existing repository groups"
-msgstr "Usuń ta grupę repozytoriów"
+msgstr "Zastosuj do wszystkich istniejących grup repozytoriów"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:36
 msgid "Permissions for the Default user on new repository groups."
@@ -2768,7 +2804,6 @@
 msgstr "Grupa użytkownika"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:45
-#, fuzzy
 msgid ""
 "All default permissions on each user group will be reset to chosen "
 "permission, note that all custom default permission on user groups will "
@@ -2787,9 +2822,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:53
-#, fuzzy
 msgid "Top level repository creation"
-msgstr "Tworzenie repozytorium"
+msgstr "Tworzenie repozytoriów najwyższego poziomu"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:56
 msgid ""
@@ -2839,20 +2873,20 @@
 
 #: kallithea/templates/admin/permissions/permissions_ips.html:12
 #: kallithea/templates/admin/users/user_edit_ips.html:22
-#, fuzzy, python-format
+#, python-format
 msgid "Confirm to delete this IP address: %s"
-msgstr "Potwierdź, aby usunąć to ip: %s"
+msgstr "Potwierdź, aby usunąć to IP: %s"
 
 #: kallithea/templates/admin/permissions/permissions_ips.html:18
 #: kallithea/templates/admin/users/user_edit_ips.html:29
 #, fuzzy
 msgid "All IP addresses are allowed."
-msgstr "Wszystkie adresy IP są dozwolone"
+msgstr "Wszystkie adresy IP są dozwolone."
 
 #: kallithea/templates/admin/permissions/permissions_ips.html:25
 #: kallithea/templates/admin/users/user_edit_ips.html:37
 msgid "New IP address"
-msgstr "Nowy adres ip"
+msgstr "Nowy adres IP"
 
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:11
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:11
@@ -2873,7 +2907,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:42
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:19
 msgid "Group parent"
-msgstr "Rodzic gropy"
+msgstr "Rodzic grupy"
 
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:49
 #: kallithea/templates/admin/repos/repo_add_base.html:35
@@ -2907,7 +2941,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr "Zaawansowane"
 
@@ -2952,7 +2986,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:25
 msgid "Delete this repository group"
-msgstr "Usuń ta grupę repozytoriów"
+msgstr "Usuń tę grupę repozytoriów"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 msgid "Not visible"
@@ -2962,19 +2996,19 @@
 #, fuzzy
 #| msgid "Disabled"
 msgid "Visible"
-msgstr "Wyłączone"
+msgstr "Widoczne"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #, fuzzy
 #| msgid "Add Repository"
 msgid "Add repos"
-msgstr "Dodaj Repozytorium"
+msgstr "Dodaj Repozytoria"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10
 #, fuzzy
 #| msgid "Add user group"
 msgid "Add/Edit groups"
-msgstr "Dodaj grupę użytkowników"
+msgstr "Dodaj/edytuj grupę użytkowników"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:11
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:11
@@ -3001,7 +3035,7 @@
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:71
 #, fuzzy
 msgid "Revoke"
-msgstr "odwołane"
+msgstr "odwołaj"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:81
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:77
@@ -3024,29 +3058,21 @@
 "private repositories and other groups if selected."
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-"Włącz blokowanie pobierania przez grupy. Opcja ta będzie stosowana do "
-"wszystkich innych grup i repozytoriów wewnątrz"
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 #, fuzzy
 msgid "Remove this group"
-msgstr "Tworzenie grup użytkowników"
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+msgstr "Usuń tę grupę użytkowników"
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 #, fuzzy
 msgid "Confirm to delete this group"
-msgstr "Potwierdź usunięcie grupy użytkowników: %s"
+msgstr "Potwierdź usunięcie grupy użytkowników"
 
 #: kallithea/templates/admin/repo_groups/repo_group_show.html:4
 #, fuzzy, python-format
 #| msgid "Repository Group: %s"
 msgid "Repository group %s"
-msgstr "Grupa Repozytoriów: %s"
+msgstr "Grupa Repozytoriów %s"
 
 #: kallithea/templates/admin/repo_groups/repo_groups.html:5
 #, fuzzy
@@ -3061,7 +3087,7 @@
 #: kallithea/templates/admin/repos/repo_add_base.html:12
 #, fuzzy
 msgid "Clone remote repository"
-msgstr "[utworzone] repozytorium"
+msgstr "Klonuj zdalne repozytorium"
 
 #: kallithea/templates/admin/repos/repo_add_base.html:16
 msgid ""
@@ -3070,7 +3096,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
@@ -3078,7 +3104,7 @@
 "Powinna być krótka i na temat. Użyj pliku README dla dłuższych opisów."
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr "Opcjonalnie wybierz grupę do wprowadzenia tego repozytorium."
@@ -3088,7 +3114,7 @@
 msgstr "Rodzaj repozytorium do stworzenia."
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr "Docelowa rewizja"
@@ -3102,7 +3128,7 @@
 #: kallithea/templates/admin/repos/repo_creating.html:9
 #, fuzzy, python-format
 msgid "%s Creating Repository"
-msgstr "utworzone repozytorium %s"
+msgstr "Tworzenie repozytorium %s"
 
 #: kallithea/templates/admin/repos/repo_creating.html:13
 msgid "Creating repository"
@@ -3141,15 +3167,15 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr "Statystyki"
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:1
 #, fuzzy
 msgid "Parent"
-msgstr "Rodzic gropy"
+msgstr "Rodzic grupy"
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:5
 msgid "Set"
@@ -3158,12 +3184,12 @@
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:7
 #, fuzzy
 msgid "Manually set this repository as a fork of another from the list."
-msgstr "Ręczne ustawienie rozwidlenia z listy"
+msgstr "Ręczne ustawienie rozwidlenia z listy."
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:20
 #, fuzzy
 msgid "Public Journal Visibility"
-msgstr "Dziennik publiczny"
+msgstr "Widoczność dziennika publicznego"
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:27
 msgid "Remove from public journal"
@@ -3172,7 +3198,7 @@
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:32
 #, fuzzy
 msgid "Add to Public Journal"
-msgstr "Dziennik publiczny"
+msgstr "Dodaj do dziennika publicznego"
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:37
 #, fuzzy
@@ -3181,62 +3207,20 @@
 "public journal."
 msgstr ""
 "Wszystkie działania wykonywane na tym repozytorium będą dostępne dla "
-"wszystkich w dzienniku publicznym"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-#, fuzzy
-msgid "Change Locking"
-msgstr "Włącz blokowanie"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-#, fuzzy
-msgid "Confirm to unlock repository."
-msgstr "Potwierdź odblokowanie repozytorium"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-#, fuzzy
-msgid "Unlock Repository"
-msgstr "Odblokowane repozytorium"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-#, fuzzy
-msgid "Confirm to lock repository."
-msgstr "Potwierdź blokowanie repozytorium"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-#, fuzzy
-msgid "Lock Repository"
-msgstr "Odblokowane repozytorium"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr "Repozytorium nie jest zablokowane"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
+"wszystkich w dzienniku publicznym."
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
 #: kallithea/templates/data_table/_dt_elements.html:68
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "Potwierdź usunięcie repozytorium: %s"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
 #, fuzzy
 msgid "Delete this Repository"
-msgstr "Usuń ta grupę repozytoriów"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+msgstr "Usuń to repozytorium"
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, fuzzy, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
@@ -3244,15 +3228,15 @@
 msgstr[1] "to repozytorium ma %s forki"
 msgstr[2] "to repozytorium ma %s forków"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr "Ustaw jako rozwidlenie"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr "Usuń rozwidlenie"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3271,7 +3255,7 @@
 "repository will be cached again."
 msgstr ""
 "Ręcznie unieważnienie cache dla tego repozytorium. Przy pierwszym "
-"dostępie do repozytorium zostanie dodany do bufora ponownie"
+"dostępie do repozytorium zostanie dodane do bufora ponownie."
 
 #: kallithea/templates/admin/repos/repo_edit_caches.html:9
 #, fuzzy
@@ -3329,7 +3313,7 @@
 #: kallithea/templates/admin/repos/repo_edit_fields.html:61
 #, fuzzy
 msgid "Extra fields are disabled."
-msgstr "Avatary są wyłączone"
+msgstr "Dodatkowe pola są wyłączone."
 
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:20
 #, fuzzy
@@ -3345,36 +3329,28 @@
 #: kallithea/templates/admin/repos/repo_edit_remote.html:7
 #, fuzzy
 msgid "Remote repository URL"
-msgstr "Utworzone repozytorium %s"
+msgstr "URL zdalnego repozytorium"
 
 #: kallithea/templates/admin/repos/repo_edit_remote.html:15
 #, fuzzy
 msgid "Pull Changes from Remote Repository"
-msgstr "[pobieranie z zdalnego] do repozytorium"
+msgstr "pobieranie zmian ze zdalnego repozytorium"
 
 #: kallithea/templates/admin/repos/repo_edit_remote.html:17
 #, fuzzy
 msgid "Confirm to pull changes from remote repository."
-msgstr "Potwierdź pull z zdalnej strony"
+msgstr "Potwierdź pobranie zmian ze zdalnego repozytorium."
 
 #: kallithea/templates/admin/repos/repo_edit_remote.html:23
 msgid "This repository does not have a remote repository URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-#, fuzzy
-msgid "Permanent Repository ID"
-msgstr "prywatne repozytorium"
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr ""
-
 #: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#, fuzzy
+msgid "Permanent URL"
+msgstr "Stałe ID repozytorium"
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3384,32 +3360,32 @@
 "other cases that you need to hardcode the URL into a 3rd party service."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 #, fuzzy
 msgid "Remote repository"
-msgstr "[utworzone] repozytorium"
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+msgstr "Zdalne repozytorium"
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 #, fuzzy
 msgid "Repository URL"
-msgstr "Repozytorium"
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+msgstr "URL Repozytorium"
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr "Wersja domyślna dla plików stronicowania, pobierania plików, readme"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr "Zmiana właściciela tego repozytorium."
 
@@ -3424,12 +3400,12 @@
 #: kallithea/templates/admin/repos/repo_edit_statistics.html:10
 #, fuzzy
 msgid "Reset Statistics"
-msgstr "%s Statystyki"
+msgstr "Resetuj Statystyki"
 
 #: kallithea/templates/admin/repos/repo_edit_statistics.html:10
 #, fuzzy
 msgid "Confirm to remove current statistics."
-msgstr "Potwierdź usunięcie aktualnych statystyk"
+msgstr "Potwierdź usunięcie aktualnych statystyk."
 
 #: kallithea/templates/admin/repos/repos.html:5
 #, fuzzy
@@ -3522,8 +3498,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 #, fuzzy
 msgid "Save Settings"
 msgstr "Zapisz ustawienia"
@@ -3535,7 +3511,7 @@
 #: kallithea/templates/admin/settings/settings_hooks.html:17
 #, fuzzy
 msgid "Custom Hooks"
-msgstr "Niestandardowa aktualizacja"
+msgstr "Niestandardowy Hook"
 
 #: kallithea/templates/admin/settings/settings_hooks.html:18
 msgid ""
@@ -3556,7 +3532,7 @@
 #: kallithea/templates/admin/settings/settings_mapping.html:9
 #, fuzzy
 msgid "Delete records of missing repositories"
-msgstr "Szukaj we wszystkich repozytoriach"
+msgstr "Usuń wpisy o brakujących repozytoriach"
 
 #: kallithea/templates/admin/settings/settings_mapping.html:12
 msgid ""
@@ -3624,10 +3600,6 @@
 msgid "Kallithea version"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr ""
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr ""
@@ -3643,21 +3615,13 @@
 #: kallithea/templates/admin/settings/settings_system.html:11
 #, fuzzy
 msgid "Git version"
-msgstr "Edycja Uprawnień"
+msgstr "Wersja Git"
 
 #: kallithea/templates/admin/settings/settings_system.html:12
 msgid "Git path"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr ""
 
@@ -3666,42 +3630,34 @@
 msgstr "Pokaż rozmiar repozytorium po wysłaniu zmian"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
-msgstr "Logi poleceń wysłania zmian użytkowników"
+msgid "Update repository after push (hg update)"
+msgstr "Aktualizacja repozytorium po wysłaniu zmian (aktualizacja hg)"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr "Logi poleceń połączenia gałęzi użytkowników"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
-msgid "Update repository after push (hg update)"
-msgstr "Aktualizacja repozytorium po wysłaniu zmian (aktualizacja hg)"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:33
 #, fuzzy
 msgid "Mercurial extensions"
 msgstr "Rozszerzenia Mercurial"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
-msgstr "Rozszerzenia dużych pliów"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+msgstr "Rozszerzenia dużych plików"
+
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr "Rozszerzenia hgsubversion"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:47
+#: kallithea/templates/admin/settings/settings_vcs.html:35
 msgid ""
 "Requires hgsubversion library to be installed. Enables cloning of remote "
 "Subversion repositories while converting them to Mercurial."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:59
+#: kallithea/templates/admin/settings/settings_vcs.html:47
 #, fuzzy
 msgid "Location of repositories"
-msgstr "Ogólna liczba repozytoriów"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+msgstr "Położenie repozytoriów"
+
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
@@ -3709,7 +3665,7 @@
 "Kliknij, aby odblokować. Musisz ponownie uruchomić Kallithea żeby "
 "wprowadzić to ustawienie w życie."
 
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3759,10 +3715,9 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-#, fuzzy
-msgid "Clone URL"
-msgstr "Url klonowania"
+#, fuzzy
+msgid "HTTP Clone URL"
+msgstr "URL klonowania"
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
 msgid ""
@@ -3779,60 +3734,76 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+#, fuzzy
+msgid "SSH Clone URL"
+msgstr "URL klonowania"
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 #, fuzzy
 #| msgid "Repository Size"
 msgid "Repository page size"
 msgstr "Rozmiar Repozytorium"
 
-#: kallithea/templates/admin/settings/settings_visual.html:57
+#: kallithea/templates/admin/settings/settings_visual.html:68
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:62
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:70
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr "Ikony"
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
 msgstr "Pokazuj w publicznym repo ikonę w repozytoriach"
 
-#: kallithea/templates/admin/settings/settings_visual.html:81
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr "Pokazuj w prywatnym repo ikonę w repozytoriach"
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 #, fuzzy
 msgid "Show public/private icons next to repository names."
-msgstr "Pokazuj w publicznym repo ikonę w repozytoriach"
-
-#: kallithea/templates/admin/settings/settings_visual.html:89
+msgstr "Pokazuj  ikonę publiczne/prywatne repo w repozytoriach."
+
+#: kallithea/templates/admin/settings/settings_visual.html:100
 #, fuzzy
 msgid "Meta Tagging"
 msgstr "Tagowanie meta"
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr ""
 
@@ -3866,7 +3837,7 @@
 #: kallithea/templates/admin/user_groups/user_group_edit.html:33
 #, fuzzy
 msgid "Show Members"
-msgstr "użytkownik"
+msgstr "Pokaż użytkowników"
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:1
 #, python-format
@@ -3877,7 +3848,7 @@
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:23
 #: kallithea/templates/admin/user_groups/user_groups.html:40
 msgid "Members"
-msgstr "Użytkownik"
+msgstr "Użytkownicy"
 
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
 #: kallithea/templates/data_table/_dt_elements.html:102
@@ -3904,7 +3875,7 @@
 #: kallithea/templates/admin/user_groups/user_groups.html:5
 #, fuzzy
 msgid "User Groups Administration"
-msgstr "Użytkownicy grupy administracji"
+msgstr "Administracja grup użytkowników"
 
 #: kallithea/templates/admin/users/user_add.html:5
 msgid "Add user"
@@ -3996,19 +3967,19 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr "Repozytorium mercurial"
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr "Repozytorium git"
 
 #: kallithea/templates/base/base.html:115
 #, fuzzy
 msgid "Create Fork"
-msgstr "Usuń rozwidlenie"
+msgstr "Stwórz rozwidlenie"
 
 #: kallithea/templates/base/base.html:127
 #: kallithea/templates/summary/summary.html:9
@@ -4051,168 +4022,142 @@
 msgstr "Porównaj"
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr "Szukaj"
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr "Odblokowany"
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr "zablokowane"
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr "Obserwuj"
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr "Nie obserwuj"
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr "Gałąź"
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr "Stwórz nowe żądanie połączenia gałęzi"
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr "Przełącz do"
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr ""
 
-#: kallithea/templates/base/base.html:296
+#: kallithea/templates/base/base.html:289
 msgid "Show recent activity"
 msgstr "Pokaż ostatnią aktywność"
 
+#: kallithea/templates/base/base.html:295
+#: kallithea/templates/base/base.html:296
+msgid "Public journal"
+msgstr "Dziennik publiczny"
+
+#: kallithea/templates/base/base.html:301
+msgid "Show public gists"
+msgstr "Wyświetl publiczne gists"
+
 #: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
-msgid "Public journal"
-msgstr "Dziennik publiczny"
-
-#: kallithea/templates/base/base.html:308
-msgid "Show public gists"
-msgstr "Wyświetl publiczne gists"
-
-#: kallithea/templates/base/base.html:309
 msgid "Gists"
 msgstr "Gists"
 
-#: kallithea/templates/base/base.html:313
+#: kallithea/templates/base/base.html:306
 #, fuzzy
 msgid "All Public Gists"
 msgstr "Wszystkie publiczne gists"
 
-#: kallithea/templates/base/base.html:315
+#: kallithea/templates/base/base.html:308
 #, fuzzy
 msgid "My Public Gists"
 msgstr "Moje publiczne gists"
 
-#: kallithea/templates/base/base.html:316
+#: kallithea/templates/base/base.html:309
 #, fuzzy
 msgid "My Private Gists"
 msgstr "Moje prywatne gists"
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr "Szukaj we wszystkich repozytoriach"
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 #, fuzzy
 msgid "My Pull Requests"
-msgstr "Połączone gałęzie"
-
-#: kallithea/templates/base/base.html:360
+msgstr "Moje połączone gałęzie"
+
+#: kallithea/templates/base/base.html:353
 #, fuzzy
 msgid "Not Logged In"
-msgstr "Zaloguj się"
-
-#: kallithea/templates/base/base.html:369
+msgstr "Niezalogowany"
+
+#: kallithea/templates/base/base.html:362
 #, fuzzy
 msgid "Login to Your Account"
 msgstr "Zaloguj się do swojego konta"
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 #, fuzzy
 #| msgid "Forgot password ?"
 msgid "Forgot password?"
 msgstr "Nie pamiętasz hasła?"
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 #, fuzzy
 #| msgid "Don't have an account ?"
 msgid "Don't have an account?"
 msgstr "Nie masz konta?"
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr "Wyloguj się"
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-#, fuzzy
-msgid "Inherit defaults"
-msgstr "Repozytoria domyślne"
+msgid "Create repositories"
+msgstr "Utwórz repozytorium"
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-#, fuzzy
-#| msgid "Default permissions"
-msgid "default permissions"
-msgstr "Domyślne uprawnienia"
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr "Utwórz repozytorium"
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 "Wybierz tę opcję, aby umożliwić stworzenie repozytorium dla tego "
 "użytkownika"
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr "Tworzenie grup użytkowników"
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 "Wybierz tę opcję, aby umożliwić utworzenie grupy użytkowników dla tego "
 "użytkownika"
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr "Rozwidlenie repozytorium"
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 "Wybierz tę opcję, aby umożliwić rozwidlania repozytorium dla tego "
@@ -4255,7 +4200,7 @@
 #, fuzzy
 #| msgid "Enable downloads"
 msgid "Unable to post"
-msgstr "Włącz pobieranie"
+msgstr "Nie można opublikować"
 
 #: kallithea/templates/base/root.html:31
 #, fuzzy
@@ -4323,7 +4268,7 @@
 #: kallithea/templates/base/root.html:45
 #, fuzzy
 msgid "No revisions"
-msgstr "rewizja"
+msgstr "Brak sprawdzenia"
 
 #: kallithea/templates/base/root.html:46
 msgid "Type name of user or member to grant permission"
@@ -4336,7 +4281,7 @@
 #: kallithea/templates/base/root.html:48
 #, fuzzy
 msgid "Confirm to revoke permission for {0}: {1} ?"
-msgstr "potwierdzić odwołanie pozwolenie na {0}: {1} ?"
+msgstr "potwierdzić odwołanie pozwolenia na {0}: {1} ?"
 
 #: kallithea/templates/base/root.html:51
 #: kallithea/templates/compare/compare_diff.html:108
@@ -4388,7 +4333,7 @@
 #: kallithea/templates/changelog/changelog.html:54
 #, fuzzy
 msgid "Go to tip of repository"
-msgstr "Potwierdź blokowanie repozytorium"
+msgstr "Idź do początku repozytorium"
 
 #: kallithea/templates/changelog/changelog.html:59
 #: kallithea/templates/forks/forks_data.html:16
@@ -4399,13 +4344,13 @@
 #: kallithea/templates/changelog/changelog.html:61
 #, fuzzy, python-format
 msgid "Compare fork with parent repository (%s)"
-msgstr "porównaj gałęzie %s"
+msgstr "porównaj gałęzie (%s)"
 
 #: kallithea/templates/changelog/changelog.html:65
 #: kallithea/templates/files/files.html:29
 #, fuzzy
 msgid "Branch filter:"
-msgstr "filtr"
+msgstr "filtr gałęzi:"
 
 #: kallithea/templates/changelog/changelog.html:221
 msgid "There are no changes yet"
@@ -4459,7 +4404,7 @@
 #: kallithea/templates/changelog/changelog_table.html:41
 #, fuzzy, python-format
 msgid "Changeset status: %s by %s"
-msgstr "Status grupy zmian: %s"
+msgstr "Status grupy zmian: %s przez %s"
 
 #: kallithea/templates/changelog/changelog_table.html:60
 msgid "Expand commit message"
@@ -4470,7 +4415,7 @@
 #| msgid "%d comment"
 #| msgid_plural "%d comments"
 msgid "%s comments"
-msgstr "%d komentarz"
+msgstr "%s komentarz"
 
 #: kallithea/templates/changelog/changelog_table.html:80
 #: kallithea/templates/changeset/changeset.html:63
@@ -4528,7 +4473,7 @@
 #: kallithea/templates/changeset/changeset.html:96
 #, fuzzy
 msgid "Grafted from:"
-msgstr "Utworzono"
+msgstr "Połączono z:"
 
 #: kallithea/templates/changeset/changeset.html:102
 msgid "Transplanted from:"
@@ -4537,12 +4482,12 @@
 #: kallithea/templates/changeset/changeset.html:108
 #, fuzzy
 msgid "Replaced by:"
-msgstr "utworzono"
+msgstr "Zastąpiono przez:"
 
 #: kallithea/templates/changeset/changeset.html:122
 #, fuzzy
 msgid "Preceded by:"
-msgstr "utworzono"
+msgstr "Poprzedzone przez:"
 
 #: kallithea/templates/changeset/changeset.html:139
 #: kallithea/templates/compare/compare_diff.html:59
@@ -4587,7 +4532,7 @@
 #: kallithea/templates/changeset/changeset_file_comment.html:22
 #, fuzzy
 msgid "No title"
-msgstr "nowy plik"
+msgstr "Brak tytułu"
 
 #: kallithea/templates/changeset/changeset_file_comment.html:24
 #, fuzzy
@@ -4597,20 +4542,20 @@
 #: kallithea/templates/changeset/changeset_file_comment.html:30
 #, fuzzy
 msgid "Delete comment?"
-msgstr "%d komentarz"
+msgstr "Usunąć komentarz?"
 
 #: kallithea/templates/changeset/changeset_file_comment.html:38
 #: kallithea/templates/changeset/changeset_file_comment.html:71
 #, fuzzy
 msgid "Status change"
-msgstr "Ostatnia aktywność"
+msgstr "Ostatnia zmiana"
 
 #: kallithea/templates/changeset/changeset_file_comment.html:87
 #, fuzzy
 msgid "Comments are in plain text. Use @username to notify another user."
 msgstr ""
-"Użyj @username wewnątrz tego tekstu, aby wysłać powiadomienie do "
-"użytkownika strony"
+"Komentarz są w surowym tekście. Użyj @username wewnątrz tego tekstu, aby "
+"wysłać powiadomienie do użytkownika strony."
 
 #: kallithea/templates/changeset/changeset_file_comment.html:93
 #, fuzzy
@@ -4643,7 +4588,7 @@
 
 #: kallithea/templates/changeset/changeset_file_comment.html:137
 msgid "You need to be logged in to comment."
-msgstr "Musisz być zalogowany żeby komentarz."
+msgstr "Musisz być zalogowany żeby dodać komentarz."
 
 #: kallithea/templates/changeset/changeset_file_comment.html:137
 msgid "Login now"
@@ -4710,18 +4655,18 @@
 #: kallithea/templates/changeset/diff_block.html:42
 #, fuzzy
 msgid "Deleted"
-msgstr "usuń"
+msgstr "Usunięty"
 
 #: kallithea/templates/changeset/diff_block.html:44
 #, fuzzy
 msgid "Renamed"
-msgstr "zmień nazwę"
+msgstr "Zmieniono nazwę"
 
 #: kallithea/templates/changeset/diff_block.html:48
 #, fuzzy, python-format
 #| msgid "Unknown revision %s"
 msgid "Unknown operation: %r"
-msgstr "Nieznana wersja %s"
+msgstr "Nieznane działanie: %r"
 
 #: kallithea/templates/changeset/diff_block.html:52
 #, fuzzy
@@ -4747,7 +4692,7 @@
 
 #: kallithea/templates/changeset/diff_block.html:72
 msgid "Show inline comments"
-msgstr "Pokaż online komentarz"
+msgstr "Pokaż wewnętrzne komentarze"
 
 #: kallithea/templates/compare/compare_cs.html:5
 msgid "No changesets"
@@ -4777,7 +4722,7 @@
 #: kallithea/templates/compare/compare_cs.html:54
 #, fuzzy
 msgid "is"
-msgstr "Gist"
+msgstr "jest"
 
 #: kallithea/templates/compare/compare_cs.html:55
 #, fuzzy, python-format
@@ -4853,13 +4798,13 @@
 #, fuzzy, python-format
 #| msgid "%(user)s commented on changeset %(age)s"
 msgid "Mention in Comment on Changeset \"%s\""
-msgstr "%(user)s skomentował zatwierdzenie %(when)s"
+msgstr "Skomentowano zatwierdzenie \"%s\""
 
 #: kallithea/templates/email_templates/changeset_comment.html:4
 #, fuzzy, python-format
 #| msgid "%(user)s commented on changeset %(age)s"
 msgid "Comment on Changeset \"%s\""
-msgstr "%(user)s skomentował zatwierdzenie %(when)s"
+msgstr "Skomentowano zatwierdzenie %s"
 
 #: kallithea/templates/email_templates/changeset_comment.html:20
 #, fuzzy
@@ -4887,13 +4832,13 @@
 #, fuzzy
 #| msgid "Status change"
 msgid "Status change:"
-msgstr "Ostatnia aktywność"
+msgstr "Ostatnia aktywność:"
 
 #: kallithea/templates/email_templates/comment.html:33
 #, fuzzy
 #| msgid "Repository has been locked"
 msgid "The pull request has been closed."
-msgstr "Repozytorium nie jest zablokowane"
+msgstr "Żądanie połączenia zmian zostało zamknięte."
 
 #: kallithea/templates/email_templates/password_reset.html:9
 #, python-format
@@ -4994,7 +4939,7 @@
 msgstr "%s Pliki różnic"
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr "Pliki %s"
@@ -5006,7 +4951,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr ""
 
@@ -5036,7 +4981,7 @@
 #: kallithea/templates/files/files_add.html:53
 #, fuzzy
 msgid "New file type"
-msgstr "nowy plik"
+msgstr "nowy typ pliku"
 
 #: kallithea/templates/files/files_add.html:64
 #: kallithea/templates/files/files_delete.html:34
@@ -5060,7 +5005,7 @@
 msgstr "Wczytywanie listy plików..."
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr "Rozmiar"
 
@@ -5076,7 +5021,7 @@
 #: kallithea/templates/files/files_browser.html:58
 #, fuzzy
 msgid "Last Committer"
-msgstr "Autor"
+msgstr "Ostatni komentujący"
 
 #: kallithea/templates/files/files_delete.html:4
 #, python-format
@@ -5143,7 +5088,7 @@
 #, fuzzy, python-format
 #| msgid "Deleted branch: %s"
 msgid "Edit on Branch: %s"
-msgstr "Usunięta gałąź: %s"
+msgstr "Edycja gałęzi: %s"
 
 #: kallithea/templates/files/files_source.html:37
 msgid "Editing binary files not allowed"
@@ -5167,17 +5112,17 @@
 #: kallithea/templates/files/files_source.html:69
 #, fuzzy
 msgid "File is too big to display."
-msgstr "Plik jest za duży do wyświetlenia"
+msgstr "Plik jest za duży do wyświetlenia."
 
 #: kallithea/templates/files/files_source.html:71
 #, fuzzy
 msgid "Show full annotation anyway."
-msgstr "Pokaż pełną historię"
+msgstr "Pokaż pełną historię."
 
 #: kallithea/templates/files/files_source.html:73
 #, fuzzy
 msgid "Show as raw."
-msgstr "wyświetl jako raw"
+msgstr "wyświetl jako raw."
 
 #: kallithea/templates/files/files_ypjax.html:5
 msgid "annotation"
@@ -5197,8 +5142,8 @@
 msgstr "Obserwatorzy %s"
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr "Obserwuje"
 
@@ -5218,7 +5163,9 @@
 #: kallithea/templates/forks/fork.html:53
 #, fuzzy
 msgid "Default revision for files page, downloads, whoosh, and readme."
-msgstr "Wersja domyślna dla plików stronicowania, pobierania plików, readme"
+msgstr ""
+"Wersja domyślna dla plików stronicowania, pobierania plików, whoosh i "
+"readme."
 
 #: kallithea/templates/forks/fork.html:58
 msgid "Private"
@@ -5250,8 +5197,8 @@
 msgstr "Gałąź %s"
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr "Gałęzie"
 
@@ -5329,12 +5276,12 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:6
 #, fuzzy
 msgid "No entries"
-msgstr "Brak wpisów jeszcze"
+msgstr "Brak wpisów"
 
 #: kallithea/templates/pullrequests/pullrequest_data.html:14
 #, fuzzy
 msgid "Vote"
-msgstr "odwołane"
+msgstr "Głosuj"
 
 #: kallithea/templates/pullrequests/pullrequest_data.html:17
 msgid "Age"
@@ -5370,7 +5317,7 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:67
 #, fuzzy
 msgid "Delete Pull Request"
-msgstr "Nowa prośba o połączenie gałęzi"
+msgstr "Usuń prośbę o połączenie gałęzi"
 
 #: kallithea/templates/pullrequests/pullrequest_data.html:68
 msgid "Confirm to delete this pull request"
@@ -5384,7 +5331,7 @@
 #: kallithea/templates/pullrequests/pullrequest_show.html:6
 #, fuzzy, python-format
 msgid "%s Pull Request %s"
-msgstr "%s Połączonych gałęzi #%s"
+msgstr "%s Połączonych gałęzi %s"
 
 #: kallithea/templates/pullrequests/pullrequest_show.html:10
 #, fuzzy, python-format
@@ -5394,7 +5341,7 @@
 #: kallithea/templates/pullrequests/pullrequest_show.html:54
 #, fuzzy
 msgid "Summarize the changes"
-msgstr "Zatwierdź zmiany"
+msgstr "Podsumuj zmiany"
 
 #: kallithea/templates/pullrequests/pullrequest_show.html:67
 msgid "Voting Result"
@@ -5412,7 +5359,7 @@
 #: kallithea/templates/pullrequests/pullrequest_show.html:86
 #, fuzzy
 msgid "on"
-msgstr "brak"
+msgstr "na"
 
 #: kallithea/templates/pullrequests/pullrequest_show.html:92
 msgid "Target"
@@ -5432,7 +5379,7 @@
 #, fuzzy
 #| msgid "Registration"
 msgid "Next iteration"
-msgstr "Rejestracja"
+msgstr "Następne działanie"
 
 #: kallithea/templates/pullrequests/pullrequest_show.html:153
 msgid "Current revision - no change"
@@ -5455,18 +5402,18 @@
 #: kallithea/templates/pullrequests/pullrequest_show.html:189
 #, fuzzy
 msgid "Cancel Changes"
-msgstr "Ostatnia aktywność"
+msgstr "Anuluj zmiany"
 
 #: kallithea/templates/pullrequests/pullrequest_show.html:197
 #, fuzzy
 #| msgid "reviewer"
 msgid "Reviewers"
-msgstr "recenzent"
+msgstr "recenzenci"
 
 #: kallithea/templates/pullrequests/pullrequest_show.html:223
 #, fuzzy
 msgid "Remove reviewer"
-msgstr "recenzent"
+msgstr "Usuń recenzenta"
 
 #: kallithea/templates/pullrequests/pullrequest_show.html:234
 msgid "Type name of reviewer to add"
@@ -5475,7 +5422,7 @@
 #: kallithea/templates/pullrequests/pullrequest_show.html:240
 #, fuzzy
 msgid "Potential Reviewers"
-msgstr "Podgląd komentarza"
+msgstr "Potencjalni recenzenci"
 
 #: kallithea/templates/pullrequests/pullrequest_show.html:243
 msgid "Click to add the repository owner as reviewer:"
@@ -5484,12 +5431,12 @@
 #: kallithea/templates/pullrequests/pullrequest_show.html:268
 #, fuzzy
 msgid "Pull Request Content"
-msgstr "Wniosek połączenia zmienił status"
+msgstr "Zawartość żądania połączenia"
 
 #: kallithea/templates/pullrequests/pullrequest_show.html:283
 #, fuzzy
 msgid "Common ancestor"
-msgstr "Skomentuj grupę zmian"
+msgstr "Wspólny przodek"
 
 #: kallithea/templates/pullrequests/pullrequest_show_all.html:6
 #, python-format
@@ -5499,12 +5446,12 @@
 #: kallithea/templates/pullrequests/pullrequest_show_all.html:11
 #, fuzzy, python-format
 msgid "Pull Requests from '%s'"
-msgstr "Połączonych gałęzi #%s"
+msgstr "Połączonych gałęzi z \"%s\""
 
 #: kallithea/templates/pullrequests/pullrequest_show_all.html:13
 #, fuzzy, python-format
 msgid "Pull Requests to '%s'"
-msgstr "Połączonych gałęzi #%s"
+msgstr "Połączonych gałęzi z \"%s\""
 
 #: kallithea/templates/pullrequests/pullrequest_show_all.html:31
 #, fuzzy
@@ -5519,7 +5466,7 @@
 #: kallithea/templates/pullrequests/pullrequest_show_all.html:36
 #, fuzzy, python-format
 msgid "Show Pull Requests from '%s'"
-msgstr "Pokaż Prośby Pobrania %s"
+msgstr "Pokaż Prośby Pobrania \"%s\""
 
 #: kallithea/templates/pullrequests/pullrequest_show_all.html:44
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:28
@@ -5540,12 +5487,12 @@
 #, fuzzy
 #| msgid "Pull Request Reviewers"
 msgid "Pull Requests Needing My Review"
-msgstr "Recenzje wniosków połączenia gałęzi"
+msgstr "Żądania połączenia gałęzi wymagające mojej recenzji"
 
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:40
 #, fuzzy
 msgid "Pull Requests I Participate In"
-msgstr "Biorę udział w"
+msgstr "Żądania połączenia gałęzi w których biorę udział"
 
 #: kallithea/templates/search/search.html:6
 #, python-format
@@ -5578,9 +5525,9 @@
 msgid "File names"
 msgstr "Nazwy plików"
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr "Brak uprawnień"
 
@@ -5590,20 +5537,20 @@
 msgstr "%s Statystyki"
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr "%s ATOM"
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr "%s RSS"
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr "Włącz"
 
@@ -5612,12 +5559,12 @@
 msgstr "Statystyki zebrane: "
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr "pliki"
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr "Pokaż więcej"
 
@@ -5658,98 +5605,189 @@
 msgid "%s Summary"
 msgstr "Podsumowanie %s"
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr "Repozytorium zablokowane przez %s"
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr "Repozytorium odblokowane"
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr "Gałąź z"
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr "Klonuj z"
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr "Pokaż ID"
-
+#: kallithea/templates/summary/summary.html:54
+#, fuzzy
+msgid "Clone URL"
+msgstr "URL klonowania"
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr "Pokaż nazwę"
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+#, fuzzy
+#| msgid "Last Name"
+msgid "Use Name"
+msgstr "Nazwisko"
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr "Statystyki"
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr "Pobierz"
 
-#: kallithea/templates/summary/summary.html:101
+#: kallithea/templates/summary/summary.html:109
 msgid "There are no downloads yet"
 msgstr "Nie pobrano jeszcze plików"
 
-#: kallithea/templates/summary/summary.html:103
+#: kallithea/templates/summary/summary.html:111
 msgid "Downloads are disabled for this repository"
 msgstr "Pliki do pobrania są zostały wyłączone dla tego repozytorium"
 
-#: kallithea/templates/summary/summary.html:109
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr "Pobierz jako zip"
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr "Zaznacz tu żeby pobrać archiwum z subrepozytorium"
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 #, fuzzy
 msgid "With subrepos"
 msgstr "z subrepozytorium"
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr "Kanał RSS"
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 #, fuzzy
 msgid "Latest Changes"
-msgstr "Ostatnia aktywność"
-
-#: kallithea/templates/summary/summary.html:177
+msgstr "Ostatnie zmiany"
+
+#: kallithea/templates/summary/summary.html:185
 #, fuzzy
 msgid "Quick Start"
 msgstr "Szybki start"
 
-#: kallithea/templates/summary/summary.html:188
+#: kallithea/templates/summary/summary.html:196
 msgid "Add or upload files directly via Kallithea"
 msgstr "Dodaj lub prześlij pliki bezpośrednio przez stronę"
 
-#: kallithea/templates/summary/summary.html:196
+#: kallithea/templates/summary/summary.html:204
 #, fuzzy
 msgid "Push new repository"
 msgstr "Wyślij zmiany do nowego repo"
 
-#: kallithea/templates/summary/summary.html:204
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr "Istniejące repozytorium?"
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr "Pobierz %s jak %s"
 
+#~ msgid "This repository has been locked by %s on %s"
+#~ msgstr "Repozytorium zostało zablokowane przez %s na %s"
+
+#~ msgid "Repository has been locked"
+#~ msgstr "Repozytorium zostało zablokowane"
+
+#~ msgid "Repository has been unlocked"
+#~ msgstr "Repozytorium zostało odblokowane"
+
+#~ msgid "An error occurred during unlocking"
+#~ msgstr "Wystąpił błąd podczas odblokowywania"
+
+#~ msgid "Token mismatch"
+#~ msgstr "Niezgodność tokenu"
+
+#~ msgid "Enable locking"
+#~ msgstr "Włącz blokowanie"
+
+#~ msgid "Enable lock-by-pulling on repository."
+#~ msgstr "Włącz blokowanie pobierania w repozytorium."
+
+#~ msgid ""
+#~ "Enable lock-by-pulling on group. This option will be applied to all "
+#~ "other groups and repositories inside"
+#~ msgstr ""
+#~ "Włącz blokowanie pobierania przez grupy. Opcja ta będzie stosowana do "
+#~ "wszystkich innych grup i repozytoriów wewnątrz"
+
+#, fuzzy
+#~ msgid "Change Locking"
+#~ msgstr "Włącz blokowanie"
+
+#, fuzzy
+#~ msgid "Confirm to unlock repository."
+#~ msgstr "Potwierdź odblokowanie repozytorium."
+
+#, fuzzy
+#~ msgid "Unlock Repository"
+#~ msgstr "Odblokuj repozytorium"
+
+#, fuzzy
+#~ msgid "Confirm to lock repository."
+#~ msgstr "Potwierdź blokowanie repozytorium."
+
+#, fuzzy
+#~ msgid "Lock Repository"
+#~ msgstr "Zablokuj repozytorium"
+
+#~ msgid "Repository is not locked"
+#~ msgstr "Repozytorium nie jest zablokowane"
+
+#~ msgid "Log user push commands"
+#~ msgstr "Logi poleceń wysłania zmian użytkowników"
+
+#~ msgid "Log user pull commands"
+#~ msgstr "Logi poleceń połączenia gałęzi użytkowników"
+
+#~ msgid "Unlock"
+#~ msgstr "Odblokowany"
+
+#~ msgid "Lock"
+#~ msgstr "zablokowane"
+
+#, fuzzy
+#~ msgid "Inherit defaults"
+#~ msgstr "Dziedziczenie domyślne"
+
+#, fuzzy
+#~| msgid "Default permissions"
+#~ msgid "default permissions"
+#~ msgstr "Domyślne uprawnienia"
+
+#~ msgid "Repository locked by %s"
+#~ msgstr "Repozytorium zablokowane przez %s"
+
+#~ msgid "Repository unlocked"
+#~ msgstr "Repozytorium odblokowane"
+
+#~ msgid "Show by ID"
+#~ msgstr "Pokaż ID"
+
+#~ msgid "Show by Name"
+#~ msgstr "Pokaż nazwę"
+
 #~ msgid "There is no index to search in. Please run whoosh indexer"
 #~ msgstr "Nie ma szukanego indeksu. Proszę uruchomić indeksowanie whoosh"
 
@@ -5982,9 +6020,6 @@
 #~ msgid "invalid user name"
 #~ msgstr "niepoprawna nazwa użytkownika"
 
-#~ msgid "Your account is disabled"
-#~ msgstr "Twoje konto jest wyłączone"
-
 #~ msgid "invalid clone URL"
 #~ msgstr "nieprawidłowe url klonowania"
 
--- a/kallithea/i18n/pt_BR/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/pt_BR/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,16 +1,12 @@
-# Portuguese (Brazil) translations for Kallithea.
 # Copyright (C) 2014 RhodeCode GmbH, and others.
 # This file is distributed under the same license as the Kallithea project.
-# Translators:
-# Augusto Herrmann <augusto.herrmann@gmail.com>, 2012
-# gnustavo <gustavo@gnustavo.com>, 2013
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\n"
 "PO-Revision-Date: 2014-02-13 14:34+0000\n"
-"Last-Translator: marcinkuzminski <marcin@python-blog.com>\n"
+"Last-Translator: Marcin Kuźmiński <marcin@python-works.com>\n"
 "Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
 "kallithea/kallithea/pt_BR/>\n"
 "Language: pt_BR\n"
@@ -20,14 +16,14 @@
 "Plural-Forms: nplurals=2; plural=(n > 1)\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr "Não há nenhum changeset ainda"
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -36,95 +32,95 @@
 msgid "None"
 msgstr "Nenhum"
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr "(fechado)"
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr "Mostrar espaços em branco"
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr "Ignorar espaços em branco"
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 #, fuzzy
 msgid "No permission to change status"
 msgstr "Vote para estado do pull request"
 
-#: kallithea/controllers/changeset.py:214
+#: kallithea/controllers/changeset.py:212
 #, fuzzy, python-format
 msgid "Successfully deleted pull request %s"
 msgstr "Pull request excluído com sucesso"
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr ""
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, fuzzy, python-format
 #| msgid "Go to tip of repository"
 msgid "Could not find other repository %s"
 msgstr "Confirme para travar repositório"
 
-#: kallithea/controllers/compare.py:72
+#: kallithea/controllers/compare.py:74
 msgid "Cannot compare repositories of different types"
 msgstr ""
 
-#: kallithea/controllers/compare.py:244
-msgid "Cannot show empty diff"
-msgstr ""
-
 #: kallithea/controllers/compare.py:246
+msgid "Cannot show empty diff"
+msgstr ""
+
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr ""
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr ""
 
-#: kallithea/controllers/error.py:70
+#: kallithea/controllers/error.py:71
 #, fuzzy
 msgid "No response"
 msgstr "revisões"
 
-#: kallithea/controllers/error.py:71
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr ""
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr ""
 "A requisição não pôde ser compreendida pelo servidor devido à sintaxe mal "
 "formada."
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr "Acesso não autorizado ao recurso"
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr "Você não tem permissão para ver esta página"
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr "O recurso não pôde ser encontrado"
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
@@ -147,123 +143,117 @@
 msgid "Changeset was too big and was cut off..."
 msgstr "Conjunto de mudanças era grande demais e foi cortado..."
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr "%s - feed %s"
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
 msgstr "Modificações no repositório %s"
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr "Clique aqui para adicionar um novo arquivo"
 
-#: kallithea/controllers/files.py:93
+#: kallithea/controllers/files.py:86
 #, fuzzy
 #| msgid "There are no forks yet"
 msgid "There are no files yet."
 msgstr "Ainda não há bifurcações"
 
-#: kallithea/controllers/files.py:193
+#: kallithea/controllers/files.py:186
 #, fuzzy, python-format
 msgid "%s at %s"
 msgstr "em %s e %s"
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr "Este repositório foi travado por %s em %s"
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 #, fuzzy
 msgid "You can only delete files with revision being a valid branch"
 msgstr "Só é possível editar arquivos quando a revisão é um ramo válido"
 
-#: kallithea/controllers/files.py:322
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr ""
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr "Ocorreu um erro ao realizar commit"
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 #, fuzzy
 msgid "You can only edit files with revision being a valid branch"
 msgstr "Só é possível editar arquivos quando a revisão é um ramo válido"
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr "Arquivo %s editado via Kallithea"
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr "Sem modificações"
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr "Commit realizado com sucesso para %s"
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr "Arquivo adicionado via Kallithea"
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr "Nenhum conteúdo"
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr "Nenhum nome de arquivo"
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr "O caminho deve ser relativo e não pode conter .."
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr "Downloads desabilitados"
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr "Revisão desconhecida %s"
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr "Repositório vazio"
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr "Tipo de arquivo desconhecido"
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr "Conjuntos de mudanças"
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
 msgstr "Ramos"
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr "Etiquetas"
 
@@ -272,11 +262,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr "Ocorreu um erro ao bifurcar o repositório %s"
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr ""
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -284,184 +274,184 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr "Repositórios"
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
 msgstr "Ramo"
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr "Ramos Fechados"
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr ""
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr ""
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr "Diário Público"
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr "Diário"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
 msgstr ""
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, 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:190
 #, fuzzy
 msgid "A password reset confirmation code has been sent"
 msgstr "Seu link de reinicialização de senha foi enviado"
 
-#: kallithea/controllers/login.py:238
+#: kallithea/controllers/login.py:239
 #, fuzzy
 msgid "Invalid password reset token"
 msgstr "Link para trocar senha"
 
-#: kallithea/controllers/admin/my_account.py:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr "Conjunto de Mudanças"
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr "Especial"
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr "Ramos pares"
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr "Marcadores"
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 #, fuzzy
 msgid "Error occurred while creating pull request"
 msgstr "Ocorreu um erro durante o envio do pull request"
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr "Novo pull request criado com sucesso"
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 #, fuzzy
 #| msgid "Pull request update created"
 msgid "New pull request iteration created"
 msgstr "Revisores do pull request"
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 #, fuzzy
 msgid "No description"
 msgstr "Descrição"
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 #, fuzzy
 msgid "Pull request updated"
 msgstr "Pull requests para %s"
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr "Pull request excluído com sucesso"
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, python-format
 msgid "Revision %s not found in %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, python-format
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr ""
 
+#: kallithea/controllers/pullrequests.py:520
+#, python-format
+msgid "This pull request has already been merged to %s."
+msgstr ""
+
 #: kallithea/controllers/pullrequests.py:522
-#, python-format
-msgid "This pull request has already been merged to %s."
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:524
 msgid "This pull request has been closed and can not be updated."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, python-format
 msgid "The following additional changes are available on %s:"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 msgid "No additional changesets found for iterating on this pull request."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 msgid "Git pull requests don't support iterating yet."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, python-format
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 
@@ -478,22 +468,22 @@
 msgid "An error occurred during search operation."
 msgstr "Ocorreu um erro durante essa operação de busca"
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 #, fuzzy
 msgid "No data ready yet"
 msgstr "Ainda não há dados carregados"
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr "As estatísticas estão desabillitadas para este repositório"
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -505,126 +495,139 @@
 msgid "Error occurred during update of defaults"
 msgstr "Ocorreu um erro durnge a atualização dos padrões"
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 #, fuzzy
 msgid "Forever"
 msgstr "para sempre"
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
 #: kallithea/controllers/admin/users.py:249
 msgid "5 minutes"
 msgstr "cinco minutos"
 
-#: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
 #: kallithea/controllers/admin/users.py:250
 msgid "1 hour"
 msgstr "uma hora"
 
-#: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
 #: kallithea/controllers/admin/users.py:251
 msgid "1 day"
 msgstr "um dia"
 
-#: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr "um mês"
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr "Ocorreu um erro durante a criação de um gist"
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr "Gist %s excluído"
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 #, fuzzy
 msgid "Unmodified"
 msgstr "Última alteração"
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:230
-msgid "Successfully updated gist data"
-msgstr ""
-
 #: kallithea/controllers/admin/gists.py:233
+msgid "Successfully updated gist data"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 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"
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr "Sua conta foi atualizada com sucesso"
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr "Ocorreu um erro durante a atualização do usuário %s"
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr "Email %s adicionado ao usuário"
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr "Ocorreu um erro durante o salvamento do email"
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr "Email removido do usuário"
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, python-format
+msgid "SSH key %s successfully added"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+#, fuzzy
+#| msgid "Successfully deleted user"
+msgid "SSH key successfully deleted"
+msgstr "Usuário excluído com sucesso"
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -632,9 +635,9 @@
 msgid "Read"
 msgstr "Ler"
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -642,9 +645,9 @@
 msgid "Write"
 msgstr "Gravar"
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -667,368 +670,351 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr "Administrador"
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:50
 msgid "Disabled"
 msgstr "Desabilitado"
 
-#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:80
 msgid "Allowed with manual account activation"
 msgstr "Permitido com ativação manual de conta"
 
-#: kallithea/controllers/admin/permissions.py:80
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr "Permitido com ativação automática de conta"
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr "Ativação manual de conta externa"
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr "Ativação automática de conta externa"
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr "Habilitado"
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr "Ocorreu um erro durante a atualização das permissões"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, 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:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr "Grupo de repositórios %s criado"
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Grupo de repositórios %s atualizado"
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, 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:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, 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:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, 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:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Grupo de repositórios %s excluído"
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, 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:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 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:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr "Permissões atualizadas do Grupo de Repositórios"
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr "Ocorreu um erro durante a revocação das permissões"
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Erro ao criar repositório %s"
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Repositório %s criado de %s"
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Repositório %s bifurcado como %s"
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr "Repositório %s criado"
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Repositório %s atualizado com sucesso"
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, 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:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr "%s bifurcações excluídas"
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Repositório %s excluído"
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, 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:290
+#: kallithea/controllers/admin/repos.py:289
 #, 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:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr "Permissões do repositório atualizadas"
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:390
+#: kallithea/controllers/admin/repos.py:391
 #, 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:401
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr "Ocorreu um erro durante a remoção do campo"
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr "Atualizada a visibilidade do repositório no diário público"
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 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:466
+#: kallithea/controllers/admin/repos.py:468
 msgid "Nothing"
 msgstr "Nada"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:470
 #, 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:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr "Ocorreu um erro durante essa operação"
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-#, fuzzy
-msgid "Repository has been locked"
-msgstr "Repositório não está travado"
+#: kallithea/controllers/admin/repos.py:490
+msgid "Cache invalidation successful"
+msgstr ""
 
 #: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-#, fuzzy
-msgid "Repository has been unlocked"
-msgstr "Repositório não está travado"
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr "Ocorreu um erro durante o destravamento"
-
-#: kallithea/controllers/admin/repos.py:528
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:532
 msgid "An error occurred during cache invalidation"
 msgstr "Ocorreu um erro ao invalidar o cache"
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr "Realizado pull de localização remota"
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 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:579
+#: kallithea/controllers/admin/repos.py:541
 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:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr "Configurações de VCS atualizadas"
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 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:180
+#: kallithea/controllers/admin/settings.py:176
 #, 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:192
+#: kallithea/controllers/admin/settings.py:188
 #, 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:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr "Configurações da aplicação atualizadas"
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr "Configurações de visualização atualizadas"
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 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:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 #, fuzzy
 msgid "Hook already exists"
 msgstr "Ainda não há dados carregados"
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:357
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:363
+#: kallithea/controllers/admin/settings.py:360
 msgid "Added new hook"
 msgstr "Adicionado novo gancho"
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr "Atualizados os ganchos"
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr "Ocorreu um erro durante a criação do hook"
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr "Tarefa de reindexação do whoosh agendada"
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr "Grupo de usuários %s criado"
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, 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:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr "Grupo de usuários %s atualizado"
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, 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:217
+#: kallithea/controllers/admin/user_groups.py:212
 msgid "Successfully deleted user group"
 msgstr "Grupo de usuários excluído com sucesso"
 
-#: kallithea/controllers/admin/user_groups.py:222
+#: kallithea/controllers/admin/user_groups.py:217
 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:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr "O grupo destino não pode ser o mesmo"
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr "Permissões do Grupo de Usuários atualizadas"
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr "Permissões atualizadas"
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr "Ocorreu um erro durante o salvamento das permissões"
 
@@ -1058,223 +1044,225 @@
 msgid "The default user cannot be edited"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr "Ocorreu um erro durante o salvamento do IP"
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 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:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr "Você precisa estar logado para ver essa página"
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr ""
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr ""
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, fuzzy, python-format
 #| msgid "Changeset not found"
 msgid "Changeset for %s %s not found in %s"
 msgstr "Conjunto de alterações não encontrado"
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+#, fuzzy
+#| msgid "Your account is disabled"
+msgid "SSH access is disabled."
+msgstr "Sua conta está desabilitada"
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr "Arquivo binário"
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 "Conjunto de mudanças é grande demais e foi cortado, use o menu de "
 "diferenças para ver as diferenças"
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr "Nenhuma alteração detectada"
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "Excluído ramo: %s"
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr "Tag criada: %s"
 
-#: kallithea/lib/helpers.py:625
+#: kallithea/lib/helpers.py:666
 #, fuzzy, python-format
 #| msgid "Changeset not found"
 msgid "Changeset %s not found"
 msgstr "Conjunto de alterações não encontrado"
 
-#: kallithea/lib/helpers.py:674
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "Ver todos os conjuntos de mudanças combinados %s->%s"
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 #, fuzzy
 msgid "Compare view"
 msgstr "comparar exibir"
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr "e"
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr "%s mais"
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "revisões"
 
-#: kallithea/lib/helpers.py:725
+#: kallithea/lib/helpers.py:766
 #, fuzzy, python-format
 msgid "Fork name %s"
 msgstr "nome da bifurcação %s"
 
-#: kallithea/lib/helpers.py:746
+#: kallithea/lib/helpers.py:787
 #, fuzzy, python-format
 msgid "Pull request %s"
 msgstr "Pull request #%s"
 
-#: kallithea/lib/helpers.py:756
+#: kallithea/lib/helpers.py:797
 msgid "[deleted] repository"
 msgstr "repositório [excluído]"
 
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
 msgid "[created] repository"
 msgstr "repositório [criado]"
 
-#: kallithea/lib/helpers.py:760
+#: kallithea/lib/helpers.py:801
 msgid "[created] repository as fork"
 msgstr "repositório [criado] como uma bifurcação"
 
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
 msgid "[forked] repository"
 msgstr "repositório [bifurcado]"
 
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
 msgid "[updated] repository"
 msgstr "repositório [atualizado]"
 
-#: kallithea/lib/helpers.py:766
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr "[baixado] archive do repositório"
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr "[excluir] repositório"
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr "usuário [criado]"
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr "usuário [atualizado]"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr "[criado] grupo de usuários"
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr "[atualizado] grupo de usuários"
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr "[comentado] em revisão no repositório"
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr "[comentado] no pull request para"
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr "[fechado] pull request para"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr "[realizado push] para"
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr "[commitado via Kallithea] no repositório"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr "[pulled do remote] no repositório"
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr "[realizado pull] a partir de"
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr "[passou a seguir] o repositório"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr "[parou de seguir] o repositório"
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr " e mais %s"
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "Nenhum arquivo"
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr "novo arquivo"
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr "mod"
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr "excluir"
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr "renomear"
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1285,69 +1273,96 @@
 "renomeado a partir do sistema de arquivos. Por favor, execute a aplicação "
 "outra vez para varrer novamente por repositórios"
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] "%d ano"
 msgstr[1] "%d anos"
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] "%d mês"
 msgstr[1] "%d meses"
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] "%d dia"
 msgstr[1] "%d dias"
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] "%d hora"
 msgstr[1] "%d horas"
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] "%d minuto"
 msgstr[1] "%d minutos"
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] "%d segundo"
 msgstr[1] "%d segundos"
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr "em %s"
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr "%s atrás"
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr "em %s e %s"
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s e %s atrás"
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr "agora há pouco"
 
@@ -1356,147 +1371,147 @@
 msgid "on line %s"
 msgstr "na linha %s"
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr "[Menção]"
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr "nível superior"
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr "Administrador do Kallithea"
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1706
+#: kallithea/model/db.py:1640
 #, fuzzy
 msgid "Default user has read access to new repositories"
 msgstr "Acesso não autorizado ao recurso"
 
-#: kallithea/model/db.py:1707
+#: kallithea/model/db.py:1641
 #, fuzzy
 msgid "Default user has write access to new repositories"
 msgstr "Acesso não autorizado ao recurso"
 
-#: kallithea/model/db.py:1708
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1711
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 #, fuzzy
 msgid "Only admins can create repository groups"
 msgstr "Grupo de repositórios %s criado"
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 #, fuzzy
 msgid "Non-admins can create repository groups"
 msgstr "Grupo de repositórios %s criado"
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 #, fuzzy
 msgid "Only admins can create user groups"
 msgstr "Criar grupos de usuários"
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 #, fuzzy
 msgid "Non-admins can create user groups"
 msgstr "Criar grupos de usuários"
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1730
+#: kallithea/model/db.py:1664
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1732
+#: kallithea/model/db.py:1666
 #, fuzzy
 msgid "Only admins can fork repositories"
 msgstr "Criar repositórios"
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 #, fuzzy
 msgid "Non-admins can fork repositories"
 msgstr "Invalidar o cache para todos os repositórios"
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr "Registro desatilitado"
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 #, fuzzy
 msgid "User registration with manual account activation"
 msgstr "Registro de Usuário com ativação manual de conta"
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 #, fuzzy
 msgid "User registration with automatic account activation"
 msgstr "Registro de Usuário com ativação automática de conta"
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 #, fuzzy
 msgid "Not reviewed"
 msgstr "Não Revisado"
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 #, fuzzy
 msgid "Under review"
 msgstr "Sob Revisão"
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 #, fuzzy
 #| msgid "Approved"
 msgid "Not approved"
 msgstr "Aprovado"
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr "Aprovado"
 
@@ -1522,7 +1537,7 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, fuzzy, python-format
 #| msgid "[Comment] %(repo_name)s pull request %(pr_nice_id)s from %(ref)s"
 msgid ""
@@ -1530,95 +1545,111 @@
 "%(branch)s"
 msgstr "[comentado] no pull request para"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, fuzzy, python-format
 msgid "New user %(new_username)s registered"
 msgstr "O username \"%(new_username)s\" não é válido"
 
-#: kallithea/model/notification.py:170
+#: kallithea/model/notification.py:169
 #, 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:171
+#: kallithea/model/notification.py:170
 #, 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:184
+#: kallithea/model/notification.py:183
 #, fuzzy
 msgid "Closing"
 msgstr "Usando"
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, fuzzy, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
 msgstr ""
 "%(user)s solicita sua revisão no pull request $%(pr_id)s: %(pr_title)s"
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 #, fuzzy
 #| msgid "Create Pull Request"
 msgid "Cannot create empty pull request"
 msgstr "Criar Pull Request"
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 #, fuzzy
 #| msgid "Confirm to delete this pull request"
 msgid "You are not authorized to create the pull request"
 msgstr "Confirme para excluir este pull request"
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 msgid "Missing changesets since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, python-format
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, python-format
 msgid ""
 "This iteration is based on another %s revision and there is no simple "
 "diff."
 msgstr ""
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, python-format
 msgid "No changes found on %s %s since previous iteration."
 msgstr ""
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr "tip mais recente"
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, fuzzy, python-format
+#| msgid "Changeset not found"
+msgid "SSH key %r not found"
+msgstr "Conjunto de alterações não encontrado"
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr "Novo registro de usuário"
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 #, fuzzy
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
@@ -1626,7 +1657,7 @@
 "Você não pode remover esse usuário, pois ele é crucial para toda a "
 "aplicação"
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:255
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
@@ -1635,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:263
+#: kallithea/model/user.py:260
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
@@ -1644,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:270
+#: kallithea/model/user.py:267
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
@@ -1653,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:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr "Link para trocar senha"
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 #, fuzzy
 msgid "Password reset notification"
 msgstr "Link para trocar senha"
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr "O valor não pode ser uma lista vazia"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:72
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "O username \\\"%(username)s\\\" já existe"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:74
 #, fuzzy, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "O username \"%(username)s\" não é válido"
 
-#: kallithea/model/validators.py:78
+#: kallithea/model/validators.py:76
 #, fuzzy
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
@@ -1692,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:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr "O username \"%(username)s\" não é válido"
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr "Nome inválido de grupo de usuários"
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:132
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr "O grupo de usuários \"%(usergroup)s\" já existe"
 
-#: kallithea/model/validators.py:136
+#: kallithea/model/validators.py:134
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
@@ -1719,107 +1750,103 @@
 "underscores, pontos ou hífens, e deve começar om um caractere alfa-"
 "numérico"
 
-#: kallithea/model/validators.py:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr "Não é possível associar esse grupo como progenitor"
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:175
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr "O grupo \\\"%(group_name)s\\\" já existe"
 
-#: kallithea/model/validators.py:179
+#: kallithea/model/validators.py:177
 #, 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:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr "Caracteres inválidos (não-ascii) na senha"
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr "Senhas não conferem"
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 #, fuzzy
 msgid "Invalid username or password"
 msgstr "senha inválida"
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr "Descompasso de Token"
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, 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:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr "Um repositório chamado %(repo)s já existe"
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, 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:333
+#: kallithea/model/validators.py:318
 #, 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:419
+#: kallithea/model/validators.py:404
 #, fuzzy
 msgid "Invalid repository URL"
 msgstr "repositório privado"
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:430
 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:460
+#: kallithea/model/validators.py:445
 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:462
+#: kallithea/model/validators.py:447
 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:512
+#: kallithea/model/validators.py:497
 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:552
+#: kallithea/model/validators.py:537
 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:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr "Esse não é um caminho válido"
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 #, fuzzy
 msgid "This email address is already in use"
 msgstr "Esse endereço de e-mail já está tomado"
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, fuzzy, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "o e-mail \"%(email)s\" não existe."
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
@@ -1827,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:731
+#: kallithea/model/validators.py:716
 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:732
+#: kallithea/model/validators.py:717
 #, 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:765
+#: kallithea/model/validators.py:750
 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:779
+#: kallithea/model/validators.py:764
 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:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1887,24 +1914,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr "Descrição"
 
@@ -1921,7 +1954,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1929,11 +1962,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr "Dono"
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr "Entrar"
@@ -1948,7 +1981,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1956,7 +1989,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr "Senha"
@@ -2121,10 +2154,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr "Ação"
@@ -2173,22 +2208,22 @@
 msgstr ""
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr "Salvar"
 
@@ -2207,14 +2242,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr "Repositório privado"
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2224,36 +2259,25 @@
 "adicionadas como colaboradores."
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr "Habilitar estatísticas"
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr "Habilitar janela de estatísticas na página de sumário."
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr "Habilitar downloads"
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr "Habilitar menu de descarregar na página de sumário."
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr "Habilitar travas"
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr "Habilitar trava-por-pulling no repositório."
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2300,8 +2324,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 #, fuzzy
 msgid "Never"
 msgstr "nunca"
@@ -2335,7 +2361,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr ""
 
@@ -2371,23 +2397,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2415,7 +2443,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2475,7 +2503,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr "Minha Conta"
 
@@ -2489,26 +2517,31 @@
 msgid "Email Addresses"
 msgstr "Novo endereço de email"
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
+#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/users/user_edit.html:32
+msgid "SSH Keys"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
 msgid "API Keys"
 msgstr ""
 
-#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/my_account/my_account.html:32
 #, fuzzy
 msgid "Owned Repositories"
 msgstr "repositórios"
 
-#: kallithea/templates/admin/my_account/my_account.html:30
+#: kallithea/templates/admin/my_account/my_account.html:33
 #: kallithea/templates/journal/journal.html:33
 #, fuzzy
 msgid "Watched Repositories"
 msgstr "Criar repositórios"
 
-#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 #, fuzzy
 msgid "Show Permissions"
 msgstr "Copiar permissões"
@@ -2537,7 +2570,9 @@
 msgstr "Confirme para excluir este IP: %s"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 #, fuzzy
 msgid "Remove"
 msgstr "Removido"
@@ -2555,12 +2590,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr "Adicionar"
 
@@ -2664,6 +2701,47 @@
 msgid "Name"
 msgstr "Nome"
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+#, fuzzy
+#| msgid "Last Name"
+msgid "Last Used"
+msgstr "Último Nome"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, fuzzy, python-format
+msgid "Confirm to remove this SSH key: %s"
+msgstr "Confirme para excluir este IP: %s"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+#, fuzzy
+msgid "New SSH key"
+msgstr "Próxima chave de campo"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+#, fuzzy
+#| msgid "Public repository"
+msgid "Public key"
+msgstr "Repositório público"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 #, fuzzy
 msgid "Repositories You are Watching"
@@ -2682,7 +2760,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr ""
 
@@ -2724,7 +2802,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2894,7 +2972,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr ""
 
@@ -3010,20 +3088,12 @@
 "private repositories and other groups if selected."
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-"Habilitar trava-por-pulling no grupo. Esta opção será aplicada a todos os "
-"outros grupos e repositórios dentro deles"
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 #, fuzzy
 msgid "Remove this group"
 msgstr "Criar grupos de usuários"
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 #, fuzzy
 msgid "Confirm to delete this group"
 msgstr "Confirme para excluir este grupo de usuário: %s"
@@ -3056,7 +3126,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
@@ -3065,7 +3135,7 @@
 "longas."
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr "Opcionalmente selecione um grupo no qual colocar esse repositório."
@@ -3075,7 +3145,7 @@
 msgstr "Tipo de repositório a criar."
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr "Revisão de pouso"
@@ -3128,8 +3198,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr "Estatísticas"
 
@@ -3172,75 +3242,33 @@
 "Todas as ações feitas nesse repositório serão acessíveis a todos no "
 "diário público"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-#, fuzzy
-msgid "Change Locking"
-msgstr "Habilitar travas"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-#, fuzzy
-msgid "Confirm to unlock repository."
-msgstr "Confirme para destravar repositório"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-#, fuzzy
-msgid "Unlock Repository"
-msgstr "Repositório público"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-#, fuzzy
-msgid "Confirm to lock repository."
-msgstr "Confirme para travar repositório"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-#, fuzzy
-msgid "Lock Repository"
-msgstr "Repositório público"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr "Repositório não está travado"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
 #: kallithea/templates/data_table/_dt_elements.html:68
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "Confirma excluir esse repositório: %s"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
 #, fuzzy
 msgid "Delete this Repository"
 msgstr "[excluir] repositório"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, fuzzy, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
 msgstr[0] "este repositório tem %s bifurcação"
 msgstr[1] "este repositório tem %s bifurcações"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr "Desassociar bifurcações"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr "Excluir bifurcações"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3349,20 +3377,12 @@
 msgid "This repository does not have a remote repository URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-#, fuzzy
-msgid "Permanent Repository ID"
+#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#, fuzzy
+msgid "Permanent URL"
 msgstr "repositório privado"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3372,32 +3392,32 @@
 "other cases that you need to hardcode the URL into a 3rd party service."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 #, fuzzy
 msgid "Remote repository"
 msgstr "repositório [criado]"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 #, fuzzy
 msgid "Repository URL"
 msgstr "Repositório"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr "Revisão padrão para página de arquivos, downloads, whoosh e readme"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr "Mudar o dono desse repositório."
 
@@ -3510,8 +3530,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 #, fuzzy
 msgid "Save Settings"
 msgstr "Salvar configurações"
@@ -3612,10 +3632,6 @@
 msgid "Kallithea version"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr ""
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr ""
@@ -3637,15 +3653,7 @@
 msgid "Git path"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr ""
 
@@ -3654,42 +3662,34 @@
 msgstr "Mostrar tamanho do repositório após o push"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
-msgstr "Armazenar registro de comandos de push dos usuários"
+msgid "Update repository after push (hg update)"
+msgstr "Atualizar repositório após realizar push (hg update)"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr "Armazenar registro de comandos de pull dos usuários"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
-msgid "Update repository after push (hg update)"
-msgstr "Atualizar repositório após realizar push (hg update)"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:33
 #, fuzzy
 msgid "Mercurial extensions"
 msgstr "Extensões do Mercurial"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr "Habilitar extensão largefiles"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr "Habilitar extensão hgsubversion"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:47
+#: kallithea/templates/admin/settings/settings_vcs.html:35
 msgid ""
 "Requires hgsubversion library to be installed. Enables cloning of remote "
 "Subversion repositories while converting them to Mercurial."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:59
+#: kallithea/templates/admin/settings/settings_vcs.html:47
 #, fuzzy
 msgid "Location of repositories"
 msgstr "Criar repositórios"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
@@ -3697,7 +3697,7 @@
 "Clique para destravar. Você deve reiniciar o Kallithea para que esta "
 "configuração tenha efeito."
 
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3746,9 +3746,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-#, fuzzy
-msgid "Clone URL"
+#, fuzzy
+msgid "HTTP Clone URL"
 msgstr "URL de clonagem"
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
@@ -3766,60 +3765,76 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+#, fuzzy
+msgid "SSH Clone URL"
+msgstr "URL de clonagem"
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 #, fuzzy
 #| msgid "Repository Size"
 msgid "Repository page size"
 msgstr "Tamanho do Repositório"
 
-#: kallithea/templates/admin/settings/settings_visual.html:57
+#: kallithea/templates/admin/settings/settings_visual.html:68
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:62
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:70
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr "Ícones"
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
 msgstr "Mostrar ícone de repositório público nos repositórios"
 
-#: kallithea/templates/admin/settings/settings_visual.html:81
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr "Mostrar ícone de repositório privado nos repositórios"
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 #, fuzzy
 msgid "Show public/private icons next to repository names."
 msgstr "Mostrar ícone de repositório público nos repositórios"
 
-#: kallithea/templates/admin/settings/settings_visual.html:89
+#: kallithea/templates/admin/settings/settings_visual.html:100
 #, fuzzy
 msgid "Meta Tagging"
 msgstr "Meta-Tagging"
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr ""
 
@@ -3983,12 +3998,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr "Repositório Mercurial"
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr "Repositório Git"
 
@@ -4038,168 +4053,142 @@
 msgstr "Compare"
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr "Pesquisar"
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr "Destravar"
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr "Travar"
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr "Seguir"
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr "Parar de seguir"
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr "Bifurcação"
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr "Criar Pull Request"
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr "Trocar Para"
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr ""
 
-#: kallithea/templates/base/base.html:296
+#: kallithea/templates/base/base.html:289
 msgid "Show recent activity"
 msgstr "Mostrar atividade recente"
 
+#: kallithea/templates/base/base.html:295
+#: kallithea/templates/base/base.html:296
+msgid "Public journal"
+msgstr "Diário público"
+
+#: kallithea/templates/base/base.html:301
+msgid "Show public gists"
+msgstr "Mostrar gists públicos"
+
 #: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
-msgid "Public journal"
-msgstr "Diário público"
-
-#: kallithea/templates/base/base.html:308
-msgid "Show public gists"
-msgstr "Mostrar gists públicos"
-
-#: kallithea/templates/base/base.html:309
 msgid "Gists"
 msgstr "Gists"
 
-#: kallithea/templates/base/base.html:313
+#: kallithea/templates/base/base.html:306
 #, fuzzy
 msgid "All Public Gists"
 msgstr "Todos os gists públicos"
 
-#: kallithea/templates/base/base.html:315
+#: kallithea/templates/base/base.html:308
 #, fuzzy
 msgid "My Public Gists"
 msgstr "Meus gists públicos"
 
-#: kallithea/templates/base/base.html:316
+#: kallithea/templates/base/base.html:309
 #, fuzzy
 msgid "My Private Gists"
 msgstr "Meus gists privados"
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr "Buscar nos repositórios"
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 #, fuzzy
 msgid "My Pull Requests"
 msgstr "Pull requests"
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 #, fuzzy
 msgid "Not Logged In"
 msgstr "Não logado"
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 #, fuzzy
 msgid "Login to Your Account"
 msgstr "Entrar com sua conta"
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 #, fuzzy
 #| msgid "Forgot password ?"
 msgid "Forgot password?"
 msgstr "Esqueceu a senha ?"
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 #, fuzzy
 #| msgid "Don't have an account ?"
 msgid "Don't have an account?"
 msgstr "Não possui uma conta ?"
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr "Sair"
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-#, fuzzy
-msgid "Inherit defaults"
-msgstr "Padrões de repositórios"
+msgid "Create repositories"
+msgstr "Criar repositórios"
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-#, fuzzy
-#| msgid "Default permissions"
-msgid "default permissions"
-msgstr "Permissões padrão"
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr "Criar repositórios"
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 "Selecione esta opção para permitir a criação de repositórios para este "
 "usuário"
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr "Criar grupos de usuários"
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 "Selecione esta opção para permitir a criação de grupos de usuários para "
 "este usuário"
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr "Bufurcar repositórios"
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 "Selecione esta opção para permitir a bifurcação de repositórios para este "
@@ -4976,7 +4965,7 @@
 msgstr "%s Diff de Arquivo"
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr "%s Arquivos"
@@ -4988,7 +4977,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr ""
 
@@ -5042,7 +5031,7 @@
 msgstr "Carregando lista de arquivos..."
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr "Tamanho"
 
@@ -5178,8 +5167,8 @@
 msgstr "%s Seguidores"
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr "Seguidores"
 
@@ -5231,8 +5220,8 @@
 msgstr "%s Bifurcações"
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr "Bifurcações"
 
@@ -5560,9 +5549,9 @@
 msgid "File names"
 msgstr "Nomes dos arquivos"
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr "Permissão negada"
 
@@ -5572,20 +5561,20 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr "%s ATOM feed"
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr "%s RSS feed"
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr "Habilitar"
 
@@ -5594,12 +5583,12 @@
 msgstr "Estatísticas coletadas:"
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr "arquivos"
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr "Mostrar mais"
 
@@ -5640,98 +5629,191 @@
 msgid "%s Summary"
 msgstr "%s Sumário"
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr "Repositório travado por %s"
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr "Repositório destravado"
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr "Bifurcação de"
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr "Clonar de"
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr "Mostrar por ID"
-
+#: kallithea/templates/summary/summary.html:54
+#, fuzzy
+msgid "Clone URL"
+msgstr "URL de clonagem"
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr "Mostrar por Nome"
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+#, fuzzy
+#| msgid "Last Name"
+msgid "Use Name"
+msgstr "Último Nome"
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr "Tendências em arquivos"
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr "Download"
 
-#: kallithea/templates/summary/summary.html:101
+#: kallithea/templates/summary/summary.html:109
 msgid "There are no downloads yet"
 msgstr "Ainda não há downloads"
 
-#: kallithea/templates/summary/summary.html:103
+#: kallithea/templates/summary/summary.html:111
 msgid "Downloads are disabled for this repository"
 msgstr "Downloads estão desabilitados para este repositório"
 
-#: kallithea/templates/summary/summary.html:109
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr "Download como zip"
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr "Marque isto para descarregar arquivo com subrepositórios"
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 #, fuzzy
 msgid "With subrepos"
 msgstr "com subrepositórios"
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr "Feed"
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 #, fuzzy
 msgid "Latest Changes"
 msgstr "Mudanças mais recentes"
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 #, fuzzy
 msgid "Quick Start"
 msgstr "Início rápido"
 
-#: kallithea/templates/summary/summary.html:188
+#: kallithea/templates/summary/summary.html:196
 msgid "Add or upload files directly via Kallithea"
 msgstr "Adicionar ou enviar arquivos diretamente pelo Kallithea"
 
-#: kallithea/templates/summary/summary.html:196
+#: kallithea/templates/summary/summary.html:204
 #, fuzzy
 msgid "Push new repository"
 msgstr "Fazer push de novo repositório"
 
-#: kallithea/templates/summary/summary.html:204
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr "Repositório existente?"
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr "Descarregar %s como %s"
 
+#~ msgid "This repository has been locked by %s on %s"
+#~ msgstr "Este repositório foi travado por %s em %s"
+
+#, fuzzy
+#~ msgid "Repository has been locked"
+#~ msgstr "Repositório não está travado"
+
+#, fuzzy
+#~ msgid "Repository has been unlocked"
+#~ msgstr "Repositório não está travado"
+
+#~ msgid "An error occurred during unlocking"
+#~ msgstr "Ocorreu um erro durante o destravamento"
+
+#~ msgid "Token mismatch"
+#~ msgstr "Descompasso de Token"
+
+#~ msgid "Enable locking"
+#~ msgstr "Habilitar travas"
+
+#~ msgid "Enable lock-by-pulling on repository."
+#~ msgstr "Habilitar trava-por-pulling no repositório."
+
+#~ msgid ""
+#~ "Enable lock-by-pulling on group. This option will be applied to all "
+#~ "other groups and repositories inside"
+#~ msgstr ""
+#~ "Habilitar trava-por-pulling no grupo. Esta opção será aplicada a todos "
+#~ "os outros grupos e repositórios dentro deles"
+
+#, fuzzy
+#~ msgid "Change Locking"
+#~ msgstr "Habilitar travas"
+
+#, fuzzy
+#~ msgid "Confirm to unlock repository."
+#~ msgstr "Confirme para destravar repositório"
+
+#, fuzzy
+#~ msgid "Unlock Repository"
+#~ msgstr "Repositório público"
+
+#, fuzzy
+#~ msgid "Confirm to lock repository."
+#~ msgstr "Confirme para travar repositório"
+
+#, fuzzy
+#~ msgid "Lock Repository"
+#~ msgstr "Repositório público"
+
+#~ msgid "Repository is not locked"
+#~ msgstr "Repositório não está travado"
+
+#~ msgid "Log user push commands"
+#~ msgstr "Armazenar registro de comandos de push dos usuários"
+
+#~ msgid "Log user pull commands"
+#~ msgstr "Armazenar registro de comandos de pull dos usuários"
+
+#~ msgid "Unlock"
+#~ msgstr "Destravar"
+
+#~ msgid "Lock"
+#~ msgstr "Travar"
+
+#, fuzzy
+#~ msgid "Inherit defaults"
+#~ msgstr "Padrões de repositórios"
+
+#, fuzzy
+#~| msgid "Default permissions"
+#~ msgid "default permissions"
+#~ msgstr "Permissões padrão"
+
+#~ msgid "Repository locked by %s"
+#~ msgstr "Repositório travado por %s"
+
+#~ msgid "Repository unlocked"
+#~ msgstr "Repositório destravado"
+
+#~ msgid "Show by ID"
+#~ msgstr "Mostrar por ID"
+
+#~ msgid "Show by Name"
+#~ msgstr "Mostrar por Nome"
+
 #~ msgid "There is no index to search in. Please run whoosh indexer"
 #~ msgstr ""
 #~ "Não há índice onde pesquisa. Por favor execute o indexador whoosh"
@@ -5954,9 +6036,6 @@
 #~ msgid "invalid user name"
 #~ msgstr "nome de usuário inválido"
 
-#~ msgid "Your account is disabled"
-#~ msgstr "Sua conta está desabilitada"
-
 #~ msgid "invalid clone URL"
 #~ msgstr "URL de clonagem inválida"
 
--- a/kallithea/i18n/ru/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/ru/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,24 +1,10 @@
-# Russian translations for Kallithea.
 # Copyright (C) 2014 RhodeCode GmbH, and others.
 # This file is distributed under the same license as the Kallithea project.
-# Translators:
-# ArcheR <aleclitvinov1980@gmail.com>, 2013
-# mokeev1995 <mokeev_andre@mail.ru>, 2013
-# Andrey Mivrenik <myvrenik@gmail.com>, 2013
-# invision70 <invision70@gmail.com>, 2014
-# ivlevdenis <ivlevdenis.ru@gmail.com>, 2013
-# Mikhail Zholobov <legal90@gmail.com>, 2013
-# Ruslan Bekenev <furyinbox@gmail.com>, 2013
-# SkryabinD <skryabind@gmail.com>, 2014
-# softforwinxp <softforwinxp@gmail.com>, 2013
-# zhmylove <zhmylove@narod.ru>, 2013
-# Andrej Shadura <andrew@shadura.me>, 2015, 2016.
-#
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\n"
 "PO-Revision-Date: 2017-01-05 14:58+0000\n"
 "Last-Translator: Andrej Shadura <andrew@shadura.me>\n"
 "Language-Team: Russian <https://hosted.weblate.org/projects/kallithea/"
@@ -32,14 +18,14 @@
 "X-Generator: Weblate 2.11-dev\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr "Ещё не было изменений"
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -48,95 +34,95 @@
 msgid "None"
 msgstr "Ничего"
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr "(закрыто)"
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr "Отображать пробелы"
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr "Игнорировать пробелы"
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr "Увеличить контекст до %(num)s строк"
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 #, fuzzy
 #| msgid "No permissions defined yet"
 msgid "No permission to change status"
 msgstr "Привилегии еще не назначены"
 
-#: kallithea/controllers/changeset.py:214
+#: kallithea/controllers/changeset.py:212
 #, fuzzy, python-format
 msgid "Successfully deleted pull request %s"
 msgstr "Pull-запрос успешно удалён"
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr "Нет такой ревизии в этом репозитории"
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, fuzzy, python-format
 #| msgid "Go to tip of repository"
 msgid "Could not find other repository %s"
 msgstr "Перейти на верхушку репозитория"
 
-#: kallithea/controllers/compare.py:72
+#: kallithea/controllers/compare.py:74
 #, fuzzy
 #| msgid "Cannot compare repositories without using common ancestor"
 msgid "Cannot compare repositories of different types"
 msgstr "Невозможно сравнивать репозитории без общего предка"
 
-#: kallithea/controllers/compare.py:244
+#: kallithea/controllers/compare.py:246
 msgid "Cannot show empty diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:246
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr ""
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr "Невозможно сравнивать репозитории без общего предка"
 
-#: kallithea/controllers/error.py:70
+#: kallithea/controllers/error.py:71
 msgid "No response"
 msgstr "Нет ответа"
 
-#: kallithea/controllers/error.py:71
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr "Неизвестная ошибка"
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr "Запрос не распознан сервером из-за неправильного синтаксиса."
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr "Несанкционированный доступ к ресурсу"
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr "У вас нет прав для просмотра этой страницы"
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr "Ресурс не найден"
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
@@ -158,126 +144,120 @@
 msgid "Changeset was too big and was cut off..."
 msgstr "Изменения оказались слишком большими и были вырезаны..."
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr "Лента новостей %s %s"
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
 msgstr "Изменения в репозитории %s"
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr "Нажмите чтобы добавить новый файл"
 
-#: kallithea/controllers/files.py:93
+#: kallithea/controllers/files.py:86
 #, fuzzy
 #| msgid "There are no files yet. %s"
 msgid "There are no files yet."
 msgstr "Нет файлов. %s"
 
-#: kallithea/controllers/files.py:193
+#: kallithea/controllers/files.py:186
 #, python-format
 msgid "%s at %s"
 msgstr "%s (%s)"
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr "Репозиторий заблокировал %s в %s"
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 msgid "You can only delete files with revision being a valid branch"
 msgstr ""
 "Вы можете удалять файлы только в ревизии, связанной с существующей веткой "
 
-#: kallithea/controllers/files.py:322
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr "Файл %s удалён с помощью Kallithea"
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr "Файл %s удалён"
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr "Во время коммита произошла ошибка"
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 msgid "You can only edit files with revision being a valid branch"
 msgstr ""
 "Вы можете редактировать файлы только в ревизии, связанной с существующей "
 "веткой "
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr "Файл %s отредактирован с помощью Kallithea"
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr "Без изменений"
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr "Изменения применены в %s"
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr "Файл добавлен с помощью Kallithea"
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr "Пусто"
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr "Безымянный"
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr ""
 "Расположение должно быть относительным путем, и не должно содержать \".."
 "\" в пути"
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr "Возможность скачивать отключена"
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr "Неизвестная ревизия %s"
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr "Пустой репозиторий"
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr "Неизвестный тип архива"
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr "Набор изменений"
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
 msgstr "Ветки"
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr "Метки"
 
@@ -286,11 +266,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr "Произошла ошибка во время создания форка репозитория %s"
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr "Группы"
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -298,186 +278,186 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr "Репозитории"
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
 msgstr "Ветка"
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr "Закрытые ветки"
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr "Тэги"
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr "Закладки"
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr "Публичный журнал"
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr "Журнал"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
 msgstr "Неверная капча"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "Регистрация в %s прошла успешно"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:190
 msgid "A password reset confirmation code has been sent"
 msgstr "Код для сброса пароля отправлена"
 
-#: kallithea/controllers/login.py:238
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "Неверный код сброса пароля"
 
-#: kallithea/controllers/admin/my_account.py:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Пароль обновлён"
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr "%s (закрыта)"
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr "Изменения"
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr "Специальный"
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr "Ветки участника"
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr "Закладки"
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr "Ошибка при создании pull-запроса: %s"
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr "Произошла ошибка при создании pull-запроса"
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr "Pull-запрос создан успешно"
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 #, fuzzy
 #| msgid "Pull request update created"
 msgid "New pull request iteration created"
 msgstr "Обновление для pull-запроса создано"
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr "Нет описания"
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
 msgstr "Pull-запрос обновлён"
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr "Pull-запрос успешно удалён"
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, fuzzy, python-format
 #| msgid "Changeset for %s %s not found in %s"
 msgid "Revision %s not found in %s"
 msgstr "Набор изменений не найден"
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, fuzzy, python-format
 #| msgid "No changesets found for updating this pull request."
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr "Нет изменений для обновления этого pull-запроса."
 
-#: kallithea/controllers/pullrequests.py:522
+#: kallithea/controllers/pullrequests.py:520
 #, python-format
 msgid "This pull request has already been merged to %s."
 msgstr "Этот pull-запрос уже принят на ветку %s."
 
-#: kallithea/controllers/pullrequests.py:524
+#: kallithea/controllers/pullrequests.py:522
 msgid "This pull request has been closed and can not be updated."
 msgstr "Этот pull-запрос был закрыт и не может быть обновлён."
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, python-format
 msgid "The following additional changes are available on %s:"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 #, fuzzy
 #| msgid "No changesets found for updating this pull request."
 msgid "No additional changesets found for iterating on this pull request."
 msgstr "Нет изменений для обновления этого pull-запроса."
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr "Внимание: Ветка %s имеет ещё одну верхушку: %s."
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 #, fuzzy
 #| msgid "Git pull requests don't support updates yet."
 msgid "Git pull requests don't support iterating yet."
 msgstr "Обновление pull-запросы git не поддерживается."
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, fuzzy, python-format
 #| msgid "No changesets found for updating this pull request."
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
 msgstr "Нет изменений для обновления этого pull-запроса."
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 
@@ -493,21 +473,21 @@
 msgid "An error occurred during search operation."
 msgstr "Произошла ошибка при выполнении этого поиска."
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr "Нет данных"
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr "Статистические данные отключены для этого репозитария"
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr "Настройки авторизации успешно обновлены"
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr "произошла ошибка при обновлении настроек авторизации"
 
@@ -519,126 +499,140 @@
 msgid "Error occurred during update of defaults"
 msgstr "Произошла ошибка при обновлении стандартных настроек"
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 #, fuzzy
 msgid "Forever"
 msgstr "навсегда"
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
 #: kallithea/controllers/admin/users.py:249
 msgid "5 minutes"
 msgstr "5 минут"
 
-#: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
 #: kallithea/controllers/admin/users.py:250
 msgid "1 hour"
 msgstr "1 час"
 
-#: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
 #: kallithea/controllers/admin/users.py:251
 msgid "1 day"
 msgstr "1 день"
 
-#: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr "1 месяц"
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr "Срок"
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr "Произошла ошибка во время создания gist-записи"
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr "Gist-запись %s удалена"
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
 msgstr "Неизменный"
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:230
+#: kallithea/controllers/admin/gists.py:233
 msgid "Successfully updated gist data"
 msgstr "Данные gist-записи обновлены"
 
-#: kallithea/controllers/admin/gists.py:233
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
 msgstr "Произошла ошибка при обновлении gist-записи %s"
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 "Вы не можете изменить данные этого пользователя, поскольку он важен для "
 "работы всего приложения"
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr "Ваша учетная запись успешно обновлена"
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr "Произошла ошибка при обновлении пользователя %s"
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr "Ошибка при обновлении пароля"
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr "Пользователю добавлен e-mail %s"
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr "Произошла ошибка при сохранении e-mail"
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr "E-mail пользователя удалён"
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr "API-ключ успешно создан"
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr "API-ключ успешно сброшен"
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr "API-ключ успешно удалён"
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, fuzzy, python-format
+#| msgid "API key successfully created"
+msgid "SSH key %s successfully added"
+msgstr "API-ключ успешно создан"
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+#, fuzzy
+#| msgid "API key successfully deleted"
+msgid "SSH key successfully deleted"
+msgstr "API-ключ успешно удалён"
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -646,9 +640,9 @@
 msgid "Read"
 msgstr "Чтение"
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -656,9 +650,9 @@
 msgid "Write"
 msgstr "Запись"
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -681,254 +675,239 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr "Администратор"
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:50
 msgid "Disabled"
 msgstr "Отключено"
 
-#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:80
 msgid "Allowed with manual account activation"
 msgstr "Разрешена, с ручной активацией учётной записи"
 
-#: kallithea/controllers/admin/permissions.py:80
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr "Разрешена, с автоматической активацией учётной записи"
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr "Ручная активация внешней учетной записи"
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr "Автоматическая активация внешней учетной записи"
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr "Включено"
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr "Глобальные привилегии успешно обновлены"
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr "Произошла ошибка во время обновления привилегий"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr "Произошла ошибка при создании группы репозиториев %s"
 
-#: kallithea/controllers/admin/repo_groups.py:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr "Создана новая группа репозиториев %s"
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr "Группа репозиториев %s обновлена"
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr "Произошла ошибка при обновлении группы репозиториев %s"
 
-#: kallithea/controllers/admin/repo_groups.py:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "Данная группа содержит %s репозитариев и не может быть удалена"
 
-#: kallithea/controllers/admin/repo_groups.py:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr "Группа содержит в себе %s подгрупп и не может быть удалён"
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr "Группа репозиториев %s удалена"
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr "Произошла ошибка при удалении группы репозиториев %s"
 
-#: kallithea/controllers/admin/repo_groups.py:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
 msgstr "Администратор не может отозвать свои привелегии"
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr "Привилегии группы репозиториев обновлены"
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr "Произошла ошибка при отзыве привелегии"
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr "Произошла ошибка при создании репозитория %s"
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr "Репозиторий %s создан из %s"
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr "Сделан форк(копия) репозитория %s на %s"
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr "Репозиторий %s создан"
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "Репозитарий %s успешно обновлён"
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr "Произошла ошибка во время обновления репозитория %s"
 
-#: kallithea/controllers/admin/repos.py:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr "Форки %s отсоединены"
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr "Удалены форки репозитория %s"
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr "Репозиторий %s удалён"
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr "Невозможно удалить %s, у него всё ещё есть форки"
 
-#: kallithea/controllers/admin/repos.py:290
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "Произошла ошибка во время удаления %s"
 
-#: kallithea/controllers/admin/repos.py:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr "Привилегии репозитория обновлены"
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:390
+#: kallithea/controllers/admin/repos.py:391
 #, 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:401
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr "Произошла ошибка при удалении поля"
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr "-- Не форк --"
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr "Видимость репозитория в публичном журнале обновлена"
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 msgid "An error occurred during setting this repository in public journal"
 msgstr "Произошла ошибка при установке репозитария в общедоступный журнал"
 
-#: kallithea/controllers/admin/repos.py:466
+#: kallithea/controllers/admin/repos.py:468
 msgid "Nothing"
 msgstr "Ничего"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:470
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "Репозиторий %s отмечен как форк %s"
 
-#: kallithea/controllers/admin/repos.py:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr "Произошла ошибка при выполнении операции"
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-msgid "Repository has been locked"
-msgstr "Репозиторий заблокирован"
-
-#: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-msgid "Repository has been unlocked"
-msgstr "Репозиторий разблокирован"
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr "Произошла ошибка во время разблокирования"
-
-#: kallithea/controllers/admin/repos.py:528
+#: kallithea/controllers/admin/repos.py:490
 msgid "Cache invalidation successful"
 msgstr "Кэш сброшен"
 
-#: kallithea/controllers/admin/repos.py:532
+#: kallithea/controllers/admin/repos.py:494
 msgid "An error occurred during cache invalidation"
 msgstr "Произошла ошибка при очистке кэша"
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr "Внесены изменения из удалённого репозитория"
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 msgid "An error occurred during pull from remote location"
 msgstr "Произошла ошибка при внесении изменений из удалённого репозитория"
 
-#: kallithea/controllers/admin/repos.py:579
+#: kallithea/controllers/admin/repos.py:541
 msgid "An error occurred during deletion of repository stats"
 msgstr "Произошла ошибка при удалении статистики репозитория"
 
-#: kallithea/controllers/admin/settings.py:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr "Обновлены настройки VCS"
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
@@ -936,110 +915,110 @@
 "Невозможно включить поддержку hgsubversion. Библиотека «hgsubversion» "
 "отсутствует"
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
 msgstr "Произошла ошибка при обновлении настроек приложения"
 
-#: kallithea/controllers/admin/settings.py:180
+#: kallithea/controllers/admin/settings.py:176
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr "Репозитории успешно пересканированы, добавлено: %s, удалено: %s."
 
-#: kallithea/controllers/admin/settings.py:192
+#: kallithea/controllers/admin/settings.py:188
 #, fuzzy, python-format
 msgid "Invalidated %s repositories"
 msgstr "Сбросить кэш для всех репозиториев"
 
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr "Обновленные параметры настройки приложения"
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr "Настройки визуализации обновлены"
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
 msgstr "Произошла ошибка при обновлении настроек визуализации"
 
-#: kallithea/controllers/admin/settings.py:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr "Пожалуйста, введите адрес электронной почты"
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr "Задача отправки Email создана"
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "Нет данных"
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:357
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:363
+#: kallithea/controllers/admin/settings.py:360
 msgid "Added new hook"
 msgstr "Добавлена новая ловушка"
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr "Обновлённые ловушки"
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr "произошла ошибка при создании хука"
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr "Запланирована переиндексация базы Whoosh"
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr "Создана группа пользователей %s"
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr "Произошла ошибка при создании группы пользователей %s"
 
-#: kallithea/controllers/admin/user_groups.py:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr "Группа пользователей %s обновлена"
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr "Произошла ошибка при обновлении группы пользователей %s"
 
-#: kallithea/controllers/admin/user_groups.py:217
+#: kallithea/controllers/admin/user_groups.py:212
 msgid "Successfully deleted user group"
 msgstr "Группа пользователей успешно удалена"
 
-#: kallithea/controllers/admin/user_groups.py:222
+#: kallithea/controllers/admin/user_groups.py:217
 msgid "An error occurred during deletion of user group"
 msgstr "Произошла ошибка при удалении группы пользователей"
 
-#: kallithea/controllers/admin/user_groups.py:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr "Целевая группа не может быть такой же"
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr "Привилегии группы пользователей обновлены"
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr "Обновлены привилегии"
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr "Произошла ошибка при сохранении привилегий"
 
@@ -1069,223 +1048,225 @@
 msgid "The default user cannot be edited"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr "Добавлен IP %s в белый список пользователя"
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr "Произошла ошибка при сохранении IP"
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr "Удален IP %s из белого списка пользователя"
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 "Вы должны быть зарегистрированным пользователем, чтобы выполнить это "
 "действие"
 
-#: kallithea/lib/auth.py:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr "Страница доступна только авторизованным пользователям"
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr ""
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr "Репозиторий не найден на файловой системе"
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, fuzzy, python-format
 msgid "Changeset for %s %s not found in %s"
 msgstr "Набор изменений не найден"
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+#, fuzzy
+#| msgid "Your account is disabled"
+msgid "SSH access is disabled."
+msgstr "Ваш аккаунт выключен"
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr "Двоичный файл"
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 "Набор изменения оказался слишком большими и был урезан, используйте меню "
 "сравнения для показа результата сравнения"
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr "Изменений не обнаружено"
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "Удалена ветка: %s"
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr "Создан тег: %s"
 
-#: kallithea/lib/helpers.py:625
+#: kallithea/lib/helpers.py:666
 #, fuzzy, python-format
 msgid "Changeset %s not found"
 msgstr "Набор изменений не найден"
 
-#: kallithea/lib/helpers.py:674
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "Показать отличия вместе %s->%s"
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 #, fuzzy
 msgid "Compare view"
 msgstr "сравнение"
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr "и"
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr "на %s больше"
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "версии"
 
-#: kallithea/lib/helpers.py:725
+#: kallithea/lib/helpers.py:766
 #, fuzzy, python-format
 msgid "Fork name %s"
 msgstr "имя форка %s"
 
-#: kallithea/lib/helpers.py:746
+#: kallithea/lib/helpers.py:787
 #, python-format
 msgid "Pull request %s"
 msgstr "Pull-запрос %s"
 
-#: kallithea/lib/helpers.py:756
+#: kallithea/lib/helpers.py:797
 msgid "[deleted] repository"
 msgstr "[удален] репозиторий"
 
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
 msgid "[created] repository"
 msgstr "[создан] репозиторий"
 
-#: kallithea/lib/helpers.py:760
+#: kallithea/lib/helpers.py:801
 msgid "[created] repository as fork"
 msgstr "[создан] репозиторий как форк"
 
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
 msgid "[forked] repository"
 msgstr "[форкнут] репозиторий"
 
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
 msgid "[updated] repository"
 msgstr "[обновлён] репозиторий"
 
-#: kallithea/lib/helpers.py:766
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr "[загружен] архив из репозитория"
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr "[удален] репозиторий"
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr "[создан] пользователь"
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr "[обновлён] пользователь"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr "[создана] группа пользователей"
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr "[обновлена] группа пользователей"
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr "[комментарий] к ревизии в репозитории"
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr "[прокомментировано] в запросе на внесение изменений для"
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr "[закрыт] Pull-запрос для"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr "[отправлено] в"
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr "[внесены изменения с помощью Kallithea] в репозитории"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr "[внесены изменения из удалённого репозитория] в репозиторий"
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr "[внесены изменения] из"
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr "[добавлен в наблюдения] репозиторий"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr "[удалён из наблюдения] репозиторий"
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr " и на %s больше"
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "Нет файлов"
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr "новый файл"
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr "изменён"
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr "удалён"
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr "переименован"
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr "chmod"
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1296,7 +1277,34 @@
 "переименован из файловой системы. Пожалуйста, перезапустите приложение "
 "для сканирования репозиториев"
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
@@ -1304,7 +1312,7 @@
 msgstr[1] "%d лет"
 msgstr[2] "%d года"
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
@@ -1312,7 +1320,7 @@
 msgstr[1] "%d месяца"
 msgstr[2] "%d месяцев"
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
@@ -1320,7 +1328,7 @@
 msgstr[1] "%d дня"
 msgstr[2] "%d дней"
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
@@ -1328,7 +1336,7 @@
 msgstr[1] "%d часов"
 msgstr[2] "%d часа"
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
@@ -1336,7 +1344,7 @@
 msgstr[1] "%d минут"
 msgstr[2] "%d минуты"
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
@@ -1344,27 +1352,27 @@
 msgstr[1] "%d секунды"
 msgstr[2] "%d секунды"
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr "в %s"
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr "%s назад"
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr "в %s и %s"
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s и %s назад"
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr "прямо сейчас"
 
@@ -1373,145 +1381,145 @@
 msgid "on line %s"
 msgstr "на строке %s"
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr "[Упоминание]"
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr "верхний уровень"
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr "Администратор Kallithea"
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1706
+#: kallithea/model/db.py:1640
 msgid "Default user has read access to new repositories"
 msgstr "Неавторизованные пользователи имеют право чтения новых репозиториев"
 
-#: kallithea/model/db.py:1707
+#: kallithea/model/db.py:1641
 msgid "Default user has write access to new repositories"
 msgstr ""
 "Неавторизованные пользователи имеют право записи в новые репозитории"
 
-#: kallithea/model/db.py:1708
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1711
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 msgid "Only admins can create repository groups"
 msgstr "Только администраторы могут создавать группы"
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 #, fuzzy
 msgid "Non-admins can create repository groups"
 msgstr "Создана новая группа репозиториев %s"
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 #, fuzzy
 msgid "Only admins can create user groups"
 msgstr "Создавать группы пользователей"
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 #, fuzzy
 msgid "Non-admins can create user groups"
 msgstr "Создавать группы пользователей"
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1730
+#: kallithea/model/db.py:1664
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1732
+#: kallithea/model/db.py:1666
 #, fuzzy
 msgid "Only admins can fork repositories"
 msgstr "Местонахождение репозиториев"
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 #, fuzzy
 msgid "Non-admins can fork repositories"
 msgstr "Сбросить кэш для всех репозиториев"
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr "Регистрация отключена"
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 #, fuzzy
 msgid "User registration with manual account activation"
 msgstr "Регистрация пользователя с ручной активацией учётной записи"
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 #, fuzzy
 msgid "User registration with automatic account activation"
 msgstr "Регистрация пользователя с автоматической активацией"
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 #, fuzzy
 msgid "Not reviewed"
 msgstr "Не просмотрено"
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 #, fuzzy
 msgid "Under review"
 msgstr "На рассмотрении"
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 #, fuzzy
 #| msgid "Approved"
 msgid "Not approved"
 msgstr "Одобрено"
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr "Одобрено"
 
@@ -1537,7 +1545,7 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, fuzzy, python-format
 #| msgid "[Comment] %(repo_name)s pull request %(pr_nice_id)s from %(ref)s"
 msgid ""
@@ -1545,72 +1553,72 @@
 "%(branch)s"
 msgstr "[прокомментировано] в запросе на внесение изменений для"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr "Новый пользователь \"%(new_username)s\" зарегистрирован"
 
-#: kallithea/model/notification.py:170
+#: kallithea/model/notification.py:169
 #, 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:171
+#: kallithea/model/notification.py:170
 #, 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:184
+#: kallithea/model/notification.py:183
 msgid "Closing"
 msgstr "Закрыт"
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, fuzzy, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
 msgstr ""
 "%(user)s просит вас рассмотреть pull request #%(pr_id)s: %(pr_title)s"
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 #, fuzzy
 #| msgid "Error creating pull request: %s"
 msgid "Cannot create empty pull request"
 msgstr "Ошибка при создании pull-запроса: %s"
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 #, fuzzy
 #| msgid "Confirm to delete this pull request"
 msgid "You are not authorized to create the pull request"
 msgstr "Подтвердите удаление этого pull-request'а"
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 #, fuzzy
 #| msgid "Missing changesets since the previous pull request:"
 msgid "Missing changesets since the previous iteration:"
 msgstr "Отсутствующие ревизии относительно предыдущего pull-запроса:"
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, fuzzy, python-format
 #| msgid "New changesets on %s %s since the previous pull request:"
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr "Новые ревизии на %s %s относительно предыдущего pull-запроса:"
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, fuzzy, python-format
 #| msgid ""
 #| "This pull request is based on another %s revision and there is no "
@@ -1621,26 +1629,41 @@
 msgstr ""
 "Этот pull-запрос основан на другой ревизии %s, простой diff невозможен."
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, fuzzy, python-format
 #| msgid "No changes found on %s %s since previous version."
 msgid "No changes found on %s %s since previous iteration."
 msgstr "Нет изменений на %s %s относительно предыдущей версии."
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr "последняя версия"
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, fuzzy, python-format
+msgid "SSH key %r not found"
+msgstr "Набор изменений не найден"
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr "Регистрация нового пользователя"
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 #, fuzzy
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
@@ -1648,7 +1671,7 @@
 "Вы не можете удалить пользователя, поскольку это критично для работы "
 "всего приложения"
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:255
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
@@ -1657,7 +1680,7 @@
 "Пользователь \"%s\" всё ещё является владельцем %s репозиториев и поэтому "
 "не может быть удалён. Смените владельца или удалите эти репозитории: %s"
 
-#: kallithea/model/user.py:263
+#: kallithea/model/user.py:260
 #, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
@@ -1667,7 +1690,7 @@
 "поэтому не может быть удалён. Смените владельца или удалите данные "
 "группы: %s"
 
-#: kallithea/model/user.py:270
+#: kallithea/model/user.py:267
 #, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
@@ -1677,37 +1700,37 @@
 "поэтому не может быть удалён. Смените владельца или удалите данные "
 "группы: %s"
 
-#: kallithea/model/user.py:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr "Ссылка сброса пароля"
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 #, fuzzy
 msgid "Password reset notification"
 msgstr "Ссылка сброса пароля"
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr "Значение не может быть пустым списком"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:72
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "Пользователь с именем \"%(username)s\" уже существует"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:74
 #, fuzzy, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "Имя \"%(username)s\" недопустимо"
 
-#: kallithea/model/validators.py:78
+#: kallithea/model/validators.py:76
 #, fuzzy
 msgid ""
 "Username may only contain alphanumeric characters underscores, periods or "
@@ -1717,25 +1740,25 @@
 "подчеркивания, точки и тире; а так же должно начинаться с буквы, цифры "
 "либо с символа подчеркивания"
 
-#: kallithea/model/validators.py:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr "Имя \"%(username)s\" недопустимо"
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr "Неверное имя группы пользователей"
 
-#: kallithea/model/validators.py:134
+#: kallithea/model/validators.py:132
 #, python-format
 msgid "User group \"%(usergroup)s\" already exists"
 msgstr "Группа пользователей \"%(usergroup)s\" уже существует"
 
-#: kallithea/model/validators.py:136
+#: kallithea/model/validators.py:134
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
@@ -1743,107 +1766,103 @@
 "имя группы пользователей может содержать только буквы, цифры, символы "
 "подчеркивания, точки и тире; а так же должно начинаться с буквы или цифры"
 
-#: kallithea/model/validators.py:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr "Невозможно использовать эту группу как родителя"
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:175
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr "Группа \"%(group_name)s\" уже существует"
 
-#: kallithea/model/validators.py:179
+#: kallithea/model/validators.py:177
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr "Репозитарий с  именем \"%(group_name)s\" уже существует"
 
-#: kallithea/model/validators.py:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr "Недопустимые символы (не ascii) в пароле"
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr "Неверно задан старый пароль"
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr "Пароли не совпадают"
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 #, fuzzy
 msgid "Invalid username or password"
 msgstr "неверный пароль"
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr "Несовпадение токенов"
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, fuzzy, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr "Имя репозитория %(repo)s запрещено"
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr "Репозитарий %(repo)s уже существует"
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr "Репозитарий \"%(repo)s\" уже существует в группе \"%(group)s\""
 
-#: kallithea/model/validators.py:333
+#: kallithea/model/validators.py:318
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr "Группа репозиториев \"%(repo)s\" уже существует"
 
-#: kallithea/model/validators.py:419
+#: kallithea/model/validators.py:404
 #, fuzzy
 msgid "Invalid repository URL"
 msgstr "приватный репозиторий"
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:430
 msgid "Fork has to be the same type as parent"
 msgstr "Тип форка будет совпадать с родительским"
 
-#: kallithea/model/validators.py:460
+#: kallithea/model/validators.py:445
 msgid "You don't have permissions to create repository in this group"
 msgstr "У вас недостаточно прав для создания репозиториев в этой группе"
 
-#: kallithea/model/validators.py:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
 msgstr "недостаточно прав для создания репозитория в корневом каталоге"
 
-#: kallithea/model/validators.py:512
+#: kallithea/model/validators.py:497
 msgid "You don't have permissions to create a group in this location"
 msgstr "У Вас недостаточно привилегий для создания группы в этом месте"
 
-#: kallithea/model/validators.py:552
+#: kallithea/model/validators.py:537
 msgid "This username or user group name is not valid"
 msgstr "Данное имя пользователя или группы пользователей недопустимо"
 
-#: kallithea/model/validators.py:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr "Этот путь ошибочен"
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 #, fuzzy
 msgid "This email address is already in use"
 msgstr "Этот E-mail уже занят"
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, fuzzy, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "\"%(email)s\" не существует."
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 msgid ""
 "The LDAP Login attribute of the CN must be specified - this is the name "
 "of the attribute that is equivalent to \"username\""
@@ -1851,11 +1870,11 @@
 "Для входа по LDAP должно быть указано значение аттрибута CN - это "
 "эквивалент имени пользователя"
 
-#: kallithea/model/validators.py:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr "Пожалуйста, введите существующий IPv4 или IPv6 адре"
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
@@ -1863,17 +1882,17 @@
 "Значение маски подсети должно быть в пределах от 0 до 32 (%(bits)r - "
 "неверно)"
 
-#: kallithea/model/validators.py:765
+#: kallithea/model/validators.py:750
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 "Ключевое имя может только состоять из букв, символа подчеркивания, тире "
 "или чисел"
 
-#: kallithea/model/validators.py:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr "Файла нет в каталоге"
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1915,24 +1934,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr "Описание"
 
@@ -1949,7 +1974,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1957,11 +1982,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr "Владелец"
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr "Войти"
@@ -1976,7 +2001,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1984,7 +2009,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr "Пароль"
@@ -2145,10 +2170,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr "Действие"
@@ -2200,22 +2227,22 @@
 msgstr "Плагин"
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr "Сохранить"
 
@@ -2233,14 +2260,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr "Приватный репозиторий"
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2248,36 +2275,25 @@
 msgstr "Приватные репозитории видны только их участникам."
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr "Включить статистику"
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr "Включить окно статистики на странице «Общие сведения»."
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr "Включить скачивание"
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr "Включить меню скачивания на странице «Общие сведения»."
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr "Включить блокирование"
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr "Включить автоблокировку для репозитория."
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2324,8 +2340,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 #, fuzzy
 msgid "Never"
 msgstr "никогда"
@@ -2359,7 +2377,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr "Создать новую gist-запись"
 
@@ -2395,23 +2413,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2439,7 +2459,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2499,7 +2519,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr "Мой Аккаунт"
 
@@ -2513,26 +2533,33 @@
 msgid "Email Addresses"
 msgstr "Новый E-mail"
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
+#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/users/user_edit.html:32
+#, fuzzy
+#| msgid "API Keys"
+msgid "SSH Keys"
+msgstr "API-ключи"
+
+#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
 msgid "API Keys"
 msgstr "API-ключи"
 
-#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/my_account/my_account.html:32
 #, fuzzy
 msgid "Owned Repositories"
 msgstr "репозитории"
 
-#: kallithea/templates/admin/my_account/my_account.html:30
+#: kallithea/templates/admin/my_account/my_account.html:33
 #: kallithea/templates/journal/journal.html:33
 #, fuzzy
 msgid "Watched Repositories"
 msgstr "Создать репозитории"
 
-#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 #, fuzzy
 msgid "Show Permissions"
 msgstr "Скопировать привилегии"
@@ -2561,7 +2588,9 @@
 msgstr "Подтвердите удаление этого API-ключа: %s"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 #, fuzzy
 msgid "Remove"
 msgstr "Удалено"
@@ -2580,12 +2609,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr "Добавить"
 
@@ -2688,6 +2719,47 @@
 msgid "Name"
 msgstr "Имя"
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+#, fuzzy
+#| msgid "Last Name"
+msgid "Last Used"
+msgstr "Фамилия"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, fuzzy, python-format
+msgid "Confirm to remove this SSH key: %s"
+msgstr "Подтвердите удаление этого API-ключа: %s"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+#, fuzzy
+msgid "New SSH key"
+msgstr "Ключ"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+#, fuzzy
+#| msgid "Public repository"
+msgid "Public key"
+msgstr "Публичный репозиторий"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 msgid "Repositories You are Watching"
 msgstr "Репозитории, за которыми Вы наблюдаете"
@@ -2704,7 +2776,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr "Белый список IP"
 
@@ -2746,7 +2818,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2915,7 +2987,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr "Дополнительно"
 
@@ -3032,19 +3104,11 @@
 "private repositories and other groups if selected."
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-"Включить автоблокировку для группы. Эта опция будет применена ко всем "
-"дочерним группам и репозиториям"
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
 msgstr "Удалить эту группу"
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Confirm to delete this group"
 msgstr "Подтвердите удаление этой группы пользователей"
 
@@ -3074,7 +3138,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
@@ -3082,7 +3146,7 @@
 "Короткое и осмысленное. Для развернутого описания используйте файл README."
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr "Опционально выбрать группу, в которую поместить данный репозиторий."
@@ -3092,7 +3156,7 @@
 msgstr "Тип создаваемого репозитория."
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr "Ревизия для выгрузки"
@@ -3144,8 +3208,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr "Статистика"
 
@@ -3181,54 +3245,17 @@
 "Все производимые с этим репозиторием действия будут отображаться в "
 "публичном журнале."
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-msgid "Change Locking"
-msgstr "Включить блокирование"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-msgid "Confirm to unlock repository."
-msgstr "Подтвердите снятие блокировки с репозитория."
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-msgid "Unlock Repository"
-msgstr "Разблокировать репозиторий"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-msgid "Confirm to lock repository."
-msgstr "Подтвердите блокировку репозитория."
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-msgid "Lock Repository"
-msgstr "Заблокировать репозиторий"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr "Репозиторий не заблокирован"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
 #: kallithea/templates/data_table/_dt_elements.html:68
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "Подтвердите удаление этого репозитория: %s"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
 msgid "Delete this Repository"
 msgstr "Удалить этот репозиторий"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
@@ -3236,15 +3263,15 @@
 msgstr[1] "Данный репозиторий имеет %s копии"
 msgstr[2] "Данный репозиторий имеет %s копий"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr "Отсоединить fork'и"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr "Удалить fork'и"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3348,20 +3375,12 @@
 msgid "This repository does not have a remote repository URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
+#: kallithea/templates/admin/repos/repo_edit_settings.html:10
 #, fuzzy
-msgid "Permanent Repository ID"
+msgid "Permanent URL"
 msgstr "приватный репозиторий"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3371,34 +3390,34 @@
 "other cases that you need to hardcode the URL into a 3rd party service."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 #, fuzzy
 msgid "Remote repository"
 msgstr "[создан] репозиторий"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 #, fuzzy
 msgid "Repository URL"
 msgstr "Репозиторий"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr ""
 "Ревизия по умолчанию, из которой будет производиться выгрузка файлов при "
 "скачивании"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr "Изменить владельца репозитория."
 
@@ -3507,8 +3526,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 msgid "Save Settings"
 msgstr "Сохранить настройки"
 
@@ -3606,10 +3625,6 @@
 msgid "Kallithea version"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr ""
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr ""
@@ -3630,15 +3645,7 @@
 msgid "Git path"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr ""
 
@@ -3647,40 +3654,32 @@
 msgstr "Показывать размер репозитория после отправки"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
-msgstr "Логировать пользовательские команды отправки"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr "Логировать пользовательские команды получения"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
 msgid "Update repository after push (hg update)"
 msgstr "Обновлять репозиторий после отправки (hg update)"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:33
+#: kallithea/templates/admin/settings/settings_vcs.html:21
 msgid "Mercurial extensions"
 msgstr "Расширения Mercurial"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr "Включить поддержку больших файлов"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr "Включить поддержку hgsubversion"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:47
+#: kallithea/templates/admin/settings/settings_vcs.html:35
 msgid ""
 "Requires hgsubversion library to be installed. Enables cloning of remote "
 "Subversion repositories while converting them to Mercurial."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:59
+#: kallithea/templates/admin/settings/settings_vcs.html:47
 msgid "Location of repositories"
 msgstr "Местонахождение репозиториев"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
@@ -3688,7 +3687,7 @@
 "Нажмите для разблокирования. Изменения вступят в силу после перезагрузки "
 "Kallithea."
 
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3737,8 +3736,9 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-msgid "Clone URL"
+#, fuzzy
+#| msgid "Clone URL"
+msgid "HTTP Clone URL"
 msgstr "Ссылка для клонирования"
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
@@ -3756,59 +3756,76 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+#, fuzzy
+#| msgid "Clone URL"
+msgid "SSH Clone URL"
+msgstr "Ссылка для клонирования"
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 #, fuzzy
 #| msgid "Repository Size"
 msgid "Repository page size"
 msgstr "Размер репозитория"
 
-#: kallithea/templates/admin/settings/settings_visual.html:57
+#: kallithea/templates/admin/settings/settings_visual.html:68
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:62
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:70
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr "Иконки"
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
 msgstr "Показывать иконки публичных репозиториев"
 
-#: kallithea/templates/admin/settings/settings_visual.html:81
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr "Показывать иконки приватных репозиториев"
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 msgid "Show public/private icons next to repository names."
 msgstr "Показывать иконки публичных репозиториев."
 
-#: kallithea/templates/admin/settings/settings_visual.html:89
+#: kallithea/templates/admin/settings/settings_visual.html:100
 #, fuzzy
 msgid "Meta Tagging"
 msgstr "Метатегирование"
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr ""
 
@@ -3970,12 +3987,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr "Репозиторий Mercurial"
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr "Git репозиторий"
 
@@ -4023,158 +4040,132 @@
 msgstr "Сравнить"
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr "Поиск"
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr "Разблокировать"
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr "Заблокировать"
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr "Наблюдать"
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr "Не наблюдать"
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr "Форк"
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr "Создать Pull запрос"
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr "Переключиться на"
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr ""
 
-#: kallithea/templates/base/base.html:296
+#: kallithea/templates/base/base.html:289
 msgid "Show recent activity"
 msgstr "Показать последнюю активность"
 
-#: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
+#: kallithea/templates/base/base.html:295
+#: kallithea/templates/base/base.html:296
 msgid "Public journal"
 msgstr "Общедоступный журнал"
 
-#: kallithea/templates/base/base.html:308
+#: kallithea/templates/base/base.html:301
 msgid "Show public gists"
 msgstr "Показать публичные записи"
 
-#: kallithea/templates/base/base.html:309
+#: kallithea/templates/base/base.html:302
 msgid "Gists"
 msgstr "Gist"
 
-#: kallithea/templates/base/base.html:313
+#: kallithea/templates/base/base.html:306
 msgid "All Public Gists"
 msgstr "Все публичные Gist-записи"
 
-#: kallithea/templates/base/base.html:315
+#: kallithea/templates/base/base.html:308
 msgid "My Public Gists"
 msgstr "Мои публичные Gist-записи"
 
-#: kallithea/templates/base/base.html:316
+#: kallithea/templates/base/base.html:309
 msgid "My Private Gists"
 msgstr "Мои приватные Gist-записи"
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr "Поиск по репозиториям"
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 msgid "My Pull Requests"
 msgstr "Мои Pull-запросы"
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr "Не авторизован"
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 msgid "Login to Your Account"
 msgstr "Авторизоваться"
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 #, fuzzy
 #| msgid "Forgot password ?"
 msgid "Forgot password?"
 msgstr "Забыли пароль?"
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 #, fuzzy
 #| msgid "Don't have an account ?"
 msgid "Don't have an account?"
 msgstr "Нет аккаунта?"
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr "Выход"
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-#, fuzzy
-msgid "Inherit defaults"
-msgstr "Значения по умолчанию"
+msgid "Create repositories"
+msgstr "Создать репозитории"
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-#, fuzzy
-#| msgid "Default permissions"
-msgid "default permissions"
-msgstr "Стандартные привилегии"
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr "Создать репозитории"
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr "Опция разрешает пользователю создавать репозитарии"
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr "Создавать группы пользователей"
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr "Опция разрешает пользователю создавать группы пользователей"
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr "Создавать fork от репозиториев"
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 "Выберите эту опцию чтобы разрешить данному пользователю создавать fork'и "
@@ -4939,7 +4930,7 @@
 msgstr "Сравнение файла %s"
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr "%s Файлы"
@@ -4951,7 +4942,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr ""
 
@@ -5004,7 +4995,7 @@
 msgstr "Загружается список файлов..."
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr "Размер"
 
@@ -5134,8 +5125,8 @@
 msgstr "%s Наблюдатели"
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr "Наблюдатели"
 
@@ -5188,8 +5179,8 @@
 msgstr "Форки %s"
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr "Ответвления"
 
@@ -5508,9 +5499,9 @@
 msgid "File names"
 msgstr "Имя файла"
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr "Недостаточно прав"
 
@@ -5520,20 +5511,20 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr "ATOM лента репозитория %s"
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr "RSS лента репозитория %s"
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr "Включено"
 
@@ -5542,12 +5533,12 @@
 msgstr "Полученная статистика: "
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr "файлы"
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr "Показать еще"
 
@@ -5588,95 +5579,180 @@
 msgid "%s Summary"
 msgstr "%s общие сведения"
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr "Репозитарий заблокирован %s"
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr "Репозиторий разблокирован"
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr "Форк от"
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr "Клонировать из"
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr "Показать по ID"
-
+#: kallithea/templates/summary/summary.html:54
+msgid "Clone URL"
+msgstr "Ссылка для клонирования"
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr "Показать по имени"
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+#, fuzzy
+#| msgid "Last Name"
+msgid "Use Name"
+msgstr "Фамилия"
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr "Популярные файлы"
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr "Скачать"
 
-#: kallithea/templates/summary/summary.html:101
+#: kallithea/templates/summary/summary.html:109
 msgid "There are no downloads yet"
 msgstr "Скачиваний ещё нет"
 
-#: kallithea/templates/summary/summary.html:103
+#: kallithea/templates/summary/summary.html:111
 msgid "Downloads are disabled for this repository"
 msgstr "Скачивание отключено в этом репозитории"
 
-#: kallithea/templates/summary/summary.html:109
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr "Скачать в zip"
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr "Отметьте для скачивания архива с дочерними репозиториями"
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 msgid "With subrepos"
 msgstr "С дочерними репозиториями"
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr "Лента новостей"
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 msgid "Latest Changes"
 msgstr "Последние изменения"
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 msgid "Quick Start"
 msgstr "Быстрый старт"
 
-#: kallithea/templates/summary/summary.html:188
+#: kallithea/templates/summary/summary.html:196
 msgid "Add or upload files directly via Kallithea"
 msgstr "Добавить или загрузить файлы через Kallithea"
 
-#: kallithea/templates/summary/summary.html:196
+#: kallithea/templates/summary/summary.html:204
 #, fuzzy
 msgid "Push new repository"
 msgstr "Отправить новый репозиторий"
 
-#: kallithea/templates/summary/summary.html:204
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr "Существующий репозиторий?"
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr "Скачать %s как %s"
 
+#~ msgid "This repository has been locked by %s on %s"
+#~ msgstr "Репозиторий заблокировал %s в %s"
+
+#~ msgid "Repository has been locked"
+#~ msgstr "Репозиторий заблокирован"
+
+#~ msgid "Repository has been unlocked"
+#~ msgstr "Репозиторий разблокирован"
+
+#~ msgid "An error occurred during unlocking"
+#~ msgstr "Произошла ошибка во время разблокирования"
+
+#~ msgid "Token mismatch"
+#~ msgstr "Несовпадение токенов"
+
+#~ msgid "Enable locking"
+#~ msgstr "Включить блокирование"
+
+#~ msgid "Enable lock-by-pulling on repository."
+#~ msgstr "Включить автоблокировку для репозитория."
+
+#~ msgid ""
+#~ "Enable lock-by-pulling on group. This option will be applied to all "
+#~ "other groups and repositories inside"
+#~ msgstr ""
+#~ "Включить автоблокировку для группы. Эта опция будет применена ко всем "
+#~ "дочерним группам и репозиториям"
+
+#~ msgid "Change Locking"
+#~ msgstr "Включить блокирование"
+
+#~ msgid "Confirm to unlock repository."
+#~ msgstr "Подтвердите снятие блокировки с репозитория."
+
+#~ msgid "Unlock Repository"
+#~ msgstr "Разблокировать репозиторий"
+
+#~ msgid "Confirm to lock repository."
+#~ msgstr "Подтвердите блокировку репозитория."
+
+#~ msgid "Lock Repository"
+#~ msgstr "Заблокировать репозиторий"
+
+#~ msgid "Repository is not locked"
+#~ msgstr "Репозиторий не заблокирован"
+
+#~ msgid "Log user push commands"
+#~ msgstr "Логировать пользовательские команды отправки"
+
+#~ msgid "Log user pull commands"
+#~ msgstr "Логировать пользовательские команды получения"
+
+#~ msgid "Unlock"
+#~ msgstr "Разблокировать"
+
+#~ msgid "Lock"
+#~ msgstr "Заблокировать"
+
+#, fuzzy
+#~ msgid "Inherit defaults"
+#~ msgstr "Значения по умолчанию"
+
+#, fuzzy
+#~| msgid "Default permissions"
+#~ msgid "default permissions"
+#~ msgstr "Стандартные привилегии"
+
+#~ msgid "Repository locked by %s"
+#~ msgstr "Репозитарий заблокирован %s"
+
+#~ msgid "Repository unlocked"
+#~ msgstr "Репозиторий разблокирован"
+
+#~ msgid "Show by ID"
+#~ msgstr "Показать по ID"
+
+#~ msgid "Show by Name"
+#~ msgstr "Показать по имени"
+
 #~ msgid "There is no index to search in. Please run whoosh indexer"
 #~ msgstr "Индексы отсутствуют. Пожалуйста, запустите индексатор Whoosh"
 
@@ -5908,9 +5984,6 @@
 #~ msgid "invalid user name"
 #~ msgstr "неверное имя пользователя"
 
-#~ msgid "Your account is disabled"
-#~ msgstr "Ваш аккаунт выключен"
-
 #~ msgid "invalid clone URL"
 #~ msgstr "неверный URL для клонирования"
 
--- a/kallithea/i18n/sk/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/sk/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,13 +1,11 @@
-# Slovak translations for Kallithea.
 # Copyright (C) 2014 Various authors, licensing as GPLv3
 # This file is distributed under the same license as the Kallithea project.
-# Automatically generated, 2014.
 # #, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\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/"
@@ -20,14 +18,14 @@
 "Generated-By: Babel 1.3\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr "Zatiaľ nie sú žiadne zmeny"
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -36,93 +34,93 @@
 msgid "None"
 msgstr ""
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr "(zatvorené)"
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr "Ukázať medzery"
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr "Ignorovať medzery"
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr ""
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 #, fuzzy
 msgid "No permission to change status"
 msgstr "Zmeny"
 
-#: kallithea/controllers/changeset.py:214
+#: kallithea/controllers/changeset.py:212
 #, fuzzy, python-format
 msgid "Successfully deleted pull request %s"
 msgstr "Úspešne zmazaný súbor %s"
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr "Taká revízia neexistuje"
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, fuzzy, python-format
 #| msgid "Go to tip of repository"
 msgid "Could not find other repository %s"
 msgstr "Prázdny repozitár"
 
-#: kallithea/controllers/compare.py:72
+#: kallithea/controllers/compare.py:74
 msgid "Cannot compare repositories of different types"
 msgstr ""
 
-#: kallithea/controllers/compare.py:244
-msgid "Cannot show empty diff"
-msgstr ""
-
 #: kallithea/controllers/compare.py:246
+msgid "Cannot show empty diff"
+msgstr ""
+
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr ""
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr ""
 
-#: kallithea/controllers/error.py:70
+#: kallithea/controllers/error.py:71
 #, fuzzy
 msgid "No response"
 msgstr "Neznáma revízia %s"
 
-#: kallithea/controllers/error.py:71
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr ""
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr ""
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr ""
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr "Nemáte oprávnenie na zobrazenie tejto stránky"
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr ""
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
@@ -143,121 +141,115 @@
 msgid "Changeset was too big and was cut off..."
 msgstr ""
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr ""
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
 msgstr "Zmeny na repozitáre %s"
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr "Kliknite pre pridanie nového súboru"
 
-#: kallithea/controllers/files.py:93
+#: kallithea/controllers/files.py:86
 #, fuzzy
 #| msgid "There are no files yet. %s"
 msgid "There are no files yet."
 msgstr "Zatiaľ nie sú žiadne súbory. %s"
 
-#: kallithea/controllers/files.py:193
+#: kallithea/controllers/files.py:186
 #, python-format
 msgid "%s at %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr "Tento repozitár bol uzamknutý používateľom %s dňa %s"
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 msgid "You can only delete files with revision being a valid branch"
 msgstr ""
 
-#: kallithea/controllers/files.py:322
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr "Zmazaný súbor %s cez Kallithea"
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr "Úspešne zmazaný súbor %s"
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr "Došlo k chybe pri ukladaní"
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 msgid "You can only edit files with revision being a valid branch"
 msgstr ""
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr ""
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr "Žiadne zmeny"
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr "Pridaný súbor cez Kallithea"
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr "Žiadny obsah"
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr ""
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr ""
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr "Sťahovanie vypnuté"
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr "Neznáma revízia %s"
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr "Prázdny repozitár"
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr ""
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr "Zmeny"
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
 msgstr "Vetvy"
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr "Tagy"
 
@@ -266,11 +258,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr ""
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr "Skupiny"
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -278,178 +270,178 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr "Repozitáre"
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
 msgstr "Vetva"
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr ""
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr ""
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr "Záložka"
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr ""
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr ""
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 #, fuzzy
 msgid "Bad captcha"
 msgstr "zlá captcha"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr ""
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:190
 msgid "A password reset confirmation code has been sent"
 msgstr ""
 
-#: kallithea/controllers/login.py:238
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "Úspešne aktualizované heslo"
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr "%s (zatvorené)"
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr "Záložky"
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 msgid "New pull request iteration created"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, python-format
 msgid "Revision %s not found in %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, python-format
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr ""
 
+#: kallithea/controllers/pullrequests.py:520
+#, python-format
+msgid "This pull request has already been merged to %s."
+msgstr ""
+
 #: kallithea/controllers/pullrequests.py:522
-#, python-format
-msgid "This pull request has already been merged to %s."
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:524
 msgid "This pull request has been closed and can not be updated."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, python-format
 msgid "The following additional changes are available on %s:"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 msgid "No additional changesets found for iterating on this pull request."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 msgid "Git pull requests don't support iterating yet."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, python-format
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 
@@ -465,21 +457,21 @@
 msgid "An error occurred during search operation."
 msgstr "Došlo k chybe počas vyhľadávania."
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr ""
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -491,123 +483,136 @@
 msgid "Error occurred during update of defaults"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 msgid "Forever"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
 #: kallithea/controllers/admin/users.py:249
 msgid "5 minutes"
 msgstr "5 minút"
 
-#: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
 #: kallithea/controllers/admin/users.py:250
 msgid "1 hour"
 msgstr "1 hodina"
 
-#: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
 #: kallithea/controllers/admin/users.py:251
 msgid "1 day"
 msgstr "1 deň"
 
-#: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr "1 mesiac"
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr "Došlo k chybe pri vytváraní gist"
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:230
-msgid "Successfully updated gist data"
-msgstr ""
-
 #: kallithea/controllers/admin/gists.py:233
+msgid "Successfully updated gist data"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
 msgstr "Došlo k chybe pri aktualizácii gist %s"
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr "Došlo k chybe pri aktualizácii hesla užívateľa"
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr "Došlo k chybe pri ukladaní e-mailovej adresy"
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, python-format
+msgid "SSH key %s successfully added"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+#, fuzzy
+#| msgid "Successfully deleted file %s"
+msgid "SSH key successfully deleted"
+msgstr "Úspešne zmazaný súbor %s"
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -615,9 +620,9 @@
 msgid "Read"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -625,9 +630,9 @@
 msgid "Write"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -650,364 +655,347 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
-#: kallithea/templates/admin/auth/auth_settings.html:42
-#: kallithea/templates/base/root.html:50
-msgid "Disabled"
-msgstr ""
-
 #: kallithea/controllers/admin/permissions.py:78
-msgid "Allowed with manual account activation"
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
+#: kallithea/templates/admin/auth/auth_settings.html:42
+#: kallithea/templates/base/root.html:50
+msgid "Disabled"
 msgstr ""
 
 #: kallithea/controllers/admin/permissions.py:80
+msgid "Allowed with manual account activation"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:290
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:390
+#: kallithea/controllers/admin/repos.py:391
 #, 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:401
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:466
+#: kallithea/controllers/admin/repos.py:468
 msgid "Nothing"
 msgstr "Nič"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:470
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-#, fuzzy
-msgid "Repository has been locked"
-msgstr "Tento repozitár bol uzamknutý používateľom %s dňa %s"
+#: kallithea/controllers/admin/repos.py:490
+msgid "Cache invalidation successful"
+msgstr ""
 
 #: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-#, fuzzy
-msgid "Repository has been unlocked"
-msgstr "Tento repozitár bol uzamknutý používateľom %s dňa %s"
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:528
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:532
 msgid "An error occurred during cache invalidation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:579
+#: kallithea/controllers/admin/repos.py:541
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:180
+#: kallithea/controllers/admin/settings.py:176
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:192
+#: kallithea/controllers/admin/settings.py:188
 #, fuzzy, python-format
 #| msgid "Watched Repositories"
 msgid "Invalidated %s repositories"
 msgstr "Repozitáre"
 
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 msgid "Hook already exists"
 msgstr ""
 
+#: kallithea/controllers/admin/settings.py:357
+msgid "Builtin hooks are read-only. Please use another hook name."
+msgstr ""
+
 #: kallithea/controllers/admin/settings.py:360
-msgid "Builtin hooks are read-only. Please use another hook name."
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:363
 msgid "Added new hook"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
+#: kallithea/controllers/admin/user_groups.py:212
+msgid "Successfully deleted user group"
+msgstr ""
+
 #: kallithea/controllers/admin/user_groups.py:217
-msgid "Successfully deleted user group"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:222
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr ""
 
@@ -1037,219 +1025,219 @@
 msgid "The default user cannot be edited"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 msgid "You need to be a registered user to perform this action"
 msgstr ""
 
-#: kallithea/lib/auth.py:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr ""
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr ""
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr ""
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, python-format
 msgid "Changeset for %s %s not found in %s"
 msgstr ""
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+msgid "SSH access is disabled."
+msgstr ""
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr ""
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr ""
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:625
+#: kallithea/lib/helpers.py:666
 #, fuzzy, python-format
 #| msgid "Set changeset status"
 msgid "Changeset %s not found"
 msgstr "Zmeny"
 
-#: kallithea/lib/helpers.py:674
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr ""
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr ""
 
-#: kallithea/lib/helpers.py:725
-#, python-format
-msgid "Fork name %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:746
-#, python-format
-msgid "Pull request %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:756
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:760
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
-msgid "[updated] repository"
-msgstr ""
-
 #: kallithea/lib/helpers.py:766
+#, python-format
+msgid "Fork name %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:787
+#, python-format
+msgid "Pull request %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:797
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
+msgid "[created] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:801
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
+msgid "[updated] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr ""
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr ""
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr ""
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1257,7 +1245,34 @@
 "repositories"
 msgstr ""
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
@@ -1265,7 +1280,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
@@ -1273,7 +1288,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
@@ -1281,7 +1296,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
@@ -1289,7 +1304,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
@@ -1297,7 +1312,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
@@ -1305,27 +1320,27 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr ""
 
@@ -1334,135 +1349,135 @@
 msgid "on line %s"
 msgstr ""
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1706
+#: kallithea/model/db.py:1640
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1707
+#: kallithea/model/db.py:1641
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1708
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1711
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1730
+#: kallithea/model/db.py:1664
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1732
+#: kallithea/model/db.py:1666
 #, fuzzy
 msgid "Only admins can fork repositories"
 msgstr "Repozitáre"
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 #, fuzzy
 msgid "Non-admins can fork repositories"
 msgstr "Repozitáre"
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr ""
 
@@ -1488,303 +1503,315 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:169
+#, 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:170
 #, 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:171
-#, 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:184
+#: kallithea/model/notification.py:183
 msgid "Closing"
 msgstr ""
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 msgid "Cannot create empty pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 msgid "You are not authorized to create the pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 msgid "Missing changesets since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, python-format
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, python-format
 msgid ""
 "This iteration is based on another %s revision and there is no simple "
 "diff."
 msgstr ""
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, python-format
 msgid "No changes found on %s %s since previous iteration."
 msgstr ""
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr ""
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, fuzzy, python-format
+#| msgid "Set changeset status"
+msgid "SSH key %r not found"
+msgstr "Zmeny"
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:255
 #, 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:263
+#: kallithea/model/user.py:260
 #, 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:270
+#: kallithea/model/user.py:267
 #, 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:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr ""
 
+#: kallithea/model/validators.py:72
+#, python-format
+msgid "Username \"%(username)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:74
 #, python-format
-msgid "Username \"%(username)s\" already exists"
+msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
 #: kallithea/model/validators.py:76
-#, python-format
-msgid "Username \"%(username)s\" cannot be used"
-msgstr ""
-
-#: kallithea/model/validators.py:78
 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:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr ""
 
+#: kallithea/model/validators.py:132
+#, python-format
+msgid "User group \"%(usergroup)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:134
-#, python-format
-msgid "User group \"%(usergroup)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:136
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr ""
 
+#: kallithea/model/validators.py:175
+#, python-format
+msgid "Group \"%(group_name)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:177
 #, python-format
-msgid "Group \"%(group_name)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:179
-#, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 msgid "Invalid username or password"
 msgstr ""
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr ""
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr ""
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
-#: kallithea/model/validators.py:333
+#: kallithea/model/validators.py:318
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:419
+#: kallithea/model/validators.py:404
 #, fuzzy
 msgid "Invalid repository URL"
 msgstr "Odblokovať repozitár"
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:430
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:460
+#: kallithea/model/validators.py:445
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:512
+#: kallithea/model/validators.py:497
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:552
+#: kallithea/model/validators.py:537
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 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:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:765
+#: kallithea/model/validators.py:750
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1825,24 +1852,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr ""
 
@@ -1859,7 +1892,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1867,11 +1900,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr ""
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr ""
@@ -1886,7 +1919,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1894,7 +1927,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr ""
@@ -2051,10 +2084,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr ""
@@ -2103,22 +2138,22 @@
 msgstr ""
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr ""
 
@@ -2137,14 +2172,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2152,36 +2187,25 @@
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr ""
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr ""
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr ""
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2228,8 +2252,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 msgid "Never"
 msgstr ""
 
@@ -2262,7 +2288,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr ""
 
@@ -2298,23 +2324,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2342,7 +2370,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2402,7 +2430,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr ""
 
@@ -2415,26 +2443,31 @@
 msgid "Email Addresses"
 msgstr ""
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
+#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/users/user_edit.html:32
+msgid "SSH Keys"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
 msgid "API Keys"
 msgstr ""
 
-#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/my_account/my_account.html:32
 #, fuzzy
 msgid "Owned Repositories"
 msgstr "Repozitáre"
 
-#: kallithea/templates/admin/my_account/my_account.html:30
+#: kallithea/templates/admin/my_account/my_account.html:33
 #: kallithea/templates/journal/journal.html:33
 #, fuzzy
 msgid "Watched Repositories"
 msgstr "Repozitáre"
 
-#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 msgid "Show Permissions"
 msgstr ""
 
@@ -2461,7 +2494,9 @@
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 msgid "Remove"
 msgstr ""
 
@@ -2477,12 +2512,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr ""
 
@@ -2583,6 +2620,42 @@
 msgid "Name"
 msgstr ""
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+msgid "Last Used"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, python-format
+msgid "Confirm to remove this SSH key: %s"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+msgid "New SSH key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+msgid "Public key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 msgid "Repositories You are Watching"
 msgstr ""
@@ -2599,7 +2672,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr ""
 
@@ -2636,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2796,7 +2869,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr ""
 
@@ -2905,17 +2978,11 @@
 "private repositories and other groups if selected."
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Confirm to delete this group"
 msgstr ""
 
@@ -2945,14 +3012,14 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr ""
@@ -2962,7 +3029,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr ""
@@ -3014,8 +3081,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr ""
 
@@ -3049,54 +3116,17 @@
 "public journal."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-msgid "Change Locking"
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
+#: kallithea/templates/data_table/_dt_elements.html:68
+#, python-format
+msgid "Confirm to delete this repository: %s"
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-msgid "Confirm to unlock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-msgid "Unlock Repository"
-msgstr "Odblokovať repozitár"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-msgid "Confirm to lock repository."
-msgstr "Potvrdenie blokovania repozitára."
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-msgid "Lock Repository"
-msgstr "Zablokovať repozitár"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
-#: kallithea/templates/data_table/_dt_elements.html:68
-#, python-format
-msgid "Confirm to delete this repository: %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
 msgid "Delete this Repository"
 msgstr "Vymazať tento repozitár"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
@@ -3104,15 +3134,15 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3215,20 +3245,12 @@
 msgid "This repository does not have a remote repository URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
+#: kallithea/templates/admin/repos/repo_edit_settings.html:10
 #, fuzzy
-msgid "Permanent Repository ID"
+msgid "Permanent URL"
 msgstr "Prázdny repozitár"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3238,32 +3260,32 @@
 "other cases that you need to hardcode the URL into a 3rd party service."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 #, fuzzy
 msgid "Remote repository"
 msgstr "Prázdny repozitár"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 #, fuzzy
 msgid "Repository URL"
 msgstr "Repozitáre"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr ""
 
@@ -3372,8 +3394,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 msgid "Save Settings"
 msgstr ""
 
@@ -3468,10 +3490,6 @@
 msgid "Kallithea version"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr ""
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr ""
@@ -3492,15 +3510,7 @@
 msgid "Git path"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr ""
 
@@ -3509,47 +3519,39 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
+msgid "Update repository after push (hg update)"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
-msgid "Update repository after push (hg update)"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:33
 msgid "Mercurial extensions"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr ""
 
+#: kallithea/templates/admin/settings/settings_vcs.html:35
+msgid ""
+"Requires hgsubversion library to be installed. Enables cloning of remote "
+"Subversion repositories while converting them to Mercurial."
+msgstr ""
+
 #: kallithea/templates/admin/settings/settings_vcs.html:47
-msgid ""
-"Requires hgsubversion library to be installed. Enables cloning of remote "
-"Subversion repositories while converting them to Mercurial."
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:59
 #, fuzzy
 msgid "Location of repositories"
 msgstr "Repozitáre"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3598,8 +3600,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-msgid "Clone URL"
+msgid "HTTP Clone URL"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
@@ -3617,58 +3618,73 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+msgid "SSH Clone URL"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 #, fuzzy
 #| msgid "Repositories"
 msgid "Repository page size"
 msgstr "Repozitáre"
 
-#: kallithea/templates/admin/settings/settings_visual.html:57
+#: kallithea/templates/admin/settings/settings_visual.html:68
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:62
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:70
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:81
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 msgid "Show public/private icons next to repository names."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:89
+#: kallithea/templates/admin/settings/settings_visual.html:100
 msgid "Meta Tagging"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr ""
 
@@ -3829,12 +3845,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr ""
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr ""
 
@@ -3882,152 +3898,128 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr ""
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr ""
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr ""
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr ""
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr ""
 
+#: kallithea/templates/base/base.html:289
+msgid "Show recent activity"
+msgstr ""
+
+#: kallithea/templates/base/base.html:295
 #: kallithea/templates/base/base.html:296
-msgid "Show recent activity"
+msgid "Public journal"
+msgstr ""
+
+#: kallithea/templates/base/base.html:301
+msgid "Show public gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
-msgid "Public journal"
+msgid "Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:306
+msgid "All Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:308
-msgid "Show public gists"
+msgid "My Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:309
-msgid "Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:313
-msgid "All Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:315
-msgid "My Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:316
 msgid "My Private Gists"
 msgstr ""
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr ""
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 msgid "My Pull Requests"
 msgstr ""
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr ""
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 msgid "Login to Your Account"
 msgstr ""
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 msgid "Forgot password?"
 msgstr ""
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 msgid "Don't have an account?"
 msgstr ""
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr ""
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-#, fuzzy
-msgid "Inherit defaults"
-msgstr "Repozitáre"
+msgid "Create repositories"
+msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-msgid "default permissions"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 
@@ -4764,7 +4756,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr ""
@@ -4776,7 +4768,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr ""
 
@@ -4829,7 +4821,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr ""
 
@@ -4958,8 +4950,8 @@
 msgstr ""
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr ""
 
@@ -5010,8 +5002,8 @@
 msgstr ""
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr ""
 
@@ -5317,9 +5309,9 @@
 msgid "File names"
 msgstr ""
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr ""
 
@@ -5329,20 +5321,20 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr ""
 
@@ -5351,12 +5343,12 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr ""
 
@@ -5397,95 +5389,123 @@
 msgid "%s Summary"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr ""
-
+#: kallithea/templates/summary/summary.html:54
+msgid "Clone URL"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+msgid "Use Name"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:101
-msgid "There are no downloads yet"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:103
-msgid "Downloads are disabled for this repository"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:109
+msgid "There are no downloads yet"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:111
+msgid "Downloads are disabled for this repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 msgid "With subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 msgid "Latest Changes"
 msgstr "Posledné zmeny"
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 msgid "Quick Start"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:188
-msgid "Add or upload files directly via Kallithea"
-msgstr ""
-
 #: kallithea/templates/summary/summary.html:196
+msgid "Add or upload files directly via Kallithea"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:204
 #, fuzzy
 msgid "Push new repository"
 msgstr "Prázdny repozitár"
 
-#: kallithea/templates/summary/summary.html:204
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr ""
 
+#~ msgid "This repository has been locked by %s on %s"
+#~ msgstr "Tento repozitár bol uzamknutý používateľom %s dňa %s"
+
+#, fuzzy
+#~ msgid "Repository has been locked"
+#~ msgstr "Tento repozitár bol uzamknutý používateľom %s dňa %s"
+
+#, fuzzy
+#~ msgid "Repository has been unlocked"
+#~ msgstr "Tento repozitár bol uzamknutý používateľom %s dňa %s"
+
+#~ msgid "Unlock Repository"
+#~ msgstr "Odblokovať repozitár"
+
+#~ msgid "Confirm to lock repository."
+#~ msgstr "Potvrdenie blokovania repozitára."
+
+#~ msgid "Lock Repository"
+#~ msgstr "Zablokovať repozitár"
+
+#, fuzzy
+#~ msgid "Inherit defaults"
+#~ msgstr "Repozitáre"
+
 #, fuzzy
 #~| msgid "Repository URL"
 #~ msgid "Repository Group"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/i18n/tr/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,5406 @@
+# Translations template for Kallithea.
+# Copyright (C) 2019 Various authors, licensing as GPLv3
+# This file is distributed under the same license as the Kallithea project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2019.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Kallithea 0.4.99\n"
+"Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\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/"
+"kallithea/tr/>\n"
+"Language: tr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 3.10-dev\n"
+"Generated-By: Babel 2.6.0\n"
+
+#: kallithea/controllers/changelog.py:67
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
+msgid "There are no changesets yet"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:7
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:7
+#: kallithea/templates/base/perms_summary.html:14
+msgid "None"
+msgstr "Yok"
+
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
+msgid "(closed)"
+msgstr "(kapalı)"
+
+#: kallithea/controllers/changeset.py:81
+msgid "Show whitespace"
+msgstr "Boşlukları göster"
+
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
+#: kallithea/templates/files/diff_2way.html:55
+msgid "Ignore whitespace"
+msgstr ""
+
+#: kallithea/controllers/changeset.py:161
+#, python-format
+msgid "Increase diff context to %(num)s lines"
+msgstr ""
+
+#: kallithea/controllers/changeset.py:201
+msgid "No permission to change status"
+msgstr ""
+
+#: kallithea/controllers/changeset.py:212
+#, python-format
+msgid "Successfully deleted pull request %s"
+msgstr ""
+
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
+msgid "Such revision does not exist for this repository"
+msgstr ""
+
+#: kallithea/controllers/compare.py:68
+#, python-format
+msgid "Could not find other repository %s"
+msgstr ""
+
+#: kallithea/controllers/compare.py:74
+msgid "Cannot compare repositories of different types"
+msgstr ""
+
+#: kallithea/controllers/compare.py:246
+msgid "Cannot show empty diff"
+msgstr ""
+
+#: kallithea/controllers/compare.py:248
+msgid "No ancestor found for merge diff"
+msgstr ""
+
+#: kallithea/controllers/compare.py:252
+msgid "Multiple merge ancestors found for merge compare"
+msgstr ""
+
+#: kallithea/controllers/compare.py:268
+msgid "Cannot compare repositories without using common ancestor"
+msgstr ""
+
+#: kallithea/controllers/error.py:71
+msgid "No response"
+msgstr ""
+
+#: kallithea/controllers/error.py:72
+msgid "Unknown error"
+msgstr ""
+
+#: kallithea/controllers/error.py:85
+msgid ""
+"The request could not be understood by the server due to malformed syntax."
+msgstr ""
+
+#: kallithea/controllers/error.py:88
+msgid "Unauthorized access to resource"
+msgstr ""
+
+#: kallithea/controllers/error.py:90
+msgid "You don't have permission to view this page"
+msgstr ""
+
+#: kallithea/controllers/error.py:92
+msgid "The resource could not be found"
+msgstr ""
+
+#: kallithea/controllers/error.py:94
+msgid ""
+"The server encountered an unexpected condition which prevented it from "
+"fulfilling the request."
+msgstr ""
+
+#: kallithea/controllers/feed.py:63
+#, python-format
+msgid "%s committed on %s"
+msgstr ""
+
+#: kallithea/controllers/feed.py:88
+#: kallithea/templates/changeset/changeset.html:154
+#: kallithea/templates/changeset/changeset.html:173
+#: kallithea/templates/compare/compare_diff.html:81
+#: kallithea/templates/compare/compare_diff.html:95
+#: kallithea/templates/pullrequests/pullrequest_show.html:309
+#: kallithea/templates/pullrequests/pullrequest_show.html:333
+msgid "Changeset was too big and was cut off..."
+msgstr ""
+
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
+#, python-format
+msgid "%s %s feed"
+msgstr ""
+
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
+#, python-format
+msgid "Changes on %s repository"
+msgstr ""
+
+#: kallithea/controllers/files.py:85
+msgid "Click here to add new file"
+msgstr ""
+
+#: kallithea/controllers/files.py:86
+msgid "There are no files yet."
+msgstr ""
+
+#: kallithea/controllers/files.py:186
+#, python-format
+msgid "%s at %s"
+msgstr ""
+
+#: kallithea/controllers/files.py:296
+msgid "You can only delete files with revision being a valid branch"
+msgstr ""
+
+#: kallithea/controllers/files.py:307
+#, python-format
+msgid "Deleted file %s via Kallithea"
+msgstr ""
+
+#: kallithea/controllers/files.py:331
+#, python-format
+msgid "Successfully deleted file %s"
+msgstr ""
+
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
+msgid "Error occurred during commit"
+msgstr ""
+
+#: kallithea/controllers/files.py:350
+msgid "You can only edit files with revision being a valid branch"
+msgstr ""
+
+#: kallithea/controllers/files.py:364
+#, python-format
+msgid "Edited file %s via Kallithea"
+msgstr ""
+
+#: kallithea/controllers/files.py:380
+msgid "No changes"
+msgstr ""
+
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
+#, python-format
+msgid "Successfully committed to %s"
+msgstr ""
+
+#: kallithea/controllers/files.py:409
+msgid "Added file via Kallithea"
+msgstr ""
+
+#: kallithea/controllers/files.py:430
+msgid "No content"
+msgstr ""
+
+#: kallithea/controllers/files.py:434
+msgid "No filename"
+msgstr ""
+
+#: kallithea/controllers/files.py:461
+msgid "Location must be relative path and must not contain .. in path"
+msgstr ""
+
+#: kallithea/controllers/files.py:493
+msgid "Downloads disabled"
+msgstr ""
+
+#: kallithea/controllers/files.py:504
+#, python-format
+msgid "Unknown revision %s"
+msgstr ""
+
+#: kallithea/controllers/files.py:506
+msgid "Empty repository"
+msgstr ""
+
+#: kallithea/controllers/files.py:508
+msgid "Unknown archive type"
+msgstr ""
+
+#: kallithea/controllers/files.py:729
+#: kallithea/templates/changeset/changeset_range.html:9
+#: kallithea/templates/email_templates/pull_request.html:64
+#: kallithea/templates/pullrequests/pullrequest.html:84
+msgid "Changesets"
+msgstr ""
+
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
+msgid "Branches"
+msgstr ""
+
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
+msgid "Tags"
+msgstr ""
+
+#: kallithea/controllers/forks.py:174
+#, python-format
+msgid "An error occurred during repository forking %s"
+msgstr ""
+
+#: kallithea/controllers/home.py:79
+msgid "Groups"
+msgstr ""
+
+#: kallithea/controllers/home.py:89
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
+#: kallithea/templates/admin/repos/repo_add.html:12
+#: kallithea/templates/admin/repos/repo_add.html:16
+#: kallithea/templates/admin/repos/repos.html:9
+#: kallithea/templates/admin/users/user_edit_advanced.html:6
+#: kallithea/templates/base/base.html:56
+#: kallithea/templates/base/base.html:73
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
+msgid "Repositories"
+msgstr ""
+
+#: kallithea/controllers/home.py:122
+#: kallithea/templates/files/files_add.html:32
+#: kallithea/templates/files/files_delete.html:23
+#: kallithea/templates/files/files_edit.html:32
+msgid "Branch"
+msgstr ""
+
+#: kallithea/controllers/home.py:128
+msgid "Closed Branches"
+msgstr ""
+
+#: kallithea/controllers/home.py:134
+msgid "Tag"
+msgstr ""
+
+#: kallithea/controllers/home.py:140
+msgid "Bookmark"
+msgstr ""
+
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
+#: kallithea/templates/journal/public_journal.html:4
+#: kallithea/templates/journal/public_journal.html:18
+msgid "Public Journal"
+msgstr ""
+
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
+#: kallithea/templates/journal/journal.html:5
+#: kallithea/templates/journal/journal.html:13
+msgid "Journal"
+msgstr ""
+
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
+msgid "Bad captcha"
+msgstr ""
+
+#: kallithea/controllers/login.py:146
+#, python-format
+msgid "You have successfully registered with %s"
+msgstr ""
+
+#: kallithea/controllers/login.py:190
+msgid "A password reset confirmation code has been sent"
+msgstr ""
+
+#: kallithea/controllers/login.py:239
+msgid "Invalid password reset token"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
+msgid "Successfully updated password"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:68
+#, python-format
+msgid "Invalid reviewer \"%s\" specified"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:131
+#, python-format
+msgid "%s (closed)"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:158
+#: kallithea/templates/changeset/changeset.html:12
+msgid "Changeset"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:179
+msgid "Special"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:180
+msgid "Peer branches"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
+msgid "Bookmarks"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:318
+#, python-format
+msgid "Error creating pull request: %s"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
+msgid "Error occurred while creating pull request"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:350
+msgid "Successfully opened new pull request"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:373
+msgid "New pull request iteration created"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:401
+#, python-format
+msgid "Meanwhile, the following reviewers have been added: %s"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:405
+#, python-format
+msgid "Meanwhile, the following reviewers have been removed: %s"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
+msgid "No description"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:430
+msgid "Pull request updated"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:443
+msgid "Successfully deleted pull request"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:479
+#, python-format
+msgid "Revision %s not found in %s"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:506
+#, python-format
+msgid "Error: changesets not found when displaying pull request from %s."
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:520
+#, python-format
+msgid "This pull request has already been merged to %s."
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:522
+msgid "This pull request has been closed and can not be updated."
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:546
+#, python-format
+msgid "The following additional changes are available on %s:"
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
+msgid "No additional changesets found for iterating on this pull request."
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:560
+#, python-format
+msgid "Note: Branch %s has another head: %s."
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:567
+msgid "Git pull requests don't support iterating yet."
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:569
+#, python-format
+msgid ""
+"Error: some changesets not found when displaying pull request from %s."
+msgstr ""
+
+#: kallithea/controllers/pullrequests.py:593
+msgid "The diff can't be shown - the PR revisions could not be found."
+msgstr ""
+
+#: kallithea/controllers/search.py:136
+msgid "Invalid search query. Try quoting it."
+msgstr ""
+
+#: kallithea/controllers/search.py:140
+msgid "The server has no search index."
+msgstr ""
+
+#: kallithea/controllers/search.py:143
+msgid "An error occurred during search operation."
+msgstr ""
+
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
+msgid "No data ready yet"
+msgstr ""
+
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
+msgid "Statistics are disabled for this repository"
+msgstr ""
+
+#: kallithea/controllers/admin/auth_settings.py:137
+msgid "Auth settings updated successfully"
+msgstr ""
+
+#: kallithea/controllers/admin/auth_settings.py:148
+msgid "error occurred during update of auth settings"
+msgstr ""
+
+#: kallithea/controllers/admin/defaults.py:75
+msgid "Default settings updated successfully"
+msgstr ""
+
+#: kallithea/controllers/admin/defaults.py:90
+msgid "Error occurred during update of defaults"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/users.py:248
+msgid "Forever"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/users.py:249
+msgid "5 minutes"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/users.py:250
+msgid "1 hour"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
+#: kallithea/controllers/admin/users.py:251
+msgid "1 day"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/users.py:252
+msgid "1 month"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
+#: kallithea/controllers/admin/users.py:254
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:65
+#: kallithea/templates/admin/users/user_edit_api_keys.html:65
+msgid "Lifetime"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:142
+msgid "Error occurred during gist creation"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:158
+#, python-format
+msgid "Deleted gist %s"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:198
+msgid "Unmodified"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:228
+msgid "Successfully updated gist content"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:233
+msgid "Successfully updated gist data"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:236
+#, python-format
+msgid "Error occurred during update of gist %s"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
+msgid "You can't edit this user since it's crucial for entire application"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:119
+msgid "Your account was updated successfully"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:134
+#: kallithea/controllers/admin/users.py:181
+#, python-format
+msgid "Error occurred during update of user %s"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:168
+msgid "Error occurred during update of user password"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
+#, python-format
+msgid "Added email %s to user"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
+msgid "An error occurred during email saving"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
+msgid "Removed email from user"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:248
+#: kallithea/controllers/admin/users.py:271
+msgid "API key successfully created"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:257
+#: kallithea/controllers/admin/users.py:281
+msgid "API key successfully reset"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:261
+#: kallithea/controllers/admin/users.py:285
+msgid "API key successfully deleted"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, python-format
+msgid "SSH key %s successfully added"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+msgid "SSH key successfully deleted"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:8
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
+#: kallithea/templates/base/perms_summary.html:15
+msgid "Read"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:9
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
+#: kallithea/templates/base/perms_summary.html:16
+msgid "Write"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
+#: kallithea/templates/admin/auth/auth_settings.html:9
+#: kallithea/templates/admin/defaults/defaults.html:9
+#: kallithea/templates/admin/permissions/permissions.html:9
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:9
+#: kallithea/templates/admin/repo_groups/repo_group_edit.html:9
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:47
+#: kallithea/templates/admin/repo_groups/repo_groups.html:9
+#: kallithea/templates/admin/repos/repo_add.html:10
+#: kallithea/templates/admin/repos/repo_add.html:14
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:10
+#: kallithea/templates/admin/settings/settings.html:9
+#: kallithea/templates/admin/user_groups/user_group_add.html:8
+#: kallithea/templates/admin/user_groups/user_group_edit.html:9
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:10
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:47
+#: kallithea/templates/admin/user_groups/user_groups.html:9
+#: kallithea/templates/admin/users/user_add.html:8
+#: kallithea/templates/admin/users/user_edit.html:9
+#: kallithea/templates/admin/users/user_edit_profile.html:81
+#: kallithea/templates/admin/users/users.html:9
+#: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:327
+#: kallithea/templates/base/base.html:328
+#: kallithea/templates/base/perms_summary.html:17
+msgid "Admin"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
+#: kallithea/templates/admin/auth/auth_settings.html:42
+#: kallithea/templates/base/root.html:50
+msgid "Disabled"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:80
+msgid "Allowed with manual account activation"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:82
+msgid "Allowed with automatic account activation"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
+msgid "Manual activation of external account"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
+msgid "Automatic activation of external account"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
+#: kallithea/templates/admin/auth/auth_settings.html:42
+#: kallithea/templates/base/root.html:49
+msgid "Enabled"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:127
+msgid "Global permissions updated successfully"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:142
+msgid "Error occurred during update of permissions"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:172
+#, python-format
+msgid "Error occurred during creation of repository group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:177
+#, python-format
+msgid "Created repository group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:224
+#, python-format
+msgid "Updated repository group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:240
+#, python-format
+msgid "Error occurred during update of repository group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:250
+#, python-format
+msgid "This group contains %s repositories and cannot be deleted"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:257
+#, python-format
+msgid "This group contains %s subgroups and cannot be deleted"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:263
+#, python-format
+msgid "Removed repository group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:268
+#, python-format
+msgid "Error occurred during deletion of repository group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
+msgid "Cannot revoke permission for yourself as admin"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:367
+msgid "Repository group permissions updated"
+msgstr ""
+
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
+msgid "An error occurred during revoking of permission"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:136
+#, python-format
+msgid "Error creating repository %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:194
+#, python-format
+msgid "Created repository %s from %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:203
+#, python-format
+msgid "Forked repository %s as %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:206
+#, python-format
+msgid "Created repository %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:235
+#, python-format
+msgid "Repository %s updated successfully"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:255
+#, python-format
+msgid "Error occurred during update of repository %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:273
+#, python-format
+msgid "Detached %s forks"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:276
+#, python-format
+msgid "Deleted %s forks"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:281
+#, python-format
+msgid "Deleted repository %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:284
+#, python-format
+msgid "Cannot delete repository %s which still has forks"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:289
+#, python-format
+msgid "An error occurred during deletion of %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:329
+msgid "Repository permissions updated"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:388
+#, python-format
+msgid "Field validation error: %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:391
+#, python-format
+msgid "An error occurred during creation of field: %r"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:402
+msgid "An error occurred during removal of field"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:416
+msgid "-- Not a fork --"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:448
+msgid "Updated repository visibility in public journal"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:452
+msgid "An error occurred during setting this repository in public journal"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:468
+msgid "Nothing"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:470
+#, python-format
+msgid "Marked repository %s as fork of %s"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:477
+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
+msgid "Pulled from remote location"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:510
+msgid "An error occurred during pull from remote location"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:541
+msgid "An error occurred during deletion of repository stats"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:131
+msgid "Updated VCS settings"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
+msgid ""
+"Unable to activate hgsubversion support. The \"hgsubversion\" library is "
+"missing"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
+msgid "Error occurred while updating application settings"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:176
+#, python-format
+msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:188
+#, python-format
+msgid "Invalidated %s repositories"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:229
+msgid "Updated application settings"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:283
+msgid "Updated visualisation settings"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:288
+msgid "Error occurred during updating visualisation settings"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:312
+msgid "Please enter email address"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:327
+msgid "Send email task created"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:355
+msgid "Hook already exists"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:357
+msgid "Builtin hooks are read-only. Please use another hook name."
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:360
+msgid "Added new hook"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:376
+msgid "Updated hooks"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:380
+msgid "Error occurred during hook creation"
+msgstr ""
+
+#: kallithea/controllers/admin/settings.py:404
+msgid "Whoosh reindex task scheduled"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:138
+#, python-format
+msgid "Created user group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:151
+#, python-format
+msgid "Error occurred during creation of user group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:179
+#, python-format
+msgid "Updated user group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:201
+#, python-format
+msgid "Error occurred during update of user group %s"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:212
+msgid "Successfully deleted user group"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:217
+msgid "An error occurred during deletion of user group"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:273
+msgid "Target group cannot be the same"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:279
+msgid "User group permissions updated"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
+msgid "Updated permissions"
+msgstr ""
+
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
+msgid "An error occurred during permissions saving"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:123
+#, python-format
+msgid "Created user %s"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:138
+#, python-format
+msgid "Error occurred during creation of user %s"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:162
+msgid "User updated successfully"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:190
+msgid "Successfully deleted user"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:195
+msgid "An error occurred during deletion of user"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:203
+msgid "The default user cannot be edited"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:409
+#, python-format
+msgid "Added IP address %s to user whitelist"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:415
+msgid "An error occurred while adding IP address"
+msgstr ""
+
+#: kallithea/controllers/admin/users.py:427
+msgid "Removed IP address from user whitelist"
+msgstr ""
+
+#: kallithea/lib/auth.py:684
+msgid "You need to be a registered user to perform this action"
+msgstr ""
+
+#: kallithea/lib/auth.py:712
+msgid "You need to be signed in to view this page"
+msgstr ""
+
+#: kallithea/lib/base.py:483
+msgid ""
+"CSRF token leak has been detected - all form tokens have been expired"
+msgstr ""
+
+#: kallithea/lib/base.py:580
+msgid "Repository not found in the filesystem"
+msgstr ""
+
+#: kallithea/lib/base.py:605
+#, python-format
+msgid "Changeset for %s %s not found in %s"
+msgstr ""
+
+#: kallithea/lib/base.py:647
+msgid "SSH access is disabled."
+msgstr ""
+
+#: kallithea/lib/diffs.py:194
+msgid "Binary file"
+msgstr ""
+
+#: kallithea/lib/diffs.py:214
+msgid ""
+"Changeset was too big and was cut off, use diff menu to display this diff"
+msgstr ""
+
+#: kallithea/lib/diffs.py:224
+msgid "No changes detected"
+msgstr ""
+
+#: kallithea/lib/helpers.py:653
+#, python-format
+msgid "Deleted branch: %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:655
+#, python-format
+msgid "Created tag: %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:666
+#, python-format
+msgid "Changeset %s not found"
+msgstr ""
+
+#: kallithea/lib/helpers.py:715
+#, python-format
+msgid "Show all combined changesets %s->%s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:721
+msgid "Compare view"
+msgstr ""
+
+#: kallithea/lib/helpers.py:740
+msgid "and"
+msgstr ""
+
+#: kallithea/lib/helpers.py:741
+#, python-format
+msgid "%s more"
+msgstr ""
+
+#: kallithea/lib/helpers.py:742
+#: kallithea/templates/changelog/changelog.html:43
+msgid "revisions"
+msgstr ""
+
+#: kallithea/lib/helpers.py:766
+#, python-format
+msgid "Fork name %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:787
+#, python-format
+msgid "Pull request %s"
+msgstr ""
+
+#: kallithea/lib/helpers.py:797
+msgid "[deleted] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
+msgid "[created] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:801
+msgid "[created] repository as fork"
+msgstr ""
+
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
+msgid "[forked] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
+msgid "[updated] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:807
+msgid "[downloaded] archive from repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:809
+msgid "[delete] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:817
+msgid "[created] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:819
+msgid "[updated] user"
+msgstr ""
+
+#: kallithea/lib/helpers.py:821
+msgid "[created] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:823
+msgid "[updated] user group"
+msgstr ""
+
+#: kallithea/lib/helpers.py:825
+msgid "[commented] on revision in repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:827
+msgid "[commented] on pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:829
+msgid "[closed] pull request for"
+msgstr ""
+
+#: kallithea/lib/helpers.py:831
+msgid "[pushed] into"
+msgstr ""
+
+#: kallithea/lib/helpers.py:833
+msgid "[committed via Kallithea] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:835
+msgid "[pulled from remote] into repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:837
+msgid "[pulled] from"
+msgstr ""
+
+#: kallithea/lib/helpers.py:839
+msgid "[started following] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:841
+msgid "[stopped following] repository"
+msgstr ""
+
+#: kallithea/lib/helpers.py:961
+#, python-format
+msgid " and %s more"
+msgstr ""
+
+#: kallithea/lib/helpers.py:965
+#: kallithea/templates/compare/compare_diff.html:69
+#: kallithea/templates/pullrequests/pullrequest_show.html:297
+msgid "No files"
+msgstr ""
+
+#: kallithea/lib/helpers.py:990
+msgid "new file"
+msgstr ""
+
+#: kallithea/lib/helpers.py:993
+msgid "mod"
+msgstr ""
+
+#: kallithea/lib/helpers.py:996
+msgid "del"
+msgstr ""
+
+#: kallithea/lib/helpers.py:999
+msgid "rename"
+msgstr ""
+
+#: kallithea/lib/helpers.py:1004
+msgid "chmod"
+msgstr ""
+
+#: kallithea/lib/helpers.py:1297
+#, python-format
+msgid ""
+"%s repository is not mapped to db perhaps it was created or renamed from "
+"the filesystem please run the application again in order to rescan "
+"repositories"
+msgstr ""
+
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
+#, python-format
+msgid "%d year"
+msgid_plural "%d years"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/lib/utils2.py:335
+#, python-format
+msgid "%d month"
+msgid_plural "%d months"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/lib/utils2.py:336
+#, python-format
+msgid "%d day"
+msgid_plural "%d days"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/lib/utils2.py:337
+#, python-format
+msgid "%d hour"
+msgid_plural "%d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/lib/utils2.py:338
+#, python-format
+msgid "%d minute"
+msgid_plural "%d minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/lib/utils2.py:339
+#, python-format
+msgid "%d second"
+msgid_plural "%d seconds"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/lib/utils2.py:355
+#, python-format
+msgid "in %s"
+msgstr ""
+
+#: kallithea/lib/utils2.py:357
+#, python-format
+msgid "%s ago"
+msgstr ""
+
+#: kallithea/lib/utils2.py:359
+#, python-format
+msgid "in %s and %s"
+msgstr ""
+
+#: kallithea/lib/utils2.py:362
+#, python-format
+msgid "%s and %s ago"
+msgstr ""
+
+#: kallithea/lib/utils2.py:365
+msgid "just now"
+msgstr ""
+
+#: kallithea/model/comment.py:68
+#, python-format
+msgid "on line %s"
+msgstr ""
+
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
+msgid "[Mention]"
+msgstr ""
+
+#: kallithea/model/db.py:1496
+msgid "top level"
+msgstr ""
+
+#: kallithea/model/db.py:1637
+msgid "Kallithea Administrator"
+msgstr ""
+
+#: kallithea/model/db.py:1639
+msgid "Default user has no access to new repositories"
+msgstr ""
+
+#: kallithea/model/db.py:1640
+msgid "Default user has read access to new repositories"
+msgstr ""
+
+#: kallithea/model/db.py:1641
+msgid "Default user has write access to new repositories"
+msgstr ""
+
+#: kallithea/model/db.py:1642
+msgid "Default user has admin access to new repositories"
+msgstr ""
+
+#: kallithea/model/db.py:1644
+msgid "Default user has no access to new repository groups"
+msgstr ""
+
+#: kallithea/model/db.py:1645
+msgid "Default user has read access to new repository groups"
+msgstr ""
+
+#: kallithea/model/db.py:1646
+msgid "Default user has write access to new repository groups"
+msgstr ""
+
+#: kallithea/model/db.py:1647
+msgid "Default user has admin access to new repository groups"
+msgstr ""
+
+#: kallithea/model/db.py:1649
+msgid "Default user has no access to new user groups"
+msgstr ""
+
+#: kallithea/model/db.py:1650
+msgid "Default user has read access to new user groups"
+msgstr ""
+
+#: kallithea/model/db.py:1651
+msgid "Default user has write access to new user groups"
+msgstr ""
+
+#: kallithea/model/db.py:1652
+msgid "Default user has admin access to new user groups"
+msgstr ""
+
+#: kallithea/model/db.py:1654
+msgid "Only admins can create repository groups"
+msgstr ""
+
+#: kallithea/model/db.py:1655
+msgid "Non-admins can create repository groups"
+msgstr ""
+
+#: kallithea/model/db.py:1657
+msgid "Only admins can create user groups"
+msgstr ""
+
+#: kallithea/model/db.py:1658
+msgid "Non-admins can create user groups"
+msgstr ""
+
+#: kallithea/model/db.py:1660
+msgid "Only admins can create top level repositories"
+msgstr ""
+
+#: kallithea/model/db.py:1661
+msgid "Non-admins can create top level repositories"
+msgstr ""
+
+#: kallithea/model/db.py:1663
+msgid ""
+"Repository creation enabled with write permission to a repository group"
+msgstr ""
+
+#: kallithea/model/db.py:1664
+msgid ""
+"Repository creation disabled with write permission to a repository group"
+msgstr ""
+
+#: kallithea/model/db.py:1666
+msgid "Only admins can fork repositories"
+msgstr ""
+
+#: kallithea/model/db.py:1667
+msgid "Non-admins can fork repositories"
+msgstr ""
+
+#: kallithea/model/db.py:1669
+msgid "Registration disabled"
+msgstr ""
+
+#: kallithea/model/db.py:1670
+msgid "User registration with manual account activation"
+msgstr ""
+
+#: kallithea/model/db.py:1671
+msgid "User registration with automatic account activation"
+msgstr ""
+
+#: kallithea/model/db.py:2206
+msgid "Not reviewed"
+msgstr ""
+
+#: kallithea/model/db.py:2207
+msgid "Under review"
+msgstr ""
+
+#: kallithea/model/db.py:2208
+msgid "Not approved"
+msgstr ""
+
+#: kallithea/model/db.py:2209
+msgid "Approved"
+msgstr ""
+
+#: kallithea/model/forms.py:58
+msgid "Please enter a login"
+msgstr ""
+
+#: kallithea/model/forms.py:59
+#, python-format
+msgid "Enter a value %(min)i characters long or more"
+msgstr ""
+
+#: kallithea/model/forms.py:67
+msgid "Please enter a password"
+msgstr ""
+
+#: kallithea/model/forms.py:68
+#, python-format
+msgid "Enter %(min)i characters or more"
+msgstr ""
+
+#: kallithea/model/forms.py:170
+msgid "Name must not contain only digits"
+msgstr ""
+
+#: kallithea/model/notification.py:164
+#, python-format
+msgid ""
+"[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
+"%(branch)s"
+msgstr ""
+
+#: kallithea/model/notification.py:167
+#, python-format
+msgid "New user %(new_username)s registered"
+msgstr ""
+
+#: kallithea/model/notification.py:169
+#, 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:170
+#, 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:183
+msgid "Closing"
+msgstr ""
+
+#: kallithea/model/pull_request.py:73
+#, python-format
+msgid ""
+"%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
+msgstr ""
+
+#: kallithea/model/pull_request.py:209
+msgid "Cannot create empty pull request"
+msgstr ""
+
+#: kallithea/model/pull_request.py:217
+#, python-format
+msgid ""
+"Cannot create pull request - criss cross merge detected, please merge a "
+"later %s revision to %s"
+msgstr ""
+
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
+msgid "You are not authorized to create the pull request"
+msgstr ""
+
+#: kallithea/model/pull_request.py:339
+msgid "Missing changesets since the previous iteration:"
+msgstr ""
+
+#: kallithea/model/pull_request.py:346
+#, python-format
+msgid "New changesets on %s %s since the previous iteration:"
+msgstr ""
+
+#: kallithea/model/pull_request.py:353
+msgid "Ancestor didn't change - diff since previous iteration:"
+msgstr ""
+
+#: kallithea/model/pull_request.py:360
+#, python-format
+msgid ""
+"This iteration is based on another %s revision and there is no simple "
+"diff."
+msgstr ""
+
+#: kallithea/model/pull_request.py:362
+#, python-format
+msgid "No changes found on %s %s since previous iteration."
+msgstr ""
+
+#: kallithea/model/pull_request.py:388
+#, python-format
+msgid "Closed, next iteration: %s ."
+msgstr ""
+
+#: kallithea/model/scm.py:668
+msgid "latest tip"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, python-format
+msgid "SSH key %r not found"
+msgstr ""
+
+#: kallithea/model/user.py:186
+msgid "New user registration"
+msgstr ""
+
+#: kallithea/model/user.py:250
+msgid ""
+"You can't remove this user since it is crucial for the entire application"
+msgstr ""
+
+#: kallithea/model/user.py:255
+#, 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:260
+#, 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:267
+#, 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:361
+msgid "Password reset link"
+msgstr ""
+
+#: kallithea/model/user.py:408
+msgid "Password reset notification"
+msgstr ""
+
+#: kallithea/model/user.py:409
+#, 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
+msgid "Value cannot be an empty list"
+msgstr ""
+
+#: kallithea/model/validators.py:72
+#, python-format
+msgid "Username \"%(username)s\" already exists"
+msgstr ""
+
+#: kallithea/model/validators.py:74
+#, python-format
+msgid "Username \"%(username)s\" cannot be used"
+msgstr ""
+
+#: kallithea/model/validators.py:76
+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
+msgid "The input is not valid"
+msgstr ""
+
+#: kallithea/model/validators.py:110
+#, 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
+#, python-format
+msgid "User group \"%(usergroup)s\" already exists"
+msgstr ""
+
+#: kallithea/model/validators.py:134
+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
+#, python-format
+msgid "Group \"%(group_name)s\" already exists"
+msgstr ""
+
+#: kallithea/model/validators.py:177
+#, python-format
+msgid "Repository with name \"%(group_name)s\" already exists"
+msgstr ""
+
+#: kallithea/model/validators.py:233
+msgid "Invalid characters (non-ascii) in password"
+msgstr ""
+
+#: kallithea/model/validators.py:248
+msgid "Invalid old password"
+msgstr ""
+
+#: kallithea/model/validators.py:264
+msgid "Passwords do not match"
+msgstr ""
+
+#: kallithea/model/validators.py:279
+msgid "Invalid username or password"
+msgstr ""
+
+#: kallithea/model/validators.py:313
+#, python-format
+msgid "Repository name %(repo)s is not allowed"
+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
+msgid "Invalid repository URL"
+msgstr ""
+
+#: kallithea/model/validators.py:405
+msgid ""
+"Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
+"svn+https URL"
+msgstr ""
+
+#: kallithea/model/validators.py:430
+msgid "Fork has to be the same type as parent"
+msgstr ""
+
+#: kallithea/model/validators.py:445
+msgid "You don't have permissions to create repository in this group"
+msgstr ""
+
+#: kallithea/model/validators.py:447
+msgid "no permission to create repository in root location"
+msgstr ""
+
+#: kallithea/model/validators.py:497
+msgid "You don't have permissions to create a group in this location"
+msgstr ""
+
+#: kallithea/model/validators.py:537
+msgid "This username or user group name is not valid"
+msgstr ""
+
+#: kallithea/model/validators.py:630
+msgid "This is not a valid path"
+msgstr ""
+
+#: kallithea/model/validators.py:647
+msgid "This email address is already in use"
+msgstr ""
+
+#: kallithea/model/validators.py:667
+#, python-format
+msgid "Email address \"%(email)s\" not found"
+msgstr ""
+
+#: kallithea/model/validators.py:704
+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
+msgid "Please enter a valid IPv4 or IPv6 address"
+msgstr ""
+
+#: kallithea/model/validators.py:717
+#, python-format
+msgid ""
+"The network size (bits) must be within the range of 0-32 (not %(bits)r)"
+msgstr ""
+
+#: kallithea/model/validators.py:750
+msgid "Key name can only consist of letters, underscore, dash or numbers"
+msgstr ""
+
+#: kallithea/model/validators.py:764
+msgid "Filename cannot be inside a directory"
+msgstr ""
+
+#: kallithea/model/validators.py:780
+#, python-format
+msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
+msgstr ""
+
+#: kallithea/templates/about.html:4 kallithea/templates/about.html:13
+msgid "About"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_add.html:5
+#: kallithea/templates/admin/repos/repo_add.html:19
+#: kallithea/templates/admin/repos/repos.html:23
+#: kallithea/templates/index_base.html:25
+#: kallithea/templates/index_base.html:30
+msgid "Add Repository"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:5
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:13
+#: kallithea/templates/admin/repo_groups/repo_groups.html:25
+#: kallithea/templates/index_base.html:27
+#: kallithea/templates/index_base.html:32
+msgid "Add Repository Group"
+msgstr ""
+
+#: kallithea/templates/index_base.html:37
+msgid "You have admin right to this group, and can edit it"
+msgstr ""
+
+#: kallithea/templates/index_base.html:37
+msgid "Edit Repository Group"
+msgstr ""
+
+#: kallithea/templates/admin/admin_log.html:7
+#: kallithea/templates/admin/permissions/permissions_globals.html:14
+#: kallithea/templates/index_base.html:53
+msgid "Repository"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:59
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
+#: kallithea/templates/admin/repo_groups/repo_groups.html:40
+#: kallithea/templates/admin/repos/repo_add_base.html:21
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
+#: kallithea/templates/admin/repos/repos.html:39
+#: kallithea/templates/admin/user_groups/user_group_add.html:33
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
+#: kallithea/templates/admin/user_groups/user_groups.html:39
+#: kallithea/templates/admin/users/user_edit_api_keys.html:59
+#: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
+#: kallithea/templates/pullrequests/pullrequest_show.html:38
+#: kallithea/templates/pullrequests/pullrequest_show.html:59
+#: kallithea/templates/summary/summary.html:87
+msgid "Description"
+msgstr ""
+
+#: kallithea/templates/index_base.html:60
+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
+msgid "Tip"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
+#: kallithea/templates/admin/repo_groups/repo_groups.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
+#: 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/pullrequests/pullrequest_data.html:16
+#: kallithea/templates/pullrequests/pullrequest_show.html:124
+#: kallithea/templates/pullrequests/pullrequest_show.html:219
+#: kallithea/templates/summary/summary.html:132
+msgid "Owner"
+msgstr ""
+
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
+#: kallithea/templates/login.html:19
+msgid "Log In"
+msgstr ""
+
+#: kallithea/templates/login.html:17
+#, python-format
+msgid "Log In to %s"
+msgstr ""
+
+#: kallithea/templates/admin/admin_log.html:5
+#: kallithea/templates/admin/my_account/my_account_profile.html:18
+#: kallithea/templates/admin/users/user_add.html:27
+#: 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/login.html:28 kallithea/templates/register.html:31
+msgid "Username"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:27
+#: kallithea/templates/admin/users/user_add.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
+#: kallithea/templates/register.html:38
+msgid "Password"
+msgstr ""
+
+#: kallithea/templates/login.html:44
+msgid "Stay logged in after browser restart"
+msgstr ""
+
+#: kallithea/templates/login.html:52
+msgid "Forgot your password ?"
+msgstr ""
+
+#: kallithea/templates/login.html:55
+msgid "Don't have an account ?"
+msgstr ""
+
+#: kallithea/templates/login.html:62
+msgid "Sign In"
+msgstr ""
+
+#: kallithea/templates/password_reset.html:5
+msgid "Password Reset"
+msgstr ""
+
+#: kallithea/templates/password_reset.html:21
+#: kallithea/templates/password_reset_confirmation.html:16
+#, python-format
+msgid "Reset Your Password to %s"
+msgstr ""
+
+#: kallithea/templates/password_reset.html:23
+#: kallithea/templates/password_reset_confirmation.html:5
+#: kallithea/templates/password_reset_confirmation.html:18
+msgid "Reset Your Password"
+msgstr ""
+
+#: kallithea/templates/password_reset.html:30
+msgid "Email Address"
+msgstr ""
+
+#: kallithea/templates/password_reset.html:38
+#: kallithea/templates/register.html:74
+msgid "Captcha"
+msgstr ""
+
+#: kallithea/templates/password_reset.html:47
+msgid "Send Password Reset Email"
+msgstr ""
+
+#: kallithea/templates/password_reset.html:52
+msgid ""
+"A password reset link will be sent to the specified email address if it "
+"is registered in the system."
+msgstr ""
+
+#: kallithea/templates/password_reset_confirmation.html:23
+#, python-format
+msgid "You are about to set a new password for the email address %s."
+msgstr ""
+
+#: kallithea/templates/password_reset_confirmation.html:24
+msgid ""
+"Note that you must use the same browser session for this as the one used "
+"to request the password reset."
+msgstr ""
+
+#: kallithea/templates/password_reset_confirmation.html:29
+msgid "Code you received in the email"
+msgstr ""
+
+#: kallithea/templates/password_reset_confirmation.html:36
+msgid "New Password"
+msgstr ""
+
+#: kallithea/templates/password_reset_confirmation.html:43
+msgid "Confirm New Password"
+msgstr ""
+
+#: kallithea/templates/password_reset_confirmation.html:51
+msgid "Confirm"
+msgstr ""
+
+#: kallithea/templates/register.html:5 kallithea/templates/register.html:24
+#: kallithea/templates/register.html:83
+msgid "Sign Up"
+msgstr ""
+
+#: kallithea/templates/register.html:22
+#, python-format
+msgid "Sign Up to %s"
+msgstr ""
+
+#: kallithea/templates/register.html:45
+msgid "Re-enter password"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_profile.html:25
+#: kallithea/templates/admin/users/user_add.html:48
+#: kallithea/templates/admin/users/user_edit_profile.html:60
+#: kallithea/templates/admin/users/users.html:38
+#: kallithea/templates/register.html:52
+msgid "First Name"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_profile.html:32
+#: kallithea/templates/admin/users/user_add.html:55
+#: kallithea/templates/admin/users/user_edit_profile.html:67
+#: kallithea/templates/admin/users/users.html:39
+#: kallithea/templates/register.html:59
+msgid "Last Name"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_profile.html:39
+#: 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/register.html:66
+msgid "Email"
+msgstr ""
+
+#: kallithea/templates/register.html:85
+msgid "Registered accounts are ready to use and need no further action."
+msgstr ""
+
+#: kallithea/templates/register.html:87
+msgid "Please wait for an administrator to activate your account."
+msgstr ""
+
+#: kallithea/templates/admin/admin.html:5
+#: kallithea/templates/admin/admin.html:13
+#: kallithea/templates/base/base.html:55
+msgid "Admin Journal"
+msgstr ""
+
+#: kallithea/templates/admin/admin.html:10
+#: kallithea/templates/journal/journal.html:10
+msgid "journal filter..."
+msgstr ""
+
+#: kallithea/templates/admin/admin.html:12
+#: kallithea/templates/journal/journal.html:12
+msgid "Filter"
+msgstr ""
+
+#: kallithea/templates/admin/admin.html:13
+#: kallithea/templates/journal/journal.html:13
+#, python-format
+msgid "%s Entry"
+msgid_plural "%s Entries"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/admin/admin_log.html:6
+#: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
+#: kallithea/templates/admin/repo_groups/repo_groups.html:43
+#: kallithea/templates/admin/repos/repo_edit_fields.html:9
+#: kallithea/templates/admin/repos/repos.html:44
+#: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
+#: kallithea/templates/admin/users/users.html:45
+msgid "Action"
+msgstr ""
+
+#: kallithea/templates/admin/admin_log.html:8
+msgid "Date"
+msgstr ""
+
+#: kallithea/templates/admin/admin_log.html:9
+msgid "From IP"
+msgstr ""
+
+#: kallithea/templates/admin/admin_log.html:61
+msgid "No actions yet"
+msgstr ""
+
+#: kallithea/templates/admin/auth/auth_settings.html:5
+msgid "Authentication Settings"
+msgstr ""
+
+#: kallithea/templates/admin/auth/auth_settings.html:11
+#: kallithea/templates/base/base.html:61
+msgid "Authentication"
+msgstr ""
+
+#: kallithea/templates/admin/auth/auth_settings.html:27
+msgid "Authentication Plugins"
+msgstr ""
+
+#: kallithea/templates/admin/auth/auth_settings.html:29
+msgid "Enabled Plugins"
+msgstr ""
+
+#: kallithea/templates/admin/auth/auth_settings.html:32
+msgid ""
+"Comma-separated list of plugins; Kallithea will try user authentication "
+"in plugin order"
+msgstr ""
+
+#: kallithea/templates/admin/auth/auth_settings.html:36
+msgid "Available built-in plugins"
+msgstr ""
+
+#: kallithea/templates/admin/auth/auth_settings.html:53
+msgid "Plugin"
+msgstr ""
+
+#: kallithea/templates/admin/auth/auth_settings.html:101
+#: kallithea/templates/admin/defaults/defaults.html:59
+#: kallithea/templates/admin/my_account/my_account_password.html:30
+#: kallithea/templates/admin/my_account/my_account_profile.html:47
+#: kallithea/templates/admin/permissions/permissions_globals.html:95
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:58
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:84
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
+#: kallithea/templates/admin/settings/settings_hooks.html:46
+#: kallithea/templates/admin/user_groups/user_group_add.html:48
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
+#: kallithea/templates/admin/users/user_add.html:80
+#: kallithea/templates/admin/users/user_edit_profile.html:89
+#: kallithea/templates/base/default_perms_box.html:42
+msgid "Save"
+msgstr ""
+
+#: kallithea/templates/admin/defaults/defaults.html:5
+#: kallithea/templates/admin/defaults/defaults.html:11
+#: kallithea/templates/base/base.html:62
+msgid "Repository Defaults"
+msgstr ""
+
+#: kallithea/templates/admin/defaults/defaults.html:27
+#: kallithea/templates/admin/repos/repo_add_base.html:42
+#: kallithea/templates/admin/repos/repo_edit_fields.html:8
+msgid "Type"
+msgstr ""
+
+#: kallithea/templates/admin/defaults/defaults.html:34
+#: kallithea/templates/admin/repos/repo_add_base.html:56
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
+#: kallithea/templates/data_table/_dt_elements.html:21
+msgid "Private repository"
+msgstr ""
+
+#: kallithea/templates/admin/defaults/defaults.html:37
+#: kallithea/templates/admin/repos/repo_add_base.html:59
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
+#: kallithea/templates/forks/fork.html:61
+msgid ""
+"Private repositories are only visible to people explicitly added as "
+"collaborators."
+msgstr ""
+
+#: kallithea/templates/admin/defaults/defaults.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
+msgid "Enable statistics"
+msgstr ""
+
+#: kallithea/templates/admin/defaults/defaults.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
+msgid "Enable statistics window on summary page."
+msgstr ""
+
+#: kallithea/templates/admin/defaults/defaults.html:50
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
+msgid "Enable downloads"
+msgstr ""
+
+#: kallithea/templates/admin/defaults/defaults.html:53
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
+msgid "Enable download menu on summary page."
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:5
+#: kallithea/templates/admin/gists/edit.html:18
+msgid "Edit Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:35
+#, python-format
+msgid ""
+"Gist was updated since you started editing. Copy your changes and click "
+"%(here)s to reload new version."
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:36
+msgid "here"
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:51
+#: kallithea/templates/admin/gists/new.html:35
+msgid "Gist description ..."
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:54
+#: kallithea/templates/admin/gists/new.html:38
+msgid "Gist lifetime"
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:59
+#: kallithea/templates/admin/gists/edit.html:61
+#: kallithea/templates/admin/gists/index.html:54
+#: kallithea/templates/admin/gists/index.html:56
+#: kallithea/templates/admin/gists/show.html:45
+#: kallithea/templates/admin/gists/show.html:47
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:7
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:31
+#: kallithea/templates/admin/users/user_edit_api_keys.html:7
+#: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_api_keys.html:31
+msgid "Expires"
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:59
+#: kallithea/templates/admin/gists/index.html:54
+#: kallithea/templates/admin/gists/show.html:45
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:7
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
+#: kallithea/templates/admin/users/user_edit_api_keys.html:7
+#: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
+msgid "Never"
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:145
+msgid "Update Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/edit.html:146
+#: kallithea/templates/base/root.html:27
+#: kallithea/templates/changeset/changeset_file_comment.html:130
+msgid "Cancel"
+msgstr ""
+
+#: kallithea/templates/admin/gists/index.html:6
+#: kallithea/templates/admin/gists/index.html:16
+#, python-format
+msgid "Private Gists for User %s"
+msgstr ""
+
+#: kallithea/templates/admin/gists/index.html:8
+#: kallithea/templates/admin/gists/index.html:18
+#, python-format
+msgid "Public Gists for User %s"
+msgstr ""
+
+#: kallithea/templates/admin/gists/index.html:10
+#: kallithea/templates/admin/gists/index.html:20
+msgid "Public Gists"
+msgstr ""
+
+#: kallithea/templates/admin/gists/index.html:37
+#: kallithea/templates/admin/gists/show.html:25
+#: kallithea/templates/base/base.html:305
+msgid "Create New Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/index.html:51
+#: kallithea/templates/data_table/_dt_elements.html:78
+msgid "Created"
+msgstr ""
+
+#: kallithea/templates/admin/gists/index.html:66
+msgid "There are no gists yet"
+msgstr ""
+
+#: kallithea/templates/admin/gists/new.html:5
+#: kallithea/templates/admin/gists/new.html:18
+msgid "New Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/new.html:45
+msgid "Name this gist ..."
+msgstr ""
+
+#: kallithea/templates/admin/gists/new.html:53
+msgid "Create Private Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/new.html:54
+msgid "Create Public Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/new.html:55
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:14
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:73
+#: kallithea/templates/admin/my_account/my_account_emails.html:47
+#: kallithea/templates/admin/my_account/my_account_password.html:31
+#: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
+#: kallithea/templates/admin/permissions/permissions_globals.html:96
+#: kallithea/templates/admin/permissions/permissions_ips.html:34
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
+#: kallithea/templates/admin/repos/repo_edit_fields.html:54
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:85
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
+#: kallithea/templates/admin/settings/settings_global.html:50
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
+#: kallithea/templates/admin/users/user_edit_api_keys.html:14
+#: kallithea/templates/admin/users/user_edit_api_keys.html:73
+#: kallithea/templates/admin/users/user_edit_emails.html:47
+#: kallithea/templates/admin/users/user_edit_ips.html:45
+#: kallithea/templates/admin/users/user_edit_profile.html:90
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/files/files_add.html:69
+#: kallithea/templates/files/files_delete.html:41
+#: kallithea/templates/files/files_edit.html:72
+#: kallithea/templates/pullrequests/pullrequest.html:78
+msgid "Reset"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:5
+#: kallithea/templates/admin/gists/show.html:9
+msgid "Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:10
+msgid "URL"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:35
+msgid "Public Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:37
+msgid "Private Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:54
+#: kallithea/templates/admin/my_account/my_account_emails.html:23
+#: kallithea/templates/admin/permissions/permissions_ips.html:11
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
+#: kallithea/templates/admin/repos/repo_edit_fields.html:19
+#: kallithea/templates/admin/settings/settings_hooks.html:30
+#: kallithea/templates/admin/users/user_edit_emails.html:23
+#: 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/files/files_source.html:35
+#: kallithea/templates/files/files_source.html:38
+#: kallithea/templates/files/files_source.html:41
+#: kallithea/templates/pullrequests/pullrequest_data.html:20
+msgid "Delete"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:54
+msgid "Confirm to delete this Gist"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:61
+#: 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/files/diff_2way.html:56
+#: kallithea/templates/files/files_source.html:37
+#: kallithea/templates/files/files_source.html:40
+#: kallithea/templates/pullrequests/pullrequest_show.html:41
+msgid "Edit"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:63
+#: kallithea/templates/files/files_edit.html:52
+#: kallithea/templates/files/files_source.html:30
+msgid "Show as Raw"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:69
+msgid "created"
+msgstr ""
+
+#: kallithea/templates/admin/gists/show.html:82
+msgid "Show as raw"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:5
+#: kallithea/templates/admin/my_account/my_account.html:9
+#: kallithea/templates/base/base.html:390
+msgid "My Account"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:25
+#: kallithea/templates/admin/users/user_edit.html:29
+msgid "Profile"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:26
+msgid "Email Addresses"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/users/user_edit.html:32
+msgid "SSH Keys"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
+msgid "API Keys"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:32
+msgid "Owned Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:33
+#: kallithea/templates/journal/journal.html:33
+msgid "Watched Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:34
+#: kallithea/templates/admin/permissions/permissions.html:30
+#: kallithea/templates/admin/user_groups/user_group_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:37
+msgid "Show Permissions"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:5
+#: kallithea/templates/admin/users/user_edit_api_keys.html:5
+msgid "Built-in"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:13
+#: kallithea/templates/admin/users/user_edit_api_keys.html:13
+#, python-format
+msgid "Confirm to reset this API key: %s"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:29
+#: kallithea/templates/admin/users/user_edit_api_keys.html:29
+msgid "Expired"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:39
+#: kallithea/templates/admin/users/user_edit_api_keys.html:39
+#, python-format
+msgid "Confirm to remove this API key: %s"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
+#: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
+msgid "Remove"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:48
+#: kallithea/templates/admin/users/user_edit_api_keys.html:48
+msgid "No additional API keys specified"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:56
+#: kallithea/templates/admin/users/user_edit_api_keys.html:56
+msgid "New API key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:72
+#: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
+#: kallithea/templates/admin/permissions/permissions_ips.html:33
+#: kallithea/templates/admin/repos/repo_add_base.html:64
+#: kallithea/templates/admin/repos/repo_edit_fields.html:53
+#: kallithea/templates/admin/users/user_edit_api_keys.html:72
+#: kallithea/templates/admin/users/user_edit_emails.html:46
+#: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
+msgid "Add"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:81
+#, python-format
+msgid ""
+"\n"
+"API keys are used to let scripts or services access %s using your\n"
+"account, as if you had provided the script or service with your actual\n"
+"password.\n"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_api_keys.html:86
+msgid ""
+"\n"
+"Like passwords, API keys should therefore never be shared with others,\n"
+"nor passed to untrusted scripts or services. If such sharing should\n"
+"happen anyway, reset the API key on this page to prevent further use.\n"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_emails.html:9
+#: kallithea/templates/admin/users/user_edit_emails.html:9
+msgid "Primary"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_emails.html:24
+#: kallithea/templates/admin/users/user_edit_emails.html:24
+#, python-format
+msgid "Confirm to delete this email: %s"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_emails.html:30
+#: kallithea/templates/admin/users/user_edit_emails.html:30
+msgid "No additional emails specified."
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_emails.html:39
+#: kallithea/templates/admin/users/user_edit_emails.html:39
+msgid "New email address"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_password.html:1
+msgid "Change Your Account Password"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_password.html:8
+msgid "Current password"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_password.html:15
+#: kallithea/templates/admin/users/user_edit_profile.html:46
+msgid "New password"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_password.html:22
+msgid "Confirm new password"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_password.html:39
+#, python-format
+msgid ""
+"This account is managed with %s and the password cannot be changed here"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_perms.html:3
+msgid "Current IP"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_profile.html:4
+#: kallithea/templates/admin/users/user_edit_profile.html:4
+msgid "Gravatar"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_profile.html:10
+#: kallithea/templates/admin/users/user_edit_profile.html:10
+#, python-format
+msgid "Change %s avatar at"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_profile.html:12
+#: kallithea/templates/admin/users/user_edit_profile.html:12
+msgid "Avatars are disabled"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_repos.html:1
+msgid "Repositories You Own"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_repos.html:13
+#: kallithea/templates/admin/my_account/my_account_watched.html:13
+#: kallithea/templates/admin/repo_groups/repo_groups.html:39
+#: kallithea/templates/admin/repos/repo_add_base.html:6
+#: kallithea/templates/admin/repos/repo_edit_settings.html:4
+#: kallithea/templates/admin/repos/repos.html:38
+#: kallithea/templates/admin/user_groups/user_groups.html:38
+#: kallithea/templates/base/perms_summary.html:54
+#: kallithea/templates/files/files_browser.html:54
+msgid "Name"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+msgid "Last Used"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, python-format
+msgid "Confirm to remove this SSH key: %s"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+msgid "New SSH key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+msgid "Public key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_watched.html:1
+msgid "Repositories You are Watching"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions.html:5
+#: kallithea/templates/admin/permissions/permissions.html:11
+#: kallithea/templates/base/base.html:60
+msgid "Default Permissions"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions.html:28
+#: kallithea/templates/admin/settings/settings.html:29
+msgid "Global"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions.html:29
+#: kallithea/templates/admin/users/user_edit.html:35
+msgid "IP Whitelist"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:4
+msgid "Anonymous access"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:8
+msgid "Allow anonymous access"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:10
+#, python-format
+msgid ""
+"Allow access to Kallithea without needing to log in. Anonymous users use "
+"%s user permissions."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:19
+msgid ""
+"All default permissions on each repository will be reset to chosen "
+"permission, note that all custom default permission on repositories will "
+"be lost"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:20
+msgid "Apply to all existing repositories"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:23
+msgid "Permissions for the Default user on new repositories."
+msgstr ""
+
+#: 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/forks/fork.html:42
+msgid "Repository group"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:32
+msgid ""
+"All default permissions on each repository group will be reset to chosen "
+"permission, note that all custom default permission on repository groups "
+"will be lost"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:33
+msgid "Apply to all existing repository groups"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:36
+msgid "Permissions for the Default user on new repository groups."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:40
+#: kallithea/templates/data_table/_dt_elements.html:141
+msgid "User group"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:45
+msgid ""
+"All default permissions on each user group will be reset to chosen "
+"permission, note that all custom default permission on user groups will "
+"be lost"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:46
+msgid "Apply to all existing user groups"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:49
+msgid "Permissions for the Default user on new user groups."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:53
+msgid "Top level repository creation"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:56
+msgid ""
+"Enable this to allow non-admins to create repositories at the top level."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:57
+msgid ""
+"Note: This will also give all users API access to create repositories "
+"everywhere. That might change in future versions."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:61
+msgid "Repository creation with group write access"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:64
+msgid ""
+"With this, write permission to a repository group allows creating "
+"repositories inside that group. Without this, group write permissions "
+"mean nothing."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:68
+msgid "User group creation"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:71
+msgid "Enable this to allow non-admins to create user groups."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:75
+msgid "Repository forking"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:78
+msgid "Enable this to allow non-admins to fork repositories."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:82
+msgid "Registration"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_globals.html:88
+msgid "External auth account activation"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_ips.html:12
+#: kallithea/templates/admin/users/user_edit_ips.html:22
+#, python-format
+msgid "Confirm to delete this IP address: %s"
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_ips.html:18
+#: kallithea/templates/admin/users/user_edit_ips.html:29
+msgid "All IP addresses are allowed."
+msgstr ""
+
+#: kallithea/templates/admin/permissions/permissions_ips.html:25
+#: kallithea/templates/admin/users/user_edit_ips.html:37
+msgid "New IP address"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:11
+#: kallithea/templates/admin/repo_groups/repo_group_edit.html:11
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:89
+#: kallithea/templates/admin/repo_groups/repo_groups.html:9
+#: kallithea/templates/base/base.html:57
+#: kallithea/templates/base/base.html:76
+msgid "Repository Groups"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:28
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:5
+#: kallithea/templates/admin/user_groups/user_group_add.html:27
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:4
+msgid "Group name"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:42
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:19
+msgid "Group parent"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:49
+#: kallithea/templates/admin/repos/repo_add_base.html:35
+msgid "Copy parent group permissions"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_add.html:52
+#: kallithea/templates/admin/repos/repo_add_base.html:38
+msgid "Copy permission set from parent repository group."
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit.html:5
+#, python-format
+msgid "%s Repository Group Settings"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit.html:29
+msgid "Add Child Group"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit.html:36
+#: kallithea/templates/admin/repos/repo_edit.html:12
+#: kallithea/templates/admin/repos/repo_edit.html:25
+#: kallithea/templates/admin/settings/settings.html:11
+#: kallithea/templates/admin/user_groups/user_group_edit.html:29
+#: kallithea/templates/base/base.html:63
+#: kallithea/templates/base/base.html:152
+msgid "Settings"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
+#: kallithea/templates/admin/repos/repo_edit.html:31
+#: kallithea/templates/admin/user_groups/user_group_edit.html:30
+#: kallithea/templates/admin/users/user_edit.html:36
+msgid "Advanced"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit.html:38
+#: kallithea/templates/admin/repos/repo_edit.html:28
+#: kallithea/templates/admin/user_groups/user_group_edit.html:31
+msgid "Permissions"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:1
+#, python-format
+msgid "Repository Group: %s"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:6
+msgid "Top level repositories"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:7
+msgid "Total repositories"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:8
+msgid "Children groups"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:9
+#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:7
+#: kallithea/templates/admin/users/user_edit_advanced.html:8
+#: kallithea/templates/pullrequests/pullrequest_show.html:118
+msgid "Created on"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
+#: kallithea/templates/data_table/_dt_elements.html:121
+#, python-format
+msgid "Confirm to delete this group: %s with %s repository"
+msgid_plural "Confirm to delete this group: %s with %s repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:25
+msgid "Delete this repository group"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
+msgid "Not visible"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
+msgid "Visible"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
+msgid "Add repos"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10
+msgid "Add/Edit groups"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:11
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:11
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:11
+msgid "User/User Group"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:28
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:45
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:23
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:36
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:28
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:45
+msgid "Default"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:34
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:71
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:42
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:67
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:34
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:71
+msgid "Revoke"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:81
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:77
+#: kallithea/templates/admin/user_groups/user_group_edit_perms.html:81
+msgid "Add new"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:87
+msgid "Apply to children"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:91
+msgid "Both"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:92
+msgid ""
+"Set or revoke permission to all children of that group, including non-"
+"private repositories and other groups if selected."
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
+msgid "Remove this group"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
+msgid "Confirm to delete this group"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_group_show.html:4
+#, python-format
+msgid "Repository group %s"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_groups.html:5
+msgid "Repository Groups Administration"
+msgstr ""
+
+#: kallithea/templates/admin/repo_groups/repo_groups.html:41
+msgid "Number of Top-level Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_add_base.html:12
+msgid "Clone remote repository"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_add_base.html:16
+msgid ""
+"Optional: URL of a remote repository. If set, the repository will be "
+"created as a clone from this URL."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_add_base.html:24
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/forks/fork.html:37
+msgid ""
+"Keep it short and to the point. Use a README file for longer descriptions."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_add_base.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
+#: kallithea/templates/forks/fork.html:45
+msgid "Optionally select a group to put this repository into."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_add_base.html:45
+msgid "Type of repository to create."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_add_base.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
+#: kallithea/templates/forks/fork.html:50
+msgid "Landing revision"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_add_base.html:52
+msgid ""
+"Default revision for files page, downloads, full text search index and "
+"readme generation"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_creating.html:9
+#, python-format
+msgid "%s Creating Repository"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_creating.html:13
+msgid "Creating repository"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_creating.html:27
+#, python-format
+msgid ""
+"Repository \"%(repo_name)s\" is being created, you will be redirected "
+"when this process is finished.repo_name"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_creating.html:39
+msgid ""
+"We're sorry but error occurred during this operation. Please check your "
+"Kallithea server logs, or contact administrator."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit.html:8
+#, python-format
+msgid "%s Repository Settings"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit.html:34
+msgid "Extra Fields"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit.html:37
+msgid "Caches"
+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
+msgid "Statistics"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:1
+msgid "Parent"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:5
+msgid "Set"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:7
+msgid "Manually set this repository as a fork of another from the list."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:20
+msgid "Public Journal Visibility"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:27
+msgid "Remove from public journal"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:32
+msgid "Add to Public Journal"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:37
+msgid ""
+"All actions done in this repository will be visible to everyone in the "
+"public journal."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
+#: kallithea/templates/data_table/_dt_elements.html:68
+#, python-format
+msgid "Confirm to delete this repository: %s"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
+msgid "Delete this Repository"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
+#, python-format
+msgid "This repository has %s fork"
+msgid_plural "This repository has %s forks"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
+msgid "Detach forks"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
+msgid "Delete forks"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
+msgid ""
+"The deleted repository will be moved away and hidden until the "
+"administrator expires it. The administrator can both permanently delete "
+"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: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"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_fields.html:31
+msgid "New field key"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_fields.html:38
+msgid "New field label"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_fields.html:40
+msgid "Enter short label"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_fields.html:45
+msgid "New field description"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_fields.html:47
+msgid "Enter description of a field"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_fields.html:61
+msgid "Extra fields are disabled."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_permissions.html:20
+msgid "Private Repository"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_remote.html:4
+msgid "Fork of repository"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_remote.html:7
+msgid "Remote repository URL"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_remote.html:15
+msgid "Pull Changes from Remote Repository"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_remote.html:17
+msgid "Confirm to pull changes from remote repository."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_remote.html:23
+msgid "This repository does not have a remote repository URL."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+msgid "Permanent URL"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
+msgid ""
+"In case this repository is renamed or moved into another group the "
+"repository URL changes.\n"
+"                               Using the above permanent URL guarantees "
+"that this repository always will be accessible on that URL.\n"
+"                               This is useful for CI systems, or any "
+"other cases that you need to hardcode the URL into a 3rd party service."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
+msgid "Remote repository"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
+msgid "Repository URL"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
+msgid ""
+"Optional: URL of a remote repository. If set, the repository can be "
+"pulled from this URL."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
+msgid "Default revision for files page, downloads, whoosh and readme"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/pullrequests/pullrequest_show.html:131
+msgid "Type name of user"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
+msgid "Change owner of this repository."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_statistics.html:5
+msgid "Processed commits"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_statistics.html:6
+msgid "Processed progress"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_statistics.html:10
+msgid "Reset Statistics"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_statistics.html:10
+msgid "Confirm to remove current statistics."
+msgstr ""
+
+#: kallithea/templates/admin/repos/repos.html:5
+msgid "Repositories Administration"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repos.html:43
+msgid "State"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings.html:5
+msgid "Settings Administration"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings.html:27
+msgid "VCS"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings.html:28
+msgid "Remap and Rescan"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings.html:30
+msgid "Visual"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings.html:32
+#: kallithea/templates/admin/settings/settings_vcs.html:4
+msgid "Hooks"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings.html:33
+msgid "Full Text Search"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings.html:34
+msgid "System Info"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_email.html:4
+msgid "Send test email to"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_email.html:12
+msgid "Send"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:4
+msgid "Site branding"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:7
+msgid "Set a custom title for your Kallithea Service."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:12
+msgid "HTTP authentication realm"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:19
+msgid "HTML/JavaScript/CSS customization block"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:22
+msgid ""
+"HTML (possibly with                         JavaScript and/or CSS) that "
+"will be added to the bottom                         of every page. This "
+"can be used for web analytics                         systems, but also "
+"to                         perform instance-specific customizations like "
+"adding a                         project banner at the top of every page."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:32
+msgid "ReCaptcha public key"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:35
+msgid "Public key for reCaptcha system."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:40
+msgid "ReCaptcha private key"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:43
+msgid ""
+"Private key for reCaptcha system. Setting this value will enable captcha "
+"on registration."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_global.html:49
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
+msgid "Save Settings"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_hooks.html:3
+msgid "Built-in Mercurial Hooks (Read-Only)"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_hooks.html:17
+msgid "Custom Hooks"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_hooks.html:18
+msgid ""
+"Hooks can be used to trigger actions on certain events such as push / "
+"pull. They can trigger Python functions or external applications."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_hooks.html:60
+msgid "Failed to remove hook"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:4
+msgid "Rescan options"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:9
+msgid "Delete records of missing repositories"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:12
+msgid ""
+"Check this option to remove all comments, pull requests and other records "
+"related to repositories that no longer exist in the filesystem."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:17
+msgid "Invalidate cache for all repositories"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:20
+msgid "Check this to reload data and clear cache keys for all repositories."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:25
+msgid "Install Git hooks"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:28
+msgid ""
+"Verify if Kallithea's Git hooks are installed for each repository. "
+"Current hooks will be updated to the latest version."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:32
+msgid "Overwrite existing Git hooks"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:35
+msgid ""
+"If installing Git hooks, overwrite any existing hooks, even if they do "
+"not seem to come from Kallithea. WARNING: This operation will destroy any "
+"custom git hooks you may have deployed by hand!"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_mapping.html:41
+msgid "Rescan Repositories"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_search.html:4
+msgid "Index build option"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_search.html:9
+msgid "Build from scratch"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_search.html:12
+msgid ""
+"This option completely reindexeses all of the repositories for proper "
+"fulltext search capabilities."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_search.html:18
+msgid "Reindex"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_system.html:2
+msgid "Checking for updates..."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_system.html:7
+msgid "Kallithea version"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_system.html:8
+msgid "Kallithea configuration file"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_system.html:9
+msgid "Python version"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_system.html:10
+msgid "Platform"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_system.html:11
+msgid "Git version"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_system.html:12
+msgid "Git path"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_system.html:22
+msgid "Python Packages"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:9
+msgid "Show repository size after push"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:15
+msgid "Update repository after push (hg update)"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:21
+msgid "Mercurial extensions"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:26
+msgid "Enable largefiles extension"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:32
+msgid "Enable hgsubversion extension"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:35
+msgid ""
+"Requires hgsubversion library to be installed. Enables cloning of remote "
+"Subversion repositories while converting them to Mercurial."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:47
+msgid "Location of repositories"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:52
+msgid ""
+"Click to unlock. You must restart Kallithea in order to make this setting "
+"take effect."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_vcs.html:56
+msgid ""
+"Filesystem location where repositories are stored. After changing this "
+"value, a restart and rescan of the repository folder are both required."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:4
+msgid "General"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:9
+msgid "Use repository extra fields"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:12
+msgid "Allows storing additional customized fields per repository."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:17
+msgid "Show Kallithea version"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:20
+msgid ""
+"Shows or hides a version number of Kallithea displayed in the footer."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:25
+msgid "Show user Gravatars"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:29
+msgid ""
+"Gravatar URL allows you to use another avatar server application.\n"
+"                                                        The following "
+"variables of the URL will be replaced accordingly.\n"
+"                                                        {scheme}    "
+"'http' or 'https' sent from running Kallithea server,\n"
+"                                                        {email}     user "
+"email,\n"
+"                                                        {md5email}  md5 "
+"hash of the user email (like at gravatar.com),\n"
+"                                                        {size}      size "
+"of the image that is expected from the server application,\n"
+"                                                        {netloc}    "
+"network location/server host of running Kallithea server"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:40
+msgid "HTTP Clone URL"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:43
+msgid ""
+"Schema of clone URL construction eg. '{scheme}://{user}@{netloc}/"
+"{repo}'.\n"
+"                                                    The following "
+"variables are available:\n"
+"                                                    {scheme} 'http' or "
+"'https' sent from running Kallithea server,\n"
+"                                                    {user}   current user "
+"username,\n"
+"                                                    {netloc} network "
+"location/server host of running Kallithea server,\n"
+"                                                    {repo}   full "
+"repository name,\n"
+"                                                    {repoid} ID of "
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+msgid "SSH Clone URL"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
+msgid "Repository page size"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:68
+msgid ""
+"Number of items displayed in the repository pages before pagination is "
+"shown."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:73
+msgid "Admin page size"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:76
+msgid ""
+"Number of items displayed in the admin pages grids before pagination is "
+"shown."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:81
+msgid "Icons"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:86
+msgid "Show public repository icon on repositories"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:92
+msgid "Show private repository icon on repositories"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:95
+msgid "Show public/private icons next to repository names."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:100
+msgid "Meta Tagging"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:105
+msgid ""
+"Parses meta tags from the repository description field and turns them "
+"into colored tags."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:109
+msgid "Stylify recognised meta tags:"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_add.html:5
+msgid "Add user group"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_add.html:10
+#: kallithea/templates/admin/user_groups/user_group_edit.html:11
+#: kallithea/templates/admin/user_groups/user_groups.html:9
+#: kallithea/templates/base/base.html:59
+#: kallithea/templates/base/base.html:79
+msgid "User Groups"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_add.html:12
+#: kallithea/templates/admin/user_groups/user_groups.html:24
+msgid "Add User Group"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_add.html:36
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:13
+msgid "Short, optional description for this user group."
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit.html:5
+#, python-format
+msgid "%s user group settings"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit.html:33
+msgid "Show Members"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:1
+#, python-format
+msgid "User Group: %s"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:6
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:23
+#: kallithea/templates/admin/user_groups/user_groups.html:40
+msgid "Members"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:19
+#: kallithea/templates/data_table/_dt_elements.html:102
+#, python-format
+msgid "Confirm to delete this user group: %s"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:21
+msgid "Delete this user group"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit_members.html:11
+msgid "No members yet"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:26
+msgid "Chosen group members"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_group_edit_settings.html:39
+msgid "Available members"
+msgstr ""
+
+#: kallithea/templates/admin/user_groups/user_groups.html:5
+msgid "User Groups Administration"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_add.html:5
+msgid "Add user"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_add.html:10
+#: kallithea/templates/admin/users/user_edit.html:11
+#: kallithea/templates/admin/users/users.html:9
+#: kallithea/templates/base/base.html:58
+msgid "Users"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_add.html:12
+#: kallithea/templates/admin/users/users.html:23
+msgid "Add User"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_add.html:41
+msgid "Password confirmation"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit.html:5
+#, python-format
+msgid "%s user settings"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit.html:30
+msgid "Emails"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_advanced.html:1
+#, python-format
+msgid "User: %s"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_advanced.html:7
+#: kallithea/templates/admin/users/user_edit_profile.html:32
+msgid "Source of Record"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_advanced.html:9
+#: kallithea/templates/admin/users/users.html:41
+msgid "Last Login"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_advanced.html:10
+msgid "Member of User Groups"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_advanced.html:21
+#: kallithea/templates/data_table/_dt_elements.html:90
+#, python-format
+msgid "Confirm to delete this user: %s"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_advanced.html:23
+msgid "Delete this user"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_ips.html:7
+#, python-format
+msgid "Inherited from %s"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_profile.html:39
+msgid "Name in Source of Record"
+msgstr ""
+
+#: kallithea/templates/admin/users/user_edit_profile.html:53
+msgid "New password confirmation"
+msgstr ""
+
+#: kallithea/templates/admin/users/users.html:5
+msgid "Users Administration"
+msgstr ""
+
+#: kallithea/templates/admin/users/users.html:44
+msgid "Auth Type"
+msgstr ""
+
+#: kallithea/templates/base/base.html:16
+#, python-format
+msgid "Server instance: %s"
+msgstr ""
+
+#: kallithea/templates/base/base.html:28
+msgid "Support"
+msgstr ""
+
+#: kallithea/templates/base/base.html:86
+#: kallithea/templates/base/base.html:417
+msgid "Mercurial repository"
+msgstr ""
+
+#: kallithea/templates/base/base.html:89
+#: kallithea/templates/base/base.html:420
+msgid "Git repository"
+msgstr ""
+
+#: kallithea/templates/base/base.html:115
+msgid "Create Fork"
+msgstr ""
+
+#: kallithea/templates/base/base.html:127
+#: kallithea/templates/summary/summary.html:9
+msgid "Summary"
+msgstr ""
+
+#: kallithea/templates/base/base.html:129
+#: kallithea/templates/base/base.html:131
+#: kallithea/templates/changelog/changelog.html:16
+msgid "Changelog"
+msgstr ""
+
+#: kallithea/templates/base/base.html:133
+#: kallithea/templates/files/files.html:11
+msgid "Files"
+msgstr ""
+
+#: kallithea/templates/base/base.html:135
+#, python-format
+msgid "Show Pull Requests for %s"
+msgstr ""
+
+#: kallithea/templates/base/base.html:135
+msgid "Pull Requests"
+msgstr ""
+
+#: kallithea/templates/base/base.html:146
+#: kallithea/templates/base/base.html:148
+msgid "Options"
+msgstr ""
+
+#: kallithea/templates/base/base.html:156
+#: kallithea/templates/forks/forks_data.html:18
+msgid "Compare Fork"
+msgstr ""
+
+#: kallithea/templates/base/base.html:158
+msgid "Compare"
+msgstr ""
+
+#: kallithea/templates/base/base.html:160
+#: kallithea/templates/base/base.html:315
+#: kallithea/templates/search/search.html:14
+#: kallithea/templates/search/search.html:67
+msgid "Search"
+msgstr ""
+
+#: kallithea/templates/base/base.html:167
+msgid "Follow"
+msgstr ""
+
+#: kallithea/templates/base/base.html:168
+msgid "Unfollow"
+msgstr ""
+
+#: kallithea/templates/base/base.html:171
+#: kallithea/templates/forks/fork.html:9
+msgid "Fork"
+msgstr ""
+
+#: kallithea/templates/base/base.html:172
+#: kallithea/templates/pullrequests/pullrequest.html:77
+msgid "Create Pull Request"
+msgstr ""
+
+#: kallithea/templates/base/base.html:184
+msgid "Switch To"
+msgstr ""
+
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
+msgid "No matches found"
+msgstr ""
+
+#: kallithea/templates/base/base.html:289
+msgid "Show recent activity"
+msgstr ""
+
+#: kallithea/templates/base/base.html:295
+#: kallithea/templates/base/base.html:296
+msgid "Public journal"
+msgstr ""
+
+#: kallithea/templates/base/base.html:301
+msgid "Show public gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:302
+msgid "Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:306
+msgid "All Public Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:308
+msgid "My Public Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:309
+msgid "My Private Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:314
+msgid "Search in repositories"
+msgstr ""
+
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
+#: kallithea/templates/pullrequests/pullrequest_show_my.html:6
+#: kallithea/templates/pullrequests/pullrequest_show_my.html:10
+msgid "My Pull Requests"
+msgstr ""
+
+#: kallithea/templates/base/base.html:353
+msgid "Not Logged In"
+msgstr ""
+
+#: kallithea/templates/base/base.html:362
+msgid "Login to Your Account"
+msgstr ""
+
+#: kallithea/templates/base/base.html:372
+msgid "Forgot password?"
+msgstr ""
+
+#: kallithea/templates/base/base.html:376
+msgid "Don't have an account?"
+msgstr ""
+
+#: kallithea/templates/base/base.html:393
+msgid "Log Out"
+msgstr ""
+
+#: kallithea/templates/base/base.html:517
+msgid "Parent rev."
+msgstr ""
+
+#: kallithea/templates/base/base.html:526
+msgid "Child rev."
+msgstr ""
+
+#: kallithea/templates/base/default_perms_box.html:11
+msgid "Create repositories"
+msgstr ""
+
+#: kallithea/templates/base/default_perms_box.html:15
+msgid "Select this option to allow repository creation for this user"
+msgstr ""
+
+#: kallithea/templates/base/default_perms_box.html:21
+msgid "Create user groups"
+msgstr ""
+
+#: kallithea/templates/base/default_perms_box.html:25
+msgid "Select this option to allow user group creation for this user"
+msgstr ""
+
+#: kallithea/templates/base/default_perms_box.html:31
+msgid "Fork repositories"
+msgstr ""
+
+#: kallithea/templates/base/default_perms_box.html:35
+msgid "Select this option to allow repository forking for this user"
+msgstr ""
+
+#: kallithea/templates/base/perms_summary.html:13
+#: kallithea/templates/changelog/changelog.html:41
+msgid "Show"
+msgstr ""
+
+#: kallithea/templates/base/perms_summary.html:22
+msgid "No permissions defined yet"
+msgstr ""
+
+#: kallithea/templates/base/perms_summary.html:30
+#: kallithea/templates/base/perms_summary.html:55
+msgid "Permission"
+msgstr ""
+
+#: kallithea/templates/base/perms_summary.html:32
+#: kallithea/templates/base/perms_summary.html:57
+msgid "Edit Permission"
+msgstr ""
+
+#: kallithea/templates/base/perms_summary.html:92
+msgid "No permission defined"
+msgstr ""
+
+#: kallithea/templates/base/root.html:28
+msgid "Retry"
+msgstr ""
+
+#: kallithea/templates/base/root.html:29
+#: kallithea/templates/changeset/changeset_file_comment.html:65
+msgid "Submitting ..."
+msgstr ""
+
+#: kallithea/templates/base/root.html:30
+msgid "Unable to post"
+msgstr ""
+
+#: kallithea/templates/base/root.html:31
+msgid "Add Another Comment"
+msgstr ""
+
+#: kallithea/templates/base/root.html:32
+msgid "Stop following this repository"
+msgstr ""
+
+#: kallithea/templates/base/root.html:33
+msgid "Start following this repository"
+msgstr ""
+
+#: kallithea/templates/base/root.html:34
+msgid "Group"
+msgstr ""
+
+#: kallithea/templates/base/root.html:35
+msgid "Loading ..."
+msgstr ""
+
+#: kallithea/templates/base/root.html:36
+msgid "loading ..."
+msgstr ""
+
+#: kallithea/templates/base/root.html:37
+msgid "Search truncated"
+msgstr ""
+
+#: kallithea/templates/base/root.html:38
+msgid "No matching files"
+msgstr ""
+
+#: kallithea/templates/base/root.html:39
+msgid "Open New Pull Request from {0}"
+msgstr ""
+
+#: kallithea/templates/base/root.html:40
+msgid "Open New Pull Request for {0} &rarr; {1}"
+msgstr ""
+
+#: kallithea/templates/base/root.html:41
+msgid "Show Selected Changesets {0} &rarr; {1}"
+msgstr ""
+
+#: kallithea/templates/base/root.html:42
+msgid "Selection Link"
+msgstr ""
+
+#: kallithea/templates/base/root.html:43
+#: kallithea/templates/changeset/diff_block.html:7
+msgid "Collapse Diff"
+msgstr ""
+
+#: kallithea/templates/base/root.html:44
+msgid "Expand Diff"
+msgstr ""
+
+#: kallithea/templates/base/root.html:45
+msgid "No revisions"
+msgstr ""
+
+#: kallithea/templates/base/root.html:46
+msgid "Type name of user or member to grant permission"
+msgstr ""
+
+#: kallithea/templates/base/root.html:47
+msgid "Failed to revoke permission"
+msgstr ""
+
+#: kallithea/templates/base/root.html:48
+msgid "Confirm to revoke permission for {0}: {1} ?"
+msgstr ""
+
+#: kallithea/templates/base/root.html:51
+#: kallithea/templates/compare/compare_diff.html:108
+msgid "Select changeset"
+msgstr ""
+
+#: kallithea/templates/base/root.html:52
+msgid "Specify changeset"
+msgstr ""
+
+#: kallithea/templates/base/root.html:53
+msgid "Click to sort ascending"
+msgstr ""
+
+#: kallithea/templates/base/root.html:54
+msgid "Click to sort descending"
+msgstr ""
+
+#: kallithea/templates/base/root.html:55
+msgid "No records found."
+msgstr ""
+
+#: kallithea/templates/base/root.html:56
+msgid "Data error."
+msgstr ""
+
+#: kallithea/templates/base/root.html:57
+msgid "Loading..."
+msgstr ""
+
+#: kallithea/templates/changelog/changelog.html:8
+#, python-format
+msgid "%s Changelog"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog.html:23
+#, python-format
+msgid "showing %d out of %d revision"
+msgid_plural "showing %d out of %d revisions"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/changelog/changelog.html:47
+msgid "Clear selection"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog.html:54
+msgid "Go to tip of repository"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog.html:59
+#: kallithea/templates/forks/forks_data.html:16
+#, python-format
+msgid "Compare fork with %s"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog.html:61
+#, python-format
+msgid "Compare fork with parent repository (%s)"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog.html:65
+#: kallithea/templates/files/files.html:29
+msgid "Branch filter:"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog.html:221
+msgid "There are no changes yet"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_details.html:4
+#: kallithea/templates/changeset/changeset.html:77
+msgid "Removed"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_details.html:5
+#: kallithea/templates/changeset/changeset.html:78
+msgid "Changed"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_details.html:6
+#: kallithea/templates/changeset/changeset.html:79
+#: kallithea/templates/changeset/diff_block.html:38
+msgid "Added"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_details.html:8
+#: kallithea/templates/changelog/changelog_details.html:9
+#: kallithea/templates/changelog/changelog_details.html:10
+#: kallithea/templates/changeset/changeset.html:81
+#: kallithea/templates/changeset/changeset.html:82
+#: kallithea/templates/changeset/changeset.html:83
+#, python-format
+msgid "Affected %s files"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:20
+msgid "First (oldest) changeset in this list"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:22
+msgid "Last (most recent) changeset in this list"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:24
+msgid "Position in this list of changesets"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:35
+#, python-format
+msgid ""
+"Changeset status: %s by %s\n"
+"Click to open associated pull request %s"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:41
+#, python-format
+msgid "Changeset status: %s by %s"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:60
+msgid "Expand commit message"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:76
+#, python-format
+msgid "%s comments"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:80
+#: kallithea/templates/changeset/changeset.html:63
+#: kallithea/templates/changeset/changeset_range.html:84
+#, python-format
+msgid "Bookmark %s"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:83
+#: kallithea/templates/changeset/changeset.html:67
+#: kallithea/templates/changeset/changeset_range.html:90
+#: kallithea/templates/pullrequests/pullrequest_show.html:165
+#, python-format
+msgid "Tag %s"
+msgstr ""
+
+#: kallithea/templates/changelog/changelog_table.html:102
+#: kallithea/templates/changeset/changeset.html:71
+#: kallithea/templates/changeset/changeset_range.html:94
+#, python-format
+msgid "Branch %s"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:8
+#, python-format
+msgid "%s Changeset"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:34
+msgid "Changeset status"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:43
+#: kallithea/templates/changeset/diff_block.html:64
+#: kallithea/templates/files/diff_2way.html:51
+msgid "Raw diff"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:46
+msgid "Patch diff"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:49
+#: kallithea/templates/changeset/diff_block.html:66
+#: kallithea/templates/files/diff_2way.html:54
+msgid "Download diff"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:59
+#: kallithea/templates/changeset/changeset_range.html:80
+msgid "Merge"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:96
+msgid "Grafted from:"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:102
+msgid "Transplanted from:"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:108
+msgid "Replaced by:"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:122
+msgid "Preceded by:"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset.html:139
+#: kallithea/templates/compare/compare_diff.html:59
+#: kallithea/templates/pullrequests/pullrequest_show.html:290
+#, python-format
+msgid "%s file changed"
+msgid_plural "%s files changed"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/changeset/changeset.html:141
+#: kallithea/templates/compare/compare_diff.html:61
+#: kallithea/templates/pullrequests/pullrequest_show.html:292
+#, python-format
+msgid "%s file changed with %s insertions and %s deletions"
+msgid_plural "%s files changed with %s insertions and %s deletions"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/changeset/changeset.html:154
+#: kallithea/templates/changeset/changeset.html:173
+#: kallithea/templates/compare/compare_diff.html:81
+#: kallithea/templates/pullrequests/pullrequest_show.html:309
+#: kallithea/templates/pullrequests/pullrequest_show.html:333
+msgid "Show full diff anyway"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:20
+msgid "comment"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:21
+msgid "on pull request"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:22
+msgid "No title"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:24
+msgid "on this changeset"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:30
+msgid "Delete comment?"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:38
+#: kallithea/templates/changeset/changeset_file_comment.html:71
+msgid "Status change"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:87
+msgid "Comments are in plain text. Use @username to notify another user."
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:93
+msgid "Set changeset status"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:95
+msgid "Vote for pull request status"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:101
+#: kallithea/templates/changeset/diff_block.html:46
+msgid "No change"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:114
+msgid "Finish pull request"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:117
+msgid "Close"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:129
+msgid "Comment"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:137
+msgid "You need to be logged in to comment."
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:137
+msgid "Login now"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:141
+msgid "Hide"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:153
+#, python-format
+msgid "%d comment"
+msgid_plural "%d comments"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:154
+#, python-format
+msgid "%d inline"
+msgid_plural "%d inline"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/changeset/changeset_file_comment.html:155
+#, python-format
+msgid "%d general"
+msgid_plural "%d general"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/changeset/changeset_range.html:5
+#, python-format
+msgid "%s Changesets"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_range.html:43
+#, python-format
+msgid "Changeset status: %s"
+msgstr ""
+
+#: kallithea/templates/changeset/changeset_range.html:50
+msgid "Files affected"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:30
+msgid "No file before"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:33
+msgid "File before"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:40
+msgid "Modified"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:42
+msgid "Deleted"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:44
+msgid "Renamed"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:48
+#, python-format
+msgid "Unknown operation: %r"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:52
+msgid "No file after"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:55
+msgid "File after"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:60
+#: kallithea/templates/files/diff_2way.html:43
+msgid "Show full diff for this file"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:62
+#: kallithea/templates/files/diff_2way.html:47
+msgid "Show full side-by-side diff for this file"
+msgstr ""
+
+#: kallithea/templates/changeset/diff_block.html:72
+msgid "Show inline comments"
+msgstr ""
+
+#: kallithea/templates/compare/compare_cs.html:5
+msgid "No changesets"
+msgstr ""
+
+#: kallithea/templates/compare/compare_cs.html:12
+msgid "Criss cross merge situation with multiple merge ancestors detected!"
+msgstr ""
+
+#: kallithea/templates/compare/compare_cs.html:15
+msgid ""
+"Please merge the target branch to your branch before creating a pull "
+"request."
+msgstr ""
+
+#: kallithea/templates/compare/compare_cs.html:19
+msgid "Merge Ancestor"
+msgstr ""
+
+#: kallithea/templates/compare/compare_cs.html:40
+msgid "Show merge diff"
+msgstr ""
+
+#: kallithea/templates/compare/compare_cs.html:54
+msgid "is"
+msgstr ""
+
+#: kallithea/templates/compare/compare_cs.html:55
+#, python-format
+msgid "%s changesets"
+msgstr ""
+
+#: kallithea/templates/compare/compare_cs.html:56
+msgid "behind"
+msgstr ""
+
+#: kallithea/templates/compare/compare_diff.html:6
+#: kallithea/templates/compare/compare_diff.html:8
+#, python-format
+msgid "%s Compare"
+msgstr ""
+
+#: kallithea/templates/compare/compare_diff.html:13
+#: kallithea/templates/compare/compare_diff.html:41
+msgid "Compare Revisions"
+msgstr ""
+
+#: kallithea/templates/compare/compare_diff.html:39
+msgid "Swap"
+msgstr ""
+
+#: kallithea/templates/compare/compare_diff.html:48
+msgid "Compare revisions, branches, bookmarks, or tags."
+msgstr ""
+
+#: kallithea/templates/compare/compare_diff.html:53
+#: kallithea/templates/pullrequests/pullrequest_show.html:278
+#, python-format
+msgid "Showing %s commit"
+msgid_plural "Showing %s commits"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/compare/compare_diff.html:95
+msgid "Show full diff"
+msgstr ""
+
+#: kallithea/templates/data_table/_dt_elements.html:23
+msgid "Public repository"
+msgstr ""
+
+#: kallithea/templates/data_table/_dt_elements.html:29
+msgid "Repository creation in progress..."
+msgstr ""
+
+#: kallithea/templates/data_table/_dt_elements.html:42
+msgid "No changesets yet"
+msgstr ""
+
+#: kallithea/templates/data_table/_dt_elements.html:48
+#: kallithea/templates/data_table/_dt_elements.html:50
+#, 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
+#, python-format
+msgid "Subscribe to %s atom feed"
+msgstr ""
+
+#: kallithea/templates/data_table/_dt_elements.html:76
+msgid "Creating"
+msgstr ""
+
+#: kallithea/templates/email_templates/changeset_comment.html:4
+#, python-format
+msgid "Mention in Comment on Changeset \"%s\""
+msgstr ""
+
+#: kallithea/templates/email_templates/changeset_comment.html:4
+#, python-format
+msgid "Comment on Changeset \"%s\""
+msgstr ""
+
+#: kallithea/templates/email_templates/changeset_comment.html:20
+msgid "Changeset on"
+msgstr ""
+
+#: kallithea/templates/email_templates/changeset_comment.html:23
+#: kallithea/templates/email_templates/pull_request.html:22
+#: kallithea/templates/email_templates/pull_request.html:28
+#: kallithea/templates/email_templates/pull_request_comment.html:30
+#: kallithea/templates/email_templates/pull_request_comment.html:36
+msgid "branch"
+msgstr ""
+
+#: kallithea/templates/email_templates/changeset_comment.html:29
+#: kallithea/templates/email_templates/pull_request.html:15
+#: kallithea/templates/email_templates/pull_request_comment.html:23
+msgid "by"
+msgstr ""
+
+#: kallithea/templates/email_templates/comment.html:27
+msgid "Status change:"
+msgstr ""
+
+#: kallithea/templates/email_templates/comment.html:33
+msgid "The pull request has been closed."
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:9
+#, python-format
+msgid "Hello %s"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:16
+msgid "We have received a request to reset the password for your account."
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:25
+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
+msgid "To set a new password, click the following link"
+msgstr ""
+
+#: kallithea/templates/email_templates/password_reset.html:33
+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
+msgid ""
+"If it weren't you who requested the password reset, just disregard this "
+"message."
+msgstr ""
+
+#: kallithea/templates/email_templates/pull_request.html:4
+#, python-format
+msgid "Mention on Pull Request %s \"%s\" by %s"
+msgstr ""
+
+#: kallithea/templates/email_templates/pull_request.html:4
+#, python-format
+msgid "Added as Reviewer of Pull Request %s \"%s\" by %s"
+msgstr ""
+
+#: kallithea/templates/email_templates/pull_request.html:12
+#: kallithea/templates/email_templates/pull_request_comment.html:20
+msgid "Pull request"
+msgstr ""
+
+#: kallithea/templates/email_templates/pull_request.html:19
+#: kallithea/templates/email_templates/pull_request_comment.html:27
+msgid "from"
+msgstr ""
+
+#: kallithea/templates/email_templates/pull_request.html:25
+#: kallithea/templates/email_templates/pull_request_comment.html:33
+msgid "to"
+msgstr ""
+
+#: kallithea/templates/email_templates/pull_request_comment.html:4
+#, python-format
+msgid "Mention in Comment on Pull Request %s \"%s\""
+msgstr ""
+
+#: kallithea/templates/email_templates/pull_request_comment.html:4
+#, python-format
+msgid "Pull Request %s \"%s\" Closed"
+msgstr ""
+
+#: kallithea/templates/email_templates/pull_request_comment.html:4
+#, python-format
+msgid "Comment on Pull Request %s \"%s\""
+msgstr ""
+
+#: kallithea/templates/email_templates/registration.html:22
+msgid "Full Name"
+msgstr ""
+
+#: kallithea/templates/files/diff_2way.html:15
+#, python-format
+msgid "%s File side-by-side diff"
+msgstr ""
+
+#: kallithea/templates/files/diff_2way.html:19
+#: kallithea/templates/files/file_diff.html:8
+msgid "File diff"
+msgstr ""
+
+#: kallithea/templates/files/file_diff.html:4
+#, python-format
+msgid "%s File Diff"
+msgstr ""
+
+#: kallithea/templates/files/files.html:4
+#: kallithea/templates/files/files.html:74
+#, python-format
+msgid "%s Files"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:4
+#, python-format
+msgid "%s Files Add"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:21
+#: kallithea/templates/files/files_ypjax.html:9
+#: kallithea/templates/summary/summary.html:199
+msgid "Add New File"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:39
+#: kallithea/templates/files/files_edit.html:39
+#: kallithea/templates/files/files_ypjax.html:3
+msgid "Location"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:41
+msgid "Enter filename..."
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:43
+#: kallithea/templates/files/files_add.html:47
+msgid "or"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:43
+msgid "Upload File"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:47
+msgid "Create New File"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:53
+msgid "New file type"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:64
+#: kallithea/templates/files/files_delete.html:34
+#: kallithea/templates/files/files_edit.html:67
+msgid "Commit Message"
+msgstr ""
+
+#: kallithea/templates/files/files_add.html:68
+#: kallithea/templates/files/files_delete.html:40
+#: kallithea/templates/files/files_edit.html:71
+msgid "Commit Changes"
+msgstr ""
+
+#: kallithea/templates/files/files_browser.html:40
+msgid "Search File List"
+msgstr ""
+
+#: kallithea/templates/files/files_browser.html:45
+msgid "Loading file list..."
+msgstr ""
+
+#: kallithea/templates/files/files_browser.html:55
+#: kallithea/templates/summary/summary.html:153
+msgid "Size"
+msgstr ""
+
+#: kallithea/templates/files/files_browser.html:56
+msgid "Last Revision"
+msgstr ""
+
+#: kallithea/templates/files/files_browser.html:57
+msgid "Last Modified"
+msgstr ""
+
+#: kallithea/templates/files/files_browser.html:58
+msgid "Last Committer"
+msgstr ""
+
+#: kallithea/templates/files/files_delete.html:4
+#, python-format
+msgid "%s Files Delete"
+msgstr ""
+
+#: kallithea/templates/files/files_delete.html:12
+#: kallithea/templates/files/files_delete.html:30
+msgid "Delete file"
+msgstr ""
+
+#: kallithea/templates/files/files_edit.html:4
+#, python-format
+msgid "%s File Edit"
+msgstr ""
+
+#: kallithea/templates/files/files_edit.html:21
+msgid "Edit file"
+msgstr ""
+
+#: kallithea/templates/files/files_edit.html:51
+#: kallithea/templates/files/files_source.html:28
+msgid "Show Annotation"
+msgstr ""
+
+#: kallithea/templates/files/files_edit.html:53
+#: kallithea/templates/files/files_source.html:31
+msgid "Download as Raw"
+msgstr ""
+
+#: kallithea/templates/files/files_edit.html:56
+msgid "Source"
+msgstr ""
+
+#: kallithea/templates/files/files_history_box.html:2
+#, python-format
+msgid "%s author"
+msgid_plural "%s authors"
+msgstr[0] ""
+msgstr[1] ""
+
+#: kallithea/templates/files/files_source.html:6
+msgid "Diff to Revision"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:7
+msgid "Show at Revision"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:9
+msgid "Show Full History"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:10
+msgid "Show Authors"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:26
+msgid "Show Source"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:34
+#, python-format
+msgid "Edit on Branch: %s"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:37
+msgid "Editing binary files not allowed"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:40
+msgid "Editing files allowed only when on branch head revision"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:41
+msgid "Deleting files allowed only when on branch head revision"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:58
+#, python-format
+msgid "Binary file (%s)"
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:69
+msgid "File is too big to display."
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:71
+msgid "Show full annotation anyway."
+msgstr ""
+
+#: kallithea/templates/files/files_source.html:73
+msgid "Show as raw."
+msgstr ""
+
+#: kallithea/templates/files/files_ypjax.html:5
+msgid "annotation"
+msgstr ""
+
+#: kallithea/templates/files/files_ypjax.html:23
+msgid "Go Back"
+msgstr ""
+
+#: kallithea/templates/files/files_ypjax.html:24
+msgid "No files at given path"
+msgstr ""
+
+#: kallithea/templates/followers/followers.html:5
+#, python-format
+msgid "%s Followers"
+msgstr ""
+
+#: kallithea/templates/followers/followers.html:9
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
+msgid "Followers"
+msgstr ""
+
+#: kallithea/templates/followers/followers_data.html:9
+msgid "Started following -"
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:5
+#, python-format
+msgid "Fork repository %s"
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:25
+msgid "Fork name"
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:53
+msgid "Default revision for files page, downloads, whoosh, and readme."
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:58
+msgid "Private"
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:66
+msgid "Copy permissions"
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:69
+msgid "Copy permissions from forked repository"
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:75
+msgid "Update after clone"
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:78
+msgid "Checkout source after making a clone"
+msgstr ""
+
+#: kallithea/templates/forks/fork.html:85
+msgid "Fork this Repository"
+msgstr ""
+
+#: kallithea/templates/forks/forks.html:5
+#, python-format
+msgid "%s Forks"
+msgstr ""
+
+#: kallithea/templates/forks/forks.html:9
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
+msgid "Forks"
+msgstr ""
+
+#: kallithea/templates/forks/forks_data.html:14
+msgid "Forked"
+msgstr ""
+
+#: kallithea/templates/forks/forks_data.html:24
+msgid "There are no forks yet"
+msgstr ""
+
+#: kallithea/templates/journal/journal.html:22
+msgid "ATOM journal feed"
+msgstr ""
+
+#: kallithea/templates/journal/journal.html:23
+msgid "RSS journal feed"
+msgstr ""
+
+#: kallithea/templates/journal/journal.html:34
+msgid "My Repositories"
+msgstr ""
+
+#: kallithea/templates/journal/journal_data.html:42
+msgid "No entries yet"
+msgstr ""
+
+#: kallithea/templates/journal/public_journal.html:10
+msgid "ATOM public journal feed"
+msgstr ""
+
+#: kallithea/templates/journal/public_journal.html:11
+msgid "RSS public journal feed"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest.html:4
+#: kallithea/templates/pullrequests/pullrequest.html:8
+msgid "New Pull Request"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest.html:26
+#: kallithea/templates/pullrequests/pullrequest_data.html:15
+#: kallithea/templates/pullrequests/pullrequest_show.html:29
+#: kallithea/templates/pullrequests/pullrequest_show.html:52
+msgid "Title"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest.html:28
+msgid "Summarize the changes - or leave empty"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest.html:35
+#: kallithea/templates/pullrequests/pullrequest_show.html:61
+msgid "Write a short description on this pull request"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest.html:40
+msgid "Changeset flow"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest.html:46
+msgid "Origin repository"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest.html:52
+#: kallithea/templates/pullrequests/pullrequest.html:68
+msgid "Revision"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest.html:62
+msgid "Destination repository"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:6
+msgid "No entries"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:14
+msgid "Vote"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:17
+msgid "Age"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:18
+msgid "From"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:19
+msgid "To"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:28
+#, python-format
+msgid "You voted: %s"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:30
+msgid "You didn't vote"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:35
+msgid "(no title)"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:37
+#: kallithea/templates/pullrequests/pullrequest_show.html:31
+#: kallithea/templates/pullrequests/pullrequest_show.html:73
+msgid "Closed"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:67
+msgid "Delete Pull Request"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:68
+msgid "Confirm to delete this pull request"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_data.html:70
+#, python-format
+msgid "Confirm again to delete this pull request with %s comments"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:6
+#, python-format
+msgid "%s Pull Request %s"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:10
+#, python-format
+msgid "Pull request %s from %s#%s"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:54
+msgid "Summarize the changes"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:67
+msgid "Voting Result"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:70
+#: kallithea/templates/pullrequests/pullrequest_show.html:71
+msgid "Pull request status calculated from votes"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:81
+msgid "Origin"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:86
+msgid "on"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:92
+msgid "Target"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:95
+msgid ""
+"This is just a range of changesets and doesn't have a target or a real "
+"merge ancestor."
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:103
+msgid "Pull changes"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:136
+msgid "Next iteration"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:153
+msgid "Current revision - no change"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:177
+msgid ""
+"Pull request iterations do not change content once created. Select a "
+"revision to create a new iteration."
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:187
+msgid "Save Changes"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:188
+msgid "Create New Iteration with Changes"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:189
+msgid "Cancel Changes"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:197
+msgid "Reviewers"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:223
+msgid "Remove reviewer"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:234
+msgid "Type name of reviewer to add"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:240
+msgid "Potential Reviewers"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:243
+msgid "Click to add the repository owner as reviewer:"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:268
+msgid "Pull Request Content"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show.html:283
+msgid "Common ancestor"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_all.html:6
+#, python-format
+msgid "%s Pull Requests"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_all.html:11
+#, python-format
+msgid "Pull Requests from '%s'"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_all.html:13
+#, python-format
+msgid "Pull Requests to '%s'"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_all.html:31
+msgid "Open New Pull Request"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_all.html:34
+#, python-format
+msgid "Show Pull Requests to %s"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_all.html:36
+#, python-format
+msgid "Show Pull Requests from '%s'"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_all.html:44
+#: kallithea/templates/pullrequests/pullrequest_show_my.html:28
+msgid "Hide closed pull requests (only show open pull requests)"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_all.html:46
+#: kallithea/templates/pullrequests/pullrequest_show_my.html:30
+msgid "Show closed pull requests (in addition to open pull requests)"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_my.html:34
+msgid "Pull Requests Created by Me"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_my.html:37
+msgid "Pull Requests Needing My Review"
+msgstr ""
+
+#: kallithea/templates/pullrequests/pullrequest_show_my.html:40
+msgid "Pull Requests I Participate In"
+msgstr ""
+
+#: kallithea/templates/search/search.html:6
+#, python-format
+msgid "%s Search"
+msgstr ""
+
+#: kallithea/templates/search/search.html:8
+#: kallithea/templates/search/search.html:16
+msgid "Search in All Repositories"
+msgstr ""
+
+#: kallithea/templates/search/search.html:47
+msgid "Search term"
+msgstr ""
+
+#: kallithea/templates/search/search.html:54
+msgid "Search in"
+msgstr ""
+
+#: kallithea/templates/search/search.html:56
+msgid "File contents"
+msgstr ""
+
+#: kallithea/templates/search/search.html:57
+msgid "Commit messages"
+msgstr ""
+
+#: kallithea/templates/search/search.html:58
+msgid "File names"
+msgstr ""
+
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
+msgid "Permission denied"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:4
+#, python-format
+msgid "%s Statistics"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:16
+#: kallithea/templates/summary/summary.html:27
+#, python-format
+msgid "%s ATOM feed"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:17
+#: kallithea/templates/summary/summary.html:28
+#, python-format
+msgid "%s RSS feed"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:35
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
+msgid "Enable"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:38
+msgid "Stats gathered: "
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:87
+#: kallithea/templates/summary/summary.html:371
+msgid "files"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:111
+#: kallithea/templates/summary/summary.html:401
+msgid "Show more"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:405
+msgid "commits"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:406
+msgid "files added"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:407
+msgid "files changed"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:408
+msgid "files removed"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:410
+msgid "commit"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:411
+msgid "file added"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:412
+msgid "file changed"
+msgstr ""
+
+#: kallithea/templates/summary/statistics.html:413
+msgid "file removed"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:5
+#, python-format
+msgid "%s Summary"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:13
+msgid "Fork of"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:18
+msgid "Clone from"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:54
+msgid "Clone URL"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
+#: kallithea/templates/summary/summary.html:73
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+msgid "Use Name"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
+msgid "Trending files"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:106
+msgid "Download"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:109
+msgid "There are no downloads yet"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:111
+msgid "Downloads are disabled for this repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:117
+msgid "Download as zip"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:121
+msgid "Check this to download archive with subrepos"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:123
+msgid "With subrepos"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
+msgid "Feed"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:183
+msgid "Latest Changes"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:185
+msgid "Quick Start"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:196
+msgid "Add or upload files directly via Kallithea"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:204
+msgid "Push new repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:212
+msgid "Existing repository?"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:230
+#, python-format
+msgid "Readme file from revision %s:%s"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:315
+#, python-format
+msgid "Download %s as %s"
+msgstr ""
--- a/kallithea/i18n/uk/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/uk/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,34 +1,31 @@
-# Translations template for Kallithea.
 # Copyright (C) 2017 Various authors, licensing as GPLv3
 # This file is distributed under the same license as the Kallithea project.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2017.
-#
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3.2\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
-"PO-Revision-Date: 2018-03-31 21:42+0000\n"
-"Last-Translator: Максим Якимчук <xpinovo@gmail.com>\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\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/"
-"stable/uk/>\n"
+"kallithea/uk/>\n"
 "Language: uk\n"
 "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"
-"X-Generator: Weblate 2.20-dev\n"
+"X-Generator: Weblate 3.10-dev\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
-msgstr ""
-
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+msgstr "Наборів змін немає"
+
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -37,99 +34,100 @@
 msgid "None"
 msgstr "Нічого"
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
-msgstr ""
-
-#: kallithea/controllers/changeset.py:83
+msgstr "(закрито)"
+
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr "Відображати пробіли"
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr "Ігнорувати пробіли"
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
-msgstr ""
-
-#: kallithea/controllers/changeset.py:203
+msgstr "Збільшити відмінність контексту для %(num)s рядків"
+
+#: kallithea/controllers/changeset.py:201
 msgid "No permission to change status"
-msgstr ""
-
-#: kallithea/controllers/changeset.py:214
+msgstr "У вас немає дозволу змінювати статус"
+
+#: kallithea/controllers/changeset.py:212
 #, python-format
 msgid "Successfully deleted pull request %s"
-msgstr ""
-
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+msgstr "Успішно вилучено pull request %s"
+
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
-msgstr ""
-
-#: kallithea/controllers/compare.py:66
+msgstr "Така редакція не існує для цього репозиторію"
+
+#: kallithea/controllers/compare.py:68
 #, python-format
 msgid "Could not find other repository %s"
-msgstr ""
-
-#: kallithea/controllers/compare.py:72
+msgstr "Не вдалося знайти інший репозиторій %s"
+
+#: kallithea/controllers/compare.py:74
 msgid "Cannot compare repositories of different types"
-msgstr ""
-
-#: kallithea/controllers/compare.py:244
-msgid "Cannot show empty diff"
-msgstr ""
+msgstr "Не вдається порівняти репозиторії різних типів"
 
 #: kallithea/controllers/compare.py:246
+msgid "Cannot show empty diff"
+msgstr "Не вдалося відобразити пусті відмінності"
+
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
-msgstr ""
-
-#: kallithea/controllers/compare.py:250
+msgstr "Не знайдено предка для злиття відмінностей"
+
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
-msgstr ""
-
-#: kallithea/controllers/compare.py:266
+msgstr "Множинні злиття предків знайдено для злиття порівняти"
+
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
-msgstr ""
-
-#: kallithea/controllers/error.py:70
-msgid "No response"
-msgstr ""
+msgstr "Не вдається порівняти репозиторії без використання спільного предка"
 
 #: kallithea/controllers/error.py:71
+msgid "No response"
+msgstr "Немає відповіді"
+
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr "Невідома помилка"
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
-msgstr ""
-
-#: kallithea/controllers/error.py:87
+msgstr "Запит не може бути зрозумілий сервером через синтаксичні помилки."
+
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
-msgstr ""
-
-#: kallithea/controllers/error.py:89
+msgstr "Несанкціонований доступ до ресурсів"
+
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
-msgstr ""
-
-#: kallithea/controllers/error.py:91
+msgstr "Ви не маєте дозволу на перегляд цієї сторінки"
+
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
-msgstr ""
-
-#: kallithea/controllers/error.py:93
+msgstr "Ресурс не може бути знайдений"
+
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
 msgstr ""
+"На сервері виявлено неочікувану умову, яка перешкоджала виконанню запиту."
 
 #: kallithea/controllers/feed.py:63
 #, python-format
 msgid "%s committed on %s"
-msgstr ""
+msgstr "%s зафіксовано на %s"
 
 #: kallithea/controllers/feed.py:88
 #: kallithea/templates/changeset/changeset.html:154
@@ -139,134 +137,129 @@
 #: kallithea/templates/pullrequests/pullrequest_show.html:309
 #: kallithea/templates/pullrequests/pullrequest_show.html:333
 msgid "Changeset was too big and was cut off..."
-msgstr ""
-
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+msgstr "Changeset був занадто великий і був відрізаний..."
+
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
-msgstr ""
-
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+msgstr "%s %s канал"
+
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
-msgstr ""
-
-#: kallithea/controllers/files.py:92
+msgstr "Зміни в репозиторії  %s"
+
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
-msgstr ""
-
-#: kallithea/controllers/files.py:93
+msgstr "Натисніть тут, щоб додати новий файл"
+
+#: kallithea/controllers/files.py:86
 msgid "There are no files yet."
-msgstr ""
-
-#: kallithea/controllers/files.py:193
+msgstr "Файлів ще немає."
+
+#: kallithea/controllers/files.py:186
 #, python-format
 msgid "%s at %s"
-msgstr ""
-
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr ""
-
-#: kallithea/controllers/files.py:311
+msgstr "%s у  %s"
+
+#: kallithea/controllers/files.py:296
 msgid "You can only delete files with revision being a valid branch"
-msgstr ""
-
-#: kallithea/controllers/files.py:322
+msgstr "Видаляти файли можна лише з ревізії припустимого бренчу"
+
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
-msgstr ""
-
-#: kallithea/controllers/files.py:344
+msgstr "Видалений файл %s через Kallithea"
+
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
-msgstr ""
-
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+msgstr "Успішно видалений файл %s"
+
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
-msgstr ""
-
-#: kallithea/controllers/files.py:371
+msgstr "Під час фіксації сталася помилка"
+
+#: kallithea/controllers/files.py:350
 msgid "You can only edit files with revision being a valid branch"
-msgstr ""
-
-#: kallithea/controllers/files.py:385
+msgstr "Редагувати файли можна лише з ревізії, що належить валідному бренчу"
+
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
-msgstr ""
-
-#: kallithea/controllers/files.py:401
+msgstr "Відредагований файл %s через Kallithea"
+
+#: kallithea/controllers/files.py:380
 msgid "No changes"
-msgstr ""
-
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+msgstr "Нема змін"
+
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
-msgstr ""
-
-#: kallithea/controllers/files.py:437
+msgstr "Успішно зафіксовано в  %s"
+
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
-msgstr ""
-
-#: kallithea/controllers/files.py:458
+msgstr "Доданий файл через Kallithea"
+
+#: kallithea/controllers/files.py:430
 msgid "No content"
-msgstr ""
-
-#: kallithea/controllers/files.py:462
+msgstr "Немає вмісту"
+
+#: kallithea/controllers/files.py:434
 msgid "No filename"
-msgstr ""
-
-#: kallithea/controllers/files.py:487
+msgstr "Не вказано назви файлу"
+
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr ""
-
-#: kallithea/controllers/files.py:519
+"Розташування має бути відносним шляхом і не повинен містити .. в шляху"
+
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
-msgstr ""
-
-#: kallithea/controllers/files.py:530
+msgstr "Завантаження вимкнено"
+
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
-msgstr ""
-
-#: kallithea/controllers/files.py:532
+msgstr "Невідома редакція %s"
+
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
-msgstr ""
-
-#: kallithea/controllers/files.py:534
+msgstr "Порожній репозиторій"
+
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
-msgstr ""
-
-#: kallithea/controllers/files.py:755
+msgstr "Невідомий тип архіву"
+
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
-msgstr ""
-
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+msgstr "Набори змін"
+
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
-msgstr ""
-
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+msgstr "Гілки"
+
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
-msgstr ""
+msgstr "Теги"
 
 #: kallithea/controllers/forks.py:174
 #, python-format
 msgid "An error occurred during repository forking %s"
-msgstr ""
-
-#: kallithea/controllers/home.py:78
+msgstr "Під час forking репозиторію %s сталася помилка"
+
+#: kallithea/controllers/home.py:79
 msgid "Groups"
-msgstr ""
-
-#: kallithea/controllers/home.py:88
+msgstr "Групи"
+
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -274,355 +267,371 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
-msgstr ""
-
-#: kallithea/controllers/home.py:121
+msgstr "Репозиторії"
+
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
-msgstr ""
-
-#: kallithea/controllers/home.py:127
+msgstr "Гілка"
+
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
-msgstr ""
-
-#: kallithea/controllers/home.py:133
+msgstr "Закриті Гілки"
+
+#: kallithea/controllers/home.py:134
 msgid "Tag"
-msgstr ""
-
-#: kallithea/controllers/home.py:139
+msgstr "Тег"
+
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
-msgstr ""
-
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+msgstr "Закладка"
+
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
-msgstr ""
-
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+msgstr "Публічний журнал"
+
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr "Журнал"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
-msgstr ""
-
-#: kallithea/controllers/login.py:145
+msgstr "Погана капча"
+
+#: kallithea/controllers/login.py:146
 #, python-format
 msgid "You have successfully registered with %s"
-msgstr ""
-
-#: kallithea/controllers/login.py:189
+msgstr "Ви успішно зареєстровані з  %s"
+
+#: kallithea/controllers/login.py:190
 msgid "A password reset confirmation code has been sent"
-msgstr ""
-
-#: kallithea/controllers/login.py:238
+msgstr "Надісланий код підтвердження скидання пароля"
+
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
-msgstr ""
-
-#: kallithea/controllers/admin/my_account.py:155
-#: kallithea/controllers/login.py:243
+msgstr "Недійсний маркер скидання пароля"
+
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:71
+msgstr "Пароль успішно оновлений"
+
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:133
+msgstr "Вказаний недійсний рецензент \"%s\""
+
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:160
+msgstr "%s (закрито)"
+
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:181
+msgstr "Набір змін"
+
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:182
+msgstr "Спеціальний"
+
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:320
+msgstr "Закладки"
+
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+msgstr "Помилка створення pull request: %s"
+
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:352
+msgstr "Сталася помилка при створенні pull request"
+
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:375
+msgstr "Новий pull request успішно відкритий"
+
+#: kallithea/controllers/pullrequests.py:373
 msgid "New pull request iteration created"
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:403
+msgstr "Створено нову ітерацію запиту на pull request"
+
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:407
+msgstr "Тим часом додано наступних рецензентів: %s"
+
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+msgstr "Тим часом було видалено наступних рецензентів: %s"
+
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr "Без опису"
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:445
+msgstr "Pull request оновлено"
+
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:481
+msgstr "Успішно вилучено pull request"
+
+#: kallithea/controllers/pullrequests.py:479
 #, python-format
 msgid "Revision %s not found in %s"
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:508
+msgstr "Ревізія %s не знайдена в %s"
+
+#: kallithea/controllers/pullrequests.py:506
 #, python-format
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr ""
-
-#: kallithea/controllers/pullrequests.py:522
+"Помилка: changesets не знайдено під час відображення pull request з %s."
+
+#: kallithea/controllers/pullrequests.py:520
 #, python-format
 msgid "This pull request has already been merged to %s."
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:524
+msgstr "Цей pull request уже об'єднано з  %s."
+
+#: kallithea/controllers/pullrequests.py:522
 msgid "This pull request has been closed and can not be updated."
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:543
+msgstr "Цей pull request закрито, його не можна оновити."
+
+#: kallithea/controllers/pullrequests.py:546
 #, python-format
 msgid "The following additional changes are available on %s:"
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+msgstr "Наступні додаткові зміни доступні на %s:"
+
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 msgid "No additional changesets found for iterating on this pull request."
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:557
+msgstr "Немає додаткових змін для ітератування на  pull request."
+
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:564
+msgstr "Примітка: гілка %s має іншу голову: %s."
+
+#: kallithea/controllers/pullrequests.py:567
 msgid "Git pull requests don't support iterating yet."
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:566
+msgstr "Git pull requests не підтримують ітерацію."
+
+#: kallithea/controllers/pullrequests.py:569
 #, python-format
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
 msgstr ""
-
-#: kallithea/controllers/pullrequests.py:590
+"Помилка: деякі changesets  не знайдені під час відображення pull request "
+"з %s."
+
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
-msgstr ""
+msgstr "Різниця не може бути показана - версії PR не вдалося знайти."
 
 #: kallithea/controllers/search.py:136
 msgid "Invalid search query. Try quoting it."
-msgstr ""
+msgstr "Неприпустимий пошуковий запит. Спробуйте цитувати його."
 
 #: kallithea/controllers/search.py:140
 msgid "The server has no search index."
-msgstr ""
+msgstr "Сервер не має індексу пошуку."
 
 #: kallithea/controllers/search.py:143
 msgid "An error occurred during search operation."
-msgstr ""
-
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+msgstr "Сталася помилка під час операції пошуку."
+
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
-msgstr ""
-
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+msgstr "Дані ще не готові"
+
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
-msgstr ""
-
-#: kallithea/controllers/admin/auth_settings.py:135
+msgstr "Статистичні дані для цього репозиторію вимкнено"
+
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
-msgstr ""
-
-#: kallithea/controllers/admin/auth_settings.py:146
+msgstr "Параметри автентифікації успішно оновлено"
+
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
-msgstr ""
+msgstr "під час оновлення параметрів автентифікації сталася помилка"
 
 #: kallithea/controllers/admin/defaults.py:75
 msgid "Default settings updated successfully"
-msgstr ""
+msgstr "Параметри за промовчанням оновлено успішно"
 
 #: kallithea/controllers/admin/defaults.py:90
 msgid "Error occurred during update of defaults"
-msgstr ""
-
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+msgstr "Сталася помилка під час оновлення за промовчанням"
+
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 msgid "Forever"
-msgstr ""
-
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
+msgstr "Назавжди"
+
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
 #: kallithea/controllers/admin/users.py:249
 msgid "5 minutes"
 msgstr "5 хвилин"
 
-#: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
 #: kallithea/controllers/admin/users.py:250
 msgid "1 hour"
-msgstr ""
-
-#: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
+msgstr "1 година"
+
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
 #: kallithea/controllers/admin/users.py:251
 msgid "1 day"
 msgstr "1 день"
 
-#: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr "1 місяць"
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
-msgstr ""
-
-#: kallithea/controllers/admin/gists.py:140
+msgstr "Постійно"
+
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
-msgstr ""
-
-#: kallithea/controllers/admin/gists.py:156
+msgstr "Сталася помилка під час створення GIST"
+
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
-msgstr ""
-
-#: kallithea/controllers/admin/gists.py:196
+msgstr "Видалено gist %s"
+
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
-msgstr ""
-
-#: kallithea/controllers/admin/gists.py:225
+msgstr "Незмінений"
+
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
-msgstr ""
-
-#: kallithea/controllers/admin/gists.py:230
-msgid "Successfully updated gist data"
-msgstr ""
+msgstr "Зміст gist успішно оновлено"
 
 #: kallithea/controllers/admin/gists.py:233
+msgid "Successfully updated gist data"
+msgstr "Дані gist успішно оновлені"
+
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
-msgstr ""
-
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+msgstr "Сталася помилка під час оновлення gist %s"
+
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
-
-#: kallithea/controllers/admin/my_account.py:117
+"Ви не можете редагувати цього користувача, оскільки це важливо для всієї "
+"програми"
+
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
-msgstr ""
-
-#: kallithea/controllers/admin/my_account.py:132
+msgstr "Ваш обліковий запис успішно оновлено"
+
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
-msgstr ""
-
-#: kallithea/controllers/admin/my_account.py:166
+msgstr "Сталася помилка під час оновлення користувача %s"
+
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
-msgstr ""
-
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+msgstr "Сталася помилка під час оновлення пароля користувача"
+
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
-msgstr ""
-
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+msgstr "Додано email %s користувачу"
+
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
-msgstr ""
-
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+msgstr "Сталася помилка під час збереження електронної пошти"
+
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
-msgstr ""
-
-#: kallithea/controllers/admin/my_account.py:246
+msgstr "Видалено email користувача"
+
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
-msgstr ""
-
-#: kallithea/controllers/admin/my_account.py:255
+msgstr "API ключ успішно створений"
+
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
-msgstr ""
-
-#: kallithea/controllers/admin/my_account.py:259
+msgstr "Ключ API успішно скинуто"
+
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
-msgstr ""
-
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+msgstr "API ключ успішно видалений"
+
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, python-format
+msgid "SSH key %s successfully added"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+msgid "SSH key successfully deleted"
+msgstr ""
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
 #: kallithea/templates/base/perms_summary.html:15
 msgid "Read"
-msgstr ""
-
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+msgstr "Читати"
+
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
 #: kallithea/templates/base/perms_summary.html:16
 msgid "Write"
-msgstr ""
-
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+msgstr "Писати"
+
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -645,601 +654,593 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
-msgstr ""
-
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
+msgstr "Адмін"
+
+#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:50
 msgid "Disabled"
-msgstr ""
-
-#: kallithea/controllers/admin/permissions.py:78
-msgid "Allowed with manual account activation"
-msgstr ""
+msgstr "Вимкнуто"
 
 #: kallithea/controllers/admin/permissions.py:80
+msgid "Allowed with manual account activation"
+msgstr "Дозволено з ручною активацією облікового запису"
+
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
-msgstr ""
-
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+msgstr "Дозволено з автоматичною активацію облікового запису"
+
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
-msgstr ""
-
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+msgstr "Ручна Активація зовнішнього акаунту"
+
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
-msgstr ""
-
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+msgstr "Автоматична Активація зовнішнього акаунту"
+
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
-msgstr ""
-
-#: kallithea/controllers/admin/permissions.py:125
+msgstr "Увімкнено"
+
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
-msgstr ""
-
-#: kallithea/controllers/admin/permissions.py:140
+msgstr "Глобальні права успішно оновлено"
+
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
-msgstr ""
-
-#: kallithea/controllers/admin/repo_groups.py:174
+msgstr "Сталася помилка під час оновлення прав"
+
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Error occurred during creation of repository group %s"
-msgstr ""
-
-#: kallithea/controllers/admin/repo_groups.py:179
+msgstr "Сталася помилка при створенні repository group %s"
+
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
-msgstr ""
-
-#: kallithea/controllers/admin/repo_groups.py:226
+msgstr "Створена група репозиторіїв %s"
+
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
-msgstr ""
-
-#: kallithea/controllers/admin/repo_groups.py:242
+msgstr "Оновлено групу репозиторіїв %s"
+
+#: kallithea/controllers/admin/repo_groups.py:240
 #, python-format
 msgid "Error occurred during update of repository group %s"
-msgstr ""
-
-#: kallithea/controllers/admin/repo_groups.py:252
+msgstr "Сталася помилка при оновленні repository group %s"
+
+#: kallithea/controllers/admin/repo_groups.py:250
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
-msgstr ""
-
-#: kallithea/controllers/admin/repo_groups.py:259
+msgstr "Ця група містить %s репозиторії, і їх неможливо видалити"
+
+#: kallithea/controllers/admin/repo_groups.py:257
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
-msgstr ""
-
-#: kallithea/controllers/admin/repo_groups.py:265
+msgstr "Ця група містить %s підгрупи і не може бути видалена"
+
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
-msgstr ""
-
-#: kallithea/controllers/admin/repo_groups.py:270
+msgstr "Видалена група репозиторіїв %s"
+
+#: kallithea/controllers/admin/repo_groups.py:268
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
-msgstr ""
-
-#: kallithea/controllers/admin/repo_groups.py:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+msgstr "Сталася помилка під час видалення групи репохиторіїв %s"
+
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
-msgstr ""
-
-#: kallithea/controllers/admin/repo_groups.py:369
+msgstr "Неможливо відкликати дозвіл для себе як адміністратора"
+
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
-msgstr ""
-
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+msgstr "Оновлено дозволи групи репозиторіїв"
+
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:137
+msgstr "Сталася помилка під час відкликання прав"
+
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:195
+msgstr "Помилка створення репозиторію  %s"
+
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:204
+msgstr "Створено репозиторій  %s з %s"
+
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:207
+msgstr "Роздвоєно репозиторій %s як %s"
+
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:236
+msgstr "Створено репозиторій %s"
+
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:256
+msgstr "Репозиторій %s успішно оновлений"
+
+#: kallithea/controllers/admin/repos.py:255
 #, python-format
 msgid "Error occurred during update of repository %s"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:274
+msgstr "Сталася помилка при оновленні репозиторію %s"
+
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:277
+msgstr "Від'єднано %s forks"
+
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:282
+msgstr "Видалено %s forks"
+
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:285
+msgstr "Видалений репозиторій %s"
+
+#: kallithea/controllers/admin/repos.py:284
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:290
+msgstr "Неможливо видалити репозиторій %s, що ще має forks"
+
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:330
+msgstr "Сталася помилка під час видалення %s"
+
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:387
+msgstr "Права доступів до репозиторіїв оновлено"
+
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:390
+msgstr "Помилка перевірки поля: %s"
+
+#: kallithea/controllers/admin/repos.py:391
 #, python-format
 msgid "An error occurred during creation of field: %r"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:401
+msgstr "Сталася помилка під час створення поля: %r"
+
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:415
+msgstr "Під час видалення поля виникла помилка"
+
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:446
+msgstr "-- Не fork --"
+
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:450
+msgstr "Оновлено видимість репозиторія в публічному журналі"
+
+#: kallithea/controllers/admin/repos.py:452
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
-
-#: kallithea/controllers/admin/repos.py:466
-msgid "Nothing"
-msgstr ""
+"Сталася помилка під час налаштувань цього репозиторію в публічному журналі"
 
 #: kallithea/controllers/admin/repos.py:468
+msgid "Nothing"
+msgstr "Нічого"
+
+#: kallithea/controllers/admin/repos.py:470
 #, python-format
 msgid "Marked repository %s as fork of %s"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:475
+msgstr "Позначено репозиторій %s як відгалуження від %s"
+
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-msgid "Repository has been locked"
-msgstr ""
+msgstr "Сталася помилка під час виконання цієї операції"
+
+#: kallithea/controllers/admin/repos.py:490
+msgid "Cache invalidation successful"
+msgstr "Інвалідація кешу успішна"
 
 #: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-msgid "Repository has been unlocked"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:528
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:532
 msgid "An error occurred during cache invalidation"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:545
+msgstr "Сталася помилка під час Анулювання кеша"
+
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:548
+msgstr "Витягнуто з віддаленого місця"
+
+#: kallithea/controllers/admin/repos.py:510
 msgid "An error occurred during pull from remote location"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:579
+msgstr "Сталася помилка під час витягування з віддаленого розташування"
+
+#: kallithea/controllers/admin/repos.py:541
 msgid "An error occurred during deletion of repository stats"
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:135
+msgstr "Під час видалення статистики репозиторію сталася помилка"
+
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+msgstr "Оновлені налаштування VCS"
+
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
-
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+"Не вдається активувати підтримку hgsubversion. Бібліотека \"hgsubversion"
+"\" відсутня"
+
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:180
+msgstr "Під час оновлення параметрів застосунку сталася помилка"
+
+#: kallithea/controllers/admin/settings.py:176
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:192
+msgstr "Репозиторії успішно перескановано. Додано: %s. Видалено: %s."
+
+#: kallithea/controllers/admin/settings.py:188
 #, python-format
 msgid "Invalidated %s repositories"
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:233
+msgstr "До оновлення %s репозиторіїв"
+
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:286
+msgstr "Оновлені параметри застосунку"
+
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:291
+msgstr "Оновлені параметри візуалізації"
+
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:315
+msgstr "Під час оновлення параметрів візуалізації сталася помилка"
+
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:330
+msgstr "Будь ласка, введіть адресу електронної пошти"
+
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:358
+msgstr "Надіслати електронною поштою завдання створено"
+
+#: kallithea/controllers/admin/settings.py:355
 msgid "Hook already exists"
-msgstr ""
+msgstr "Hook вже існує"
+
+#: kallithea/controllers/admin/settings.py:357
+msgid "Builtin hooks are read-only. Please use another hook name."
+msgstr ""
+"Вбудовані hooks доступні лише для читання. Будь ласка, використовуйте "
+"інше ім'я hook."
 
 #: kallithea/controllers/admin/settings.py:360
-msgid "Builtin hooks are read-only. Please use another hook name."
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:363
 msgid "Added new hook"
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:379
+msgstr "Додано новий hook"
+
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:383
+msgstr "Оновлено hooks"
+
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:407
+msgstr "Сталася помилка під час створення hook"
+
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:143
+msgstr "Завдання реіндекса Whoosh заплановано"
+
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:156
+msgstr "Створена Група користувачів %s"
+
+#: kallithea/controllers/admin/user_groups.py:151
 #, python-format
 msgid "Error occurred during creation of user group %s"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:184
+msgstr "Під час створення групи користувачів  %s сталася помилка"
+
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:206
+msgstr "Оновлена група користувачів %s"
+
+#: kallithea/controllers/admin/user_groups.py:201
 #, python-format
 msgid "Error occurred during update of user group %s"
-msgstr ""
+msgstr "Сталася помилка під час оновлення групи користувачів %s"
+
+#: kallithea/controllers/admin/user_groups.py:212
+msgid "Successfully deleted user group"
+msgstr "Група користувачів успішно видалена"
 
 #: kallithea/controllers/admin/user_groups.py:217
-msgid "Successfully deleted user group"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:222
 msgid "An error occurred during deletion of user group"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:278
+msgstr "Під час видалення групи користувачів сталася помилка"
+
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:284
+msgstr "Цільова група не може бути однаковою"
+
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+msgstr "Права на групи користувачів оновлені"
+
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+msgstr "Оновлені дозволи"
+
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
-msgstr ""
+msgstr "Сталася помилка під час збереження дозволів"
 
 #: kallithea/controllers/admin/users.py:123
 #, python-format
 msgid "Created user %s"
-msgstr ""
+msgstr "Створено користувача %s"
 
 #: kallithea/controllers/admin/users.py:138
 #, python-format
 msgid "Error occurred during creation of user %s"
-msgstr ""
+msgstr "Під час створення користувача %s сталася помилка"
 
 #: kallithea/controllers/admin/users.py:162
 msgid "User updated successfully"
-msgstr ""
+msgstr "Користувач успішно оновлений"
 
 #: kallithea/controllers/admin/users.py:190
 msgid "Successfully deleted user"
-msgstr ""
+msgstr "Користувач успішно видалений"
 
 #: kallithea/controllers/admin/users.py:195
 msgid "An error occurred during deletion of user"
-msgstr ""
+msgstr "Сталася помилка під час видалення користувача"
 
 #: kallithea/controllers/admin/users.py:203
 msgid "The default user cannot be edited"
-msgstr ""
-
-#: kallithea/controllers/admin/users.py:412
+msgstr "Користувача за промовчанням не можна редагувати"
+
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
-msgstr ""
-
-#: kallithea/controllers/admin/users.py:418
+msgstr "Додана IP-адреса %s в білий список користувача"
+
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
-msgstr ""
-
-#: kallithea/controllers/admin/users.py:430
+msgstr "Сталася помилка під час додавання IP-адреси"
+
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
-msgstr ""
-
-#: kallithea/lib/auth.py:824
+msgstr "Вилучено IP-адресу з білого списку користувачів"
+
+#: kallithea/lib/auth.py:684
 msgid "You need to be a registered user to perform this action"
-msgstr ""
-
-#: kallithea/lib/auth.py:852
+msgstr "Для виконання цієї дії потрібно бути зареєстрованим користувачем"
+
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
-msgstr ""
-
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr ""
-
-#: kallithea/lib/base.py:495
+msgstr "Ви повинні бути зареєстровані для перегляду цієї сторінки"
+
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
-msgstr ""
-
-#: kallithea/lib/base.py:583
+msgstr "Виявлено витік токенів CSRF - всі маркери форми минули"
+
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
-msgstr ""
-
-#: kallithea/lib/base.py:608
+msgstr "Репозиторій не знайдено у файловій системі"
+
+#: kallithea/lib/base.py:605
 #, python-format
 msgid "Changeset for %s %s not found in %s"
-msgstr ""
-
-#: kallithea/lib/diffs.py:193
+msgstr "Набір змін для %s %s не знайдено в %s"
+
+#: kallithea/lib/base.py:647
+msgid "SSH access is disabled."
+msgstr ""
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
-msgstr ""
-
-#: kallithea/lib/diffs.py:213
+msgstr "Двійковий файл"
+
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
-
-#: kallithea/lib/diffs.py:223
+"Набір змін був занадто великий і було відрізано, використовуйте меню діфф "
+"для показу цього порівняння"
+
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
-msgstr ""
-
-#: kallithea/lib/helpers.py:612
+msgstr "Не виявлено змін"
+
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:614
+msgstr "Видалено гілку: %s"
+
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:625
+msgstr "Створено тег: %s"
+
+#: kallithea/lib/helpers.py:666
 #, python-format
 msgid "Changeset %s not found"
-msgstr ""
-
-#: kallithea/lib/helpers.py:674
+msgstr "Набір змін %s не знайдено"
+
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:680
+msgstr "Показати всі комбіновані набори змін %s- >%s"
+
+#: kallithea/lib/helpers.py:721
 msgid "Compare view"
-msgstr ""
-
-#: kallithea/lib/helpers.py:699
+msgstr "Порівняйте вигляд"
+
+#: kallithea/lib/helpers.py:740
 msgid "and"
-msgstr ""
-
-#: kallithea/lib/helpers.py:700
+msgstr "і"
+
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
-msgstr ""
-
-#: kallithea/lib/helpers.py:701
+msgstr "%s більше"
+
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
-msgstr ""
-
-#: kallithea/lib/helpers.py:725
-#, python-format
-msgid "Fork name %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:746
-#, python-format
-msgid "Pull request %s"
-msgstr ""
-
-#: kallithea/lib/helpers.py:756
-msgid "[deleted] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
-msgid "[created] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:760
-msgid "[created] repository as fork"
-msgstr ""
-
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
-msgid "[forked] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
-msgid "[updated] repository"
-msgstr ""
+msgstr "редакції"
 
 #: kallithea/lib/helpers.py:766
+#, python-format
+msgid "Fork name %s"
+msgstr "Ім'я розгалуження %s"
+
+#: kallithea/lib/helpers.py:787
+#, python-format
+msgid "Pull request %s"
+msgstr "Pull request %s"
+
+#: kallithea/lib/helpers.py:797
+msgid "[deleted] repository"
+msgstr "[видалений] репозиторій"
+
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
+msgid "[created] repository"
+msgstr "[створено] репозиторій"
+
+#: kallithea/lib/helpers.py:801
+msgid "[created] repository as fork"
+msgstr "[створено] репозиторій як fork"
+
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
+msgid "[forked] repository"
+msgstr "[forked] репозиторій"
+
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
+msgid "[updated] repository"
+msgstr "[оновлено] репозиторій"
+
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:768
+msgstr "[завантажити] архів з репозиторію"
+
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
-msgstr ""
-
-#: kallithea/lib/helpers.py:776
+msgstr "[видалити] репозиторій"
+
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
-msgstr ""
-
-#: kallithea/lib/helpers.py:778
+msgstr "[створено] користувач"
+
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
-msgstr ""
-
-#: kallithea/lib/helpers.py:780
+msgstr "[оновлений] користувач"
+
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
-msgstr ""
-
-#: kallithea/lib/helpers.py:782
+msgstr "[створено] групу користувачів"
+
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
-msgstr ""
-
-#: kallithea/lib/helpers.py:784
+msgstr "[оновлено] група користувачів"
+
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr ""
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr ""
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
-msgstr ""
-
-#: kallithea/lib/helpers.py:957
+msgstr "Файлів немає"
+
+#: kallithea/lib/helpers.py:990
 msgid "new file"
-msgstr ""
-
-#: kallithea/lib/helpers.py:960
+msgstr "новий файл"
+
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
-msgstr ""
-
-#: kallithea/lib/helpers.py:971
+msgstr "перейменувати"
+
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
-msgstr ""
-
-#: kallithea/lib/helpers.py:1264
+msgstr "chmod"
+
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1247,7 +1248,34 @@
 "repositories"
 msgstr ""
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
@@ -1255,7 +1283,7 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
@@ -1263,194 +1291,198 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-#: kallithea/lib/utils2.py:336
+msgstr[0] "%d день"
+msgstr[1] "%d днів"
+msgstr[2] "%d дня"
+
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-#: kallithea/lib/utils2.py:337
+msgstr[0] "%d година"
+msgstr[1] "%d годин"
+msgstr[2] "%d години"
+
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-#: kallithea/lib/utils2.py:338
+msgstr[0] "%d хвилина"
+msgstr[1] "%d хвилин"
+msgstr[2] "%d хвилини"
+
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-#: kallithea/lib/utils2.py:354
+msgstr[0] "%d секунда"
+msgstr[1] "%d секунд"
+msgstr[2] "%d секунди"
+
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
-msgstr ""
-
-#: kallithea/lib/utils2.py:356
+msgstr "в %s"
+
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
-msgstr ""
-
-#: kallithea/lib/utils2.py:358
+msgstr "%s тому"
+
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
-msgstr ""
-
-#: kallithea/lib/utils2.py:361
+msgstr "у %s і %s"
+
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
-msgstr ""
-
-#: kallithea/lib/utils2.py:364
+msgstr "%s і %s тому"
+
+#: kallithea/lib/utils2.py:365
 msgid "just now"
-msgstr ""
+msgstr "прямо зараз"
 
 #: kallithea/model/comment.py:68
 #, python-format
 msgid "on line %s"
-msgstr ""
-
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+msgstr "в рядку %s"
+
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
-msgstr ""
-
-#: kallithea/model/db.py:1562
+msgstr "[Згадування]"
+
+#: kallithea/model/db.py:1496
 msgid "top level"
-msgstr ""
-
-#: kallithea/model/db.py:1703
+msgstr "верхній рівень"
+
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
-msgstr ""
-
-#: kallithea/model/db.py:1705
+msgstr "Kallithea Адміністратор"
+
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
-msgstr ""
-
-#: kallithea/model/db.py:1706
+msgstr "Користувач за промовчанням не має доступу до нових репозиторіїв"
+
+#: kallithea/model/db.py:1640
 msgid "Default user has read access to new repositories"
 msgstr ""
-
-#: kallithea/model/db.py:1707
+"Користувач за замовчанням має доступ на перегляд  нових репозиторіїв"
+
+#: kallithea/model/db.py:1641
 msgid "Default user has write access to new repositories"
 msgstr ""
-
-#: kallithea/model/db.py:1708
+"Користувач за замовчуванням має доступ до запису до нових репозиторіїв"
+
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr ""
-
-#: kallithea/model/db.py:1710
+"Користувач за промовчанням має доступ адміністратора до нових репозиторіїв"
+
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr ""
-
-#: kallithea/model/db.py:1711
+"Користувач за замовчуванням не має доступу до нових груп репозиторіїв"
+
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1730
+#: kallithea/model/db.py:1664
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1732
+#: kallithea/model/db.py:1666
 msgid "Only admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 msgid "Non-admins can fork repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 msgid "Not reviewed"
 msgstr ""
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 msgid "Under review"
 msgstr ""
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr ""
 
@@ -1476,302 +1508,313 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:169
+#, 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:170
 #, 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:171
-#, 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:184
+#: kallithea/model/notification.py:183
 msgid "Closing"
 msgstr ""
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 msgid "Cannot create empty pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 msgid "You are not authorized to create the pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 msgid "Missing changesets since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, python-format
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, python-format
 msgid ""
 "This iteration is based on another %s revision and there is no simple "
 "diff."
 msgstr ""
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, python-format
 msgid "No changes found on %s %s since previous iteration."
 msgstr ""
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr ""
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, python-format
+msgid "SSH key %r not found"
+msgstr ""
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr ""
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:255
 #, 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:263
+#: kallithea/model/user.py:260
 #, 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:270
+#: kallithea/model/user.py:267
 #, 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:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr ""
 
+#: kallithea/model/validators.py:72
+#, python-format
+msgid "Username \"%(username)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:74
 #, python-format
-msgid "Username \"%(username)s\" already exists"
+msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
 #: kallithea/model/validators.py:76
-#, python-format
-msgid "Username \"%(username)s\" cannot be used"
-msgstr ""
-
-#: kallithea/model/validators.py:78
 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:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr ""
 
+#: kallithea/model/validators.py:132
+#, python-format
+msgid "User group \"%(usergroup)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:134
-#, python-format
-msgid "User group \"%(usergroup)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:136
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr ""
 
+#: kallithea/model/validators.py:175
+#, python-format
+msgid "Group \"%(group_name)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:177
 #, python-format
-msgid "Group \"%(group_name)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:179
-#, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr ""
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 msgid "Invalid username or password"
 msgstr ""
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr ""
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr ""
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
-#: kallithea/model/validators.py:333
+#: kallithea/model/validators.py:318
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:419
+#: kallithea/model/validators.py:404
 msgid "Invalid repository URL"
 msgstr ""
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:430
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:460
+#: kallithea/model/validators.py:445
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:512
+#: kallithea/model/validators.py:497
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:552
+#: kallithea/model/validators.py:537
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr ""
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 msgid "This email address is already in use"
 msgstr ""
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 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:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:765
+#: kallithea/model/validators.py:750
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1812,24 +1855,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr ""
 
@@ -1846,7 +1895,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1854,11 +1903,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr ""
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr ""
@@ -1873,7 +1922,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1881,7 +1930,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr ""
@@ -2038,10 +2087,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr ""
@@ -2090,22 +2141,22 @@
 msgstr ""
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr ""
 
@@ -2123,14 +2174,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2138,36 +2189,25 @@
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr ""
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr ""
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr ""
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2214,8 +2254,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 msgid "Never"
 msgstr ""
 
@@ -2248,7 +2290,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr ""
 
@@ -2276,7 +2318,7 @@
 
 #: kallithea/templates/admin/gists/new.html:54
 msgid "Create Public Gist"
-msgstr ""
+msgstr "Створити публічний GIST"
 
 #: kallithea/templates/admin/gists/new.html:55
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:14
@@ -2284,51 +2326,53 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
 #: kallithea/templates/pullrequests/pullrequest.html:78
 msgid "Reset"
-msgstr ""
+msgstr "Скинути"
 
 #: kallithea/templates/admin/gists/show.html:5
 #: kallithea/templates/admin/gists/show.html:9
 msgid "Gist"
-msgstr ""
+msgstr "Gist"
 
 #: kallithea/templates/admin/gists/show.html:10
 msgid "URL"
-msgstr ""
+msgstr "URL"
 
 #: kallithea/templates/admin/gists/show.html:35
 msgid "Public Gist"
-msgstr ""
+msgstr "Публічний GIST"
 
 #: kallithea/templates/admin/gists/show.html:37
 msgid "Private Gist"
-msgstr ""
+msgstr "Приватний Gist"
 
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2347,11 +2391,11 @@
 #: kallithea/templates/files/files_source.html:41
 #: kallithea/templates/pullrequests/pullrequest_data.html:20
 msgid "Delete"
-msgstr ""
+msgstr "Видалити"
 
 #: kallithea/templates/admin/gists/show.html:54
 msgid "Confirm to delete this Gist"
-msgstr ""
+msgstr "Підтвердіть видалення цього Gist"
 
 #: kallithea/templates/admin/gists/show.html:61
 #: kallithea/templates/base/perms_summary.html:44
@@ -2370,105 +2414,114 @@
 #: kallithea/templates/files/files_source.html:40
 #: kallithea/templates/pullrequests/pullrequest_show.html:41
 msgid "Edit"
-msgstr ""
+msgstr "Редагувати"
 
 #: kallithea/templates/admin/gists/show.html:63
 #: kallithea/templates/files/files_edit.html:52
 #: kallithea/templates/files/files_source.html:30
 msgid "Show as Raw"
-msgstr ""
+msgstr "Відображати як RAW"
 
 #: kallithea/templates/admin/gists/show.html:69
 msgid "created"
-msgstr ""
+msgstr "створено"
 
 #: kallithea/templates/admin/gists/show.html:82
 msgid "Show as raw"
-msgstr ""
+msgstr "Відображати як RAW"
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
-msgstr ""
+msgstr "Мій акаунт"
 
 #: kallithea/templates/admin/my_account/my_account.html:25
 #: kallithea/templates/admin/users/user_edit.html:29
 msgid "Profile"
-msgstr ""
+msgstr "Профіль"
 
 #: kallithea/templates/admin/my_account/my_account.html:26
 msgid "Email Addresses"
-msgstr ""
-
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
-msgid "API Keys"
-msgstr ""
+msgstr "Адреси Електронної Пошти"
 
 #: kallithea/templates/admin/my_account/my_account.html:29
-msgid "Owned Repositories"
-msgstr ""
-
-#: kallithea/templates/admin/my_account/my_account.html:30
-#: kallithea/templates/journal/journal.html:33
-msgid "Watched Repositories"
+#: kallithea/templates/admin/users/user_edit.html:32
+msgid "SSH Keys"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
+msgid "API Keys"
+msgstr "API Ключі"
+
+#: kallithea/templates/admin/my_account/my_account.html:32
+msgid "Owned Repositories"
+msgstr "Власні Репозиторії"
+
+#: kallithea/templates/admin/my_account/my_account.html:33
+#: kallithea/templates/journal/journal.html:33
+msgid "Watched Repositories"
+msgstr "Переглянуті репозиторії"
+
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 msgid "Show Permissions"
-msgstr ""
+msgstr "Показати Права доступу"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:5
 #: kallithea/templates/admin/users/user_edit_api_keys.html:5
 msgid "Built-in"
-msgstr ""
+msgstr "Вбудований"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:13
 #: kallithea/templates/admin/users/user_edit_api_keys.html:13
 #, python-format
 msgid "Confirm to reset this API key: %s"
-msgstr ""
+msgstr "Підтвердіть, щоб скинути цей ключ API: %s"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:29
 #: kallithea/templates/admin/users/user_edit_api_keys.html:29
 msgid "Expired"
-msgstr ""
+msgstr "Просрочено"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:39
 #, python-format
 msgid "Confirm to remove this API key: %s"
-msgstr ""
+msgstr "Підтвердіть, щоб видалити цей ключ API: %s"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 msgid "Remove"
-msgstr ""
+msgstr "Видалити"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:48
 #: kallithea/templates/admin/users/user_edit_api_keys.html:48
 msgid "No additional API keys specified"
-msgstr ""
+msgstr "Не вказано додаткових ключів API"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:56
 #: kallithea/templates/admin/users/user_edit_api_keys.html:56
 msgid "New API key"
-msgstr ""
+msgstr "Новий ключ API"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
-msgstr ""
+msgstr "Додати"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:81
 #, python-format
@@ -2490,40 +2543,40 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:9
 #: kallithea/templates/admin/users/user_edit_emails.html:9
 msgid "Primary"
-msgstr ""
+msgstr "Основний"
 
 #: kallithea/templates/admin/my_account/my_account_emails.html:24
 #: kallithea/templates/admin/users/user_edit_emails.html:24
 #, python-format
 msgid "Confirm to delete this email: %s"
-msgstr ""
+msgstr "Підтвердіть, щоб видалити цей email: %s"
 
 #: kallithea/templates/admin/my_account/my_account_emails.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:30
 msgid "No additional emails specified."
-msgstr ""
+msgstr "Не вказано додаткових email."
 
 #: kallithea/templates/admin/my_account/my_account_emails.html:39
 #: kallithea/templates/admin/users/user_edit_emails.html:39
 msgid "New email address"
-msgstr ""
+msgstr "Нова електронна адреса"
 
 #: kallithea/templates/admin/my_account/my_account_password.html:1
 msgid "Change Your Account Password"
-msgstr ""
+msgstr "Зміна Пароля Облікового Запису"
 
 #: kallithea/templates/admin/my_account/my_account_password.html:8
 msgid "Current password"
-msgstr ""
+msgstr "Поточний пароль"
 
 #: kallithea/templates/admin/my_account/my_account_password.html:15
 #: kallithea/templates/admin/users/user_edit_profile.html:46
 msgid "New password"
-msgstr ""
+msgstr "Новий пароль"
 
 #: kallithea/templates/admin/my_account/my_account_password.html:22
 msgid "Confirm new password"
-msgstr ""
+msgstr "Підтвердіть новий пароль"
 
 #: kallithea/templates/admin/my_account/my_account_password.html:39
 #, python-format
@@ -2533,27 +2586,27 @@
 
 #: kallithea/templates/admin/my_account/my_account_perms.html:3
 msgid "Current IP"
-msgstr ""
+msgstr "Поточний IP"
 
 #: kallithea/templates/admin/my_account/my_account_profile.html:4
 #: kallithea/templates/admin/users/user_edit_profile.html:4
 msgid "Gravatar"
-msgstr ""
+msgstr "Gravatar"
 
 #: kallithea/templates/admin/my_account/my_account_profile.html:10
 #: kallithea/templates/admin/users/user_edit_profile.html:10
 #, python-format
 msgid "Change %s avatar at"
-msgstr ""
+msgstr "Змінити %s Avatar на"
 
 #: kallithea/templates/admin/my_account/my_account_profile.html:12
 #: kallithea/templates/admin/users/user_edit_profile.html:12
 msgid "Avatars are disabled"
-msgstr ""
+msgstr "Аватарки відключені"
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:1
 msgid "Repositories You Own"
-msgstr ""
+msgstr "Репозиторії якими Ви володієте"
 
 #: kallithea/templates/admin/my_account/my_account_repos.html:13
 #: kallithea/templates/admin/my_account/my_account_watched.html:13
@@ -2565,35 +2618,71 @@
 #: kallithea/templates/base/perms_summary.html:54
 #: kallithea/templates/files/files_browser.html:54
 msgid "Name"
+msgstr "Назва"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+msgid "Last Used"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, python-format
+msgid "Confirm to remove this SSH key: %s"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+msgid "New SSH key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+msgid "Public key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
 msgstr ""
 
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 msgid "Repositories You are Watching"
-msgstr ""
+msgstr "Ви проглядаєте репозиторії"
 
 #: kallithea/templates/admin/permissions/permissions.html:5
 #: kallithea/templates/admin/permissions/permissions.html:11
 #: kallithea/templates/base/base.html:60
 msgid "Default Permissions"
-msgstr ""
+msgstr "Дозволу за замовчуванням"
 
 #: kallithea/templates/admin/permissions/permissions.html:28
 #: kallithea/templates/admin/settings/settings.html:29
 msgid "Global"
-msgstr ""
+msgstr "Глобальні"
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
-msgstr ""
+msgstr "Білий список IP"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:4
 msgid "Anonymous access"
-msgstr ""
+msgstr "Анонімний доступ"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:8
 msgid "Allow anonymous access"
-msgstr ""
+msgstr "Дозволити анонімний доступ"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:10
 #, python-format
@@ -2611,19 +2700,19 @@
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:20
 msgid "Apply to all existing repositories"
-msgstr ""
+msgstr "Поширюються на всі існуючі репозиторії"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:23
 msgid "Permissions for the Default user on new repositories."
-msgstr ""
+msgstr "Дозволи для користувача за промовчанням на нові репозиторії."
 
 #: 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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
-msgstr ""
+msgstr "Група репозиторіїв"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:32
 msgid ""
@@ -2634,16 +2723,16 @@
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:33
 msgid "Apply to all existing repository groups"
-msgstr ""
+msgstr "Застосувати до всіх наявних груп репозиторіїв"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:36
 msgid "Permissions for the Default user on new repository groups."
-msgstr ""
+msgstr "Дозволи для користувача за промовчанням на нові групи репозиторіів."
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:40
 #: kallithea/templates/data_table/_dt_elements.html:141
 msgid "User group"
-msgstr ""
+msgstr "Група користувачів"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:45
 msgid ""
@@ -2654,11 +2743,12 @@
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:46
 msgid "Apply to all existing user groups"
-msgstr ""
+msgstr "Застосувати до всіх існуючих груп користувачів"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:49
 msgid "Permissions for the Default user on new user groups."
 msgstr ""
+"Дозволи для користувача за замовчуванням для нових груп користувачів."
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:53
 msgid "Top level repository creation"
@@ -2677,7 +2767,7 @@
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:61
 msgid "Repository creation with group write access"
-msgstr ""
+msgstr "Створення сховища з доступом до групового записування"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:64
 msgid ""
@@ -2688,43 +2778,47 @@
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:68
 msgid "User group creation"
-msgstr ""
+msgstr "Створення групи користувачів"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:71
 msgid "Enable this to allow non-admins to create user groups."
 msgstr ""
+"Увімкніть цей параметр, щоб дозволити неадміністраторам створювати групи "
+"користувачів."
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:75
 msgid "Repository forking"
-msgstr ""
+msgstr "Репозиторій розгалуження"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:78
 msgid "Enable this to allow non-admins to fork repositories."
 msgstr ""
+"Увімкніть цей параметр, щоб дозволити не-адміністраторам fork "
+"репозиторіїв."
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:82
 msgid "Registration"
-msgstr ""
+msgstr "Реєстрація"
 
 #: kallithea/templates/admin/permissions/permissions_globals.html:88
 msgid "External auth account activation"
-msgstr ""
+msgstr "Активація облікового запису зовнішньої автентифікації"
 
 #: kallithea/templates/admin/permissions/permissions_ips.html:12
 #: kallithea/templates/admin/users/user_edit_ips.html:22
 #, python-format
 msgid "Confirm to delete this IP address: %s"
-msgstr ""
+msgstr "Підтвердіть, щоб видалити IP-адреса: %s"
 
 #: kallithea/templates/admin/permissions/permissions_ips.html:18
 #: kallithea/templates/admin/users/user_edit_ips.html:29
 msgid "All IP addresses are allowed."
-msgstr ""
+msgstr "Дозволено всі IP-адреси."
 
 #: kallithea/templates/admin/permissions/permissions_ips.html:25
 #: kallithea/templates/admin/users/user_edit_ips.html:37
 msgid "New IP address"
-msgstr ""
+msgstr "Нова ІР-адреса"
 
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:11
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:11
@@ -2733,29 +2827,29 @@
 #: kallithea/templates/base/base.html:57
 #: kallithea/templates/base/base.html:76
 msgid "Repository Groups"
-msgstr ""
+msgstr "Групи Репозиторіїв"
 
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:28
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:5
 #: kallithea/templates/admin/user_groups/user_group_add.html:27
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:4
 msgid "Group name"
-msgstr ""
+msgstr "Назва групи"
 
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:42
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:19
 msgid "Group parent"
-msgstr ""
+msgstr "Батьківська група"
 
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:49
 #: kallithea/templates/admin/repos/repo_add_base.html:35
 msgid "Copy parent group permissions"
-msgstr ""
+msgstr "Копіювання дозволів батьківської групи"
 
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:52
 #: kallithea/templates/admin/repos/repo_add_base.html:38
 msgid "Copy permission set from parent repository group."
-msgstr ""
+msgstr "Скопіюйте набір дозволів із батьківської групи репозиторію."
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:5
 #, python-format
@@ -2764,7 +2858,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:29
 msgid "Add Child Group"
-msgstr ""
+msgstr "Додати Дочіру групу"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:36
 #: kallithea/templates/admin/repos/repo_edit.html:12
@@ -2774,44 +2868,44 @@
 #: kallithea/templates/base/base.html:63
 #: kallithea/templates/base/base.html:152
 msgid "Settings"
-msgstr ""
+msgstr "Параметри"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
-msgstr ""
+msgstr "Додатково"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:38
 #: kallithea/templates/admin/repos/repo_edit.html:28
 #: kallithea/templates/admin/user_groups/user_group_edit.html:31
 msgid "Permissions"
-msgstr ""
+msgstr "Дозволи"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:1
 #, python-format
 msgid "Repository Group: %s"
-msgstr ""
+msgstr "Група репозиторію: %s"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:6
 msgid "Top level repositories"
-msgstr ""
+msgstr "Репозиторії верхнього рівня"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:7
 msgid "Total repositories"
-msgstr ""
+msgstr "Всього репозиторіїв"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:8
 msgid "Children groups"
-msgstr ""
+msgstr "Дочірні групи"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_advanced.html:7
 #: kallithea/templates/admin/users/user_edit_advanced.html:8
 #: kallithea/templates/pullrequests/pullrequest_show.html:118
 msgid "Created on"
-msgstr ""
+msgstr "Створено о"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:21
 #: kallithea/templates/data_table/_dt_elements.html:121
@@ -2824,29 +2918,29 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:25
 msgid "Delete this repository group"
-msgstr ""
+msgstr "Видалити цю групу репозиторіїв"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 msgid "Not visible"
-msgstr ""
+msgstr "Не видно"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 msgid "Visible"
-msgstr ""
+msgstr "Видно"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 msgid "Add repos"
-msgstr ""
+msgstr "Додати репозиторій"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:10
 msgid "Add/Edit groups"
-msgstr ""
+msgstr "Додавання/редагування груп"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:11
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:11
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:11
 msgid "User/User Group"
-msgstr ""
+msgstr "Група користувачів/користувачів"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:28
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:45
@@ -2855,7 +2949,7 @@
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:28
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:45
 msgid "Default"
-msgstr ""
+msgstr "За промовчанням"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:71
@@ -2864,58 +2958,54 @@
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:34
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:71
 msgid "Revoke"
-msgstr ""
+msgstr "Відкликати"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:81
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:77
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:81
 msgid "Add new"
-msgstr ""
+msgstr "Додати новий"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:87
 msgid "Apply to children"
-msgstr ""
+msgstr "Застосовувати до дочірніх"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:91
 msgid "Both"
-msgstr ""
+msgstr "Обидва"
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:92
 msgid ""
 "Set or revoke permission to all children of that group, including non-"
 "private repositories and other groups if selected."
 msgstr ""
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+"Встановіть або скасуйте дозвіл для всіх дітей цієї групи, включно з "
+"неприватними репозиторіями та іншими групами, якщо вони вибрані."
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
-msgstr ""
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+msgstr "Видалити цю групу"
+
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Confirm to delete this group"
-msgstr ""
+msgstr "Підтвердіть, щоб видалити цю групу"
 
 #: kallithea/templates/admin/repo_groups/repo_group_show.html:4
 #, python-format
 msgid "Repository group %s"
-msgstr ""
+msgstr "Група репозиторію: %s"
 
 #: kallithea/templates/admin/repo_groups/repo_groups.html:5
 msgid "Repository Groups Administration"
-msgstr ""
+msgstr "Адміністрування Груп Репозиторіїв"
 
 #: kallithea/templates/admin/repo_groups/repo_groups.html:41
 msgid "Number of Top-level Repositories"
-msgstr ""
+msgstr "Кількість репозиторіїв верхнього рівня"
 
 #: kallithea/templates/admin/repos/repo_add_base.html:12
 msgid "Clone remote repository"
-msgstr ""
+msgstr "Клонувати віддалений репозиторій"
 
 #: kallithea/templates/admin/repos/repo_add_base.html:16
 msgid ""
@@ -2924,42 +3014,44 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
-msgstr ""
+msgstr "За бажанням виберіть групу, в яку буде розміщено цей репозиторій."
 
 #: kallithea/templates/admin/repos/repo_add_base.html:45
 msgid "Type of repository to create."
-msgstr ""
+msgstr "Тип сховища для створення."
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
-msgstr ""
+msgstr "Цільова редакція"
 
 #: kallithea/templates/admin/repos/repo_add_base.html:52
 msgid ""
 "Default revision for files page, downloads, full text search index and "
 "readme generation"
 msgstr ""
+"Стандартна редакція для файлів сторінок, завантажень, повнотекстового "
+"індексу пошуку та генерації readme"
 
 #: kallithea/templates/admin/repos/repo_creating.html:9
 #, python-format
 msgid "%s Creating Repository"
-msgstr ""
+msgstr "%s створення репозиторію"
 
 #: kallithea/templates/admin/repos/repo_creating.html:13
 msgid "Creating repository"
-msgstr ""
+msgstr "Створення репозиторію"
 
 #: kallithea/templates/admin/repos/repo_creating.html:27
 #, python-format
@@ -2967,115 +3059,84 @@
 "Repository \"%(repo_name)s\" is being created, you will be redirected "
 "when this process is finished.repo_name"
 msgstr ""
+"Репозиторій \"%(repo_name)s\" створюється, ви будете переспрямовані, коли "
+"цей процес буде завершено.repo_name"
 
 #: kallithea/templates/admin/repos/repo_creating.html:39
 msgid ""
 "We're sorry but error occurred during this operation. Please check your "
 "Kallithea server logs, or contact administrator."
 msgstr ""
+"Вибачте, але помилка сталася під час виконання цієї операції. Будь ласка, "
+"перевірте журнали сервера Kallithea або зверніться до адміністратора."
 
 #: kallithea/templates/admin/repos/repo_edit.html:8
 #, python-format
 msgid "%s Repository Settings"
-msgstr ""
+msgstr "Параметри репозиторію %s"
 
 #: kallithea/templates/admin/repos/repo_edit.html:34
 msgid "Extra Fields"
-msgstr ""
+msgstr "Додаткові поля"
 
 #: kallithea/templates/admin/repos/repo_edit.html:37
 msgid "Caches"
-msgstr ""
+msgstr "Кеши"
 
 #: kallithea/templates/admin/repos/repo_edit.html:40
 msgid "Remote"
-msgstr ""
+msgstr "Віддалений"
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
-msgstr ""
+msgstr "Статистика"
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:1
 msgid "Parent"
-msgstr ""
+msgstr "Батьківський"
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:5
 msgid "Set"
-msgstr ""
+msgstr "Набір"
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:7
 msgid "Manually set this repository as a fork of another from the list."
-msgstr ""
+msgstr "Вручну встановити цей репозиторій як відгалуження іншого зі списку."
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:20
 msgid "Public Journal Visibility"
-msgstr ""
+msgstr "Видимість публічного журналу"
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:27
 msgid "Remove from public journal"
-msgstr ""
+msgstr "Видалити з публічного журналу"
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:32
 msgid "Add to Public Journal"
-msgstr ""
+msgstr "Додати до публічного журналу"
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:37
 msgid ""
 "All actions done in this repository will be visible to everyone in the "
 "public journal."
 msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-msgid "Change Locking"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-msgid "Confirm to unlock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-msgid "Unlock Repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-msgid "Confirm to lock repository."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-msgid "Lock Repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
+"Усі дії, зроблені в цьому репозиторії, будуть видимими для всіх у "
+"публічному журналі."
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
 #: kallithea/templates/data_table/_dt_elements.html:68
 #, python-format
 msgid "Confirm to delete this repository: %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
+msgstr "Підтвердити видалення цього сховища: %s"
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
 msgid "Delete this Repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+msgstr "Видалити цей репозиторій"
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
@@ -3083,15 +3144,15 @@
 msgstr[1] ""
 msgstr[2] ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+msgstr "Від'єднати forks"
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+msgstr "Видалити forks"
+
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3100,26 +3161,28 @@
 
 #: kallithea/templates/admin/repos/repo_edit_caches.html:4
 msgid "Invalidate Repository Cache"
-msgstr ""
+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 ""
+msgstr "Список кешованих значень"
 
 #: kallithea/templates/admin/repos/repo_edit_caches.html:12
 msgid "Prefix"
-msgstr ""
+msgstr "Префікс"
 
 #: kallithea/templates/admin/repos/repo_edit_caches.html:13
 #: kallithea/templates/admin/repos/repo_edit_fields.html:7
 msgid "Key"
-msgstr ""
+msgstr "Ключ"
 
 #: kallithea/templates/admin/repos/repo_edit_caches.html:14
 #: kallithea/templates/admin/user_groups/user_group_add.html:40
@@ -3129,78 +3192,70 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:74
 #: kallithea/templates/admin/users/users.html:42
 msgid "Active"
-msgstr ""
+msgstr "Активний"
 
 #: kallithea/templates/admin/repos/repo_edit_fields.html:6
 msgid "Label"
-msgstr ""
+msgstr "Мітка"
 
 #: kallithea/templates/admin/repos/repo_edit_fields.html:20
 #, python-format
 msgid "Confirm to delete this field: %s"
-msgstr ""
+msgstr "Підтвердити видалення цього поля: %s"
 
 #: kallithea/templates/admin/repos/repo_edit_fields.html:31
 msgid "New field key"
-msgstr ""
+msgstr "Новий ключ поля"
 
 #: kallithea/templates/admin/repos/repo_edit_fields.html:38
 msgid "New field label"
-msgstr ""
+msgstr "Нова мітка поля"
 
 #: kallithea/templates/admin/repos/repo_edit_fields.html:40
 msgid "Enter short label"
-msgstr ""
+msgstr "Введіть коротку мітку"
 
 #: kallithea/templates/admin/repos/repo_edit_fields.html:45
 msgid "New field description"
-msgstr ""
+msgstr "Опис нового поля"
 
 #: kallithea/templates/admin/repos/repo_edit_fields.html:47
 msgid "Enter description of a field"
-msgstr ""
+msgstr "Введіть опис поля"
 
 #: kallithea/templates/admin/repos/repo_edit_fields.html:61
 msgid "Extra fields are disabled."
-msgstr ""
+msgstr "Додаткові поля вимкнено."
 
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:20
 msgid "Private Repository"
-msgstr ""
+msgstr "Приватний Репозиторій"
 
 #: kallithea/templates/admin/repos/repo_edit_remote.html:4
 msgid "Fork of repository"
-msgstr ""
+msgstr "Форк репозиторію"
 
 #: kallithea/templates/admin/repos/repo_edit_remote.html:7
 msgid "Remote repository URL"
-msgstr ""
+msgstr "URL-адреса віддаленого сховища"
 
 #: kallithea/templates/admin/repos/repo_edit_remote.html:15
 msgid "Pull Changes from Remote Repository"
-msgstr ""
+msgstr "Витягнути зміни з віддаленого сховища"
 
 #: kallithea/templates/admin/repos/repo_edit_remote.html:17
 msgid "Confirm to pull changes from remote repository."
-msgstr ""
+msgstr "Підтвердьте, щоб витягнути зміни з віддаленого сховища."
 
 #: kallithea/templates/admin/repos/repo_edit_remote.html:23
 msgid "This repository does not have a remote repository URL."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "Permanent Repository ID"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr ""
+msgstr "У цьому сховищі немає URL-адреси віддаленого сховища."
 
 #: kallithea/templates/admin/repos/repo_edit_settings.html:10
+msgid "Permanent URL"
+msgstr ""
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3210,109 +3265,111 @@
 "other cases that you need to hardcode the URL into a 3rd party service."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 msgid "Remote repository"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+msgstr "Віддалений репозиторій"
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 msgid "Repository URL"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+msgstr "URL репозиторію"
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
 msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+"Опціонально: URL-адреса віддаленого сховища. Якщо встановлено, сховище "
+"можна витягнути з цієї URL-адреси."
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+msgstr "Введіть ім'я користувача"
+
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
-msgstr ""
+msgstr "Змінити власника цього сховища."
 
 #: kallithea/templates/admin/repos/repo_edit_statistics.html:5
 msgid "Processed commits"
-msgstr ""
+msgstr "Оброблені коміти"
 
 #: kallithea/templates/admin/repos/repo_edit_statistics.html:6
 msgid "Processed progress"
-msgstr ""
+msgstr "Оброблений прогрес"
 
 #: kallithea/templates/admin/repos/repo_edit_statistics.html:10
 msgid "Reset Statistics"
-msgstr ""
+msgstr "Скинути статистику"
 
 #: kallithea/templates/admin/repos/repo_edit_statistics.html:10
 msgid "Confirm to remove current statistics."
-msgstr ""
+msgstr "Підтвердьте видалення поточної статистики."
 
 #: kallithea/templates/admin/repos/repos.html:5
 msgid "Repositories Administration"
-msgstr ""
+msgstr "Адміністрування Репозиторіїв"
 
 #: kallithea/templates/admin/repos/repos.html:43
 msgid "State"
-msgstr ""
+msgstr "Стан"
 
 #: kallithea/templates/admin/settings/settings.html:5
 msgid "Settings Administration"
-msgstr ""
+msgstr "Адміністрування параметрів"
 
 #: kallithea/templates/admin/settings/settings.html:27
 msgid "VCS"
-msgstr ""
+msgstr "VCS"
 
 #: kallithea/templates/admin/settings/settings.html:28
 msgid "Remap and Rescan"
-msgstr ""
+msgstr "Ремап та Рескан"
 
 #: kallithea/templates/admin/settings/settings.html:30
 msgid "Visual"
-msgstr ""
+msgstr "Візуальний"
 
 #: kallithea/templates/admin/settings/settings.html:32
 #: kallithea/templates/admin/settings/settings_vcs.html:4
 msgid "Hooks"
-msgstr ""
+msgstr "Хуки"
 
 #: kallithea/templates/admin/settings/settings.html:33
 msgid "Full Text Search"
-msgstr ""
+msgstr "Повнотекстовий пошук"
 
 #: kallithea/templates/admin/settings/settings.html:34
 msgid "System Info"
-msgstr ""
+msgstr "Інформація про систему"
 
 #: kallithea/templates/admin/settings/settings_email.html:4
 msgid "Send test email to"
-msgstr ""
+msgstr "Надіслати тестовий лист на адресу"
 
 #: kallithea/templates/admin/settings/settings_email.html:12
 msgid "Send"
-msgstr ""
+msgstr "Надіслати"
 
 #: kallithea/templates/admin/settings/settings_global.html:4
 msgid "Site branding"
-msgstr ""
+msgstr "Брендинг сайту"
 
 #: kallithea/templates/admin/settings/settings_global.html:7
 msgid "Set a custom title for your Kallithea Service."
-msgstr ""
+msgstr "Встановіть власну назву для Сервісу Kallithea."
 
 #: kallithea/templates/admin/settings/settings_global.html:12
 msgid "HTTP authentication realm"
-msgstr ""
+msgstr "Область автентифікації HTTP"
 
 #: kallithea/templates/admin/settings/settings_global.html:19
 msgid "HTML/JavaScript/CSS customization block"
-msgstr ""
+msgstr "HTML/JavaScript/CSS блок налаштування"
 
 #: kallithea/templates/admin/settings/settings_global.html:22
 msgid ""
@@ -3325,35 +3382,37 @@
 
 #: kallithea/templates/admin/settings/settings_global.html:32
 msgid "ReCaptcha public key"
-msgstr ""
+msgstr "ReCaptcha публічний ключ"
 
 #: kallithea/templates/admin/settings/settings_global.html:35
 msgid "Public key for reCaptcha system."
-msgstr ""
+msgstr "Публічний ключ для системи reCaptcha."
 
 #: kallithea/templates/admin/settings/settings_global.html:40
 msgid "ReCaptcha private key"
-msgstr ""
+msgstr "Приватний ключ ReCaptcha"
 
 #: kallithea/templates/admin/settings/settings_global.html:43
 msgid ""
 "Private key for reCaptcha system. Setting this value will enable captcha "
 "on registration."
 msgstr ""
+"Приватний ключ для системи reCaptcha. Встановлення цього значення "
+"дозволить вмикнути капчу при реєстрації."
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 msgid "Save Settings"
-msgstr ""
+msgstr "Зберегти налаштування"
 
 #: kallithea/templates/admin/settings/settings_hooks.html:3
 msgid "Built-in Mercurial Hooks (Read-Only)"
-msgstr ""
+msgstr "Вбудовані хуки Mercurial (лише для читання)"
 
 #: kallithea/templates/admin/settings/settings_hooks.html:17
 msgid "Custom Hooks"
-msgstr ""
+msgstr "Користувацькі хуки"
 
 #: kallithea/templates/admin/settings/settings_hooks.html:18
 msgid ""
@@ -3363,43 +3422,50 @@
 
 #: kallithea/templates/admin/settings/settings_hooks.html:60
 msgid "Failed to remove hook"
-msgstr ""
+msgstr "Не вдалося видалити хук"
 
 #: kallithea/templates/admin/settings/settings_mapping.html:4
 msgid "Rescan options"
-msgstr ""
+msgstr "Параметри пересканування"
 
 #: kallithea/templates/admin/settings/settings_mapping.html:9
 msgid "Delete records of missing repositories"
-msgstr ""
+msgstr "Видалення записів відсутніх репозиторіїв"
 
 #: kallithea/templates/admin/settings/settings_mapping.html:12
 msgid ""
 "Check this option to remove all comments, pull requests and other records "
 "related to repositories that no longer exist in the filesystem."
 msgstr ""
+"Позначте цей пункт, щоб видалити всі коментарі, запити на пул-реквести та "
+"інші записи, пов'язані з репозиторіями, які більше не існують в файловій "
+"системі."
 
 #: kallithea/templates/admin/settings/settings_mapping.html:17
 msgid "Invalidate cache for all repositories"
-msgstr ""
+msgstr "Скинути кеш для всіх репозиторіїв"
 
 #: kallithea/templates/admin/settings/settings_mapping.html:20
 msgid "Check this to reload data and clear cache keys for all repositories."
 msgstr ""
+"Відмітьте це, щоб перезавантажити дані і очистити ключі кешу для всіх "
+"репозиторіїв."
 
 #: kallithea/templates/admin/settings/settings_mapping.html:25
 msgid "Install Git hooks"
-msgstr ""
+msgstr "Встановити Git хуки"
 
 #: kallithea/templates/admin/settings/settings_mapping.html:28
 msgid ""
 "Verify if Kallithea's Git hooks are installed for each repository. "
 "Current hooks will be updated to the latest version."
 msgstr ""
+"Перевірити, чи є в Git хуки для кожного репозиторію. Поточні хуки буде "
+"оновлено до останньої версії."
 
 #: kallithea/templates/admin/settings/settings_mapping.html:32
 msgid "Overwrite existing Git hooks"
-msgstr ""
+msgstr "Перезаписати існуючі хуки Git"
 
 #: kallithea/templates/admin/settings/settings_mapping.html:35
 msgid ""
@@ -3407,118 +3473,107 @@
 "not seem to come from Kallithea. WARNING: This operation will destroy any "
 "custom git hooks you may have deployed by hand!"
 msgstr ""
+"При установці Git хуків, перезаписати будь-які існуючі хуки, навіть якщо "
+"вони, здається, не приходять з Каллітея. Увага: ця операція знищить будь-"
+"які користувацькі хуки Git які ви, можливо, розгорнули вручну!"
 
 #: kallithea/templates/admin/settings/settings_mapping.html:41
 msgid "Rescan Repositories"
-msgstr ""
+msgstr "Пересканувати Репозиторії"
 
 #: kallithea/templates/admin/settings/settings_search.html:4
 msgid "Index build option"
-msgstr ""
+msgstr "Параметри побудови індексу"
 
 #: kallithea/templates/admin/settings/settings_search.html:9
 msgid "Build from scratch"
-msgstr ""
+msgstr "Побудувати з нуля"
 
 #: kallithea/templates/admin/settings/settings_search.html:12
 msgid ""
 "This option completely reindexeses all of the repositories for proper "
 "fulltext search capabilities."
 msgstr ""
+"Цей варіант повністю переіндексує репозиторії для правильного "
+"функціонування повнотекстового пошуку."
 
 #: kallithea/templates/admin/settings/settings_search.html:18
 msgid "Reindex"
-msgstr ""
+msgstr "Переіндексувати"
 
 #: kallithea/templates/admin/settings/settings_system.html:2
 msgid "Checking for updates..."
-msgstr ""
+msgstr "Перевірка оновлень..."
 
 #: kallithea/templates/admin/settings/settings_system.html:7
 msgid "Kallithea version"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr ""
+msgstr "Версія Kallithea"
 
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
-msgstr ""
+msgstr "Файл конфігурації Kallithea"
 
 #: kallithea/templates/admin/settings/settings_system.html:9
 msgid "Python version"
-msgstr ""
+msgstr "Версія Python"
 
 #: kallithea/templates/admin/settings/settings_system.html:10
 msgid "Platform"
-msgstr ""
+msgstr "Платформа"
 
 #: kallithea/templates/admin/settings/settings_system.html:11
 msgid "Git version"
-msgstr ""
+msgstr "Git версія"
 
 #: kallithea/templates/admin/settings/settings_system.html:12
 msgid "Git path"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+msgstr "Git шлях"
+
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
-msgstr ""
+msgstr "Пакети Python"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:9
 msgid "Show repository size after push"
-msgstr ""
+msgstr "Показати розмір сховища після push"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
-msgstr ""
+msgid "Update repository after push (hg update)"
+msgstr "Оновлення репозиторію після push (hg update)"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
-msgid "Update repository after push (hg update)"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:33
 msgid "Mercurial extensions"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+msgstr "Mercurial  розширення"
+
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+msgstr "Увімкнути розширення largefiles"
+
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:47
+msgstr "Увімкнути розширення hgsubversion"
+
+#: kallithea/templates/admin/settings/settings_vcs.html:35
 msgid ""
 "Requires hgsubversion library to be installed. Enables cloning of remote "
 "Subversion repositories while converting them to Mercurial."
 msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:59
+"Потрібна установка бібліотеки hgsubversion. Дозволяє клонувати віддалені "
+"сховища Subversion під час перетворення їх у Mercurial."
+
+#: kallithea/templates/admin/settings/settings_vcs.html:47
 msgid "Location of repositories"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+msgstr "Розташування репозиторіїв"
+
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
 msgstr ""
-
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+"Клацніть, щоб розблокувати. Ви повинні перезапустити Kallithea для того, "
+"щоб ця настройка набула чинності."
+
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3526,28 +3581,30 @@
 
 #: kallithea/templates/admin/settings/settings_visual.html:4
 msgid "General"
-msgstr ""
+msgstr "Загальні"
 
 #: kallithea/templates/admin/settings/settings_visual.html:9
 msgid "Use repository extra fields"
-msgstr ""
+msgstr "Використовувати додаткові поля сховища"
 
 #: kallithea/templates/admin/settings/settings_visual.html:12
 msgid "Allows storing additional customized fields per repository."
-msgstr ""
+msgstr "Дозволяє зберігати додаткові настроювані поля для кожного сховища."
 
 #: kallithea/templates/admin/settings/settings_visual.html:17
 msgid "Show Kallithea version"
-msgstr ""
+msgstr "Показати версію Kallithea"
 
 #: kallithea/templates/admin/settings/settings_visual.html:20
 msgid ""
 "Shows or hides a version number of Kallithea displayed in the footer."
 msgstr ""
+"Показує або приховує номер версії Kallithea, відображений у нижньому "
+"колонтитулі."
 
 #: kallithea/templates/admin/settings/settings_visual.html:25
 msgid "Show user Gravatars"
-msgstr ""
+msgstr "Показати Gravatars користувача"
 
 #: kallithea/templates/admin/settings/settings_visual.html:29
 msgid ""
@@ -3567,8 +3624,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-msgid "Clone URL"
+msgid "HTTP Clone URL"
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
@@ -3586,56 +3642,75 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+msgid "SSH Clone URL"
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 msgid "Repository page size"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:57
+msgstr "Розмір сторінки репозиторію"
+
+#: kallithea/templates/admin/settings/settings_visual.html:68
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
 "shown."
 msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:62
+"Кількість елементів, що відображаються на сторінках сховища перед "
+"показаним нумерацією."
+
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:65
+msgstr "Розмір адмін сторінки"
+
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:70
-msgid "Icons"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:75
-msgid "Show public repository icon on repositories"
-msgstr ""
+"Кількість елементів, що відображаються в сітках адміністратора сторінки "
+"до відображення нумерації."
 
 #: kallithea/templates/admin/settings/settings_visual.html:81
+msgid "Icons"
+msgstr "Іконки"
+
+#: kallithea/templates/admin/settings/settings_visual.html:86
+msgid "Show public repository icon on repositories"
+msgstr "Показати піктограму загальнодоступного сховища на сховищах"
+
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:84
+msgstr "Показати значок приватної репозиторію на репозиторіїв"
+
+#: kallithea/templates/admin/settings/settings_visual.html:95
 msgid "Show public/private icons next to repository names."
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:89
+msgstr "Показати публічні/приватні значки поруч із назвами сховищ."
+
+#: kallithea/templates/admin/settings/settings_visual.html:100
 msgid "Meta Tagging"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:94
+msgstr "Мета-теги"
+
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr ""
 
@@ -3796,12 +3871,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr ""
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr ""
 
@@ -3823,7 +3898,7 @@
 #: kallithea/templates/base/base.html:133
 #: kallithea/templates/files/files.html:11
 msgid "Files"
-msgstr ""
+msgstr "Файли"
 
 #: kallithea/templates/base/base.html:135
 #, python-format
@@ -3832,189 +3907,166 @@
 
 #: kallithea/templates/base/base.html:135
 msgid "Pull Requests"
-msgstr ""
+msgstr "Запити Pull Requests"
 
 #: kallithea/templates/base/base.html:146
 #: kallithea/templates/base/base.html:148
 msgid "Options"
-msgstr ""
+msgstr "Параметри"
 
 #: kallithea/templates/base/base.html:156
 #: kallithea/templates/forks/forks_data.html:18
 msgid "Compare Fork"
-msgstr ""
+msgstr "Порівняти Вилки"
 
 #: kallithea/templates/base/base.html:158
 msgid "Compare"
-msgstr ""
+msgstr "Порівняти"
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
-msgstr ""
-
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:174
+msgstr "Пошук"
+
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
-msgstr ""
-
-#: kallithea/templates/base/base.html:175
+msgstr "Слідувати"
+
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
-msgstr ""
-
-#: kallithea/templates/base/base.html:178
+msgstr "Не слідкувати"
+
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
-msgstr ""
-
-#: kallithea/templates/base/base.html:179
+msgstr "Форк"
+
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
-msgstr ""
-
-#: kallithea/templates/base/base.html:191
+msgstr "Створити Pull-Запит"
+
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
-msgstr ""
-
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+msgstr "Переключитися на"
+
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
-msgstr ""
-
+msgstr "Збігів не знайдено"
+
+#: kallithea/templates/base/base.html:289
+msgid "Show recent activity"
+msgstr "Показати недавню активність"
+
+#: kallithea/templates/base/base.html:295
 #: kallithea/templates/base/base.html:296
-msgid "Show recent activity"
+msgid "Public journal"
+msgstr "Публічний журнал"
+
+#: kallithea/templates/base/base.html:301
+msgid "Show public gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
-msgid "Public journal"
+msgid "Gists"
+msgstr "Gists"
+
+#: kallithea/templates/base/base.html:306
+msgid "All Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:308
-msgid "Show public gists"
+msgid "My Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:309
-msgid "Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:313
-msgid "All Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:315
-msgid "My Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:316
 msgid "My Private Gists"
 msgstr ""
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
-msgstr ""
-
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+msgstr "Пошук в репозиторіях"
+
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 msgid "My Pull Requests"
 msgstr ""
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr ""
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 msgid "Login to Your Account"
-msgstr ""
-
-#: kallithea/templates/base/base.html:379
+msgstr "Увійти в свій аккаунт"
+
+#: kallithea/templates/base/base.html:372
 msgid "Forgot password?"
-msgstr ""
-
-#: kallithea/templates/base/base.html:383
+msgstr "Забули пароль?"
+
+#: kallithea/templates/base/base.html:376
 msgid "Don't have an account?"
-msgstr ""
-
-#: kallithea/templates/base/base.html:400
+msgstr "Не маєте облікового запису?"
+
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
-msgstr ""
-
-#: kallithea/templates/base/base.html:524
+msgstr "Вийти"
+
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-msgid "Inherit defaults"
-msgstr ""
+msgid "Create repositories"
+msgstr "Створення репозиторіїв"
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-msgid "default permissions"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:37
+msgstr "Створення груп користувачів"
+
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 
 #: kallithea/templates/base/perms_summary.html:13
 #: kallithea/templates/changelog/changelog.html:41
 msgid "Show"
-msgstr ""
+msgstr "Показати"
 
 #: kallithea/templates/base/perms_summary.html:22
 msgid "No permissions defined yet"
-msgstr ""
+msgstr "Ще не визначено жодних дозволів"
 
 #: kallithea/templates/base/perms_summary.html:30
 #: kallithea/templates/base/perms_summary.html:55
 msgid "Permission"
-msgstr ""
+msgstr "Права"
 
 #: kallithea/templates/base/perms_summary.html:32
 #: kallithea/templates/base/perms_summary.html:57
 msgid "Edit Permission"
-msgstr ""
+msgstr "Змінити права"
 
 #: kallithea/templates/base/perms_summary.html:92
 msgid "No permission defined"
@@ -4022,20 +4074,20 @@
 
 #: kallithea/templates/base/root.html:28
 msgid "Retry"
-msgstr ""
+msgstr "Повторити"
 
 #: kallithea/templates/base/root.html:29
 #: kallithea/templates/changeset/changeset_file_comment.html:65
 msgid "Submitting ..."
-msgstr ""
+msgstr "Надсилання…"
 
 #: kallithea/templates/base/root.html:30
 msgid "Unable to post"
-msgstr ""
+msgstr "Не вдається опублікувати"
 
 #: kallithea/templates/base/root.html:31
 msgid "Add Another Comment"
-msgstr ""
+msgstr "Додати ще один коментар"
 
 #: kallithea/templates/base/root.html:32
 msgid "Stop following this repository"
@@ -4047,23 +4099,23 @@
 
 #: kallithea/templates/base/root.html:34
 msgid "Group"
-msgstr ""
+msgstr "Група"
 
 #: kallithea/templates/base/root.html:35
 msgid "Loading ..."
-msgstr ""
+msgstr "Завантаження..."
 
 #: kallithea/templates/base/root.html:36
 msgid "loading ..."
-msgstr ""
+msgstr "завантаження..."
 
 #: kallithea/templates/base/root.html:37
 msgid "Search truncated"
-msgstr ""
+msgstr "Пошук усічений"
 
 #: kallithea/templates/base/root.html:38
 msgid "No matching files"
-msgstr ""
+msgstr "Немає відповідних файлів"
 
 #: kallithea/templates/base/root.html:39
 msgid "Open New Pull Request from {0}"
@@ -4084,15 +4136,15 @@
 #: kallithea/templates/base/root.html:43
 #: kallithea/templates/changeset/diff_block.html:7
 msgid "Collapse Diff"
-msgstr ""
+msgstr "Згорнути відмінності"
 
 #: kallithea/templates/base/root.html:44
 msgid "Expand Diff"
-msgstr ""
+msgstr "Розгорнути відмінність"
 
 #: kallithea/templates/base/root.html:45
 msgid "No revisions"
-msgstr ""
+msgstr "Немає змін"
 
 #: kallithea/templates/base/root.html:46
 msgid "Type name of user or member to grant permission"
@@ -4100,7 +4152,7 @@
 
 #: kallithea/templates/base/root.html:47
 msgid "Failed to revoke permission"
-msgstr ""
+msgstr "Не вдалося відкликати дозвіл"
 
 #: kallithea/templates/base/root.html:48
 msgid "Confirm to revoke permission for {0}: {1} ?"
@@ -4109,31 +4161,31 @@
 #: kallithea/templates/base/root.html:51
 #: kallithea/templates/compare/compare_diff.html:108
 msgid "Select changeset"
-msgstr ""
+msgstr "Виберіть набір змін"
 
 #: kallithea/templates/base/root.html:52
 msgid "Specify changeset"
-msgstr ""
+msgstr "Укажіть набір змін"
 
 #: kallithea/templates/base/root.html:53
 msgid "Click to sort ascending"
-msgstr ""
+msgstr "Натисніть для сортування за зростанням"
 
 #: kallithea/templates/base/root.html:54
 msgid "Click to sort descending"
-msgstr ""
+msgstr "Натисніть для сортування за спаданням"
 
 #: kallithea/templates/base/root.html:55
 msgid "No records found."
-msgstr ""
+msgstr "Записів не знайдено."
 
 #: kallithea/templates/base/root.html:56
 msgid "Data error."
-msgstr ""
+msgstr "Помилка даних."
 
 #: kallithea/templates/base/root.html:57
 msgid "Loading..."
-msgstr ""
+msgstr "Завантаження..."
 
 #: kallithea/templates/changelog/changelog.html:8
 #, python-format
@@ -4150,7 +4202,7 @@
 
 #: kallithea/templates/changelog/changelog.html:47
 msgid "Clear selection"
-msgstr ""
+msgstr "Зняти позначення"
 
 #: kallithea/templates/changelog/changelog.html:54
 msgid "Go to tip of repository"
@@ -4174,23 +4226,23 @@
 
 #: kallithea/templates/changelog/changelog.html:221
 msgid "There are no changes yet"
-msgstr ""
+msgstr "Поки що немає змін"
 
 #: kallithea/templates/changelog/changelog_details.html:4
 #: kallithea/templates/changeset/changeset.html:77
 msgid "Removed"
-msgstr ""
+msgstr "Вилучено"
 
 #: kallithea/templates/changelog/changelog_details.html:5
 #: kallithea/templates/changeset/changeset.html:78
 msgid "Changed"
-msgstr ""
+msgstr "Змінено"
 
 #: kallithea/templates/changelog/changelog_details.html:6
 #: kallithea/templates/changeset/changeset.html:79
 #: kallithea/templates/changeset/diff_block.html:38
 msgid "Added"
-msgstr ""
+msgstr "Додано"
 
 #: kallithea/templates/changelog/changelog_details.html:8
 #: kallithea/templates/changelog/changelog_details.html:9
@@ -4228,19 +4280,19 @@
 
 #: kallithea/templates/changelog/changelog_table.html:60
 msgid "Expand commit message"
-msgstr ""
+msgstr "Розгорнути повідомлення про фіксацію"
 
 #: kallithea/templates/changelog/changelog_table.html:76
 #, python-format
 msgid "%s comments"
-msgstr ""
+msgstr "%s коментарів"
 
 #: kallithea/templates/changelog/changelog_table.html:80
 #: kallithea/templates/changeset/changeset.html:63
 #: kallithea/templates/changeset/changeset_range.html:84
 #, python-format
 msgid "Bookmark %s"
-msgstr ""
+msgstr "Закладка %s"
 
 #: kallithea/templates/changelog/changelog_table.html:83
 #: kallithea/templates/changeset/changeset.html:67
@@ -4248,23 +4300,23 @@
 #: kallithea/templates/pullrequests/pullrequest_show.html:165
 #, python-format
 msgid "Tag %s"
-msgstr ""
+msgstr "Тег %s"
 
 #: kallithea/templates/changelog/changelog_table.html:102
 #: kallithea/templates/changeset/changeset.html:71
 #: kallithea/templates/changeset/changeset_range.html:94
 #, python-format
 msgid "Branch %s"
-msgstr ""
+msgstr "Branch %s"
 
 #: kallithea/templates/changeset/changeset.html:8
 #, python-format
 msgid "%s Changeset"
-msgstr ""
+msgstr "%s Changeset"
 
 #: kallithea/templates/changeset/changeset.html:34
 msgid "Changeset status"
-msgstr ""
+msgstr "Стан набору змін"
 
 #: kallithea/templates/changeset/changeset.html:43
 #: kallithea/templates/changeset/diff_block.html:64
@@ -4285,7 +4337,7 @@
 #: kallithea/templates/changeset/changeset.html:59
 #: kallithea/templates/changeset/changeset_range.html:80
 msgid "Merge"
-msgstr ""
+msgstr "Злити"
 
 #: kallithea/templates/changeset/changeset.html:96
 msgid "Grafted from:"
@@ -4297,7 +4349,7 @@
 
 #: kallithea/templates/changeset/changeset.html:108
 msgid "Replaced by:"
-msgstr ""
+msgstr "Замінено на:"
 
 #: kallithea/templates/changeset/changeset.html:122
 msgid "Preceded by:"
@@ -4329,11 +4381,11 @@
 #: kallithea/templates/pullrequests/pullrequest_show.html:309
 #: kallithea/templates/pullrequests/pullrequest_show.html:333
 msgid "Show full diff anyway"
-msgstr ""
+msgstr "Все одно Відображати всі відмінності"
 
 #: kallithea/templates/changeset/changeset_file_comment.html:20
 msgid "comment"
-msgstr ""
+msgstr "коментар"
 
 #: kallithea/templates/changeset/changeset_file_comment.html:21
 msgid "on pull request"
@@ -4341,7 +4393,7 @@
 
 #: kallithea/templates/changeset/changeset_file_comment.html:22
 msgid "No title"
-msgstr ""
+msgstr "Без назви"
 
 #: kallithea/templates/changeset/changeset_file_comment.html:24
 msgid "on this changeset"
@@ -4607,10 +4659,8 @@
 msgstr ""
 
 #: kallithea/templates/email_templates/comment.html:27
-#, fuzzy
-#| msgid "Latest Changes"
 msgid "Status change:"
-msgstr "Останні зміни"
+msgstr "Зміна статусу:"
 
 #: kallithea/templates/email_templates/comment.html:33
 msgid "The pull request has been closed."
@@ -4707,7 +4757,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr ""
@@ -4719,7 +4769,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr ""
 
@@ -4771,7 +4821,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr ""
 
@@ -4900,8 +4950,8 @@
 msgstr ""
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr ""
 
@@ -4952,8 +5002,8 @@
 msgstr ""
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr ""
 
@@ -5259,9 +5309,9 @@
 msgid "File names"
 msgstr ""
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr ""
 
@@ -5271,20 +5321,20 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr ""
 
@@ -5293,12 +5343,12 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr "файли"
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr "Показати більше"
 
@@ -5312,117 +5362,121 @@
 
 #: kallithea/templates/summary/statistics.html:407
 msgid "files changed"
-msgstr ""
+msgstr "файли змінено"
 
 #: kallithea/templates/summary/statistics.html:408
 msgid "files removed"
-msgstr ""
+msgstr "вилучені файли"
 
 #: kallithea/templates/summary/statistics.html:410
 msgid "commit"
-msgstr ""
+msgstr "Фіксація"
 
 #: kallithea/templates/summary/statistics.html:411
 msgid "file added"
-msgstr ""
+msgstr "файл додано"
 
 #: kallithea/templates/summary/statistics.html:412
 msgid "file changed"
-msgstr ""
+msgstr "файл змінено"
 
 #: kallithea/templates/summary/statistics.html:413
 msgid "file removed"
-msgstr ""
+msgstr "файл видалено"
 
 #: kallithea/templates/summary/summary.html:5
 #, python-format
 msgid "%s Summary"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:27
+msgstr "Відгалуження з"
+
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr "Клонувати з"
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr ""
-
+#: kallithea/templates/summary/summary.html:54
+msgid "Clone URL"
+msgstr "URL клону"
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+msgid "Use Name"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:98
+msgstr "Популярні файли"
+
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:101
-msgid "There are no downloads yet"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:103
-msgid "Downloads are disabled for this repository"
-msgstr ""
+msgstr "Завантажити"
 
 #: kallithea/templates/summary/summary.html:109
+msgid "There are no downloads yet"
+msgstr "Завантажень немає"
+
+#: kallithea/templates/summary/summary.html:111
+msgid "Downloads are disabled for this repository"
+msgstr "Завантаження відключені для цього репозиторію"
+
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:113
+msgstr "Скачати як zip"
+
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 msgid "With subrepos"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+msgstr "З підрепо"
+
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:175
+msgstr "Канал"
+
+#: kallithea/templates/summary/summary.html:183
 msgid "Latest Changes"
 msgstr "Останні зміни"
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 msgid "Quick Start"
 msgstr "Швидкий старт"
 
-#: kallithea/templates/summary/summary.html:188
+#: kallithea/templates/summary/summary.html:196
 msgid "Add or upload files directly via Kallithea"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:196
-msgid "Push new repository"
-msgstr ""
+msgstr "Додайте або завантажте файли безпосередньо через Kallithea"
 
 #: kallithea/templates/summary/summary.html:204
+msgid "Push new repository"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:222
+msgstr "Існуючий репозиторій?"
+
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr ""
--- a/kallithea/i18n/zh_CN/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/zh_CN/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,17 +1,12 @@
-# Chinese (China) translations for Kallithea.
 # Copyright (C) 2014 RhodeCode GmbH, and others.
 # This file is distributed under the same license as the Kallithea project.
-# Translators:
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2011
-# mikespook <mikespook@gmail.com>, 2012
-# xpol <xpolife@gmail.com>, 2012
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
-"PO-Revision-Date: 2018-04-12 03:35+0000\n"
-"Last-Translator: Pheng Heong Tan <phtan90@gmail.com>\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\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/"
 "kallithea/kallithea/zh_Hans/>\n"
 "Language: zh_CN\n"
@@ -19,18 +14,18 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 2.20\n"
+"X-Generator: Weblate 3.8-dev\n"
 "Generated-By: Babel 1.3\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr "还没有修订集"
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -39,92 +34,92 @@
 msgid "None"
 msgstr "无"
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr "(已关闭)"
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr "显示空白"
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr "忽略空白"
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr "增加差异上下文到 %(num)s 行"
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 #, fuzzy
 #| msgid "Set changeset status"
 msgid "No permission to change status"
 msgstr "设置修订集状态"
 
-#: kallithea/controllers/changeset.py:214
+#: kallithea/controllers/changeset.py:212
 #, fuzzy, python-format
 msgid "Successfully deleted pull request %s"
 msgstr "成功删除拉取请求"
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr "在此代码库内,此修改并不存在"
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, python-format
 msgid "Could not find other repository %s"
 msgstr "找不到那个版本库 %s"
 
-#: kallithea/controllers/compare.py:72
+#: kallithea/controllers/compare.py:74
 msgid "Cannot compare repositories of different types"
 msgstr ""
 
-#: kallithea/controllers/compare.py:244
-msgid "Cannot show empty diff"
-msgstr ""
-
 #: kallithea/controllers/compare.py:246
+msgid "Cannot show empty diff"
+msgstr ""
+
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr ""
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr ""
 
-#: kallithea/controllers/error.py:70
+#: kallithea/controllers/error.py:71
 msgid "No response"
 msgstr "无响应"
 
-#: kallithea/controllers/error.py:71
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr "未知错误"
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr "由于错误的语法,服务器无法对请求进行响应。"
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr "未授权的资源访问"
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr "无权访问该页面"
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr "资源未找到"
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
@@ -145,121 +140,115 @@
 msgid "Changeset was too big and was cut off..."
 msgstr "修订集太大并已被截断..."
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr "%s %s订阅"
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
 msgstr "%s库的修改"
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr "点击这里添加新文件"
 
-#: kallithea/controllers/files.py:93
+#: kallithea/controllers/files.py:86
 #, fuzzy
 #| msgid "There are no files yet. %s"
 msgid "There are no files yet."
-msgstr "这里还没有文件。%s"
-
-#: kallithea/controllers/files.py:193
+msgstr "这里还没有文件。"
+
+#: kallithea/controllers/files.py:186
 #, python-format
 msgid "%s at %s"
 msgstr "%s 在 %s"
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr "版本库由%s于%s锁定"
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 msgid "You can only delete files with revision being a valid branch"
 msgstr "您只能删除有效分支的修订中的文件"
 
-#: kallithea/controllers/files.py:322
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr "删除文件 %s 通过 Kallithea"
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr "成功删除文件 %s"
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr "提交时发生错误"
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 msgid "You can only edit files with revision being a valid branch"
 msgstr "您只能编辑有效分支的修订中的文件"
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr "已编辑文件 %s 通过 Kallithea"
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr "无变更"
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr "成功提交到%s"
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr "已添加文件通过 Kallithea"
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr "无内容"
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr "无文件名"
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr ""
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr "下载已禁用"
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr "未知版本%s"
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr "空版本库"
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr "未知包类型"
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr "修订集"
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
 msgstr "分支"
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr "标签"
 
@@ -268,11 +257,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr "在复刻版本库%s的时候发生错误"
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr "组"
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -280,184 +269,184 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr "版本库"
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
 msgstr "分支"
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr "已关闭分支"
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr "标签"
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr "书签"
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr "公共日志"
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr "日志"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
 msgstr "验证码错误"
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr "您已成功注册 %s"
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:190
 msgid "A password reset confirmation code has been sent"
 msgstr "密码重置确认码已经发送"
 
-#: kallithea/controllers/login.py:238
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "无效的密码重置令牌"
 
-#: kallithea/controllers/admin/my_account.py:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr "成功更新密码"
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr "指定的审核者 \"%s\" 无效"
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr "%s (已关闭)"
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr "修订集"
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr "特殊"
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr "同等分支"
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr "书签"
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr "创建拉取请求出错:%s"
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr "创建拉取请求时发生错误"
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr "成功提交拉取请求"
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 #, fuzzy
 #| msgid "Pull request update created"
 msgid "New pull request iteration created"
 msgstr "拉取请求更新已创建"
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr "无描述"
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
 msgstr "拉取请求已更新"
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr "成功删除拉取请求"
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, fuzzy, python-format
 #| msgid "Changeset for %s %s not found in %s"
 msgid "Revision %s not found in %s"
 msgstr "未找到修订集"
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, fuzzy, python-format
 #| msgid "No changesets found for updating this pull request."
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr "没有找到更新此拉取请求的修订集。"
 
-#: kallithea/controllers/pullrequests.py:522
+#: kallithea/controllers/pullrequests.py:520
 #, python-format
 msgid "This pull request has already been merged to %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:524
+#: kallithea/controllers/pullrequests.py:522
 msgid "This pull request has been closed and can not be updated."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, python-format
 msgid "The following additional changes are available on %s:"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 #, fuzzy
 #| msgid "No changesets found for updating this pull request."
 msgid "No additional changesets found for iterating on this pull request."
 msgstr "没有找到更新此拉取请求的修订集。"
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 msgid "Git pull requests don't support iterating yet."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, fuzzy, python-format
 #| msgid "No changesets found for updating this pull request."
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
 msgstr "没有找到更新此拉取请求的修订集。"
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 
@@ -473,21 +462,21 @@
 msgid "An error occurred during search operation."
 msgstr "搜索操作期间发生错误。"
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr "数据尚未就绪"
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr "该版本库统计功能已经禁用"
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr "验证设置更新成功"
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr "验证设置更新时发生错误"
 
@@ -499,124 +488,138 @@
 msgid "Error occurred during update of defaults"
 msgstr "默认值更新时发生错误"
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 #, fuzzy
 msgid "Forever"
 msgstr "检视者"
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
+#: kallithea/controllers/admin/gists.py:60
+#: kallithea/controllers/admin/my_account.py:233
 #: kallithea/controllers/admin/users.py:249
 msgid "5 minutes"
 msgstr "5 分钟"
 
-#: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
+#: kallithea/controllers/admin/gists.py:61
+#: kallithea/controllers/admin/my_account.py:234
 #: kallithea/controllers/admin/users.py:250
 msgid "1 hour"
 msgstr "1 小时"
 
-#: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/gists.py:62
+#: kallithea/controllers/admin/my_account.py:235
 #: kallithea/controllers/admin/users.py:251
 msgid "1 day"
 msgstr "1 天"
 
-#: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr "1 个月"
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr "终身"
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr "gist 创建时发生错误"
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr "已删除 gist %s"
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
 msgstr "未修改"
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr "成功更新 gist 内容"
 
-#: kallithea/controllers/admin/gists.py:230
+#: kallithea/controllers/admin/gists.py:233
 msgid "Successfully updated gist data"
 msgstr "成功更新 gist 数据"
 
-#: kallithea/controllers/admin/gists.py:233
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
 msgstr "gist %s 更新时发生错误"
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr "由于是系统帐号,无法编辑该用户"
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr "你的帐号已经更新完成"
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr "用户 %s 更新时发生错误"
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr "用户密码更新时发生错误"
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr "已为用户添加电子邮件 %s"
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr "保存电子邮件时发生错误"
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr "成功删除用户电子邮件"
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr "API 密钥创建成功"
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr "API 密钥重置成功"
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr "API 密钥删除成功"
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, fuzzy, python-format
+#| msgid "API key successfully created"
+msgid "SSH key %s successfully added"
+msgstr "API 密钥创建成功"
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+#, fuzzy
+#| msgid "API key successfully deleted"
+msgid "SSH key successfully deleted"
+msgstr "API 密钥删除成功"
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -624,9 +627,9 @@
 msgid "Read"
 msgstr "读"
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -634,9 +637,9 @@
 msgid "Write"
 msgstr "写"
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -659,365 +662,348 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr "管理"
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:50
 msgid "Disabled"
 msgstr "停用"
 
-#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:80
 msgid "Allowed with manual account activation"
 msgstr "已允许手动激活账号"
 
-#: kallithea/controllers/admin/permissions.py:80
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr "已允许自动激活账号"
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr "外部账号手动激活"
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr "外部账号自动激活"
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr "启用"
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr "全局权限更新成功"
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr "权限更新时发生错误"
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr "这个组内有%s个版本库因而无法删除"
 
-#: kallithea/controllers/admin/repo_groups.py:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "版本库%s成功更新"
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, fuzzy, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr "无法删除%s因为它还有其他分复刻本库"
 
-#: kallithea/controllers/admin/repos.py:290
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr "在删除%s的时候发生错误"
 
-#: kallithea/controllers/admin/repos.py:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:390
+#: kallithea/controllers/admin/repos.py:391
 #, 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:401
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr "成功更新在公共日志中的可见性"
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 msgid "An error occurred during setting this repository in public journal"
 msgstr "设置版本库到公共日志时发生错误"
 
-#: kallithea/controllers/admin/repos.py:466
+#: kallithea/controllers/admin/repos.py:468
 msgid "Nothing"
 msgstr "无"
 
-#: kallithea/controllers/admin/repos.py:468
+#: kallithea/controllers/admin/repos.py:470
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr "成功将版本库%s标记为复刻自%s"
 
-#: kallithea/controllers/admin/repos.py:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr "在搜索操作中发生错误"
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-#, fuzzy
-msgid "Repository has been locked"
-msgstr "版本库未锁定"
+#: kallithea/controllers/admin/repos.py:490
+msgid "Cache invalidation successful"
+msgstr ""
 
 #: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-#, fuzzy
-msgid "Repository has been unlocked"
-msgstr "版本库未锁定"
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr "解锁时发生错误"
-
-#: kallithea/controllers/admin/repos.py:528
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:532
 msgid "An error occurred during cache invalidation"
 msgstr "清除缓存时发生错误"
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr "成功拉取自远程路径"
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 msgid "An error occurred during pull from remote location"
 msgstr "从远程路径拉取时发生错误"
 
-#: kallithea/controllers/admin/repos.py:579
+#: kallithea/controllers/admin/repos.py:541
 msgid "An error occurred during deletion of repository stats"
 msgstr "删除版本库统计时发生错误"
 
-#: kallithea/controllers/admin/settings.py:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr "成功更新版本控制系统设置"
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:180
+#: kallithea/controllers/admin/settings.py:176
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:192
+#: kallithea/controllers/admin/settings.py:188
 #, fuzzy, python-format
 msgid "Invalidated %s repositories"
 msgstr "清除版本库缓存"
 
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr "更新应用设置"
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr "成功更新可视化设置"
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 #, fuzzy
 #| msgid "No data ready yet"
 msgid "Hook already exists"
 msgstr "数据尚未就绪"
 
-#: kallithea/controllers/admin/settings.py:360
+#: kallithea/controllers/admin/settings.py:357
 msgid "Builtin hooks are read-only. Please use another hook name."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:363
+#: kallithea/controllers/admin/settings.py:360
 msgid "Added new hook"
 msgstr "新建钩子"
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr "更新钩子"
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr "Whoosh重新索引任务调度"
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
+#: kallithea/controllers/admin/user_groups.py:212
+msgid "Successfully deleted user group"
+msgstr ""
+
 #: kallithea/controllers/admin/user_groups.py:217
-msgid "Successfully deleted user group"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:222
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr "保存权限时发生错误"
 
@@ -1047,219 +1033,221 @@
 msgid "The default user cannot be edited"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 msgid "You need to be a registered user to perform this action"
 msgstr "必须是注册用户才能进行此操作"
 
-#: kallithea/lib/auth.py:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr "必须登录才能访问该页面"
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr ""
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr ""
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, fuzzy, python-format
 msgid "Changeset for %s %s not found in %s"
 msgstr "未找到修订集"
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+#, fuzzy
+#| msgid "Your account is disabled"
+msgid "SSH access is disabled."
+msgstr "该帐号已被禁用"
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr ""
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr "修订集过大并已被截断,使用差异菜单查看此差异"
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr "未发现差异"
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr "已经删除分支%s"
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr "创建标签%s"
 
-#: kallithea/lib/helpers.py:625
+#: kallithea/lib/helpers.py:666
 #, fuzzy, python-format
 msgid "Changeset %s not found"
 msgstr "未找到修订集"
 
-#: kallithea/lib/helpers.py:674
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr "显示所有合并的修订集 %s->%s"
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 #, fuzzy
 msgid "Compare view"
 msgstr "比较显示"
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr "还有"
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr "%s个"
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "修订"
 
-#: kallithea/lib/helpers.py:725
+#: kallithea/lib/helpers.py:766
 #, fuzzy, python-format
 msgid "Fork name %s"
 msgstr "复刻名称%s"
 
-#: kallithea/lib/helpers.py:746
+#: kallithea/lib/helpers.py:787
 #, fuzzy, python-format
 msgid "Pull request %s"
 msgstr "拉取请求#%s"
 
-#: kallithea/lib/helpers.py:756
+#: kallithea/lib/helpers.py:797
 msgid "[deleted] repository"
 msgstr "[删除]版本库"
 
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
 msgid "[created] repository"
 msgstr "[创建]版本库"
 
-#: kallithea/lib/helpers.py:760
+#: kallithea/lib/helpers.py:801
 msgid "[created] repository as fork"
 msgstr "[创建]复刻版本库"
 
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
 msgid "[forked] repository"
 msgstr "[复刻]版本库"
 
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
 msgid "[updated] repository"
 msgstr "[更新]版本库"
 
-#: kallithea/lib/helpers.py:766
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr "[删除]版本库"
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr "[创建]用户"
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr "[更新]用户"
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr "[评论]了版本库中的修订"
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr "[评论]拉取请求"
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr "[关闭] 拉取请求"
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr "[推送]到"
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr "[通过Kallithea提交]到版本库"
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr "[远程拉取]到版本库"
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr "[拉取]自"
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr "[开始关注]版本库"
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr "[停止关注]版本库"
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr " 还有%s个"
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr "无文件"
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1269,63 +1257,90 @@
 "版本库%s没有映射到数据库,可能是从文件系统创建或者重命名,请重启Kallithea"
 "以重新扫描版本库"
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] "%d年"
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] "%d月"
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] "%d天"
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] "%d时"
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] "%d分"
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] "%d秒"
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr "%s"
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr "%s前"
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr "%s零%s"
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr "%s零%s前"
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr "刚才"
 
@@ -1334,143 +1349,143 @@
 msgid "on line %s"
 msgstr "在%s行"
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr "[提及]"
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr "Kallithea 管理员"
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1706
+#: kallithea/model/db.py:1640
 #, fuzzy
 msgid "Default user has read access to new repositories"
 msgstr "未授权的资源访问"
 
-#: kallithea/model/db.py:1707
+#: kallithea/model/db.py:1641
 #, fuzzy
 msgid "Default user has write access to new repositories"
 msgstr "未授权的资源访问"
 
-#: kallithea/model/db.py:1708
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1711
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 #, fuzzy
 msgid "Only admins can create repository groups"
 msgstr "没有在该版本库组中创建版本库的权限"
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 #, fuzzy
 msgid "Non-admins can create repository groups"
 msgstr "没有在该版本库组中创建版本库的权限"
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1730
+#: kallithea/model/db.py:1664
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1732
+#: kallithea/model/db.py:1666
 #, fuzzy
 msgid "Only admins can fork repositories"
 msgstr "创建版本库"
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 #, fuzzy
 msgid "Non-admins can fork repositories"
 msgstr "创建版本库"
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 #, fuzzy
 msgid "Not reviewed"
 msgstr "未检视"
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 #, fuzzy
 msgid "Under review"
 msgstr "检视中"
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 #, fuzzy
 #| msgid "Approved"
 msgid "Not approved"
 msgstr "已批准"
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr "已批准"
 
@@ -1496,7 +1511,7 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, fuzzy, python-format
 #| msgid "[Comment] %(repo_name)s changeset %(short_id)s on %(branch)s"
 msgid ""
@@ -1504,104 +1519,119 @@
 "%(branch)s"
 msgstr "[评论] %(repo_name)s 修订集 %(short_id)s 在 %(branch)s"
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, fuzzy, python-format
 msgid "New user %(new_username)s registered"
 msgstr "用户名称 %(new_username)s 无效"
 
-#: kallithea/model/notification.py:170
+#: kallithea/model/notification.py:169
 #, 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:171
+#: kallithea/model/notification.py:170
 #, 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:184
+#: kallithea/model/notification.py:183
 #, fuzzy
 msgid "Closing"
 msgstr "使用中"
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 #, fuzzy
 #| msgid "Error creating pull request: %s"
 msgid "Cannot create empty pull request"
 msgstr "创建拉取请求出错:%s"
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 #, fuzzy
 #| msgid "Confirm to delete this pull request"
 msgid "You are not authorized to create the pull request"
 msgstr "确认删除拉取请求"
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 #, fuzzy
 #| msgid "Missing changesets since the previous pull request:"
 msgid "Missing changesets since the previous iteration:"
 msgstr "缺少上次拉取请求之后的修订集:"
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, fuzzy, python-format
 #| msgid "New changesets on %s %s since the previous pull request:"
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr "在上次拉取请求之后,在 %s %s 上的新修订集:"
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, python-format
 msgid ""
 "This iteration is based on another %s revision and there is no simple "
 "diff."
 msgstr ""
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, fuzzy, python-format
 #| msgid "New changesets on %s %s since the previous pull request:"
 msgid "No changes found on %s %s since previous iteration."
 msgstr "在上次拉取请求之后,在 %s %s 上的新修订集:"
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr "最新tip版本"
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, fuzzy, python-format
+msgid "SSH key %r not found"
+msgstr "未找到修订集"
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 #, fuzzy
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr "由于是系统帐号,无法删除该用户"
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:255
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s repositories and cannot be removed. Switch "
@@ -1610,7 +1640,7 @@
 "由于用户 \"%s\" 拥有版本库%s因而无法删除,请修改版本库所有者或删除版本"
 "库。%s"
 
-#: kallithea/model/user.py:263
+#: kallithea/model/user.py:260
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s repository groups and cannot be removed. Switch "
@@ -1619,7 +1649,7 @@
 "由于用户 \"%s\" 拥有版本库%s因而无法删除,请修改版本库所有者或删除版本"
 "库。%s"
 
-#: kallithea/model/user.py:270
+#: kallithea/model/user.py:267
 #, fuzzy, python-format
 msgid ""
 "User \"%s\" still owns %s user groups and cannot be removed. Switch "
@@ -1628,191 +1658,187 @@
 "由于用户 \"%s\" 拥有版本库%s因而无法删除,请修改版本库所有者或删除版本"
 "库。%s"
 
-#: kallithea/model/user.py:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 #, fuzzy
 msgid "Password reset notification"
 msgstr "确认密码"
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr "值不能为空"
 
-#: kallithea/model/validators.py:74
+#: kallithea/model/validators.py:72
 #, python-format
 msgid "Username \"%(username)s\" already exists"
 msgstr "用户名称%(username)s已经存在"
 
-#: kallithea/model/validators.py:76
+#: kallithea/model/validators.py:74
 #, fuzzy, python-format
 msgid "Username \"%(username)s\" cannot be used"
 msgstr "用户名称 %(username)s 无效"
 
-#: kallithea/model/validators.py:78
+#: kallithea/model/validators.py:76
 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:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr "用户名称 %(username)s 无效"
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr ""
 
+#: kallithea/model/validators.py:132
+#, python-format
+msgid "User group \"%(usergroup)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:134
-#, python-format
-msgid "User group \"%(usergroup)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:136
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 
-#: kallithea/model/validators.py:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr "不能将这个组作为parent"
 
-#: kallithea/model/validators.py:177
+#: kallithea/model/validators.py:175
 #, python-format
 msgid "Group \"%(group_name)s\" already exists"
 msgstr "组 \"%(group_name)s\" 已经存在"
 
-#: kallithea/model/validators.py:179
+#: kallithea/model/validators.py:177
 #, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr "已经存在名为 \"%(group_name)s\" 的版本库"
 
-#: kallithea/model/validators.py:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr "密码含有无效(非ASCII)字符"
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr "密码不符"
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 #, fuzzy
 msgid "Invalid username or password"
 msgstr "无效密码"
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr "令牌不匹配"
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, fuzzy, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr "版本库名称不能为%(repo)s"
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr "已经存在版本库%(repo)s"
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr "版本库组 \"%(group)s\" 中已经存在版本库 \"%(repo)s\""
 
-#: kallithea/model/validators.py:333
+#: kallithea/model/validators.py:318
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:419
+#: kallithea/model/validators.py:404
 #, fuzzy
 msgid "Invalid repository URL"
 msgstr "私有版本库"
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:430
 msgid "Fork has to be the same type as parent"
 msgstr "复刻版本库必须和父版本库类型相同"
 
-#: kallithea/model/validators.py:460
+#: kallithea/model/validators.py:445
 msgid "You don't have permissions to create repository in this group"
 msgstr "没有在该版本库组中创建版本库的权限"
 
-#: kallithea/model/validators.py:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:512
+#: kallithea/model/validators.py:497
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:552
+#: kallithea/model/validators.py:537
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr "不是一个合法的路径"
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 #, fuzzy
 msgid "This email address is already in use"
 msgstr "该邮件地址已被使用"
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, fuzzy, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr "邮件地址\"%(email)s\"不存在"
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 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:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:765
+#: kallithea/model/validators.py:750
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1853,24 +1879,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr "描述"
 
@@ -1887,7 +1919,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1895,11 +1927,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr "所有者"
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr "登录"
@@ -1914,7 +1946,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1922,7 +1954,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr "密码"
@@ -2084,10 +2116,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr "操作"
@@ -2136,22 +2170,22 @@
 msgstr ""
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr "保存"
 
@@ -2170,14 +2204,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr "私有版本库"
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2185,36 +2219,25 @@
 msgstr "私有版本库只对成员可见。"
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr "启用统计"
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr "启用概况页面上的统计窗口。"
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr "启用下载"
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr "启用概况页面上的下载菜单。"
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr "启用锁定"
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr "启用版本库的拉取锁定。"
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2261,8 +2284,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 #, fuzzy
 msgid "Never"
 msgstr "检视者"
@@ -2296,7 +2321,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr ""
 
@@ -2332,23 +2357,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2376,7 +2403,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2436,7 +2463,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr "我的账户"
 
@@ -2450,26 +2477,31 @@
 msgid "Email Addresses"
 msgstr "增加邮箱"
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
+#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/users/user_edit.html:32
+msgid "SSH Keys"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
 msgid "API Keys"
 msgstr ""
 
-#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/my_account/my_account.html:32
 #, fuzzy
 msgid "Owned Repositories"
 msgstr "版本库"
 
-#: kallithea/templates/admin/my_account/my_account.html:30
+#: kallithea/templates/admin/my_account/my_account.html:33
 #: kallithea/templates/journal/journal.html:33
 #, fuzzy
 msgid "Watched Repositories"
 msgstr "创建版本库"
 
-#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 #, fuzzy
 msgid "Show Permissions"
 msgstr "拷贝权限"
@@ -2497,7 +2529,9 @@
 msgstr "确认删除用户:%s"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 #, fuzzy
 msgid "Remove"
 msgstr "移除"
@@ -2514,12 +2548,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr "增加"
 
@@ -2623,6 +2659,46 @@
 msgid "Name"
 msgstr "名称"
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+#, fuzzy
+#| msgid "Last Name"
+msgid "Last Used"
+msgstr "姓"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, fuzzy, python-format
+msgid "Confirm to remove this SSH key: %s"
+msgstr "确认删除用户:%s"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+msgid "New SSH key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+#, fuzzy
+#| msgid "Public repository"
+msgid "Public key"
+msgstr "公共版本库"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 #, fuzzy
 msgid "Repositories You are Watching"
@@ -2641,7 +2717,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr ""
 
@@ -2680,7 +2756,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2842,7 +2918,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr ""
 
@@ -2954,17 +3030,11 @@
 "private repositories and other groups if selected."
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr "启用组的拉取锁定。这个选项将应用到组内的其他组和版本库"
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 #, fuzzy
 msgid "Confirm to delete this group"
 msgstr "确认删除用户:%s"
@@ -2997,14 +3067,14 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
 msgstr "保持简短。用README文件来写更长的描述。"
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr "可选的选择一个组将版本库放到其中。"
@@ -3014,7 +3084,7 @@
 msgstr "要创建的版本库类型。"
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr "默认修订"
@@ -3066,8 +3136,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr "统计"
 
@@ -3106,74 +3176,32 @@
 "public journal."
 msgstr "任何人都可以在公共日志上看到这个版本库上的所有动作"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-#, fuzzy
-msgid "Change Locking"
-msgstr "启用锁定"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
-#, fuzzy
-msgid "Confirm to unlock repository."
-msgstr "确认解锁版本库"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-#, fuzzy
-msgid "Unlock Repository"
-msgstr "公共版本库"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-#, fuzzy
-msgid "Confirm to lock repository."
-msgstr "确认锁定版本库"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-#, fuzzy
-msgid "Lock Repository"
-msgstr "公共版本库"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr "版本库未锁定"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
 #: kallithea/templates/data_table/_dt_elements.html:68
 #, python-format
 msgid "Confirm to delete this repository: %s"
 msgstr "确认删除版本库:%s"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:48
 #, fuzzy
 msgid "Delete this Repository"
 msgstr "[删除]版本库"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
 msgstr[0] ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3280,20 +3308,12 @@
 msgid "This repository does not have a remote repository URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-#, fuzzy
-msgid "Permanent Repository ID"
+#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#, fuzzy
+msgid "Permanent URL"
 msgstr "私有版本库"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3303,32 +3323,32 @@
 "other cases that you need to hardcode the URL into a 3rd party service."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 #, fuzzy
 msgid "Remote repository"
 msgstr "[创建]版本库"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 #, fuzzy
 msgid "Repository URL"
 msgstr "版本库"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr "文件浏览、下载、whoosh和README的默认修订版本"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr "修改这个版本库的所有者。"
 
@@ -3441,8 +3461,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 #, fuzzy
 msgid "Save Settings"
 msgstr "保存设置"
@@ -3541,10 +3561,6 @@
 msgid "Kallithea version"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr ""
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr ""
@@ -3566,15 +3582,7 @@
 msgid "Git path"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr ""
 
@@ -3583,48 +3591,40 @@
 msgstr "推送后显示版本库大小"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
-msgstr "记录用户推送命令"
+msgid "Update repository after push (hg update)"
+msgstr "推送后更新版本库(hg update)"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr "记录用户拉取命令"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
-msgid "Update repository after push (hg update)"
-msgstr "推送后更新版本库(hg update)"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:33
 #, fuzzy
 msgid "Mercurial extensions"
 msgstr "Mercurial扩展"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:47
+#: kallithea/templates/admin/settings/settings_vcs.html:35
 msgid ""
 "Requires hgsubversion library to be installed. Enables cloning of remote "
 "Subversion repositories while converting them to Mercurial."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:59
+#: kallithea/templates/admin/settings/settings_vcs.html:47
 #, fuzzy
 msgid "Location of repositories"
 msgstr "创建版本库"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3673,9 +3673,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
-#, fuzzy
-msgid "Clone URL"
+#, fuzzy
+msgid "HTTP Clone URL"
 msgstr "克隆地址"
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
@@ -3693,60 +3692,76 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+#, fuzzy
+msgid "SSH Clone URL"
+msgstr "克隆地址"
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 #, fuzzy
 #| msgid "repositories"
 msgid "Repository page size"
 msgstr "版本库"
 
-#: kallithea/templates/admin/settings/settings_visual.html:57
+#: kallithea/templates/admin/settings/settings_visual.html:68
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:62
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:70
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr "图标"
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
 msgstr "显示公共版本库图标"
 
-#: kallithea/templates/admin/settings/settings_visual.html:81
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr "显示私有版本库图标"
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 #, fuzzy
 msgid "Show public/private icons next to repository names."
 msgstr "显示公共版本库图标"
 
-#: kallithea/templates/admin/settings/settings_visual.html:89
+#: kallithea/templates/admin/settings/settings_visual.html:100
 #, fuzzy
 msgid "Meta Tagging"
 msgstr "元标记"
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr ""
 
@@ -3910,12 +3925,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr "Mercurial版本库"
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr "Git版本库"
 
@@ -3965,160 +3980,134 @@
 msgstr "比较显示"
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr "搜索"
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr "复刻"
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr ""
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr ""
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr ""
 
+#: kallithea/templates/base/base.html:289
+msgid "Show recent activity"
+msgstr ""
+
+#: kallithea/templates/base/base.html:295
 #: kallithea/templates/base/base.html:296
-msgid "Show recent activity"
+msgid "Public journal"
+msgstr "公共日志"
+
+#: kallithea/templates/base/base.html:301
+msgid "Show public gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
-msgid "Public journal"
-msgstr "公共日志"
+msgid "Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:306
+msgid "All Public Gists"
+msgstr ""
 
 #: kallithea/templates/base/base.html:308
-msgid "Show public gists"
+msgid "My Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:309
-msgid "Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:313
-msgid "All Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:315
-msgid "My Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:316
 msgid "My Private Gists"
 msgstr ""
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr ""
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 #, fuzzy
 msgid "My Pull Requests"
 msgstr "拉取请求"
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr ""
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 #, fuzzy
 msgid "Login to Your Account"
 msgstr "登录"
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 #, fuzzy
 #| msgid "Forgot password ?"
 msgid "Forgot password?"
 msgstr "忘记密码?"
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 #, fuzzy
 #| msgid "Don't have an account ?"
 msgid "Don't have an account?"
 msgstr "还没有帐号?"
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr "退出"
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-#, fuzzy
-msgid "Inherit defaults"
-msgstr "版本库默认设置"
+msgid "Create repositories"
+msgstr "创建版本库"
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-#, fuzzy
-#| msgid "Default permissions"
-msgid "default permissions"
-msgstr "默认权限"
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr "创建版本库"
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr "复刻版本库"
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 
@@ -4874,7 +4863,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr ""
@@ -4886,7 +4875,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr ""
 
@@ -4940,7 +4929,7 @@
 msgstr "加载文件列表..."
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr "大小"
 
@@ -5071,8 +5060,8 @@
 msgstr "%s个关注者"
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr "关注者"
 
@@ -5124,8 +5113,8 @@
 msgstr "%s个复刻"
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr "复刻"
 
@@ -5452,9 +5441,9 @@
 msgid "File names"
 msgstr "文件名"
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr "权限不足"
 
@@ -5464,20 +5453,20 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr ""
 
@@ -5486,12 +5475,12 @@
 msgstr "已收集的统计: "
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr "文件"
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr ""
 
@@ -5532,98 +5521,183 @@
 msgid "%s Summary"
 msgstr "%s概要"
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr "版本库由%s锁定"
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr "版本库未锁定"
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr "复刻自"
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr "克隆自"
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr "按ID显示"
-
+#: kallithea/templates/summary/summary.html:54
+#, fuzzy
+msgid "Clone URL"
+msgstr "克隆地址"
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr "以名字显示"
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+#, fuzzy
+#| msgid "Last Name"
+msgid "Use Name"
+msgstr "姓"
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr "文件趋势图"
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr "下载"
 
-#: kallithea/templates/summary/summary.html:101
+#: kallithea/templates/summary/summary.html:109
 msgid "There are no downloads yet"
 msgstr "无下载"
 
-#: kallithea/templates/summary/summary.html:103
+#: kallithea/templates/summary/summary.html:111
 msgid "Downloads are disabled for this repository"
 msgstr "这个版本库的下载已经禁用"
 
-#: kallithea/templates/summary/summary.html:109
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr "zip打包下载"
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr "勾选以下载包含子版本库的压缩包"
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 #, fuzzy
 msgid "With subrepos"
 msgstr "包括子版本库"
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 #, fuzzy
 msgid "Latest Changes"
 msgstr "文件已更改"
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 #, fuzzy
 msgid "Quick Start"
 msgstr "快速入门"
 
-#: kallithea/templates/summary/summary.html:188
+#: kallithea/templates/summary/summary.html:196
 msgid "Add or upload files directly via Kallithea"
 msgstr "通过Kallithea直接添加或者上传文件"
 
-#: kallithea/templates/summary/summary.html:196
+#: kallithea/templates/summary/summary.html:204
 #, fuzzy
 msgid "Push new repository"
 msgstr "推送新版本库"
 
-#: kallithea/templates/summary/summary.html:204
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr "已有版本库?"
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr "下载%s为%s包"
 
+#~ msgid "This repository has been locked by %s on %s"
+#~ msgstr "版本库由%s于%s锁定"
+
+#, fuzzy
+#~ msgid "Repository has been locked"
+#~ msgstr "版本库未锁定"
+
+#, fuzzy
+#~ msgid "Repository has been unlocked"
+#~ msgstr "版本库未锁定"
+
+#~ msgid "An error occurred during unlocking"
+#~ msgstr "解锁时发生错误"
+
+#~ msgid "Token mismatch"
+#~ msgstr "令牌不匹配"
+
+#~ msgid "Enable locking"
+#~ msgstr "启用锁定"
+
+#~ msgid "Enable lock-by-pulling on repository."
+#~ msgstr "启用版本库的拉取锁定。"
+
+#~ msgid ""
+#~ "Enable lock-by-pulling on group. This option will be applied to all "
+#~ "other groups and repositories inside"
+#~ msgstr "启用组的拉取锁定。这个选项将应用到组内的其他组和版本库"
+
+#, fuzzy
+#~ msgid "Change Locking"
+#~ msgstr "启用锁定"
+
+#, fuzzy
+#~ msgid "Confirm to unlock repository."
+#~ msgstr "确认解锁版本库"
+
+#, fuzzy
+#~ msgid "Unlock Repository"
+#~ msgstr "公共版本库"
+
+#, fuzzy
+#~ msgid "Confirm to lock repository."
+#~ msgstr "确认锁定版本库"
+
+#, fuzzy
+#~ msgid "Lock Repository"
+#~ msgstr "公共版本库"
+
+#~ msgid "Repository is not locked"
+#~ msgstr "版本库未锁定"
+
+#~ msgid "Log user push commands"
+#~ msgstr "记录用户推送命令"
+
+#~ msgid "Log user pull commands"
+#~ msgstr "记录用户拉取命令"
+
+#, fuzzy
+#~ msgid "Inherit defaults"
+#~ msgstr "版本库默认设置"
+
+#, fuzzy
+#~| msgid "Default permissions"
+#~ msgid "default permissions"
+#~ msgstr "默认权限"
+
+#~ msgid "Repository locked by %s"
+#~ msgstr "版本库由%s锁定"
+
+#~ msgid "Repository unlocked"
+#~ msgstr "版本库未锁定"
+
+#~ msgid "Show by ID"
+#~ msgstr "按ID显示"
+
+#~ msgid "Show by Name"
+#~ msgstr "以名字显示"
+
 #~ msgid "There is no index to search in. Please run whoosh indexer"
 #~ msgstr "没有索引用于搜索。请运行whoosh索引器"
 
@@ -5766,9 +5840,6 @@
 #~ msgid "invalid user name"
 #~ msgstr "无效用户名"
 
-#~ msgid "Your account is disabled"
-#~ msgstr "该帐号已被禁用"
-
 #~ msgid "invalid clone URL"
 #~ msgstr "无效的克隆地址"
 
--- a/kallithea/i18n/zh_TW/LC_MESSAGES/kallithea.po	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/i18n/zh_TW/LC_MESSAGES/kallithea.po	Sun Jan 05 04:07:51 2020 +0100
@@ -1,13 +1,10 @@
-# Chinese (Taiwan) translations for Kallithea.
 # Copyright (C) 2014 RhodeCode GmbH, and others.
 # This file is distributed under the same license as the Kallithea project.
-# Translators:
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2011
 msgid ""
 msgstr ""
 "Project-Id-Version: Kallithea 0.3\n"
 "Report-Msgid-Bugs-To: translations@kallithea-scm.org\n"
-"POT-Creation-Date: 2019-05-04 21:13+0200\n"
+"POT-Creation-Date: 2019-11-14 23:33+0100\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/"
@@ -21,14 +18,14 @@
 "Generated-By: Babel 1.3\n"
 
 #: kallithea/controllers/changelog.py:67
-#: kallithea/controllers/pullrequests.py:252 kallithea/lib/base.py:605
+#: kallithea/controllers/pullrequests.py:250 kallithea/lib/base.py:602
 msgid "There are no changesets yet"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:62
-#: kallithea/controllers/admin/permissions.py:66
-#: kallithea/controllers/admin/permissions.py:70
-#: kallithea/controllers/changelog.py:136
+#: kallithea/controllers/admin/permissions.py:64
+#: kallithea/controllers/admin/permissions.py:68
+#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/changelog.py:137
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:7
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:88
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:7
@@ -37,92 +34,92 @@
 msgid "None"
 msgstr "無"
 
-#: kallithea/controllers/changelog.py:139 kallithea/controllers/files.py:196
+#: kallithea/controllers/changelog.py:140 kallithea/controllers/files.py:189
 msgid "(closed)"
 msgstr "(已關閉)"
 
-#: kallithea/controllers/changeset.py:83
+#: kallithea/controllers/changeset.py:81
 msgid "Show whitespace"
 msgstr "顯示空格"
 
-#: kallithea/controllers/changeset.py:90
-#: kallithea/controllers/changeset.py:97
+#: kallithea/controllers/changeset.py:88
+#: kallithea/controllers/changeset.py:95
 #: kallithea/templates/files/diff_2way.html:55
 msgid "Ignore whitespace"
 msgstr "忽略空格"
 
-#: kallithea/controllers/changeset.py:163
+#: kallithea/controllers/changeset.py:161
 #, python-format
 msgid "Increase diff context to %(num)s lines"
 msgstr "增加 diff 上下文至 %(num)s 行"
 
-#: kallithea/controllers/changeset.py:203
+#: kallithea/controllers/changeset.py:201
 #, fuzzy
 msgid "No permission to change status"
 msgstr "尚未有任何變更"
 
-#: kallithea/controllers/changeset.py:214
+#: kallithea/controllers/changeset.py:212
 #, fuzzy, python-format
 msgid "Successfully deleted pull request %s"
 msgstr "成功遞交至 %s"
 
-#: kallithea/controllers/changeset.py:321 kallithea/controllers/files.py:96
-#: kallithea/controllers/files.py:116 kallithea/controllers/files.py:726
+#: kallithea/controllers/changeset.py:319 kallithea/controllers/files.py:89
+#: kallithea/controllers/files.py:109 kallithea/controllers/files.py:700
 msgid "Such revision does not exist for this repository"
 msgstr ""
 
-#: kallithea/controllers/compare.py:66
+#: kallithea/controllers/compare.py:68
 #, fuzzy, python-format
 #| msgid "Go to tip of repository"
 msgid "Could not find other repository %s"
 msgstr "Git 版本庫"
 
-#: kallithea/controllers/compare.py:72
+#: kallithea/controllers/compare.py:74
 msgid "Cannot compare repositories of different types"
 msgstr ""
 
-#: kallithea/controllers/compare.py:244
-msgid "Cannot show empty diff"
-msgstr ""
-
 #: kallithea/controllers/compare.py:246
+msgid "Cannot show empty diff"
+msgstr ""
+
+#: kallithea/controllers/compare.py:248
 msgid "No ancestor found for merge diff"
 msgstr ""
 
-#: kallithea/controllers/compare.py:250
+#: kallithea/controllers/compare.py:252
 msgid "Multiple merge ancestors found for merge compare"
 msgstr ""
 
-#: kallithea/controllers/compare.py:266
+#: kallithea/controllers/compare.py:268
 msgid "Cannot compare repositories without using common ancestor"
 msgstr ""
 
-#: kallithea/controllers/error.py:70
-msgid "No response"
-msgstr "未回應"
-
 #: kallithea/controllers/error.py:71
+msgid "No response"
+msgstr "未回應"
+
+#: kallithea/controllers/error.py:72
 msgid "Unknown error"
 msgstr ""
 
-#: kallithea/controllers/error.py:84
+#: kallithea/controllers/error.py:85
 msgid ""
 "The request could not be understood by the server due to malformed syntax."
 msgstr ""
 
-#: kallithea/controllers/error.py:87
+#: kallithea/controllers/error.py:88
 msgid "Unauthorized access to resource"
 msgstr ""
 
-#: kallithea/controllers/error.py:89
+#: kallithea/controllers/error.py:90
 msgid "You don't have permission to view this page"
 msgstr "您沒有權限瀏覽這個頁面"
 
-#: kallithea/controllers/error.py:91
+#: kallithea/controllers/error.py:92
 msgid "The resource could not be found"
 msgstr "找不到這個資源"
 
-#: kallithea/controllers/error.py:93
+#: kallithea/controllers/error.py:94
 msgid ""
 "The server encountered an unexpected condition which prevented it from "
 "fulfilling the request."
@@ -143,121 +140,115 @@
 msgid "Changeset was too big and was cut off..."
 msgstr ""
 
-#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:143
+#: kallithea/controllers/feed.py:111 kallithea/controllers/feed.py:140
 #, python-format
 msgid "%s %s feed"
 msgstr ""
 
-#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:145
+#: kallithea/controllers/feed.py:113 kallithea/controllers/feed.py:142
 #, python-format
 msgid "Changes on %s repository"
 msgstr "修改於版本庫 %s"
 
-#: kallithea/controllers/files.py:92
+#: kallithea/controllers/files.py:85
 msgid "Click here to add new file"
 msgstr ""
 
-#: kallithea/controllers/files.py:93
+#: kallithea/controllers/files.py:86
 #, fuzzy
 #| msgid "There are no forks yet"
 msgid "There are no files yet."
 msgstr "尚未有任何 fork"
 
-#: kallithea/controllers/files.py:193
+#: kallithea/controllers/files.py:186
 #, python-format
 msgid "%s at %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:299 kallithea/controllers/files.py:359
-#: kallithea/controllers/files.py:426
-#, python-format
-msgid "This repository has been locked by %s on %s"
-msgstr ""
-
-#: kallithea/controllers/files.py:311
+#: kallithea/controllers/files.py:296
 msgid "You can only delete files with revision being a valid branch"
 msgstr ""
 
-#: kallithea/controllers/files.py:322
+#: kallithea/controllers/files.py:307
 #, python-format
 msgid "Deleted file %s via Kallithea"
 msgstr ""
 
-#: kallithea/controllers/files.py:344
+#: kallithea/controllers/files.py:331
 #, python-format
 msgid "Successfully deleted file %s"
 msgstr ""
 
-#: kallithea/controllers/files.py:348 kallithea/controllers/files.py:414
-#: kallithea/controllers/files.py:495
+#: kallithea/controllers/files.py:335 kallithea/controllers/files.py:394
+#: kallithea/controllers/files.py:469
 msgid "Error occurred during commit"
 msgstr ""
 
-#: kallithea/controllers/files.py:371
+#: kallithea/controllers/files.py:350
 msgid "You can only edit files with revision being a valid branch"
 msgstr ""
 
-#: kallithea/controllers/files.py:385
+#: kallithea/controllers/files.py:364
 #, python-format
 msgid "Edited file %s via Kallithea"
 msgstr ""
 
-#: kallithea/controllers/files.py:401
+#: kallithea/controllers/files.py:380
 msgid "No changes"
 msgstr "沒有修改"
 
-#: kallithea/controllers/files.py:410 kallithea/controllers/files.py:484
+#: kallithea/controllers/files.py:390 kallithea/controllers/files.py:458
 #, python-format
 msgid "Successfully committed to %s"
 msgstr "成功遞交至 %s"
 
-#: kallithea/controllers/files.py:437
+#: kallithea/controllers/files.py:409
 msgid "Added file via Kallithea"
 msgstr ""
 
-#: kallithea/controllers/files.py:458
+#: kallithea/controllers/files.py:430
 msgid "No content"
 msgstr ""
 
-#: kallithea/controllers/files.py:462
+#: kallithea/controllers/files.py:434
 msgid "No filename"
 msgstr ""
 
-#: kallithea/controllers/files.py:487
+#: kallithea/controllers/files.py:461
 msgid "Location must be relative path and must not contain .. in path"
 msgstr ""
 
-#: kallithea/controllers/files.py:519
+#: kallithea/controllers/files.py:493
 msgid "Downloads disabled"
 msgstr ""
 
-#: kallithea/controllers/files.py:530
+#: kallithea/controllers/files.py:504
 #, python-format
 msgid "Unknown revision %s"
 msgstr "未知修訂 %s"
 
-#: kallithea/controllers/files.py:532
+#: kallithea/controllers/files.py:506
 msgid "Empty repository"
 msgstr "空的版本庫"
 
-#: kallithea/controllers/files.py:534
+#: kallithea/controllers/files.py:508
 msgid "Unknown archive type"
 msgstr "未知的存檔類型"
 
-#: kallithea/controllers/files.py:755
+#: kallithea/controllers/files.py:729
 #: kallithea/templates/changeset/changeset_range.html:9
 #: kallithea/templates/email_templates/pull_request.html:64
 #: kallithea/templates/pullrequests/pullrequest.html:84
 msgid "Changesets"
 msgstr "變更"
 
-#: kallithea/controllers/files.py:756
-#: kallithea/controllers/pullrequests.py:184 kallithea/model/scm.py:706
+#: kallithea/controllers/files.py:730
+#: kallithea/controllers/pullrequests.py:182 kallithea/model/scm.py:676
 msgid "Branches"
 msgstr "分支"
 
-#: kallithea/controllers/files.py:757
-#: kallithea/controllers/pullrequests.py:185 kallithea/model/scm.py:717
+#: kallithea/controllers/files.py:731
+#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:687
 msgid "Tags"
 msgstr "標籤"
 
@@ -266,11 +257,11 @@
 msgid "An error occurred during repository forking %s"
 msgstr ""
 
-#: kallithea/controllers/home.py:78
+#: kallithea/controllers/home.py:79
 msgid "Groups"
 msgstr ""
 
-#: kallithea/controllers/home.py:88
+#: kallithea/controllers/home.py:89
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:90
 #: kallithea/templates/admin/repos/repo_add.html:12
 #: kallithea/templates/admin/repos/repo_add.html:16
@@ -278,177 +269,177 @@
 #: kallithea/templates/admin/users/user_edit_advanced.html:6
 #: kallithea/templates/base/base.html:56
 #: kallithea/templates/base/base.html:73
-#: kallithea/templates/base/base.html:444 kallithea/templates/index.html:5
+#: kallithea/templates/base/base.html:437 kallithea/templates/index.html:5
 msgid "Repositories"
 msgstr "版本庫"
 
-#: kallithea/controllers/home.py:121
+#: kallithea/controllers/home.py:122
 #: kallithea/templates/files/files_add.html:32
 #: kallithea/templates/files/files_delete.html:23
 #: kallithea/templates/files/files_edit.html:32
 msgid "Branch"
 msgstr ""
 
-#: kallithea/controllers/home.py:127
+#: kallithea/controllers/home.py:128
 msgid "Closed Branches"
 msgstr ""
 
-#: kallithea/controllers/home.py:133
+#: kallithea/controllers/home.py:134
 msgid "Tag"
 msgstr ""
 
-#: kallithea/controllers/home.py:139
+#: kallithea/controllers/home.py:140
 msgid "Bookmark"
 msgstr ""
 
-#: kallithea/controllers/journal.py:113 kallithea/controllers/journal.py:155
+#: kallithea/controllers/journal.py:112 kallithea/controllers/journal.py:154
 #: kallithea/templates/journal/public_journal.html:4
 #: kallithea/templates/journal/public_journal.html:18
 msgid "Public Journal"
 msgstr "開放日誌"
 
-#: kallithea/controllers/journal.py:117 kallithea/controllers/journal.py:159
-#: kallithea/templates/base/base.html:297
+#: kallithea/controllers/journal.py:116 kallithea/controllers/journal.py:158
+#: kallithea/templates/base/base.html:290
 #: kallithea/templates/journal/journal.html:5
 #: kallithea/templates/journal/journal.html:13
 msgid "Journal"
 msgstr "日誌"
 
-#: kallithea/controllers/login.py:139 kallithea/controllers/login.py:184
+#: kallithea/controllers/login.py:140 kallithea/controllers/login.py:185
 msgid "Bad captcha"
 msgstr ""
 
-#: kallithea/controllers/login.py:145
+#: kallithea/controllers/login.py:146
 #, python-format
 msgid "You have successfully registered with %s"
 msgstr ""
 
-#: kallithea/controllers/login.py:189
+#: kallithea/controllers/login.py:190
 msgid "A password reset confirmation code has been sent"
 msgstr "密碼重設的確認碼已寄出"
 
-#: kallithea/controllers/login.py:238
+#: kallithea/controllers/login.py:239
 msgid "Invalid password reset token"
 msgstr "無效的密碼重設確認碼"
 
-#: kallithea/controllers/admin/my_account.py:155
-#: kallithea/controllers/login.py:243
+#: kallithea/controllers/admin/my_account.py:157
+#: kallithea/controllers/login.py:244
 msgid "Successfully updated password"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:71
+#: kallithea/controllers/pullrequests.py:68
 #, python-format
 msgid "Invalid reviewer \"%s\" specified"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:133
+#: kallithea/controllers/pullrequests.py:131
 #, python-format
 msgid "%s (closed)"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:160
+#: kallithea/controllers/pullrequests.py:158
 #: kallithea/templates/changeset/changeset.html:12
 msgid "Changeset"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:181
+#: kallithea/controllers/pullrequests.py:179
 msgid "Special"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:182
+#: kallithea/controllers/pullrequests.py:180
 msgid "Peer branches"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:183 kallithea/model/scm.py:712
+#: kallithea/controllers/pullrequests.py:181 kallithea/model/scm.py:682
 msgid "Bookmarks"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:320
+#: kallithea/controllers/pullrequests.py:318
 #, python-format
 msgid "Error creating pull request: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:347
-#: kallithea/controllers/pullrequests.py:370
+#: kallithea/controllers/pullrequests.py:345
+#: kallithea/controllers/pullrequests.py:368
 msgid "Error occurred while creating pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:352
+#: kallithea/controllers/pullrequests.py:350
 msgid "Successfully opened new pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:375
+#: kallithea/controllers/pullrequests.py:373
 msgid "New pull request iteration created"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:403
+#: kallithea/controllers/pullrequests.py:401
 #, python-format
 msgid "Meanwhile, the following reviewers have been added: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:407
+#: kallithea/controllers/pullrequests.py:405
 #, python-format
 msgid "Meanwhile, the following reviewers have been removed: %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:423
-#: kallithea/model/pull_request.py:234
+#: kallithea/controllers/pullrequests.py:421
+#: kallithea/model/pull_request.py:232
 msgid "No description"
 msgstr "無描述"
 
-#: kallithea/controllers/pullrequests.py:432
+#: kallithea/controllers/pullrequests.py:430
 msgid "Pull request updated"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:445
+#: kallithea/controllers/pullrequests.py:443
 msgid "Successfully deleted pull request"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:481
+#: kallithea/controllers/pullrequests.py:479
 #, python-format
 msgid "Revision %s not found in %s"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:508
+#: kallithea/controllers/pullrequests.py:506
 #, python-format
 msgid "Error: changesets not found when displaying pull request from %s."
 msgstr ""
 
+#: kallithea/controllers/pullrequests.py:520
+#, python-format
+msgid "This pull request has already been merged to %s."
+msgstr ""
+
 #: kallithea/controllers/pullrequests.py:522
-#, python-format
-msgid "This pull request has already been merged to %s."
-msgstr ""
-
-#: kallithea/controllers/pullrequests.py:524
 msgid "This pull request has been closed and can not be updated."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:543
+#: kallithea/controllers/pullrequests.py:546
 #, python-format
 msgid "The following additional changes are available on %s:"
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:545
-#: kallithea/controllers/pullrequests.py:549
+#: kallithea/controllers/pullrequests.py:548
+#: kallithea/controllers/pullrequests.py:552
 msgid "No additional changesets found for iterating on this pull request."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:557
+#: kallithea/controllers/pullrequests.py:560
 #, python-format
 msgid "Note: Branch %s has another head: %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:564
+#: kallithea/controllers/pullrequests.py:567
 msgid "Git pull requests don't support iterating yet."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:566
+#: kallithea/controllers/pullrequests.py:569
 #, python-format
 msgid ""
 "Error: some changesets not found when displaying pull request from %s."
 msgstr ""
 
-#: kallithea/controllers/pullrequests.py:590
+#: kallithea/controllers/pullrequests.py:593
 msgid "The diff can't be shown - the PR revisions could not be found."
 msgstr ""
 
@@ -464,21 +455,21 @@
 msgid "An error occurred during search operation."
 msgstr ""
 
-#: kallithea/controllers/summary.py:179
-#: kallithea/templates/summary/summary.html:395
+#: kallithea/controllers/summary.py:168
+#: kallithea/templates/summary/summary.html:412
 msgid "No data ready yet"
 msgstr ""
 
-#: kallithea/controllers/summary.py:182
-#: kallithea/templates/summary/summary.html:89
+#: kallithea/controllers/summary.py:171
+#: kallithea/templates/summary/summary.html:97
 msgid "Statistics are disabled for this repository"
 msgstr "這個版本庫的統計功能已停用"
 
-#: kallithea/controllers/admin/auth_settings.py:135
+#: kallithea/controllers/admin/auth_settings.py:137
 msgid "Auth settings updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/auth_settings.py:146
+#: kallithea/controllers/admin/auth_settings.py:148
 msgid "error occurred during update of auth settings"
 msgstr ""
 
@@ -490,123 +481,135 @@
 msgid "Error occurred during update of defaults"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:58
-#: kallithea/controllers/admin/my_account.py:230
+#: kallithea/controllers/admin/gists.py:59
+#: kallithea/controllers/admin/my_account.py:232
 #: kallithea/controllers/admin/users.py:248
 msgid "Forever"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:59
-#: kallithea/controllers/admin/my_account.py:231
-#: kallithea/controllers/admin/users.py:249
-msgid "5 minutes"
-msgstr ""
-
 #: kallithea/controllers/admin/gists.py:60
-#: kallithea/controllers/admin/my_account.py:232
-#: kallithea/controllers/admin/users.py:250
-msgid "1 hour"
+#: kallithea/controllers/admin/my_account.py:233
+#: kallithea/controllers/admin/users.py:249
+msgid "5 minutes"
 msgstr ""
 
 #: kallithea/controllers/admin/gists.py:61
-#: kallithea/controllers/admin/my_account.py:233
-#: kallithea/controllers/admin/users.py:251
-msgid "1 day"
+#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/users.py:250
+msgid "1 hour"
 msgstr ""
 
 #: kallithea/controllers/admin/gists.py:62
-#: kallithea/controllers/admin/my_account.py:234
+#: kallithea/controllers/admin/my_account.py:235
+#: kallithea/controllers/admin/users.py:251
+msgid "1 day"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:63
+#: kallithea/controllers/admin/my_account.py:236
 #: kallithea/controllers/admin/users.py:252
 msgid "1 month"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:66
-#: kallithea/controllers/admin/my_account.py:236
+#: kallithea/controllers/admin/gists.py:67
+#: kallithea/controllers/admin/my_account.py:238
 #: kallithea/controllers/admin/users.py:254
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:65
 #: kallithea/templates/admin/users/user_edit_api_keys.html:65
 msgid "Lifetime"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:140
+#: kallithea/controllers/admin/gists.py:142
 msgid "Error occurred during gist creation"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:156
+#: kallithea/controllers/admin/gists.py:158
 #, python-format
 msgid "Deleted gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:196
+#: kallithea/controllers/admin/gists.py:198
 msgid "Unmodified"
 msgstr "未修改"
 
-#: kallithea/controllers/admin/gists.py:225
+#: kallithea/controllers/admin/gists.py:228
 msgid "Successfully updated gist content"
 msgstr ""
 
-#: kallithea/controllers/admin/gists.py:230
-msgid "Successfully updated gist data"
-msgstr ""
-
 #: kallithea/controllers/admin/gists.py:233
+msgid "Successfully updated gist data"
+msgstr ""
+
+#: kallithea/controllers/admin/gists.py:236
 #, python-format
 msgid "Error occurred during update of gist %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:68 kallithea/model/user.py:214
-#: kallithea/model/user.py:235
+#: kallithea/controllers/admin/my_account.py:70 kallithea/model/user.py:211
+#: kallithea/model/user.py:232
 msgid "You can't edit this user since it's crucial for entire application"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:117
+#: kallithea/controllers/admin/my_account.py:119
 msgid "Your account was updated successfully"
 msgstr "您的帳號已更新完成"
 
-#: kallithea/controllers/admin/my_account.py:132
+#: kallithea/controllers/admin/my_account.py:134
 #: kallithea/controllers/admin/users.py:181
 #, python-format
 msgid "Error occurred during update of user %s"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:166
+#: kallithea/controllers/admin/my_account.py:168
 msgid "Error occurred during update of user password"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:207
-#: kallithea/controllers/admin/users.py:369
+#: kallithea/controllers/admin/my_account.py:209
+#: kallithea/controllers/admin/users.py:367
 #, python-format
 msgid "Added email %s to user"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:213
-#: kallithea/controllers/admin/users.py:375
+#: kallithea/controllers/admin/my_account.py:215
+#: kallithea/controllers/admin/users.py:373
 msgid "An error occurred during email saving"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:222
-#: kallithea/controllers/admin/users.py:385
+#: kallithea/controllers/admin/my_account.py:224
+#: kallithea/controllers/admin/users.py:383
 msgid "Removed email from user"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:246
+#: kallithea/controllers/admin/my_account.py:248
 #: kallithea/controllers/admin/users.py:271
 msgid "API key successfully created"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:255
+#: kallithea/controllers/admin/my_account.py:257
 #: kallithea/controllers/admin/users.py:281
 msgid "API key successfully reset"
 msgstr ""
 
-#: kallithea/controllers/admin/my_account.py:259
+#: kallithea/controllers/admin/my_account.py:261
 #: kallithea/controllers/admin/users.py:285
 msgid "API key successfully deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:63
-#: kallithea/controllers/admin/permissions.py:67
-#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/my_account.py:281
+#: kallithea/controllers/admin/users.py:456
+#, python-format
+msgid "SSH key %s successfully added"
+msgstr ""
+
+#: kallithea/controllers/admin/my_account.py:293
+#: kallithea/controllers/admin/users.py:470
+#, fuzzy
+msgid "SSH key successfully deleted"
+msgstr "成功遞交至 %s"
+
+#: kallithea/controllers/admin/permissions.py:65
+#: kallithea/controllers/admin/permissions.py:69
+#: kallithea/controllers/admin/permissions.py:73
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:8
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:8
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:8
@@ -614,9 +617,9 @@
 msgid "Read"
 msgstr "讀"
 
-#: kallithea/controllers/admin/permissions.py:64
-#: kallithea/controllers/admin/permissions.py:68
-#: kallithea/controllers/admin/permissions.py:72
+#: kallithea/controllers/admin/permissions.py:66
+#: kallithea/controllers/admin/permissions.py:70
+#: kallithea/controllers/admin/permissions.py:74
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:9
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:9
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:9
@@ -624,9 +627,9 @@
 msgid "Write"
 msgstr "寫"
 
-#: kallithea/controllers/admin/permissions.py:65
-#: kallithea/controllers/admin/permissions.py:69
-#: kallithea/controllers/admin/permissions.py:73
+#: kallithea/controllers/admin/permissions.py:67
+#: kallithea/controllers/admin/permissions.py:71
+#: kallithea/controllers/admin/permissions.py:75
 #: kallithea/templates/admin/auth/auth_settings.html:9
 #: kallithea/templates/admin/defaults/defaults.html:9
 #: kallithea/templates/admin/permissions/permissions.html:9
@@ -649,361 +652,346 @@
 #: kallithea/templates/admin/users/user_edit_profile.html:81
 #: kallithea/templates/admin/users/users.html:9
 #: kallithea/templates/admin/users/users.html:43
+#: kallithea/templates/base/base.html:320
+#: kallithea/templates/base/base.html:321
 #: kallithea/templates/base/base.html:327
 #: kallithea/templates/base/base.html:328
-#: kallithea/templates/base/base.html:334
-#: kallithea/templates/base/base.html:335
 #: kallithea/templates/base/perms_summary.html:17
 msgid "Admin"
 msgstr "管理"
 
-#: kallithea/controllers/admin/permissions.py:76
-#: kallithea/controllers/admin/permissions.py:87
-#: kallithea/controllers/admin/permissions.py:92
-#: kallithea/controllers/admin/permissions.py:95
-#: kallithea/controllers/admin/permissions.py:98
-#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:89
+#: kallithea/controllers/admin/permissions.py:94
+#: kallithea/controllers/admin/permissions.py:97
+#: kallithea/controllers/admin/permissions.py:100
+#: kallithea/controllers/admin/permissions.py:103
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:50
 msgid "Disabled"
 msgstr "停用"
 
-#: kallithea/controllers/admin/permissions.py:78
+#: kallithea/controllers/admin/permissions.py:80
 msgid "Allowed with manual account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:80
+#: kallithea/controllers/admin/permissions.py:82
 msgid "Allowed with automatic account activation"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:83 kallithea/model/db.py:1739
+#: kallithea/controllers/admin/permissions.py:85 kallithea/model/db.py:1673
 msgid "Manual activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:84 kallithea/model/db.py:1740
+#: kallithea/controllers/admin/permissions.py:86 kallithea/model/db.py:1674
 msgid "Automatic activation of external account"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:88
-#: kallithea/controllers/admin/permissions.py:91
-#: kallithea/controllers/admin/permissions.py:96
-#: kallithea/controllers/admin/permissions.py:99
-#: kallithea/controllers/admin/permissions.py:102
+#: kallithea/controllers/admin/permissions.py:90
+#: kallithea/controllers/admin/permissions.py:93
+#: kallithea/controllers/admin/permissions.py:98
+#: kallithea/controllers/admin/permissions.py:101
+#: kallithea/controllers/admin/permissions.py:104
 #: kallithea/templates/admin/auth/auth_settings.html:42
 #: kallithea/templates/base/root.html:49
 msgid "Enabled"
 msgstr "啟用"
 
-#: kallithea/controllers/admin/permissions.py:125
+#: kallithea/controllers/admin/permissions.py:127
 msgid "Global permissions updated successfully"
 msgstr ""
 
-#: kallithea/controllers/admin/permissions.py:140
+#: kallithea/controllers/admin/permissions.py:142
 msgid "Error occurred during update of permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:174
+#: kallithea/controllers/admin/repo_groups.py:172
 #, python-format
 msgid "Error occurred during creation of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:179
+#: kallithea/controllers/admin/repo_groups.py:177
 #, python-format
 msgid "Created repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:226
+#: kallithea/controllers/admin/repo_groups.py:224
 #, python-format
 msgid "Updated repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:242
+#: kallithea/controllers/admin/repo_groups.py:240
 #, python-format
 msgid "Error occurred during update of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:252
+#: kallithea/controllers/admin/repo_groups.py:250
 #, python-format
 msgid "This group contains %s repositories and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:259
+#: kallithea/controllers/admin/repo_groups.py:257
 #, python-format
 msgid "This group contains %s subgroups and cannot be deleted"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:265
+#: kallithea/controllers/admin/repo_groups.py:263
 #, python-format
 msgid "Removed repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:270
+#: kallithea/controllers/admin/repo_groups.py:268
 #, python-format
 msgid "Error occurred during deletion of repository group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:354
-#: kallithea/controllers/admin/repo_groups.py:384
-#: kallithea/controllers/admin/user_groups.py:299
+#: kallithea/controllers/admin/repo_groups.py:352
+#: kallithea/controllers/admin/repo_groups.py:382
+#: kallithea/controllers/admin/user_groups.py:294
 msgid "Cannot revoke permission for yourself as admin"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:369
+#: kallithea/controllers/admin/repo_groups.py:367
 msgid "Repository group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repo_groups.py:401
-#: kallithea/controllers/admin/repos.py:357
-#: kallithea/controllers/admin/user_groups.py:311
+#: kallithea/controllers/admin/repo_groups.py:399
+#: kallithea/controllers/admin/repos.py:358
+#: kallithea/controllers/admin/user_groups.py:306
 msgid "An error occurred during revoking of permission"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:137
+#: kallithea/controllers/admin/repos.py:136
 #, python-format
 msgid "Error creating repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:195
+#: kallithea/controllers/admin/repos.py:194
 #, python-format
 msgid "Created repository %s from %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:204
+#: kallithea/controllers/admin/repos.py:203
 #, python-format
 msgid "Forked repository %s as %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:207
+#: kallithea/controllers/admin/repos.py:206
 #, python-format
 msgid "Created repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:236
+#: kallithea/controllers/admin/repos.py:235
 #, python-format
 msgid "Repository %s updated successfully"
 msgstr "版本庫 %s 更新完成"
 
-#: kallithea/controllers/admin/repos.py:256
+#: kallithea/controllers/admin/repos.py:255
 #, python-format
 msgid "Error occurred during update of repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:274
+#: kallithea/controllers/admin/repos.py:273
 #, python-format
 msgid "Detached %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:277
+#: kallithea/controllers/admin/repos.py:276
 #, python-format
 msgid "Deleted %s forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:282
+#: kallithea/controllers/admin/repos.py:281
 #, python-format
 msgid "Deleted repository %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:285
+#: kallithea/controllers/admin/repos.py:284
 #, python-format
 msgid "Cannot delete repository %s which still has forks"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:290
+#: kallithea/controllers/admin/repos.py:289
 #, python-format
 msgid "An error occurred during deletion of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:330
+#: kallithea/controllers/admin/repos.py:329
 msgid "Repository permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:387
+#: kallithea/controllers/admin/repos.py:388
 #, python-format
 msgid "Field validation error: %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:390
+#: kallithea/controllers/admin/repos.py:391
 #, python-format
 msgid "An error occurred during creation of field: %r"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:401
+#: kallithea/controllers/admin/repos.py:402
 msgid "An error occurred during removal of field"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:415
+#: kallithea/controllers/admin/repos.py:416
 msgid "-- Not a fork --"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:446
+#: kallithea/controllers/admin/repos.py:448
 msgid "Updated repository visibility in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:450
+#: kallithea/controllers/admin/repos.py:452
 msgid "An error occurred during setting this repository in public journal"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:466
-msgid "Nothing"
-msgstr ""
-
 #: kallithea/controllers/admin/repos.py:468
+msgid "Nothing"
+msgstr ""
+
+#: kallithea/controllers/admin/repos.py:470
 #, python-format
 msgid "Marked repository %s as fork of %s"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:475
+#: kallithea/controllers/admin/repos.py:477
 msgid "An error occurred during this operation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:491
-#: kallithea/controllers/admin/repos.py:512
-msgid "Repository has been locked"
-msgstr "儲存所已被鎖定"
+#: kallithea/controllers/admin/repos.py:490
+msgid "Cache invalidation successful"
+msgstr ""
 
 #: kallithea/controllers/admin/repos.py:494
-#: kallithea/controllers/admin/repos.py:509
-msgid "Repository has been unlocked"
-msgstr "儲存所已打開"
-
-#: kallithea/controllers/admin/repos.py:497
-#: kallithea/controllers/admin/repos.py:516
-msgid "An error occurred during unlocking"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:528
-msgid "Cache invalidation successful"
-msgstr ""
-
-#: kallithea/controllers/admin/repos.py:532
 msgid "An error occurred during cache invalidation"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:545
+#: kallithea/controllers/admin/repos.py:507
 msgid "Pulled from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:548
+#: kallithea/controllers/admin/repos.py:510
 msgid "An error occurred during pull from remote location"
 msgstr ""
 
-#: kallithea/controllers/admin/repos.py:579
+#: kallithea/controllers/admin/repos.py:541
 msgid "An error occurred during deletion of repository stats"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:135
+#: kallithea/controllers/admin/settings.py:131
 msgid "Updated VCS settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:139 kallithea/lib/utils.py:231
+#: kallithea/controllers/admin/settings.py:135 kallithea/lib/utils.py:237
 msgid ""
 "Unable to activate hgsubversion support. The \"hgsubversion\" library is "
 "missing"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:145
-#: kallithea/controllers/admin/settings.py:237
+#: kallithea/controllers/admin/settings.py:141
+#: kallithea/controllers/admin/settings.py:233
 msgid "Error occurred while updating application settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:180
+#: kallithea/controllers/admin/settings.py:176
 #, python-format
 msgid "Repositories successfully rescanned. Added: %s. Removed: %s."
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:192
+#: kallithea/controllers/admin/settings.py:188
 #, fuzzy, python-format
 #| msgid "Invalidate Repository Cache"
 msgid "Invalidated %s repositories"
 msgstr "確認廢止版本庫快取"
 
-#: kallithea/controllers/admin/settings.py:233
+#: kallithea/controllers/admin/settings.py:229
 msgid "Updated application settings"
 msgstr "更新應用設定"
 
-#: kallithea/controllers/admin/settings.py:286
+#: kallithea/controllers/admin/settings.py:283
 msgid "Updated visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:291
+#: kallithea/controllers/admin/settings.py:288
 msgid "Error occurred during updating visualisation settings"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:315
+#: kallithea/controllers/admin/settings.py:312
 msgid "Please enter email address"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:330
+#: kallithea/controllers/admin/settings.py:327
 msgid "Send email task created"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:358
+#: kallithea/controllers/admin/settings.py:355
 msgid "Hook already exists"
 msgstr ""
 
+#: kallithea/controllers/admin/settings.py:357
+msgid "Builtin hooks are read-only. Please use another hook name."
+msgstr ""
+
 #: kallithea/controllers/admin/settings.py:360
-msgid "Builtin hooks are read-only. Please use another hook name."
-msgstr ""
-
-#: kallithea/controllers/admin/settings.py:363
 msgid "Added new hook"
 msgstr "新增hook"
 
-#: kallithea/controllers/admin/settings.py:379
+#: kallithea/controllers/admin/settings.py:376
 msgid "Updated hooks"
 msgstr "更新hook"
 
-#: kallithea/controllers/admin/settings.py:383
+#: kallithea/controllers/admin/settings.py:380
 msgid "Error occurred during hook creation"
 msgstr ""
 
-#: kallithea/controllers/admin/settings.py:407
+#: kallithea/controllers/admin/settings.py:404
 msgid "Whoosh reindex task scheduled"
 msgstr "Whoosh 重新索引工作排程"
 
-#: kallithea/controllers/admin/user_groups.py:143
+#: kallithea/controllers/admin/user_groups.py:138
 #, python-format
 msgid "Created user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:156
+#: kallithea/controllers/admin/user_groups.py:151
 #, python-format
 msgid "Error occurred during creation of user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:184
+#: kallithea/controllers/admin/user_groups.py:179
 #, python-format
 msgid "Updated user group %s"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:206
+#: kallithea/controllers/admin/user_groups.py:201
 #, python-format
 msgid "Error occurred during update of user group %s"
 msgstr ""
 
+#: kallithea/controllers/admin/user_groups.py:212
+msgid "Successfully deleted user group"
+msgstr ""
+
 #: kallithea/controllers/admin/user_groups.py:217
-msgid "Successfully deleted user group"
-msgstr ""
-
-#: kallithea/controllers/admin/user_groups.py:222
 msgid "An error occurred during deletion of user group"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:278
+#: kallithea/controllers/admin/user_groups.py:273
 msgid "Target group cannot be the same"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:284
+#: kallithea/controllers/admin/user_groups.py:279
 msgid "User group permissions updated"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:395
-#: kallithea/controllers/admin/users.py:340
+#: kallithea/controllers/admin/user_groups.py:388
+#: kallithea/controllers/admin/users.py:338
 msgid "Updated permissions"
 msgstr ""
 
-#: kallithea/controllers/admin/user_groups.py:399
-#: kallithea/controllers/admin/users.py:344
+#: kallithea/controllers/admin/user_groups.py:392
+#: kallithea/controllers/admin/users.py:342
 msgid "An error occurred during permissions saving"
 msgstr ""
 
@@ -1033,219 +1021,221 @@
 msgid "The default user cannot be edited"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:412
+#: kallithea/controllers/admin/users.py:409
 #, python-format
 msgid "Added IP address %s to user whitelist"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:418
+#: kallithea/controllers/admin/users.py:415
 msgid "An error occurred while adding IP address"
 msgstr ""
 
-#: kallithea/controllers/admin/users.py:430
+#: kallithea/controllers/admin/users.py:427
 msgid "Removed IP address from user whitelist"
 msgstr ""
 
-#: kallithea/lib/auth.py:824
+#: kallithea/lib/auth.py:684
 msgid "You need to be a registered user to perform this action"
 msgstr "您必須是註冊使用者才能執行這個動作"
 
-#: kallithea/lib/auth.py:852
+#: kallithea/lib/auth.py:712
 msgid "You need to be signed in to view this page"
 msgstr "您必須登入後才能瀏覽這個頁面"
 
-#: kallithea/lib/base.py:444
-msgid "Invalid API key"
-msgstr ""
-
-#: kallithea/lib/base.py:495
+#: kallithea/lib/base.py:483
 msgid ""
 "CSRF token leak has been detected - all form tokens have been expired"
 msgstr ""
 
-#: kallithea/lib/base.py:583
+#: kallithea/lib/base.py:580
 msgid "Repository not found in the filesystem"
 msgstr ""
 
-#: kallithea/lib/base.py:608
+#: kallithea/lib/base.py:605
 #, python-format
 msgid "Changeset for %s %s not found in %s"
 msgstr ""
 
-#: kallithea/lib/diffs.py:193
+#: kallithea/lib/base.py:647
+#, fuzzy
+#| msgid "Your account is disabled"
+msgid "SSH access is disabled."
+msgstr "您的帳號已被停用"
+
+#: kallithea/lib/diffs.py:194
 msgid "Binary file"
 msgstr ""
 
-#: kallithea/lib/diffs.py:213
+#: kallithea/lib/diffs.py:214
 msgid ""
 "Changeset was too big and was cut off, use diff menu to display this diff"
 msgstr ""
 
-#: kallithea/lib/diffs.py:223
+#: kallithea/lib/diffs.py:224
 msgid "No changes detected"
 msgstr "尚未有任何變更"
 
-#: kallithea/lib/helpers.py:612
+#: kallithea/lib/helpers.py:653
 #, python-format
 msgid "Deleted branch: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:614
+#: kallithea/lib/helpers.py:655
 #, python-format
 msgid "Created tag: %s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:625
+#: kallithea/lib/helpers.py:666
 #, fuzzy, python-format
 #| msgid "Set changeset status"
 msgid "Changeset %s not found"
 msgstr "尚未有任何變更"
 
-#: kallithea/lib/helpers.py:674
+#: kallithea/lib/helpers.py:715
 #, python-format
 msgid "Show all combined changesets %s->%s"
 msgstr ""
 
-#: kallithea/lib/helpers.py:680
+#: kallithea/lib/helpers.py:721
 msgid "Compare view"
 msgstr ""
 
-#: kallithea/lib/helpers.py:699
+#: kallithea/lib/helpers.py:740
 msgid "and"
 msgstr "和"
 
-#: kallithea/lib/helpers.py:700
+#: kallithea/lib/helpers.py:741
 #, python-format
 msgid "%s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:701
+#: kallithea/lib/helpers.py:742
 #: kallithea/templates/changelog/changelog.html:43
 msgid "revisions"
 msgstr "修訂"
 
-#: kallithea/lib/helpers.py:725
+#: kallithea/lib/helpers.py:766
 #, python-format
 msgid "Fork name %s"
 msgstr "分支名稱 %s"
 
-#: kallithea/lib/helpers.py:746
+#: kallithea/lib/helpers.py:787
 #, python-format
 msgid "Pull request %s"
 msgstr "提取要求 %s"
 
-#: kallithea/lib/helpers.py:756
+#: kallithea/lib/helpers.py:797
 msgid "[deleted] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:758 kallithea/lib/helpers.py:770
+#: kallithea/lib/helpers.py:799 kallithea/lib/helpers.py:811
 msgid "[created] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:760
+#: kallithea/lib/helpers.py:801
 msgid "[created] repository as fork"
 msgstr ""
 
-#: kallithea/lib/helpers.py:762 kallithea/lib/helpers.py:772
+#: kallithea/lib/helpers.py:803 kallithea/lib/helpers.py:813
 msgid "[forked] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:764 kallithea/lib/helpers.py:774
+#: kallithea/lib/helpers.py:805 kallithea/lib/helpers.py:815
 msgid "[updated] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:766
+#: kallithea/lib/helpers.py:807
 msgid "[downloaded] archive from repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:768
+#: kallithea/lib/helpers.py:809
 msgid "[delete] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:776
+#: kallithea/lib/helpers.py:817
 msgid "[created] user"
 msgstr ""
 
-#: kallithea/lib/helpers.py:778
+#: kallithea/lib/helpers.py:819
 msgid "[updated] user"
 msgstr ""
 
-#: kallithea/lib/helpers.py:780
+#: kallithea/lib/helpers.py:821
 msgid "[created] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:782
+#: kallithea/lib/helpers.py:823
 msgid "[updated] user group"
 msgstr ""
 
-#: kallithea/lib/helpers.py:784
+#: kallithea/lib/helpers.py:825
 msgid "[commented] on revision in repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:786
+#: kallithea/lib/helpers.py:827
 msgid "[commented] on pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:788
+#: kallithea/lib/helpers.py:829
 msgid "[closed] pull request for"
 msgstr ""
 
-#: kallithea/lib/helpers.py:790
+#: kallithea/lib/helpers.py:831
 msgid "[pushed] into"
 msgstr ""
 
-#: kallithea/lib/helpers.py:792
+#: kallithea/lib/helpers.py:833
 msgid "[committed via Kallithea] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:794
+#: kallithea/lib/helpers.py:835
 msgid "[pulled from remote] into repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:796
+#: kallithea/lib/helpers.py:837
 msgid "[pulled] from"
 msgstr ""
 
-#: kallithea/lib/helpers.py:798
+#: kallithea/lib/helpers.py:839
 msgid "[started following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:800
+#: kallithea/lib/helpers.py:841
 msgid "[stopped following] repository"
 msgstr ""
 
-#: kallithea/lib/helpers.py:928
+#: kallithea/lib/helpers.py:961
 #, python-format
 msgid " and %s more"
 msgstr ""
 
-#: kallithea/lib/helpers.py:932
+#: kallithea/lib/helpers.py:965
 #: kallithea/templates/compare/compare_diff.html:69
 #: kallithea/templates/pullrequests/pullrequest_show.html:297
 msgid "No files"
 msgstr ""
 
-#: kallithea/lib/helpers.py:957
+#: kallithea/lib/helpers.py:990
 msgid "new file"
 msgstr ""
 
-#: kallithea/lib/helpers.py:960
+#: kallithea/lib/helpers.py:993
 msgid "mod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:963
+#: kallithea/lib/helpers.py:996
 msgid "del"
 msgstr ""
 
-#: kallithea/lib/helpers.py:966
+#: kallithea/lib/helpers.py:999
 msgid "rename"
 msgstr ""
 
-#: kallithea/lib/helpers.py:971
+#: kallithea/lib/helpers.py:1004
 msgid "chmod"
 msgstr ""
 
-#: kallithea/lib/helpers.py:1264
+#: kallithea/lib/helpers.py:1297
 #, python-format
 msgid ""
 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -1253,63 +1243,90 @@
 "repositories"
 msgstr ""
 
-#: kallithea/lib/utils2.py:333
+#: kallithea/lib/ssh.py:71
+msgid "SSH key is missing"
+msgstr ""
+
+#: kallithea/lib/ssh.py:75
+msgid "Incorrect SSH key - it must have both a key type and a base64 part"
+msgstr ""
+
+#: kallithea/lib/ssh.py:79
+msgid "Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"
+msgstr ""
+
+#: kallithea/lib/ssh.py:82
+#, python-format
+msgid "Incorrect SSH key - unexpected characters in base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:87
+#, python-format
+msgid "Incorrect SSH key - failed to decode base64 part %r"
+msgstr ""
+
+#: kallithea/lib/ssh.py:90
+#, python-format
+msgid "Incorrect SSH key - base64 part is not %r as claimed but %r"
+msgstr ""
+
+#: kallithea/lib/utils2.py:334
 #, python-format
 msgid "%d year"
 msgid_plural "%d years"
 msgstr[0] ""
 
-#: kallithea/lib/utils2.py:334
+#: kallithea/lib/utils2.py:335
 #, python-format
 msgid "%d month"
 msgid_plural "%d months"
 msgstr[0] ""
 
-#: kallithea/lib/utils2.py:335
+#: kallithea/lib/utils2.py:336
 #, python-format
 msgid "%d day"
 msgid_plural "%d days"
 msgstr[0] ""
 
-#: kallithea/lib/utils2.py:336
+#: kallithea/lib/utils2.py:337
 #, python-format
 msgid "%d hour"
 msgid_plural "%d hours"
 msgstr[0] ""
 
-#: kallithea/lib/utils2.py:337
+#: kallithea/lib/utils2.py:338
 #, python-format
 msgid "%d minute"
 msgid_plural "%d minutes"
 msgstr[0] ""
 
-#: kallithea/lib/utils2.py:338
+#: kallithea/lib/utils2.py:339
 #, python-format
 msgid "%d second"
 msgid_plural "%d seconds"
 msgstr[0] ""
 
-#: kallithea/lib/utils2.py:354
+#: kallithea/lib/utils2.py:355
 #, python-format
 msgid "in %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:356
+#: kallithea/lib/utils2.py:357
 #, python-format
 msgid "%s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:358
+#: kallithea/lib/utils2.py:359
 #, python-format
 msgid "in %s and %s"
 msgstr ""
 
-#: kallithea/lib/utils2.py:361
+#: kallithea/lib/utils2.py:362
 #, python-format
 msgid "%s and %s ago"
 msgstr ""
 
-#: kallithea/lib/utils2.py:364
+#: kallithea/lib/utils2.py:365
 msgid "just now"
 msgstr "現在"
 
@@ -1318,134 +1335,134 @@
 msgid "on line %s"
 msgstr ""
 
-#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:117
+#: kallithea/model/comment.py:221 kallithea/model/pull_request.py:114
 msgid "[Mention]"
 msgstr ""
 
-#: kallithea/model/db.py:1562
+#: kallithea/model/db.py:1496
 msgid "top level"
 msgstr ""
 
-#: kallithea/model/db.py:1703
+#: kallithea/model/db.py:1637
 msgid "Kallithea Administrator"
 msgstr ""
 
-#: kallithea/model/db.py:1705
+#: kallithea/model/db.py:1639
 msgid "Default user has no access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1706
+#: kallithea/model/db.py:1640
 msgid "Default user has read access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1707
+#: kallithea/model/db.py:1641
 msgid "Default user has write access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1708
+#: kallithea/model/db.py:1642
 msgid "Default user has admin access to new repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1710
+#: kallithea/model/db.py:1644
 msgid "Default user has no access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1711
+#: kallithea/model/db.py:1645
 msgid "Default user has read access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1712
+#: kallithea/model/db.py:1646
 msgid "Default user has write access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1713
+#: kallithea/model/db.py:1647
 msgid "Default user has admin access to new repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1715
+#: kallithea/model/db.py:1649
 msgid "Default user has no access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1716
+#: kallithea/model/db.py:1650
 msgid "Default user has read access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1717
+#: kallithea/model/db.py:1651
 msgid "Default user has write access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1718
+#: kallithea/model/db.py:1652
 msgid "Default user has admin access to new user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1720
+#: kallithea/model/db.py:1654
 msgid "Only admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1721
+#: kallithea/model/db.py:1655
 msgid "Non-admins can create repository groups"
 msgstr ""
 
-#: kallithea/model/db.py:1723
+#: kallithea/model/db.py:1657
 msgid "Only admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1724
+#: kallithea/model/db.py:1658
 msgid "Non-admins can create user groups"
 msgstr ""
 
-#: kallithea/model/db.py:1726
+#: kallithea/model/db.py:1660
 msgid "Only admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1727
+#: kallithea/model/db.py:1661
 msgid "Non-admins can create top level repositories"
 msgstr ""
 
-#: kallithea/model/db.py:1729
+#: kallithea/model/db.py:1663
 msgid ""
 "Repository creation enabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1730
+#: kallithea/model/db.py:1664
 msgid ""
 "Repository creation disabled with write permission to a repository group"
 msgstr ""
 
-#: kallithea/model/db.py:1732
+#: kallithea/model/db.py:1666
 msgid "Only admins can fork repositories"
 msgstr "祗有管理者才能分歧版本庫"
 
-#: kallithea/model/db.py:1733
+#: kallithea/model/db.py:1667
 #, fuzzy
 msgid "Non-admins can fork repositories"
 msgstr "建立版本庫"
 
-#: kallithea/model/db.py:1735
+#: kallithea/model/db.py:1669
 msgid "Registration disabled"
 msgstr ""
 
-#: kallithea/model/db.py:1736
+#: kallithea/model/db.py:1670
 msgid "User registration with manual account activation"
 msgstr ""
 
-#: kallithea/model/db.py:1737
+#: kallithea/model/db.py:1671
 msgid "User registration with automatic account activation"
 msgstr ""
 
-#: kallithea/model/db.py:2263
+#: kallithea/model/db.py:2206
 msgid "Not reviewed"
 msgstr "未審核"
 
-#: kallithea/model/db.py:2264
+#: kallithea/model/db.py:2207
 msgid "Under review"
 msgstr "審核中"
 
-#: kallithea/model/db.py:2265
+#: kallithea/model/db.py:2208
 msgid "Not approved"
 msgstr ""
 
-#: kallithea/model/db.py:2266
+#: kallithea/model/db.py:2209
 msgid "Approved"
 msgstr ""
 
@@ -1471,304 +1488,316 @@
 msgid "Name must not contain only digits"
 msgstr ""
 
-#: kallithea/model/notification.py:165
+#: kallithea/model/notification.py:164
 #, python-format
 msgid ""
 "[Comment] %(repo_name)s changeset %(short_id)s \"%(message_short)s\" on "
 "%(branch)s"
 msgstr ""
 
-#: kallithea/model/notification.py:168
+#: kallithea/model/notification.py:167
 #, python-format
 msgid "New user %(new_username)s registered"
 msgstr ""
 
+#: kallithea/model/notification.py:169
+#, 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:170
 #, 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:171
-#, 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:184
+#: kallithea/model/notification.py:183
 msgid "Closing"
 msgstr "關閉中"
 
-#: kallithea/model/pull_request.py:76
+#: kallithea/model/pull_request.py:73
 #, python-format
 msgid ""
 "%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:211
+#: kallithea/model/pull_request.py:209
 msgid "Cannot create empty pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:219
+#: kallithea/model/pull_request.py:217
 #, python-format
 msgid ""
 "Cannot create pull request - criss cross merge detected, please merge a "
 "later %s revision to %s"
 msgstr ""
 
-#: kallithea/model/pull_request.py:247 kallithea/model/pull_request.py:382
+#: kallithea/model/pull_request.py:245 kallithea/model/pull_request.py:380
 msgid "You are not authorized to create the pull request"
 msgstr ""
 
-#: kallithea/model/pull_request.py:341
+#: kallithea/model/pull_request.py:339
 msgid "Missing changesets since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:348
+#: kallithea/model/pull_request.py:346
 #, python-format
 msgid "New changesets on %s %s since the previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:355
+#: kallithea/model/pull_request.py:353
 msgid "Ancestor didn't change - diff since previous iteration:"
 msgstr ""
 
-#: kallithea/model/pull_request.py:362
+#: kallithea/model/pull_request.py:360
 #, python-format
 msgid ""
 "This iteration is based on another %s revision and there is no simple "
 "diff."
 msgstr ""
 
-#: kallithea/model/pull_request.py:364
+#: kallithea/model/pull_request.py:362
 #, python-format
 msgid "No changes found on %s %s since previous iteration."
 msgstr ""
 
-#: kallithea/model/pull_request.py:390
+#: kallithea/model/pull_request.py:388
 #, python-format
 msgid "Closed, next iteration: %s ."
 msgstr ""
 
-#: kallithea/model/scm.py:698
+#: kallithea/model/scm.py:668
 msgid "latest tip"
 msgstr ""
 
-#: kallithea/model/user.py:189
+#: kallithea/model/ssh_key.py:56
+#, python-format
+msgid "SSH key %r is invalid: %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:68
+#, python-format
+msgid "SSH key %s is already used by %s"
+msgstr ""
+
+#: kallithea/model/ssh_key.py:89
+#, fuzzy, python-format
+#| msgid "Set changeset status"
+msgid "SSH key %r not found"
+msgstr "尚未有任何變更"
+
+#: kallithea/model/user.py:186
 msgid "New user registration"
 msgstr ""
 
-#: kallithea/model/user.py:253
+#: kallithea/model/user.py:250
 msgid ""
 "You can't remove this user since it is crucial for the entire application"
 msgstr "您無法移除這個使用者,因為係供整個應用使用"
 
-#: kallithea/model/user.py:258
+#: kallithea/model/user.py:255
 #, 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:263
+#: kallithea/model/user.py:260
 #, 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:270
+#: kallithea/model/user.py:267
 #, 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:364
+#: kallithea/model/user.py:361
 msgid "Password reset link"
 msgstr ""
 
-#: kallithea/model/user.py:413
+#: kallithea/model/user.py:408
 msgid "Password reset notification"
 msgstr ""
 
-#: kallithea/model/user.py:414
+#: kallithea/model/user.py:409
 #, python-format
 msgid ""
 "The password to your account %s has been changed using password reset "
 "form."
 msgstr ""
 
-#: kallithea/model/validators.py:54 kallithea/model/validators.py:55
+#: kallithea/model/validators.py:52 kallithea/model/validators.py:53
 msgid "Value cannot be an empty list"
 msgstr ""
 
+#: kallithea/model/validators.py:72
+#, python-format
+msgid "Username \"%(username)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:74
 #, python-format
-msgid "Username \"%(username)s\" already exists"
+msgid "Username \"%(username)s\" cannot be used"
 msgstr ""
 
 #: kallithea/model/validators.py:76
-#, python-format
-msgid "Username \"%(username)s\" cannot be used"
-msgstr ""
-
-#: kallithea/model/validators.py:78
 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:105
+#: kallithea/model/validators.py:103
 msgid "The input is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:112
+#: kallithea/model/validators.py:110
 #, python-format
 msgid "Username %(username)s is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:133
+#: kallithea/model/validators.py:131
 msgid "Invalid user group name"
 msgstr ""
 
+#: kallithea/model/validators.py:132
+#, python-format
+msgid "User group \"%(usergroup)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:134
-#, python-format
-msgid "User group \"%(usergroup)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:136
 msgid ""
 "user group name may only contain alphanumeric characters underscores, "
 "periods or dashes and must begin with alphanumeric character"
 msgstr ""
 "使用者羣組名稱可以包括文數字字元、底線、句點或破折號,必須以文數字啟頭"
 
-#: kallithea/model/validators.py:176
+#: kallithea/model/validators.py:174
 msgid "Cannot assign this group as parent"
 msgstr ""
 
+#: kallithea/model/validators.py:175
+#, python-format
+msgid "Group \"%(group_name)s\" already exists"
+msgstr ""
+
 #: kallithea/model/validators.py:177
 #, python-format
-msgid "Group \"%(group_name)s\" already exists"
-msgstr ""
-
-#: kallithea/model/validators.py:179
-#, python-format
 msgid "Repository with name \"%(group_name)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:235
+#: kallithea/model/validators.py:233
 msgid "Invalid characters (non-ascii) in password"
 msgstr ""
 
-#: kallithea/model/validators.py:250
+#: kallithea/model/validators.py:248
 msgid "Invalid old password"
 msgstr ""
 
-#: kallithea/model/validators.py:266
+#: kallithea/model/validators.py:264
 msgid "Passwords do not match"
 msgstr "密碼不相符"
 
-#: kallithea/model/validators.py:281
+#: kallithea/model/validators.py:279
 msgid "Invalid username or password"
 msgstr "無效的用戶名稱或密碼"
 
-#: kallithea/model/validators.py:312
-msgid "Token mismatch"
-msgstr ""
-
-#: kallithea/model/validators.py:328
+#: kallithea/model/validators.py:313
 #, python-format
 msgid "Repository name %(repo)s is not allowed"
 msgstr ""
 
-#: kallithea/model/validators.py:330
+#: kallithea/model/validators.py:315
 #, python-format
 msgid "Repository named %(repo)s already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:331
+#: kallithea/model/validators.py:316
 #, python-format
 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
 msgstr ""
 
-#: kallithea/model/validators.py:333
+#: kallithea/model/validators.py:318
 #, python-format
 msgid "Repository group with name \"%(repo)s\" already exists"
 msgstr ""
 
-#: kallithea/model/validators.py:419
+#: kallithea/model/validators.py:404
 msgid "Invalid repository URL"
 msgstr "無效的版本庫 URL"
 
-#: kallithea/model/validators.py:420
+#: kallithea/model/validators.py:405
 msgid ""
 "Invalid repository URL. It must be a valid http, https, ssh, svn+http or "
 "svn+https URL"
 msgstr ""
 
-#: kallithea/model/validators.py:445
+#: kallithea/model/validators.py:430
 msgid "Fork has to be the same type as parent"
 msgstr ""
 
-#: kallithea/model/validators.py:460
+#: kallithea/model/validators.py:445
 msgid "You don't have permissions to create repository in this group"
 msgstr ""
 
-#: kallithea/model/validators.py:462
+#: kallithea/model/validators.py:447
 msgid "no permission to create repository in root location"
 msgstr ""
 
-#: kallithea/model/validators.py:512
+#: kallithea/model/validators.py:497
 msgid "You don't have permissions to create a group in this location"
 msgstr ""
 
-#: kallithea/model/validators.py:552
+#: kallithea/model/validators.py:537
 msgid "This username or user group name is not valid"
 msgstr ""
 
-#: kallithea/model/validators.py:645
+#: kallithea/model/validators.py:630
 msgid "This is not a valid path"
 msgstr "不是一個有效的路徑"
 
-#: kallithea/model/validators.py:662
+#: kallithea/model/validators.py:647
 #, fuzzy
 msgid "This email address is already in use"
 msgstr "這個郵件位址已經使用了"
 
-#: kallithea/model/validators.py:682
+#: kallithea/model/validators.py:667
 #, python-format
 msgid "Email address \"%(email)s\" not found"
 msgstr ""
 
-#: kallithea/model/validators.py:719
+#: kallithea/model/validators.py:704
 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:731
+#: kallithea/model/validators.py:716
 msgid "Please enter a valid IPv4 or IPv6 address"
 msgstr ""
 
-#: kallithea/model/validators.py:732
+#: kallithea/model/validators.py:717
 #, python-format
 msgid ""
 "The network size (bits) must be within the range of 0-32 (not %(bits)r)"
 msgstr ""
 
-#: kallithea/model/validators.py:765
+#: kallithea/model/validators.py:750
 msgid "Key name can only consist of letters, underscore, dash or numbers"
 msgstr ""
 
-#: kallithea/model/validators.py:779
+#: kallithea/model/validators.py:764
 msgid "Filename cannot be inside a directory"
 msgstr ""
 
-#: kallithea/model/validators.py:795
+#: kallithea/model/validators.py:780
 #, python-format
 msgid "Plugins %(loaded)s and %(next_to_load)s both export the same name"
 msgstr ""
@@ -1809,24 +1838,30 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:59
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:61
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:5
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:58
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:60
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:35
 #: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:12
 #: kallithea/templates/admin/repo_groups/repo_groups.html:40
 #: kallithea/templates/admin/repos/repo_add_base.html:21
-#: kallithea/templates/admin/repos/repo_edit_settings.html:49
+#: kallithea/templates/admin/repos/repo_edit_settings.html:54
 #: kallithea/templates/admin/repos/repos.html:39
 #: kallithea/templates/admin/user_groups/user_group_add.html:33
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:10
 #: kallithea/templates/admin/user_groups/user_groups.html:39
 #: kallithea/templates/admin/users/user_edit_api_keys.html:59
 #: kallithea/templates/admin/users/user_edit_api_keys.html:61
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:5
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:58
+#: 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/pullrequests/pullrequest.html:33
 #: kallithea/templates/pullrequests/pullrequest_show.html:38
 #: kallithea/templates/pullrequests/pullrequest_show.html:59
-#: kallithea/templates/summary/summary.html:79
+#: kallithea/templates/summary/summary.html:87
 msgid "Description"
 msgstr "描述"
 
@@ -1843,7 +1878,7 @@
 
 #: kallithea/templates/admin/repo_groups/repo_group_edit_advanced.html:10
 #: kallithea/templates/admin/repo_groups/repo_groups.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:42
+#: kallithea/templates/admin/repos/repo_edit_settings.html:47
 #: 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
@@ -1851,11 +1886,11 @@
 #: kallithea/templates/pullrequests/pullrequest_data.html:16
 #: kallithea/templates/pullrequests/pullrequest_show.html:124
 #: kallithea/templates/pullrequests/pullrequest_show.html:219
-#: kallithea/templates/summary/summary.html:124
+#: kallithea/templates/summary/summary.html:132
 msgid "Owner"
 msgstr "擁有者"
 
-#: kallithea/templates/base/base.html:387 kallithea/templates/login.html:5
+#: kallithea/templates/base/base.html:380 kallithea/templates/login.html:5
 #: kallithea/templates/login.html:19
 msgid "Log In"
 msgstr ""
@@ -1870,7 +1905,7 @@
 #: kallithea/templates/admin/users/user_add.html:27
 #: kallithea/templates/admin/users/user_edit_profile.html:18
 #: kallithea/templates/admin/users/users.html:37
-#: kallithea/templates/base/base.html:371
+#: kallithea/templates/base/base.html:364
 #: kallithea/templates/email_templates/registration.html:11
 #: kallithea/templates/login.html:28 kallithea/templates/register.html:31
 msgid "Username"
@@ -1878,7 +1913,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:27
 #: kallithea/templates/admin/users/user_add.html:34
-#: kallithea/templates/base/base.html:375 kallithea/templates/login.html:34
+#: kallithea/templates/base/base.html:368 kallithea/templates/login.html:34
 #: kallithea/templates/register.html:38
 msgid "Password"
 msgstr "密碼"
@@ -2039,10 +2074,12 @@
 
 #: kallithea/templates/admin/admin_log.html:6
 #: kallithea/templates/admin/my_account/my_account_repos.html:16
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:7
 #: kallithea/templates/admin/repo_groups/repo_groups.html:43
 #: kallithea/templates/admin/repos/repo_edit_fields.html:9
 #: kallithea/templates/admin/repos/repos.html:44
 #: kallithea/templates/admin/user_groups/user_groups.html:43
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:7
 #: kallithea/templates/admin/users/users.html:45
 msgid "Action"
 msgstr "動作"
@@ -2091,22 +2128,22 @@
 msgstr ""
 
 #: kallithea/templates/admin/auth/auth_settings.html:101
-#: kallithea/templates/admin/defaults/defaults.html:67
+#: kallithea/templates/admin/defaults/defaults.html:59
 #: kallithea/templates/admin/my_account/my_account_password.html:30
 #: kallithea/templates/admin/my_account/my_account_profile.html:47
 #: kallithea/templates/admin/permissions/permissions_globals.html:95
 #: kallithea/templates/admin/repo_groups/repo_group_add.html:58
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:98
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:35
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:27
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:84
-#: kallithea/templates/admin/repos/repo_edit_settings.html:101
+#: kallithea/templates/admin/repos/repo_edit_settings.html:99
 #: kallithea/templates/admin/settings/settings_hooks.html:46
 #: kallithea/templates/admin/user_groups/user_group_add.html:48
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:88
 #: kallithea/templates/admin/user_groups/user_group_edit_settings.html:46
 #: kallithea/templates/admin/users/user_add.html:80
 #: kallithea/templates/admin/users/user_edit_profile.html:89
-#: kallithea/templates/base/default_perms_box.html:56
+#: kallithea/templates/base/default_perms_box.html:42
 msgid "Save"
 msgstr "儲存"
 
@@ -2125,14 +2162,14 @@
 
 #: kallithea/templates/admin/defaults/defaults.html:34
 #: kallithea/templates/admin/repos/repo_add_base.html:56
-#: kallithea/templates/admin/repos/repo_edit_settings.html:57
+#: kallithea/templates/admin/repos/repo_edit_settings.html:62
 #: kallithea/templates/data_table/_dt_elements.html:21
 msgid "Private repository"
 msgstr "私有的版本庫"
 
 #: kallithea/templates/admin/defaults/defaults.html:37
 #: kallithea/templates/admin/repos/repo_add_base.html:59
-#: kallithea/templates/admin/repos/repo_edit_settings.html:60
+#: kallithea/templates/admin/repos/repo_edit_settings.html:65
 #: kallithea/templates/forks/fork.html:61
 msgid ""
 "Private repositories are only visible to people explicitly added as "
@@ -2140,36 +2177,25 @@
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:42
-#: kallithea/templates/admin/repos/repo_edit_settings.html:64
+#: kallithea/templates/admin/repos/repo_edit_settings.html:69
 msgid "Enable statistics"
 msgstr "啟用統計"
 
 #: kallithea/templates/admin/defaults/defaults.html:45
-#: kallithea/templates/admin/repos/repo_edit_settings.html:67
+#: kallithea/templates/admin/repos/repo_edit_settings.html:72
 msgid "Enable statistics window on summary page."
 msgstr ""
 
 #: kallithea/templates/admin/defaults/defaults.html:50
-#: kallithea/templates/admin/repos/repo_edit_settings.html:71
+#: kallithea/templates/admin/repos/repo_edit_settings.html:76
 msgid "Enable downloads"
 msgstr "啟用下載"
 
 #: kallithea/templates/admin/defaults/defaults.html:53
-#: kallithea/templates/admin/repos/repo_edit_settings.html:74
+#: kallithea/templates/admin/repos/repo_edit_settings.html:79
 msgid "Enable download menu on summary page."
 msgstr ""
 
-#: kallithea/templates/admin/defaults/defaults.html:58
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:26
-#: kallithea/templates/admin/repos/repo_edit_settings.html:78
-msgid "Enable locking"
-msgstr ""
-
-#: kallithea/templates/admin/defaults/defaults.html:61
-#: kallithea/templates/admin/repos/repo_edit_settings.html:81
-msgid "Enable lock-by-pulling on repository."
-msgstr ""
-
 #: kallithea/templates/admin/gists/edit.html:5
 #: kallithea/templates/admin/gists/edit.html:18
 msgid "Edit Gist"
@@ -2216,8 +2242,10 @@
 #: kallithea/templates/admin/gists/show.html:45
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:7
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:26
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:21
 #: kallithea/templates/admin/users/user_edit_api_keys.html:7
 #: kallithea/templates/admin/users/user_edit_api_keys.html:26
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:21
 #, fuzzy
 msgid "Never"
 msgstr "擁有者"
@@ -2251,7 +2279,7 @@
 
 #: kallithea/templates/admin/gists/index.html:37
 #: kallithea/templates/admin/gists/show.html:25
-#: kallithea/templates/base/base.html:312
+#: kallithea/templates/base/base.html:305
 msgid "Create New Gist"
 msgstr ""
 
@@ -2287,23 +2315,25 @@
 #: kallithea/templates/admin/my_account/my_account_emails.html:47
 #: kallithea/templates/admin/my_account/my_account_password.html:31
 #: kallithea/templates/admin/my_account/my_account_profile.html:48
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:66
 #: kallithea/templates/admin/permissions/permissions_globals.html:96
 #: kallithea/templates/admin/permissions/permissions_ips.html:34
 #: kallithea/templates/admin/repo_groups/repo_group_edit_perms.html:99
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:36
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:28
 #: kallithea/templates/admin/repos/repo_edit_fields.html:54
 #: kallithea/templates/admin/repos/repo_edit_permissions.html:85
-#: kallithea/templates/admin/repos/repo_edit_settings.html:102
+#: kallithea/templates/admin/repos/repo_edit_settings.html:100
 #: kallithea/templates/admin/settings/settings_global.html:50
-#: kallithea/templates/admin/settings/settings_vcs.html:78
-#: kallithea/templates/admin/settings/settings_visual.html:116
+#: kallithea/templates/admin/settings/settings_vcs.html:66
+#: kallithea/templates/admin/settings/settings_visual.html:127
 #: kallithea/templates/admin/user_groups/user_group_edit_perms.html:89
 #: kallithea/templates/admin/users/user_edit_api_keys.html:14
 #: kallithea/templates/admin/users/user_edit_api_keys.html:73
 #: kallithea/templates/admin/users/user_edit_emails.html:47
 #: kallithea/templates/admin/users/user_edit_ips.html:45
 #: kallithea/templates/admin/users/user_edit_profile.html:90
-#: kallithea/templates/base/default_perms_box.html:57
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:66
+#: kallithea/templates/base/default_perms_box.html:43
 #: kallithea/templates/files/files_add.html:69
 #: kallithea/templates/files/files_delete.html:41
 #: kallithea/templates/files/files_edit.html:72
@@ -2331,7 +2361,7 @@
 #: kallithea/templates/admin/gists/show.html:54
 #: kallithea/templates/admin/my_account/my_account_emails.html:23
 #: kallithea/templates/admin/permissions/permissions_ips.html:11
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:68
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
 #: kallithea/templates/admin/repos/repo_edit_fields.html:19
 #: kallithea/templates/admin/settings/settings_hooks.html:30
 #: kallithea/templates/admin/users/user_edit_emails.html:23
@@ -2391,7 +2421,7 @@
 
 #: kallithea/templates/admin/my_account/my_account.html:5
 #: kallithea/templates/admin/my_account/my_account.html:9
-#: kallithea/templates/base/base.html:397
+#: kallithea/templates/base/base.html:390
 msgid "My Account"
 msgstr "我的帳號"
 
@@ -2404,26 +2434,31 @@
 msgid "Email Addresses"
 msgstr ""
 
-#: kallithea/templates/admin/my_account/my_account.html:28
-#: kallithea/templates/admin/users/user_edit.html:31
+#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/users/user_edit.html:32
+msgid "SSH Keys"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/users/user_edit.html:34
 msgid "API Keys"
 msgstr ""
 
-#: kallithea/templates/admin/my_account/my_account.html:29
+#: kallithea/templates/admin/my_account/my_account.html:32
 #, fuzzy
 msgid "Owned Repositories"
 msgstr "個版本庫"
 
-#: kallithea/templates/admin/my_account/my_account.html:30
+#: kallithea/templates/admin/my_account/my_account.html:33
 #: kallithea/templates/journal/journal.html:33
 #, fuzzy
 msgid "Watched Repositories"
 msgstr "建立版本庫"
 
-#: kallithea/templates/admin/my_account/my_account.html:31
+#: kallithea/templates/admin/my_account/my_account.html:34
 #: kallithea/templates/admin/permissions/permissions.html:30
 #: kallithea/templates/admin/user_groups/user_group_edit.html:32
-#: kallithea/templates/admin/users/user_edit.html:34
+#: kallithea/templates/admin/users/user_edit.html:37
 #, fuzzy
 msgid "Show Permissions"
 msgstr "權限"
@@ -2451,7 +2486,9 @@
 msgstr "確認移除目前的統計"
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:41
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:30
 #: kallithea/templates/admin/users/user_edit_api_keys.html:41
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:30
 #, fuzzy
 msgid "Remove"
 msgstr "移除檔案"
@@ -2468,12 +2505,14 @@
 
 #: kallithea/templates/admin/my_account/my_account_api_keys.html:72
 #: kallithea/templates/admin/my_account/my_account_emails.html:46
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:65
 #: kallithea/templates/admin/permissions/permissions_ips.html:33
 #: kallithea/templates/admin/repos/repo_add_base.html:64
 #: kallithea/templates/admin/repos/repo_edit_fields.html:53
 #: kallithea/templates/admin/users/user_edit_api_keys.html:72
 #: kallithea/templates/admin/users/user_edit_emails.html:46
 #: kallithea/templates/admin/users/user_edit_ips.html:44
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:65
 msgid "Add"
 msgstr ""
 
@@ -2577,6 +2616,46 @@
 msgid "Name"
 msgstr "名稱"
 
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:4
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:4
+msgid "Fingerprint"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:6
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:6
+#, fuzzy
+#| msgid "Last Name"
+msgid "Last Used"
+msgstr "姓"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:28
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:28
+#, fuzzy, python-format
+msgid "Confirm to remove this SSH key: %s"
+msgstr "確認移除目前的統計"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:39
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:39
+msgid "No SSH keys have been added"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:49
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:49
+msgid "New SSH key"
+msgstr ""
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:52
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:52
+#, fuzzy
+#| msgid "Public repository"
+msgid "Public key"
+msgstr "公開的版本庫"
+
+#: kallithea/templates/admin/my_account/my_account_ssh_keys.html:54
+#: kallithea/templates/admin/users/user_edit_ssh_keys.html:54
+msgid "Public key (contents of e.g. ~/.ssh/id_rsa.pub)"
+msgstr ""
+
 #: kallithea/templates/admin/my_account/my_account_watched.html:1
 #, fuzzy
 msgid "Repositories You are Watching"
@@ -2595,7 +2674,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/permissions/permissions.html:29
-#: kallithea/templates/admin/users/user_edit.html:32
+#: kallithea/templates/admin/users/user_edit.html:35
 msgid "IP Whitelist"
 msgstr ""
 
@@ -2634,7 +2713,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:28
+#: kallithea/templates/admin/repos/repo_edit_settings.html:33
 #: kallithea/templates/data_table/_dt_elements.html:134
 #: kallithea/templates/forks/fork.html:42
 msgid "Repository group"
@@ -2795,7 +2874,7 @@
 #: kallithea/templates/admin/repo_groups/repo_group_edit.html:37
 #: kallithea/templates/admin/repos/repo_edit.html:31
 #: kallithea/templates/admin/user_groups/user_group_edit.html:30
-#: kallithea/templates/admin/users/user_edit.html:33
+#: kallithea/templates/admin/users/user_edit.html:36
 msgid "Advanced"
 msgstr ""
 
@@ -2905,17 +2984,11 @@
 "private repositories and other groups if selected."
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:29
-msgid ""
-"Enable lock-by-pulling on group. This option will be applied to all other "
-"groups and repositories inside"
-msgstr ""
-
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Remove this group"
 msgstr ""
 
-#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:46
+#: kallithea/templates/admin/repo_groups/repo_group_edit_settings.html:38
 msgid "Confirm to delete this group"
 msgstr ""
 
@@ -2947,14 +3020,14 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:24
-#: kallithea/templates/admin/repos/repo_edit_settings.html:52
+#: kallithea/templates/admin/repos/repo_edit_settings.html:57
 #: kallithea/templates/forks/fork.html:37
 msgid ""
 "Keep it short and to the point. Use a README file for longer descriptions."
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:31
-#: kallithea/templates/admin/repos/repo_edit_settings.html:31
+#: kallithea/templates/admin/repos/repo_edit_settings.html:36
 #: kallithea/templates/forks/fork.html:45
 msgid "Optionally select a group to put this repository into."
 msgstr ""
@@ -2964,7 +3037,7 @@
 msgstr ""
 
 #: kallithea/templates/admin/repos/repo_add_base.html:49
-#: kallithea/templates/admin/repos/repo_edit_settings.html:35
+#: kallithea/templates/admin/repos/repo_edit_settings.html:40
 #: kallithea/templates/forks/fork.html:50
 msgid "Landing revision"
 msgstr ""
@@ -3016,8 +3089,8 @@
 
 #: kallithea/templates/admin/repos/repo_edit.html:43
 #: kallithea/templates/summary/statistics.html:8
-#: kallithea/templates/summary/summary.html:161
-#: kallithea/templates/summary/summary.html:162
+#: kallithea/templates/summary/summary.html:169
+#: kallithea/templates/summary/summary.html:170
 msgid "Statistics"
 msgstr "統計"
 
@@ -3054,74 +3127,32 @@
 "public journal."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:42
-#, fuzzy
-msgid "Change Locking"
-msgstr "修改紀錄"
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:46
+#: kallithea/templates/data_table/_dt_elements.html:68
+#, python-format
+msgid "Confirm to delete this repository: %s"
+msgstr ""
 
 #: kallithea/templates/admin/repos/repo_edit_advanced.html:48
 #, fuzzy
-msgid "Confirm to unlock repository."
-msgstr "確認廢止版本庫快取"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:50
-#, fuzzy
-msgid "Unlock Repository"
-msgstr "公開的版本庫"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:52
-#, python-format
-msgid "Locked by %s on %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:56
-#, fuzzy
-msgid "Confirm to lock repository."
-msgstr "確認廢止版本庫快取"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
-#, fuzzy
-msgid "Lock Repository"
-msgstr "公開的版本庫"
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:60
-msgid "Repository is not locked"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:63
-msgid ""
-"Force locking on the repository. Works only when anonymous access is "
-"disabled. Triggering a pull locks the repository.  The user who is "
-"pulling locks the repository; only the user who pulled and locked it can "
-"unlock it by doing a push."
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:72
-#: kallithea/templates/data_table/_dt_elements.html:68
-#, python-format
-msgid "Confirm to delete this repository: %s"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:74
-#, fuzzy
 msgid "Delete this Repository"
 msgstr "公開的版本庫"
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:77
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:51
 #, python-format
 msgid "This repository has %s fork"
 msgid_plural "This repository has %s forks"
 msgstr[0] ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:80
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:54
 msgid "Detach forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:84
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:58
 msgid "Delete forks"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_advanced.html:88
+#: kallithea/templates/admin/repos/repo_edit_advanced.html:62
 msgid ""
 "The deleted repository will be moved away and hidden until the "
 "administrator expires it. The administrator can both permanently delete "
@@ -3225,20 +3256,12 @@
 msgid "This repository does not have a remote repository URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
+#: kallithea/templates/admin/repos/repo_edit_settings.html:10
 #, fuzzy
-msgid "Permanent Repository ID"
+msgid "Permanent URL"
 msgstr "私有版本庫"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:7
-msgid "What is that?"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:9
-msgid "URL by id"
-msgstr ""
-
-#: kallithea/templates/admin/repos/repo_edit_settings.html:10
+#: kallithea/templates/admin/repos/repo_edit_settings.html:14
 msgid ""
 "In case this repository is renamed or moved into another group the "
 "repository URL changes.\n"
@@ -3248,32 +3271,32 @@
 "other cases that you need to hardcode the URL into a 3rd party service."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:16
+#: kallithea/templates/admin/repos/repo_edit_settings.html:21
 #, fuzzy
 msgid "Remote repository"
 msgstr "私有版本庫"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:19
+#: kallithea/templates/admin/repos/repo_edit_settings.html:24
 #, fuzzy
 msgid "Repository URL"
 msgstr "版本庫"
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:23
+#: kallithea/templates/admin/repos/repo_edit_settings.html:28
 msgid ""
 "Optional: URL of a remote repository. If set, the repository can be "
 "pulled from this URL."
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:38
+#: kallithea/templates/admin/repos/repo_edit_settings.html:43
 msgid "Default revision for files page, downloads, whoosh and readme"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:44
+#: kallithea/templates/admin/repos/repo_edit_settings.html:49
 #: kallithea/templates/pullrequests/pullrequest_show.html:131
 msgid "Type name of user"
 msgstr ""
 
-#: kallithea/templates/admin/repos/repo_edit_settings.html:45
+#: kallithea/templates/admin/repos/repo_edit_settings.html:50
 msgid "Change owner of this repository."
 msgstr ""
 
@@ -3386,8 +3409,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_global.html:49
-#: kallithea/templates/admin/settings/settings_vcs.html:77
-#: kallithea/templates/admin/settings/settings_visual.html:115
+#: kallithea/templates/admin/settings/settings_vcs.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:126
 #, fuzzy
 msgid "Save Settings"
 msgstr "儲存設定"
@@ -3486,10 +3509,6 @@
 msgid "Kallithea version"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:7
-msgid "Check for updates"
-msgstr ""
-
 #: kallithea/templates/admin/settings/settings_system.html:8
 msgid "Kallithea configuration file"
 msgstr ""
@@ -3510,15 +3529,7 @@
 msgid "Git path"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Upgrade info endpoint"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:13
-msgid "Note: please make sure this server can access this URL"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_system.html:23
+#: kallithea/templates/admin/settings/settings_system.html:22
 msgid "Python Packages"
 msgstr ""
 
@@ -3527,48 +3538,40 @@
 msgstr "push 後顯示版本庫大小"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:15
-msgid "Log user push commands"
-msgstr "紀錄使用者推送命令"
+msgid "Update repository after push (hg update)"
+msgstr "push後更新版本庫 (hg update)"
 
 #: kallithea/templates/admin/settings/settings_vcs.html:21
-msgid "Log user pull commands"
-msgstr "紀錄使用者抓取命令"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:27
-msgid "Update repository after push (hg update)"
-msgstr "push後更新版本庫 (hg update)"
-
-#: kallithea/templates/admin/settings/settings_vcs.html:33
 #, fuzzy
 msgid "Mercurial extensions"
 msgstr "Mercurial 版本庫"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:38
+#: kallithea/templates/admin/settings/settings_vcs.html:26
 msgid "Enable largefiles extension"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:44
+#: kallithea/templates/admin/settings/settings_vcs.html:32
 msgid "Enable hgsubversion extension"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:47
+#: kallithea/templates/admin/settings/settings_vcs.html:35
 msgid ""
 "Requires hgsubversion library to be installed. Enables cloning of remote "
 "Subversion repositories while converting them to Mercurial."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:59
+#: kallithea/templates/admin/settings/settings_vcs.html:47
 #, fuzzy
 msgid "Location of repositories"
 msgstr "建立版本庫"
 
-#: kallithea/templates/admin/settings/settings_vcs.html:64
+#: kallithea/templates/admin/settings/settings_vcs.html:52
 msgid ""
 "Click to unlock. You must restart Kallithea in order to make this setting "
 "take effect."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_vcs.html:68
+#: kallithea/templates/admin/settings/settings_vcs.html:56
 msgid ""
 "Filesystem location where repositories are stored. After changing this "
 "value, a restart and rescan of the repository folder are both required."
@@ -3617,9 +3620,8 @@
 msgstr ""
 
 #: kallithea/templates/admin/settings/settings_visual.html:40
-#: kallithea/templates/summary/summary.html:63
 #, fuzzy
-msgid "Clone URL"
+msgid "HTTP Clone URL"
 msgstr "複製連結"
 
 #: kallithea/templates/admin/settings/settings_visual.html:43
@@ -3637,59 +3639,75 @@
 "                                                    {repo}   full "
 "repository name,\n"
 "                                                    {repoid} ID of "
-"repository, can be used to construct clone-by-id"
-msgstr ""
-
-#: kallithea/templates/admin/settings/settings_visual.html:54
+"repository, can be used to construct clone-by-id,\n"
+"                                                    {system_user}  name "
+"of the Kallithea system user,\n"
+"                                                    {hostname}  server "
+"hostname\n"
+"                                                    "
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:56
+#, fuzzy
+msgid "SSH Clone URL"
+msgstr "複製連結"
+
+#: kallithea/templates/admin/settings/settings_visual.html:59
+msgid ""
+"Schema for constructing SSH clone URL, eg. 'ssh://{system_user}"
+"@{hostname}/{repo}'."
+msgstr ""
+
+#: kallithea/templates/admin/settings/settings_visual.html:65
 #, fuzzy
 #| msgid "repositories"
 msgid "Repository page size"
 msgstr "個版本庫"
 
-#: kallithea/templates/admin/settings/settings_visual.html:57
+#: kallithea/templates/admin/settings/settings_visual.html:68
 msgid ""
 "Number of items displayed in the repository pages before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:62
+#: kallithea/templates/admin/settings/settings_visual.html:73
 msgid "Admin page size"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:65
+#: kallithea/templates/admin/settings/settings_visual.html:76
 msgid ""
 "Number of items displayed in the admin pages grids before pagination is "
 "shown."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:70
+#: kallithea/templates/admin/settings/settings_visual.html:81
 msgid "Icons"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:75
+#: kallithea/templates/admin/settings/settings_visual.html:86
 msgid "Show public repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:81
+#: kallithea/templates/admin/settings/settings_visual.html:92
 msgid "Show private repository icon on repositories"
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:84
+#: kallithea/templates/admin/settings/settings_visual.html:95
 msgid "Show public/private icons next to repository names."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:89
+#: kallithea/templates/admin/settings/settings_visual.html:100
 #, fuzzy
 msgid "Meta Tagging"
 msgstr "設定"
 
-#: kallithea/templates/admin/settings/settings_visual.html:94
+#: kallithea/templates/admin/settings/settings_visual.html:105
 msgid ""
 "Parses meta tags from the repository description field and turns them "
 "into colored tags."
 msgstr ""
 
-#: kallithea/templates/admin/settings/settings_visual.html:98
+#: kallithea/templates/admin/settings/settings_visual.html:109
 msgid "Stylify recognised meta tags:"
 msgstr ""
 
@@ -3853,12 +3871,12 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:86
-#: kallithea/templates/base/base.html:424
+#: kallithea/templates/base/base.html:417
 msgid "Mercurial repository"
 msgstr "Mercurial 版本庫"
 
 #: kallithea/templates/base/base.html:89
-#: kallithea/templates/base/base.html:427
+#: kallithea/templates/base/base.html:420
 msgid "Git repository"
 msgstr "Git 版本庫"
 
@@ -3906,158 +3924,132 @@
 msgstr ""
 
 #: kallithea/templates/base/base.html:160
-#: kallithea/templates/base/base.html:322
+#: kallithea/templates/base/base.html:315
 #: kallithea/templates/search/search.html:14
 #: kallithea/templates/search/search.html:67
 msgid "Search"
 msgstr "搜尋"
 
-#: kallithea/templates/base/base.html:164
-msgid "Unlock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:166
-msgid "Lock"
-msgstr ""
-
-#: kallithea/templates/base/base.html:174
+#: kallithea/templates/base/base.html:167
 msgid "Follow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:175
+#: kallithea/templates/base/base.html:168
 msgid "Unfollow"
 msgstr ""
 
-#: kallithea/templates/base/base.html:178
+#: kallithea/templates/base/base.html:171
 #: kallithea/templates/forks/fork.html:9
 msgid "Fork"
 msgstr "分支"
 
-#: kallithea/templates/base/base.html:179
+#: kallithea/templates/base/base.html:172
 #: kallithea/templates/pullrequests/pullrequest.html:77
 msgid "Create Pull Request"
 msgstr ""
 
-#: kallithea/templates/base/base.html:191
+#: kallithea/templates/base/base.html:184
 msgid "Switch To"
 msgstr ""
 
-#: kallithea/templates/base/base.html:203
-#: kallithea/templates/base/base.html:452
+#: kallithea/templates/base/base.html:196
+#: kallithea/templates/base/base.html:445
 msgid "No matches found"
 msgstr ""
 
+#: kallithea/templates/base/base.html:289
+msgid "Show recent activity"
+msgstr ""
+
+#: kallithea/templates/base/base.html:295
 #: kallithea/templates/base/base.html:296
-msgid "Show recent activity"
+msgid "Public journal"
+msgstr "公開日誌"
+
+#: kallithea/templates/base/base.html:301
+msgid "Show public gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:302
-#: kallithea/templates/base/base.html:303
-msgid "Public journal"
-msgstr "公開日誌"
+msgid "Gists"
+msgstr ""
+
+#: kallithea/templates/base/base.html:306
+msgid "All Public Gists"
+msgstr ""
 
 #: kallithea/templates/base/base.html:308
-msgid "Show public gists"
+msgid "My Public Gists"
 msgstr ""
 
 #: kallithea/templates/base/base.html:309
-msgid "Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:313
-msgid "All Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:315
-msgid "My Public Gists"
-msgstr ""
-
-#: kallithea/templates/base/base.html:316
 msgid "My Private Gists"
 msgstr ""
 
-#: kallithea/templates/base/base.html:321
+#: kallithea/templates/base/base.html:314
 msgid "Search in repositories"
 msgstr ""
 
-#: kallithea/templates/base/base.html:344
-#: kallithea/templates/base/base.html:345
+#: kallithea/templates/base/base.html:337
+#: kallithea/templates/base/base.html:338
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:6
 #: kallithea/templates/pullrequests/pullrequest_show_my.html:10
 msgid "My Pull Requests"
 msgstr ""
 
-#: kallithea/templates/base/base.html:360
+#: kallithea/templates/base/base.html:353
 msgid "Not Logged In"
 msgstr ""
 
-#: kallithea/templates/base/base.html:369
+#: kallithea/templates/base/base.html:362
 msgid "Login to Your Account"
 msgstr ""
 
-#: kallithea/templates/base/base.html:379
+#: kallithea/templates/base/base.html:372
 #, fuzzy
 #| msgid "Forgot password ?"
 msgid "Forgot password?"
 msgstr "忘記密碼?"
 
-#: kallithea/templates/base/base.html:383
+#: kallithea/templates/base/base.html:376
 #, fuzzy
 #| msgid "Don't have an account ?"
 msgid "Don't have an account?"
 msgstr "沒有帳號?"
 
-#: kallithea/templates/base/base.html:400
+#: kallithea/templates/base/base.html:393
 msgid "Log Out"
 msgstr "登出"
 
-#: kallithea/templates/base/base.html:524
+#: kallithea/templates/base/base.html:517
 msgid "Parent rev."
 msgstr ""
 
-#: kallithea/templates/base/base.html:533
+#: kallithea/templates/base/base.html:526
 msgid "Child rev."
 msgstr ""
 
 #: kallithea/templates/base/default_perms_box.html:11
-#, fuzzy
-msgid "Inherit defaults"
-msgstr "個版本庫"
+msgid "Create repositories"
+msgstr "建立版本庫"
 
 #: kallithea/templates/base/default_perms_box.html:15
-#, python-format
-msgid ""
-"Select to inherit global settings, IP whitelist and permissions from the "
-"%s."
-msgstr ""
-
-#: kallithea/templates/base/default_perms_box.html:16
-#, fuzzy
-#| msgid "Default permissions"
-msgid "default permissions"
-msgstr "預設權限"
-
-#: kallithea/templates/base/default_perms_box.html:23
-msgid "Create repositories"
-msgstr "建立版本庫"
-
-#: kallithea/templates/base/default_perms_box.html:27
 msgid "Select this option to allow repository creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:33
+#: kallithea/templates/base/default_perms_box.html:21
 msgid "Create user groups"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:37
+#: kallithea/templates/base/default_perms_box.html:25
 msgid "Select this option to allow user group creation for this user"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:43
+#: kallithea/templates/base/default_perms_box.html:31
 msgid "Fork repositories"
 msgstr ""
 
-#: kallithea/templates/base/default_perms_box.html:47
+#: kallithea/templates/base/default_perms_box.html:35
 msgid "Select this option to allow repository forking for this user"
 msgstr ""
 
@@ -4797,7 +4789,7 @@
 msgstr ""
 
 #: kallithea/templates/files/files.html:4
-#: kallithea/templates/files/files.html:77
+#: kallithea/templates/files/files.html:74
 #, python-format
 msgid "%s Files"
 msgstr ""
@@ -4809,7 +4801,7 @@
 
 #: kallithea/templates/files/files_add.html:21
 #: kallithea/templates/files/files_ypjax.html:9
-#: kallithea/templates/summary/summary.html:191
+#: kallithea/templates/summary/summary.html:199
 msgid "Add New File"
 msgstr ""
 
@@ -4863,7 +4855,7 @@
 msgstr "載入檔案列表..."
 
 #: kallithea/templates/files/files_browser.html:55
-#: kallithea/templates/summary/summary.html:145
+#: kallithea/templates/summary/summary.html:153
 msgid "Size"
 msgstr "大小"
 
@@ -4993,8 +4985,8 @@
 msgstr ""
 
 #: kallithea/templates/followers/followers.html:9
-#: kallithea/templates/summary/summary.html:130
-#: kallithea/templates/summary/summary.html:131
+#: kallithea/templates/summary/summary.html:138
+#: kallithea/templates/summary/summary.html:139
 msgid "Followers"
 msgstr "追蹤者"
 
@@ -5045,8 +5037,8 @@
 msgstr ""
 
 #: kallithea/templates/forks/forks.html:9
-#: kallithea/templates/summary/summary.html:136
-#: kallithea/templates/summary/summary.html:137
+#: kallithea/templates/summary/summary.html:144
+#: kallithea/templates/summary/summary.html:145
 msgid "Forks"
 msgstr ""
 
@@ -5360,9 +5352,9 @@
 msgid "File names"
 msgstr "檔案名稱"
 
-#: kallithea/templates/search/search_commit.html:29
-#: kallithea/templates/search/search_content.html:17
-#: kallithea/templates/search/search_path.html:14
+#: kallithea/templates/search/search_commit.html:30
+#: kallithea/templates/search/search_content.html:18
+#: kallithea/templates/search/search_path.html:15
 msgid "Permission denied"
 msgstr "權限不足"
 
@@ -5372,20 +5364,20 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:16
-#: kallithea/templates/summary/summary.html:36
+#: kallithea/templates/summary/summary.html:27
 #, python-format
 msgid "%s ATOM feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:17
-#: kallithea/templates/summary/summary.html:37
+#: kallithea/templates/summary/summary.html:28
 #, python-format
 msgid "%s RSS feed"
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:35
-#: kallithea/templates/summary/summary.html:91
-#: kallithea/templates/summary/summary.html:105
+#: kallithea/templates/summary/summary.html:99
+#: kallithea/templates/summary/summary.html:113
 msgid "Enable"
 msgstr ""
 
@@ -5394,12 +5386,12 @@
 msgstr ""
 
 #: kallithea/templates/summary/statistics.html:87
-#: kallithea/templates/summary/summary.html:354
+#: kallithea/templates/summary/summary.html:371
 msgid "files"
 msgstr "檔案"
 
 #: kallithea/templates/summary/statistics.html:111
-#: kallithea/templates/summary/summary.html:384
+#: kallithea/templates/summary/summary.html:401
 msgid "Show more"
 msgstr ""
 
@@ -5440,97 +5432,145 @@
 msgid "%s Summary"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:14
-#, python-format
-msgid "Repository locked by %s"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:16
-msgid "Repository unlocked"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:22
+#: kallithea/templates/summary/summary.html:13
 msgid "Fork of"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:27
+#: kallithea/templates/summary/summary.html:18
 msgid "Clone from"
 msgstr "複製由"
 
-#: kallithea/templates/summary/summary.html:68
-msgid "Show by ID"
-msgstr ""
-
+#: kallithea/templates/summary/summary.html:54
+#, fuzzy
+msgid "Clone URL"
+msgstr "複製連結"
+
+#: kallithea/templates/summary/summary.html:63
+msgid "Use ID"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:65
 #: kallithea/templates/summary/summary.html:73
-msgid "Show by Name"
-msgstr ""
-
-#: kallithea/templates/summary/summary.html:84
+msgid "Use SSH"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:71
+#, fuzzy
+#| msgid "Last Name"
+msgid "Use Name"
+msgstr "姓"
+
+#: kallithea/templates/summary/summary.html:80
+msgid "Use HTTP"
+msgstr ""
+
+#: kallithea/templates/summary/summary.html:92
 msgid "Trending files"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:98
+#: kallithea/templates/summary/summary.html:106
 msgid "Download"
 msgstr "下載"
 
-#: kallithea/templates/summary/summary.html:101
+#: kallithea/templates/summary/summary.html:109
 msgid "There are no downloads yet"
 msgstr "沒有任何下載"
 
-#: kallithea/templates/summary/summary.html:103
+#: kallithea/templates/summary/summary.html:111
 msgid "Downloads are disabled for this repository"
 msgstr "這個版本庫的下載已停用"
 
-#: kallithea/templates/summary/summary.html:109
+#: kallithea/templates/summary/summary.html:117
 msgid "Download as zip"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:113
+#: kallithea/templates/summary/summary.html:121
 msgid "Check this to download archive with subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:115
+#: kallithea/templates/summary/summary.html:123
 msgid "With subrepos"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:153
-#: kallithea/templates/summary/summary.html:155
+#: kallithea/templates/summary/summary.html:161
+#: kallithea/templates/summary/summary.html:163
 msgid "Feed"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:175
+#: kallithea/templates/summary/summary.html:183
 #, fuzzy
 msgid "Latest Changes"
 msgstr "多個檔案修改"
 
-#: kallithea/templates/summary/summary.html:177
+#: kallithea/templates/summary/summary.html:185
 #, fuzzy
 msgid "Quick Start"
 msgstr "快速過濾..."
 
-#: kallithea/templates/summary/summary.html:188
+#: kallithea/templates/summary/summary.html:196
 msgid "Add or upload files directly via Kallithea"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:196
+#: kallithea/templates/summary/summary.html:204
 #, fuzzy
 msgid "Push new repository"
 msgstr "私有版本庫"
 
-#: kallithea/templates/summary/summary.html:204
+#: kallithea/templates/summary/summary.html:212
 msgid "Existing repository?"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:222
+#: kallithea/templates/summary/summary.html:230
 #, python-format
 msgid "Readme file from revision %s:%s"
 msgstr ""
 
-#: kallithea/templates/summary/summary.html:298
+#: kallithea/templates/summary/summary.html:315
 #, python-format
 msgid "Download %s as %s"
 msgstr "下載 %s 為 %s"
 
+#~ msgid "Repository has been locked"
+#~ msgstr "儲存所已被鎖定"
+
+#~ msgid "Repository has been unlocked"
+#~ msgstr "儲存所已打開"
+
+#, fuzzy
+#~ msgid "Change Locking"
+#~ msgstr "修改紀錄"
+
+#, fuzzy
+#~ msgid "Confirm to unlock repository."
+#~ msgstr "確認廢止版本庫快取"
+
+#, fuzzy
+#~ msgid "Unlock Repository"
+#~ msgstr "公開的版本庫"
+
+#, fuzzy
+#~ msgid "Confirm to lock repository."
+#~ msgstr "確認廢止版本庫快取"
+
+#, fuzzy
+#~ msgid "Lock Repository"
+#~ msgstr "公開的版本庫"
+
+#~ msgid "Log user push commands"
+#~ msgstr "紀錄使用者推送命令"
+
+#~ msgid "Log user pull commands"
+#~ msgstr "紀錄使用者抓取命令"
+
+#, fuzzy
+#~ msgid "Inherit defaults"
+#~ msgstr "個版本庫"
+
+#, fuzzy
+#~| msgid "Default permissions"
+#~ msgid "default permissions"
+#~ msgstr "預設權限"
+
 #~ msgid "There is no index to search in. Please run whoosh indexer"
 #~ msgstr "沒有任何索引可以搜尋。請執行 whoosh 建立索引"
 
@@ -5586,9 +5626,6 @@
 #~ msgid "invalid user name"
 #~ msgstr "無效的使用者名稱"
 
-#~ msgid "Your account is disabled"
-#~ msgstr "您的帳號已被停用"
-
 #~ msgid "invalid clone URL"
 #~ msgstr "無效的複製URL"
 
--- a/kallithea/lib/annotate.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/annotate.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,10 +27,11 @@
 
 import StringIO
 
+from pygments import highlight
+from pygments.formatters import HtmlFormatter
+
 from kallithea.lib.vcs.exceptions import VCSError
 from kallithea.lib.vcs.nodes import FileNode
-from pygments.formatters import HtmlFormatter
-from pygments import highlight
 
 
 def annotate_highlight(filenode, annotate_from_changeset_func=None,
@@ -89,7 +90,8 @@
         self.order = order or ('ls', 'annotate', 'code')
         headers = options.pop('headers', None)
         if headers and not ('ls' in headers and 'annotate' in headers and
-            'code' in headers):
+            'code' in headers
+        ):
             raise ValueError("If headers option dict is specified it must "
                 "all 'ls', 'annotate' and 'code' keys")
         self.headers = headers
--- a/kallithea/lib/auth.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/auth.py	Sun Jan 05 04:07:51 2020 +0100
@@ -24,36 +24,29 @@
 :copyright: (c) 2013 RhodeCode GmbH, and others.
 :license: GPLv3, see LICENSE.md for more details.
 """
-import os
-import logging
-import traceback
 import hashlib
 import itertools
-import collections
+import logging
+import os
 
+import ipaddr
 from decorator import decorator
-
-from tg import request, session
+from sqlalchemy.orm import joinedload
+from sqlalchemy.orm.exc import ObjectDeletedError
+from tg import request
 from tg.i18n import ugettext as _
-from webhelpers.pylonslib import secure_form
-from sqlalchemy.orm.exc import ObjectDeletedError
-from sqlalchemy.orm import joinedload
-from webob.exc import HTTPFound, HTTPBadRequest, HTTPForbidden, HTTPMethodNotAllowed
+from webob.exc import HTTPForbidden, HTTPFound
 
-from kallithea import __platform__, is_windows, is_unix
+from kallithea import __platform__, is_unix, is_windows
 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.utils2 import safe_str, safe_unicode
 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.meta import Session
 from kallithea.model.user import UserModel
-from kallithea.model.db import User, Repository, Permission, \
-    UserToPerm, UserGroupRepoToPerm, UserGroupToPerm, UserGroupMember, \
-    RepoGroup, UserGroupRepoGroupToPerm, UserIpMap, UserGroupUserGroupToPerm, \
-    UserGroup, UserApiKeys
-
-from kallithea.lib.utils2 import safe_str, safe_unicode, aslist
-from kallithea.lib.utils import get_repo_slug, get_repo_group_slug, \
-    get_user_group_slug, conditional_cache
-from kallithea.lib.caching_query import FromCache
 
 
 log = logging.getLogger(__name__)
@@ -132,8 +125,7 @@
                         % __platform__)
 
 
-def _cached_perms_data(user_id, user_is_admin, user_inherit_default_permissions,
-                       explicit):
+def _cached_perms_data(user_id, user_is_admin):
     RK = 'repositories'
     GK = 'repositories_groups'
     UK = 'user_groups'
@@ -141,12 +133,16 @@
     PERM_WEIGHTS = Permission.PERM_WEIGHTS
     permissions = {RK: {}, GK: {}, UK: {}, GLOBAL: set()}
 
-    def _choose_perm(new_perm, cur_perm):
+    def bump_permission(kind, key, new_perm):
+        """Add a new permission for kind and key.
+        Assuming the permissions are comparable, set the new permission if it
+        has higher weight, else drop it and keep the old permission.
+        """
+        cur_perm = permissions[kind][key]
         new_perm_val = PERM_WEIGHTS[new_perm]
         cur_perm_val = PERM_WEIGHTS[cur_perm]
         if new_perm_val > cur_perm_val:
-            return new_perm
-        return cur_perm
+            permissions[kind][key] = new_perm
 
     #======================================================================
     # fetch default permissions
@@ -200,15 +196,12 @@
     # defaults for repositories, taken from default user
     for perm in default_repo_perms:
         r_k = perm.UserRepoToPerm.repository.repo_name
-        if perm.Repository.private and not (perm.Repository.owner_id == user_id):
-            # disable defaults for private repos,
+        if perm.Repository.owner_id == user_id:
+            p = 'repository.admin'
+        elif perm.Repository.private:
             p = 'repository.none'
-        elif perm.Repository.owner_id == user_id:
-            # set admin if owner
-            p = 'repository.admin'
         else:
             p = perm.Permission.permission_name
-
         permissions[RK][r_k] = p
 
     # defaults for repository groups taken from default user permission
@@ -226,14 +219,8 @@
         permissions[UK][u_k] = p
 
     #======================================================================
-    # !! OVERRIDE GLOBALS !! with user permissions if any found
+    # !! Augment GLOBALS with user permissions if any found !!
     #======================================================================
-    # those can be configured from groups or users explicitly
-    _configurable = set([
-        'hg.fork.none', 'hg.fork.repository',
-        'hg.create.none', 'hg.create.repository',
-        'hg.usergroup.create.false', 'hg.usergroup.create.true'
-    ])
 
     # USER GROUPS comes first
     # user group global permissions
@@ -253,14 +240,6 @@
                 itertools.groupby(user_perms_from_users_groups,
                                   lambda x:x.users_group)]
     for gr, perms in _grouped:
-        # since user can be in multiple groups iterate over them and
-        # select the lowest permissions first (more explicit)
-        # TODO: do this^^
-        if not gr.inherit_default_permissions:
-            # NEED TO IGNORE all configurable permissions and
-            # replace them with explicitly set
-            permissions[GLOBAL] = permissions[GLOBAL] \
-                                            .difference(_configurable)
         for perm in perms:
             permissions[GLOBAL].add(perm.permission.permission_name)
 
@@ -269,14 +248,15 @@
             .options(joinedload(UserToPerm.permission)) \
             .filter(UserToPerm.user_id == user_id).all()
 
-    if not user_inherit_default_permissions:
-        # NEED TO IGNORE all configurable permissions and
-        # replace them with explicitly set
-        permissions[GLOBAL] = permissions[GLOBAL] \
-                                        .difference(_configurable)
+    for perm in user_perms:
+        permissions[GLOBAL].add(perm.permission.permission_name)
 
-        for perm in user_perms:
-            permissions[GLOBAL].add(perm.permission.permission_name)
+    # for each kind of global permissions, only keep the one with heighest weight
+    kind_max_perm = {}
+    for perm in sorted(permissions[GLOBAL], key=lambda n: PERM_WEIGHTS[n]):
+        kind = perm.rsplit('.', 1)[0]
+        kind_max_perm[kind] = perm
+    permissions[GLOBAL] = set(kind_max_perm.values())
     ## END GLOBAL PERMISSIONS
 
     #======================================================================
@@ -302,35 +282,17 @@
         .filter(UserGroupMember.user_id == user_id) \
         .all()
 
-    multiple_counter = collections.defaultdict(int)
     for perm in user_repo_perms_from_users_groups:
-        r_k = perm.UserGroupRepoToPerm.repository.repo_name
-        multiple_counter[r_k] += 1
-        p = perm.Permission.permission_name
-        cur_perm = permissions[RK][r_k]
+        bump_permission(RK,
+            perm.UserGroupRepoToPerm.repository.repo_name,
+            perm.Permission.permission_name)
 
-        if perm.Repository.owner_id == user_id:
-            # set admin if owner
-            p = 'repository.admin'
-        else:
-            if multiple_counter[r_k] > 1:
-                p = _choose_perm(p, cur_perm)
-        permissions[RK][r_k] = p
-
-    # user explicit permissions for repositories, overrides any specified
-    # by the group permission
+    # user permissions for repositories
     user_repo_perms = Permission.get_default_perms(user_id)
     for perm in user_repo_perms:
-        r_k = perm.UserRepoToPerm.repository.repo_name
-        cur_perm = permissions[RK][r_k]
-        # set admin if owner
-        if perm.Repository.owner_id == user_id:
-            p = 'repository.admin'
-        else:
-            p = perm.Permission.permission_name
-            if not explicit:
-                p = _choose_perm(p, cur_perm)
-        permissions[RK][r_k] = p
+        bump_permission(RK,
+            perm.UserRepoToPerm.repository.repo_name,
+            perm.Permission.permission_name)
 
     #======================================================================
     # !! PERMISSIONS FOR REPOSITORY GROUPS !!
@@ -353,25 +315,17 @@
      .filter(UserGroupMember.user_id == user_id) \
      .all()
 
-    multiple_counter = collections.defaultdict(int)
     for perm in user_repo_group_perms_from_users_groups:
-        g_k = perm.UserGroupRepoGroupToPerm.group.group_name
-        multiple_counter[g_k] += 1
-        p = perm.Permission.permission_name
-        cur_perm = permissions[GK][g_k]
-        if multiple_counter[g_k] > 1:
-            p = _choose_perm(p, cur_perm)
-        permissions[GK][g_k] = p
+        bump_permission(GK,
+            perm.UserGroupRepoGroupToPerm.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:
-        rg_k = perm.UserRepoGroupToPerm.group.group_name
-        p = perm.Permission.permission_name
-        cur_perm = permissions[GK][rg_k]
-        if not explicit:
-            p = _choose_perm(p, cur_perm)
-        permissions[GK][rg_k] = p
+        bump_permission(GK,
+            perm.UserRepoGroupToPerm.group.group_name,
+            perm.Permission.permission_name)
 
     #======================================================================
     # !! PERMISSIONS FOR USER GROUPS !!
@@ -391,51 +345,21 @@
      .filter(UserGroup.users_group_active == True) \
      .all()
 
-    multiple_counter = collections.defaultdict(int)
     for perm in user_group_user_groups_perms:
-        g_k = perm.UserGroupUserGroupToPerm.target_user_group.users_group_name
-        multiple_counter[g_k] += 1
-        p = perm.Permission.permission_name
-        cur_perm = permissions[UK][g_k]
-        if multiple_counter[g_k] > 1:
-            p = _choose_perm(p, cur_perm)
-        permissions[UK][g_k] = p
+        bump_permission(UK,
+            perm.UserGroupUserGroupToPerm.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:
-        u_k = perm.UserUserGroupToPerm.user_group.users_group_name
-        p = perm.Permission.permission_name
-        cur_perm = permissions[UK][u_k]
-        if not explicit:
-            p = _choose_perm(p, cur_perm)
-        permissions[UK][u_k] = p
+        bump_permission(UK,
+            perm.UserUserGroupToPerm.user_group.users_group_name,
+            perm.Permission.permission_name)
 
     return permissions
 
 
-def allowed_api_access(controller_name, whitelist=None, api_key=None):
-    """
-    Check if given controller_name is in whitelist API access
-    """
-    if not whitelist:
-        from kallithea import CONFIG
-        whitelist = aslist(CONFIG.get('api_access_controllers_whitelist'),
-                           sep=',')
-        log.debug('whitelist of API access is: %s', whitelist)
-    api_access_valid = controller_name in whitelist
-    if api_access_valid:
-        log.debug('controller:%s is in API whitelist', controller_name)
-    else:
-        msg = 'controller: %s is *NOT* in API whitelist' % (controller_name)
-        if api_key:
-            # if we use API key and don't have access it's a warning
-            log.warning(msg)
-        else:
-            log.debug(msg)
-    return api_access_valid
-
-
 class AuthUser(object):
     """
     Represents a Kallithea user, including various authentication and
@@ -448,10 +372,9 @@
     adding various non-persistent data. If lookup fails but anonymous
     access to Kallithea is enabled, the default user is loaded instead.
 
-    `AuthUser` does not by itself authenticate users and the constructor
-    sets the `is_authenticated` field to False. It's up to other parts
-    of the code to check e.g. if a supplied password is correct, and if
-    so, set `is_authenticated` to True.
+    `AuthUser` does not by itself authenticate users. It's up to other parts of
+    the code to check e.g. if a supplied password is correct, and if so, trust
+    the AuthUser object as an authenticated user.
 
     However, `AuthUser` does refuse to load a user that is not `active`.
 
@@ -468,12 +391,26 @@
     "default". Use `is_anonymous` to check for both "default" and "no user".
     """
 
-    def __init__(self, user_id=None, dbuser=None, authenticating_api_key=None,
-            is_external_auth=False):
+    @classmethod
+    def make(cls, dbuser=None, is_external_auth=False, ip_addr=None):
+        """Create an AuthUser to be authenticated ... or return None if user for some reason can't be authenticated.
+        Checks that a non-None dbuser is provided, is active, and that the IP address is ok.
+        """
+        assert ip_addr is not None
+        if dbuser is None:
+            log.info('No db user for authentication')
+            return None
+        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)
+        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
+        return cls(dbuser=dbuser, is_external_auth=is_external_auth)
 
-        self.is_authenticated = False
-        self.is_external_auth = is_external_auth
-        self.authenticating_api_key = authenticating_api_key
+    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
@@ -485,49 +422,29 @@
         self.lastname = ''
         self.email = ''
         self.admin = False
-        self.inherit_default_permissions = False
 
         # Look up database user, if necessary.
         if user_id is not None:
+            assert dbuser is None
             log.debug('Auth User lookup by USER ID %s', user_id)
             dbuser = UserModel().get(user_id)
+            assert dbuser is not None
         else:
-            # Note: dbuser is allowed to be None.
+            assert dbuser is not None
             log.debug('Auth User lookup by database user %s', dbuser)
 
-        is_user_loaded = self._fill_data(dbuser)
-
-        # If user cannot be found, try falling back to anonymous.
-        if is_user_loaded:
-            assert dbuser is not None
-            self.is_default_user = dbuser.is_default_user
+        log.debug('filling %s data', dbuser)
+        self.is_anonymous = dbuser.is_default_user
+        if dbuser.is_default_user and not dbuser.active:
+            self.username = 'None'
+            self.is_default_user = False
         else:
-            default_user = User.get_default_user(cache=True)
-            is_user_loaded = self._fill_data(default_user)
-            self.is_default_user = is_user_loaded
-
-        self.is_anonymous = not is_user_loaded or self.is_default_user
-
-        if not self.username:
-            self.username = 'None'
-
-        log.debug('Auth User is now %s', self)
-
-    def _fill_data(self, dbuser):
-        """
-        Copies database fields from a `db.User` to this `AuthUser`. Does
-        not copy `api_keys` and `permissions` attributes.
-
-        Checks that `dbuser` is `active` (and not None) before copying;
-        returns True on success.
-        """
-        if dbuser is not None and dbuser.active:
-            log.debug('filling %s data', dbuser)
+            # copy non-confidential database fields from a `db.User` to this `AuthUser`.
             for k, v in dbuser.get_dict().iteritems():
                 assert k not in ['api_keys', 'permissions']
                 setattr(self, k, v)
-            return True
-        return False
+            self.is_default_user = dbuser.is_default_user
+        log.debug('Auth User is now %s', self)
 
     @LazyProperty
     def permissions(self):
@@ -573,27 +490,21 @@
     def api_keys(self):
         return self._get_api_keys()
 
-    def __get_perms(self, user, explicit=True, cache=False):
+    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
-        :param explicit: In case there are permissions both for user and a group
-            that user is part of, explicit flag will define if user will
-            explicitly override permissions from group, if it's False it will
-            compute the decision
         """
         user_id = user.user_id
         user_is_admin = user.is_admin
-        user_inherit_default_permissions = user.inherit_default_permissions
 
         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,
-                       user_inherit_default_permissions, explicit)
+        return compute(user_id, user_is_admin)
 
     def _get_api_keys(self):
         api_keys = [self.api_key]
@@ -631,25 +542,8 @@
         return [x[0] for x in self.permissions['user_groups'].iteritems()
                 if x[1] == 'usergroup.admin']
 
-    @staticmethod
-    def check_ip_allowed(user, ip_addr):
-        """
-        Check if the given IP address (a `str`) is allowed for the given
-        user (an `AuthUser` or `db.User`).
-        """
-        allowed_ips = AuthUser.get_allowed_ips(user.user_id, cache=True,
-            inherit_from_default=user.inherit_default_permissions)
-        if check_ip_access(source_ip=ip_addr, allowed_ips=allowed_ips):
-            log.debug('IP:%s is in range of %s', ip_addr, allowed_ips)
-            return True
-        else:
-            log.info('Access for IP:%s forbidden, '
-                     'not in %s' % (ip_addr, allowed_ips))
-            return False
-
     def __repr__(self):
-        return "<AuthUser('id:%s[%s] auth:%s')>" \
-            % (self.user_id, self.username, (self.is_authenticated or self.is_default_user))
+        return "<AuthUser('id:%s[%s]')>" % (self.user_id, self.username)
 
     def to_cookie(self):
         """ Serializes this login session to a cookie `dict`. """
@@ -659,43 +553,37 @@
         }
 
     @staticmethod
-    def from_cookie(cookie):
+    def from_cookie(cookie, ip_addr):
         """
-        Deserializes an `AuthUser` from a cookie `dict`.
+        Deserializes an `AuthUser` from a cookie `dict` ... or return None.
         """
-
-        au = AuthUser(
-            user_id=cookie.get('user_id'),
+        return AuthUser.make(
+            dbuser=UserModel().get(cookie.get('user_id')),
             is_external_auth=cookie.get('is_external_auth', False),
+            ip_addr=ip_addr,
         )
-        au.is_authenticated = True
-        return au
 
     @classmethod
-    def get_allowed_ips(cls, user_id, cache=False, inherit_from_default=False):
+    def get_allowed_ips(cls, user_id, cache=False):
         _set = set()
 
-        if inherit_from_default:
-            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"))
-
-            # populate from default user
-            for ip in default_ips:
-                try:
-                    _set.add(ip.ip_addr)
-                except ObjectDeletedError:
-                    # since we use heavy caching sometimes it happens that we get
-                    # deleted objects here, we just skip them
-                    pass
+        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"))
+        for ip in default_ips:
+            try:
+                _set.add(ip.ip_addr)
+            except ObjectDeletedError:
+                # since we use heavy caching sometimes it happens that we get
+                # deleted objects here, we just skip them
+                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)
@@ -748,13 +636,10 @@
     If the "default" user is enabled and allow_default_user is true, that is
     considered valid too.
 
-    Also checks that IP address is allowed, and if using API key instead
-    of regular cookie authentication, checks that API key access is allowed
-    (based on `api_access` parameter and the API view whitelist).
+    Also checks that IP address is allowed.
     """
 
-    def __init__(self, api_access=False, allow_default_user=False):
-        self.api_access = api_access
+    def __init__(self, allow_default_user=False):
         self.allow_default_user = allow_default_user
 
     def __call__(self, func):
@@ -766,42 +651,17 @@
         loc = "%s:%s" % (controller.__class__.__name__, func.__name__)
         log.debug('Checking access for user %s @ %s', user, loc)
 
-        # Check if we used an API key to authenticate.
-        api_key = user.authenticating_api_key
-        if api_key is not None:
-            # Check that controller is enabled for API key usage.
-            if not self.api_access and not allowed_api_access(loc, api_key=api_key):
-                # controller does not allow API access
-                log.warning('API access to %s is not allowed', loc)
-                raise HTTPForbidden()
-
-            log.info('user %s authenticated with API key ****%s @ %s',
-                     user, api_key[-4:], loc)
-            return func(*fargs, **fkwargs)
-
-        # CSRF protection: Whenever a request has ambient authority (whether
-        # through a session cookie or its origin IP address), it must include
-        # the correct token, unless the HTTP method is GET or HEAD (and thus
-        # guaranteed to be side effect free. In practice, the only situation
-        # where we allow side effects without ambient authority is when the
-        # authority comes from an API key; and that is handled above.
-        if request.method not in ['GET', 'HEAD']:
-            token = request.POST.get(secure_form.token_key)
-            if not token or token != secure_form.authentication_token():
-                log.error('CSRF check failed')
-                raise HTTPForbidden()
-
         # regular user authentication
-        if user.is_authenticated:
-            log.info('user %s authenticated with regular auth @ %s', user, loc)
-            return func(*fargs, **fkwargs)
-        elif user.is_default_user:
+        if user.is_default_user:
             if self.allow_default_user:
                 log.info('default user @ %s', loc)
                 return func(*fargs, **fkwargs)
             log.info('default user is not accepted here @ %s', loc)
-        else:
-            log.warning('user %s NOT authenticated with regular auth @ %s', user, loc)
+        elif user.is_anonymous: # default user is disabled and no proper authentication
+            log.warning('user is anonymous and NOT authenticated with regular auth @ %s', loc)
+        else: # regular authentication
+            log.info('user %s authenticated with regular auth @ %s', user, loc)
+            return func(*fargs, **fkwargs)
         raise _redirect_to_login()
 
 
@@ -933,8 +793,8 @@
         global_permissions = request.authuser.permissions['global'] # usually very short
         ok = any(p in global_permissions for p in self.required_perms)
 
-        log.debug('Check %s for global %s (%s): %s' %
-            (request.authuser.username, self.required_perms, purpose, ok))
+        log.debug('Check %s for global %s (%s): %s',
+            request.authuser.username, self.required_perms, purpose, ok)
         return ok
 
 
@@ -972,18 +832,17 @@
     def __init__(self, *perms):
         self.required_perms = set(perms)
 
-    def __call__(self, user, repo_name, purpose=None):
+    def __call__(self, authuser, repo_name, purpose=None):
         # repo_name MUST be unicode, since we handle keys in ok
         # dict by unicode
         repo_name = safe_unicode(repo_name)
-        user = AuthUser(user.user_id)
 
         try:
-            ok = user.permissions['repositories'][repo_name] in self.required_perms
+            ok = authuser.permissions['repositories'][repo_name] in self.required_perms
         except KeyError:
             ok = False
 
-        log.debug('Middleware check %s for %s for repo %s (%s): %s' % (user.username, self.required_perms, repo_name, purpose, ok))
+        log.debug('Middleware check %s for %s for repo %s (%s): %s', authuser.username, self.required_perms, repo_name, purpose, ok)
         return ok
 
 
@@ -994,7 +853,6 @@
     :param source_ip:
     :param allowed_ips: list of allowed ips together with mask
     """
-    from kallithea.lib import ipaddr
     source_ip = source_ip.split('%', 1)[0]
     log.debug('checking if ip:%s is subnet of %s', source_ip, allowed_ips)
     if isinstance(allowed_ips, (tuple, list, set)):
--- a/kallithea/lib/auth_modules/__init__.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/auth_modules/__init__.py	Sun Jan 05 04:07:51 2020 +0100
@@ -15,18 +15,19 @@
 Authentication modules
 """
 
+import importlib
 import logging
 import traceback
-import importlib
 
+from kallithea.lib.auth import AuthUser, PasswordGenerator
+from kallithea.lib.compat import formatted_json, hybrid_property
 from kallithea.lib.utils2 import str2bool
-from kallithea.lib.compat import formatted_json, hybrid_property
-from kallithea.lib.auth import PasswordGenerator, AuthUser
-from kallithea.model.user import UserModel
 from kallithea.model.db import Setting, User
 from kallithea.model.meta import Session
+from kallithea.model.user import UserModel
 from kallithea.model.user_group import UserGroupModel
 
+
 log = logging.getLogger(__name__)
 
 
@@ -362,7 +363,7 @@
                                settings=plugin_settings)
         log.debug('Plugin %s extracted user `%s`', module, user)
 
-        if user is not None and not user.active:
+        if user is not None and not user.active: # give up, way before creating AuthUser
             log.error("Rejecting authentication of in-active user %s", user)
             continue
 
--- a/kallithea/lib/auth_modules/auth_container.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/auth_modules/auth_container.py	Sun Jan 05 04:07:51 2020 +0100
@@ -26,10 +26,12 @@
 """
 
 import logging
+
 from kallithea.lib import auth_modules
-from kallithea.lib.utils2 import str2bool, safe_unicode, safe_str
 from kallithea.lib.compat import hybrid_property
-from kallithea.model.db import User, Setting
+from kallithea.lib.utils2 import safe_str, safe_unicode, str2bool
+from kallithea.model.db import Setting
+
 
 log = logging.getLogger(__name__)
 
--- a/kallithea/lib/auth_modules/auth_crowd.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/auth_modules/auth_crowd.py	Sun Jan 05 04:07:51 2020 +0100
@@ -29,9 +29,10 @@
 import base64
 import logging
 import urllib2
+
 from kallithea.lib import auth_modules
-from kallithea.lib.compat import json, formatted_json, hybrid_property
-from kallithea.model.db import User
+from kallithea.lib.compat import formatted_json, hybrid_property, json
+
 
 log = logging.getLogger(__name__)
 
--- a/kallithea/lib/auth_modules/auth_internal.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/auth_modules/auth_internal.py	Sun Jan 05 04:07:51 2020 +0100
@@ -32,6 +32,7 @@
 from kallithea.lib.compat import formatted_json, hybrid_property
 from kallithea.model.db import User
 
+
 log = logging.getLogger(__name__)
 
 
--- a/kallithea/lib/auth_modules/auth_ldap.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/auth_modules/auth_ldap.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,15 +27,12 @@
 
 
 import logging
-import traceback
 
 from kallithea.lib import auth_modules
 from kallithea.lib.compat import hybrid_property
-from kallithea.lib.utils2 import safe_unicode, safe_str
-from kallithea.lib.exceptions import (
-    LdapConnectionError, LdapUsernameError, LdapPasswordError, LdapImportError
-)
-from kallithea.model.db import User
+from kallithea.lib.exceptions import LdapConnectionError, LdapImportError, LdapPasswordError, LdapUsernameError
+from kallithea.lib.utils2 import safe_str, safe_unicode
+
 
 log = logging.getLogger(__name__)
 
--- a/kallithea/lib/auth_modules/auth_pam.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/auth_modules/auth_pam.py	Sun Jan 05 04:07:51 2020 +0100
@@ -23,9 +23,18 @@
 :author: Alexey Larikov
 """
 
+import grp
 import logging
+import pwd
+import re
+import socket
+import threading
 import time
 
+from kallithea.lib import auth_modules
+from kallithea.lib.compat import formatted_json, hybrid_property
+
+
 try:
     from pam import authenticate as pam_authenticate
 except ImportError:
@@ -33,14 +42,7 @@
     from pam import pam
     pam_authenticate = pam().authenticate
 
-import pwd
-import grp
-import re
-import socket
-import threading
 
-from kallithea.lib import auth_modules
-from kallithea.lib.compat import formatted_json, hybrid_property
 
 log = logging.getLogger(__name__)
 
@@ -82,7 +84,7 @@
                 "type": "string",
                 "description": "Regex for extracting user name/email etc "
                                "from Unix userinfo",
-                "default": "(?P<last_name>.+),\s*(?P<first_name>\w+)",
+                "default": r"(?P<last_name>.+),\s*(?P<first_name>\w+)",
                 "formname": "Gecos Regex"
             }
         ]
--- a/kallithea/lib/base.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/base.py	Sun Jan 05 04:07:51 2020 +0100
@@ -29,37 +29,33 @@
 """
 
 import datetime
-import decorator
 import logging
 import time
 import traceback
 import warnings
 
-import webob.exc
+import decorator
+import paste.auth.basic
 import paste.httpexceptions
-import paste.auth.basic
 import paste.httpheaders
-from webhelpers.pylonslib import secure_form
-
-from tg import config, tmpl_context as c, request, response, session, render_template
-from tg import TGController
+import webob.exc
+from tg import TGController, config, render_template, request, response, session
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
 
-from kallithea import __version__, BACKENDS
-
+from kallithea import BACKENDS, __version__
 from kallithea.config.routing import url
-from kallithea.lib.utils2 import str2bool, safe_unicode, AttributeDict, \
-    safe_str, safe_int
 from kallithea.lib import auth_modules
 from kallithea.lib.auth import AuthUser, HasPermissionAnyMiddleware
 from kallithea.lib.compat import json
-from kallithea.lib.utils import get_repo_slug
 from kallithea.lib.exceptions import UserCreationError
-from kallithea.lib.vcs.exceptions import RepositoryError, EmptyRepositoryError, ChangesetDoesNotExistError
+from kallithea.lib.utils import get_repo_slug, is_valid_repo
+from kallithea.lib.utils2 import AttributeDict, safe_int, safe_str, safe_unicode, set_hook_environment, str2bool
+from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError
 from kallithea.model import meta
+from kallithea.model.db import PullRequest, Repository, Setting, User
+from kallithea.model.scm import ScmModel
 
-from kallithea.model.db import PullRequest, Repository, Ui, User, Setting
-from kallithea.model.scm import ScmModel
 
 log = logging.getLogger(__name__)
 
@@ -102,14 +98,14 @@
 
 
 def _get_access_path(environ):
-    path = environ.get('PATH_INFO')
+    """Return PATH_INFO from environ ... using tg.original_request if available."""
     org_req = environ.get('tg.original_request')
-    if org_req:
-        path = org_req.environ.get('PATH_INFO')
-    return path
+    if org_req is not None:
+        environ = org_req.environ
+    return environ.get('PATH_INFO')
 
 
-def log_in_user(user, remember, is_external_auth):
+def log_in_user(user, remember, is_external_auth, ip_addr):
     """
     Log a `User` in and update session and cookies. If `remember` is True,
     the session cookie is set to expire in a year; otherwise, it expires at
@@ -117,15 +113,16 @@
 
     Returns populated `AuthUser` object.
     """
+    # It should not be possible to explicitly log in as the default user.
+    assert not user.is_default_user, user
+
+    auth_user = AuthUser.make(dbuser=user, is_external_auth=is_external_auth, ip_addr=ip_addr)
+    if auth_user is None:
+        return None
+
     user.update_lastlogin()
     meta.Session().commit()
 
-    auth_user = AuthUser(dbuser=user,
-                         is_external_auth=is_external_auth)
-    # It should not be possible to explicitly log in as the default user.
-    assert not auth_user.is_default_user
-    auth_user.is_authenticated = True
-
     # Start new session to prevent session fixation attacks.
     session.invalidate()
     session['authuser'] = cookie = auth_user.to_cookie()
@@ -147,42 +144,6 @@
     return auth_user
 
 
-def check_locking_state(action, repo_name, user):
-    """
-    Checks locking on this repository, if locking is enabled, and if lock
-    is present. Returns a tuple of make_lock, locked, locked_by. make_lock
-    can have 3 states: None (do nothing), True (make lock), and False
-    (release lock). This value is later propagated to hooks, telling them
-    what to do.
-    """
-    locked = False  # defines that locked error should be thrown to user
-    make_lock = None
-    repo = Repository.get_by_repo_name(repo_name)
-    locked_by = repo.locked
-    if repo and repo.enable_locking:
-        if action == 'push':
-            # Check if repo already is locked !, if it is compare users
-            user_id, _date = locked_by
-            if user.user_id == user_id:
-                log.debug('Got push from user %s, now unlocking', user)
-                # Unlock if we have push from the user who locked
-                make_lock = False
-            else:
-                # Another used tried to push - deny access with something like 423 Locked!
-                locked = True
-        if action == 'pull':
-            if repo.locked[0] and repo.locked[1]:
-                locked = True
-            else:
-                log.debug('Setting lock on repo %s by %s', repo, user)
-                make_lock = True
-    else:
-        log.debug('Repository %s does not have locking enabled', repo)
-    log.debug('FINAL locking values make_lock:%s,locked:%s,locked_by:%s',
-              make_lock, locked, locked_by)
-    return make_lock, locked, locked_by
-
-
 class BasicAuth(paste.auth.basic.AuthBasicAuthenticator):
 
     def __init__(self, realm, authfunc, auth_http_code=None):
@@ -227,6 +188,8 @@
     (coming from a VCS client, and not a browser).
     """
 
+    scm_alias = None # 'hg' / 'git'
+
     def __init__(self, application, config):
         self.application = application
         self.config = config
@@ -236,7 +199,14 @@
         self.authenticate = BasicAuth('', auth_modules.authenticate,
                                       config.get('auth_ret_code'))
 
-    def _authorize(self, environ, start_response, action, repo_name, ip_addr):
+    @classmethod
+    def parse_request(cls, environ):
+        """If request is parsed as a request for this VCS, return a namespace with the parsed request.
+        If the request is unknown, return None.
+        """
+        raise NotImplementedError()
+
+    def _authorize(self, environ, action, repo_name, ip_addr):
         """Authenticate and authorize user.
 
         Since we're dealing with a VCS client and not a browser, we only
@@ -247,18 +217,15 @@
         Returns (user, None) on successful authentication and authorization.
         Returns (None, wsgi_app) to send the wsgi_app response to the client.
         """
-        # Check if anonymous access is allowed.
+        # Use anonymous access if allowed for action on repo.
         default_user = User.get_default_user(cache=True)
-        is_default_user_allowed = (default_user.active and
-            self._check_permission(action, default_user, repo_name, ip_addr))
-        if is_default_user_allowed:
-            return default_user, None
-
-        if not default_user.active:
-            log.debug('Anonymous access is disabled')
+        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
         else:
-            log.debug('Not authorized to access this '
-                      'repository as anonymous user')
+            if self._check_permission(action, default_authuser, repo_name):
+                return default_authuser, None
+            log.debug('Not authorized to access this repository as anonymous user')
 
         username = None
         #==============================================================
@@ -289,15 +256,14 @@
         #==============================================================
         try:
             user = User.get_by_username_or_email(username)
-            if user is None or not user.active:
-                return None, webob.exc.HTTPForbidden()
         except Exception:
             log.error(traceback.format_exc())
             return None, webob.exc.HTTPInternalServerError()
 
-        # check permissions for this repository
-        perm = self._check_permission(action, user, repo_name, ip_addr)
-        if not perm:
+        authuser = AuthUser.make(dbuser=user, ip_addr=ip_addr)
+        if authuser is None:
+            return None, webob.exc.HTTPForbidden()
+        if not self._check_permission(action, authuser, repo_name):
             return None, webob.exc.HTTPForbidden()
 
         return user, None
@@ -305,24 +271,7 @@
     def _handle_request(self, environ, start_response):
         raise NotImplementedError()
 
-    def _get_by_id(self, repo_name):
-        """
-        Gets a special pattern _<ID> from clone url and tries to replace it
-        with a repository_name for support of _<ID> permanent URLs
-
-        :param repo_name:
-        """
-
-        data = repo_name.split('/')
-        if len(data) >= 2:
-            from kallithea.lib.utils import get_repo_by_id
-            by_id_match = get_repo_by_id(repo_name)
-            if by_id_match:
-                data[1] = safe_str(by_id_match)
-
-        return '/'.join(data)
-
-    def _check_permission(self, action, user, repo_name, ip_addr=None):
+    def _check_permission(self, action, authuser, repo_name):
         """
         Checks permissions using action (push/pull) user and repository
         name
@@ -331,16 +280,9 @@
         :param user: `User` instance
         :param repo_name: repository name
         """
-        # check IP
-        ip_allowed = AuthUser.check_ip_allowed(user, ip_addr)
-        if ip_allowed:
-            log.info('Access for IP:%s allowed', ip_addr)
-        else:
-            return False
-
         if action == 'push':
             if not HasPermissionAnyMiddleware('repository.write',
-                                              'repository.admin')(user,
+                                              'repository.admin')(authuser,
                                                                   repo_name):
                 return False
 
@@ -348,7 +290,7 @@
             #any other action need at least read permission
             if not HasPermissionAnyMiddleware('repository.read',
                                               'repository.write',
-                                              'repository.admin')(user,
+                                              'repository.admin')(authuser,
                                                                   repo_name):
                 return False
 
@@ -360,10 +302,50 @@
     def __call__(self, environ, start_response):
         start = time.time()
         try:
-            return self._handle_request(environ, start_response)
+            # try parsing a request for this VCS - if it fails, call the wrapped app
+            parsed_request = self.parse_request(environ)
+            if parsed_request is None:
+                return self.application(environ, start_response)
+
+            # skip passing error to error controller
+            environ['pylons.status_code_redirect'] = True
+
+            # quick check if repo exists...
+            if not is_valid_repo(parsed_request.repo_name, self.basepath, self.scm_alias):
+                raise webob.exc.HTTPNotFound()
+
+            if parsed_request.action is None:
+                # Note: the client doesn't get the helpful error message
+                raise webob.exc.HTTPBadRequest('Unable to detect pull/push action for %r! Are you using a nonstandard command or client?' % parsed_request.repo_name)
+
+            #======================================================================
+            # CHECK PERMISSIONS
+            #======================================================================
+            ip_addr = self._get_ip_addr(environ)
+            user, response_app = self._authorize(environ, parsed_request.action, parsed_request.repo_name, ip_addr)
+            if response_app is not None:
+                return response_app(environ, start_response)
+
+            #======================================================================
+            # REQUEST HANDLING
+            #======================================================================
+            set_hook_environment(user.username, ip_addr,
+                parsed_request.repo_name, self.scm_alias, parsed_request.action)
+
+            try:
+                log.info('%s action on %s repo "%s" by "%s" from %s',
+                         parsed_request.action, self.scm_alias, parsed_request.repo_name, safe_str(user.username), ip_addr)
+                app = self._make_app(parsed_request)
+                return app(environ, start_response)
+            except Exception:
+                log.error(traceback.format_exc())
+                raise webob.exc.HTTPInternalServerError()
+
+        except webob.exc.HTTPException as e:
+            return e(environ, start_response)
         finally:
-            log = logging.getLogger('kallithea.' + self.__class__.__name__)
-            log.debug('Request time: %.3fs', time.time() - start)
+            log_ = logging.getLogger('kallithea.' + self.__class__.__name__)
+            log_.debug('Request time: %.3fs', time.time() - start)
             meta.Session.remove()
 
 
@@ -373,6 +355,19 @@
         """
         _before is called before controller methods and after __call__
         """
+        if request.needs_csrf_check:
+            # CSRF protection: Whenever a request has ambient authority (whether
+            # through a session cookie or its origin IP address), it must include
+            # the correct token, unless the HTTP method is GET or HEAD (and thus
+            # guaranteed to be side effect free. In practice, the only situation
+            # where we allow side effects without ambient authority is when the
+            # authority comes from an API key; and that is handled above.
+            from kallithea.lib import helpers as h
+            token = request.POST.get(h.session_csrf_secret_name)
+            if not token or token != h.session_csrf_secret_token():
+                log.error('CSRF check failed')
+                raise webob.exc.HTTPForbidden()
+
         c.kallithea_version = __version__
         rc_config = Setting.get_app_settings()
 
@@ -405,11 +400,13 @@
                     })();
             </script>''' % c.ga_code
         c.site_name = rc_config.get('title')
-        c.clone_uri_tmpl = rc_config.get('clone_uri_tmpl')
+        c.clone_uri_tmpl = rc_config.get('clone_uri_tmpl') or Repository.DEFAULT_CLONE_URI
+        c.clone_ssh_tmpl = rc_config.get('clone_ssh_tmpl') or Repository.DEFAULT_CLONE_SSH
 
         ## INI stored
         c.visual.allow_repo_location_change = str2bool(config.get('allow_repo_location_change', True))
         c.visual.allow_custom_hooks_settings = str2bool(config.get('allow_custom_hooks_settings', True))
+        c.ssh_enabled = str2bool(config.get('ssh_enabled', False))
 
         c.instance_id = config.get('instance_id')
         c.issues_url = config.get('bugtracker', url('issues_url'))
@@ -425,32 +422,20 @@
         self.scm_model = ScmModel()
 
     @staticmethod
-    def _determine_auth_user(api_key, bearer_token, session_authuser):
+    def _determine_auth_user(session_authuser, ip_addr):
         """
         Create an `AuthUser` object given the API key/bearer token
         (if any) and the value of the authuser session cookie.
+        Returns None if no valid user is found (like not active or no access for IP).
         """
 
-        # Authenticate by bearer token
-        if bearer_token is not None:
-            api_key = bearer_token
-
-        # Authenticate by API key
-        if api_key is not None:
-            au = AuthUser(dbuser=User.get_by_api_key(api_key),
-                authenticating_api_key=api_key, is_external_auth=True)
-            if au.is_anonymous:
-                log.warning('API key ****%s is NOT valid', api_key[-4:])
-                raise webob.exc.HTTPForbidden(_('Invalid API key'))
-            return au
-
         # Authenticate by session cookie
         # In ancient login sessions, 'authuser' may not be a dict.
         # In that case, the user will have to log in again.
         # v0.3 and earlier included an 'is_authenticated' key; if present,
         # this must be True.
         if isinstance(session_authuser, dict) and session_authuser.get('is_authenticated', True):
-            return AuthUser.from_cookie(session_authuser)
+            return AuthUser.from_cookie(session_authuser, ip_addr=ip_addr)
 
         # Authenticate by auth_container plugin (if enabled)
         if any(
@@ -466,11 +451,14 @@
                 if user_info is not None:
                     username = user_info['username']
                     user = User.get_by_username(username, case_insensitive=True)
-                    return log_in_user(user, remember=False,
-                                       is_external_auth=True)
+                    return log_in_user(user, remember=False, is_external_auth=True, ip_addr=ip_addr)
 
-        # User is anonymous
-        return AuthUser()
+        # User is default user (if active) or anonymous
+        default_user = User.get_default_user(cache=True)
+        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?
+        return authuser
 
     @staticmethod
     def _basic_security_checks():
@@ -487,11 +475,11 @@
             raise webob.exc.HTTPMethodNotAllowed()
 
         # Make sure CSRF token never appears in the URL. If so, invalidate it.
-        if secure_form.token_key in request.GET:
+        from kallithea.lib import helpers as h
+        if h.session_csrf_secret_name in request.GET:
             log.error('CSRF key leak detected')
-            session.pop(secure_form.token_key, None)
+            session.pop(h.session_csrf_secret_name, None)
             session.save()
-            from kallithea.lib import helpers as h
             h.flash(_('CSRF token leak has been detected - all form tokens have been expired'),
                     category='error')
 
@@ -504,14 +492,10 @@
 
     def __call__(self, environ, context):
         try:
-            request.ip_addr = _get_ip_addr(environ)
-            # make sure that we update permissions each time we call controller
-
+            ip_addr = _get_ip_addr(environ)
             self._basic_security_checks()
 
-            # set globals for auth user
-
-            bearer_token = None
+            api_key = request.GET.get('api_key')
             try:
                 # Request.authorization may raise ValueError on invalid input
                 type, params = request.authorization
@@ -519,18 +503,31 @@
                 pass
             else:
                 if type.lower() == 'bearer':
-                    bearer_token = params
+                    api_key = params # bearer token is an api key too
+
+            if api_key is None:
+                authuser = self._determine_auth_user(
+                    session.get('authuser'),
+                    ip_addr=ip_addr,
+                )
+                needs_csrf_check = request.method not in ['GET', 'HEAD']
 
-            authuser = self._determine_auth_user(
-                request.GET.get('api_key'),
-                bearer_token,
-                session.get('authuser'),
-            )
+            else:
+                dbuser = User.get_by_api_key(api_key)
+                if dbuser is None:
+                    log.info('No db user found for authentication with API key ****%s from %s',
+                             api_key[-4:], ip_addr)
+                authuser = AuthUser.make(dbuser=dbuser, is_external_auth=True, ip_addr=ip_addr)
+                needs_csrf_check = False # API key provides CSRF protection
 
-            if not AuthUser.check_ip_allowed(authuser, request.ip_addr):
+            if authuser is None:
+                log.info('No valid user found')
                 raise webob.exc.HTTPForbidden()
 
+            # set globals for auth user
             request.authuser = authuser
+            request.ip_addr = ip_addr
+            request.needs_csrf_check = needs_csrf_check
 
             log.info('IP: %s User: %s accessed %s',
                 request.ip_addr, request.authuser,
@@ -638,3 +635,15 @@
         log.warning(msg)
     log.debug("Returning JSON wrapped action output")
     return json.dumps(data, encoding='utf-8')
+
+@decorator.decorator
+def IfSshEnabled(func, *args, **kwargs):
+    """Decorator for functions that can only be called if SSH access is enabled.
+
+    If SSH access is disabled in the configuration file, HTTPNotFound is raised.
+    """
+    if not c.ssh_enabled:
+        from kallithea.lib import helpers as h
+        h.flash(_("SSH access is disabled."), category='warning')
+        raise webob.exc.HTTPNotFound()
+    return func(*args, **kwargs)
--- a/kallithea/lib/caching_query.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/caching_query.py	Sun Jan 05 04:07:51 2020 +0100
@@ -18,10 +18,10 @@
 """
 import beaker
 from beaker.exceptions import BeakerException
-
 from sqlalchemy.orm.interfaces import MapperOption
 from sqlalchemy.orm.query import Query
 from sqlalchemy.sql import visitors
+
 from kallithea.lib.utils2 import safe_str
 
 
--- a/kallithea/lib/celerylib/__init__.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/celerylib/__init__.py	Sun Jan 05 04:07:51 2020 +0100
@@ -26,18 +26,16 @@
 """
 
 
+import logging
 import os
-import logging
+from hashlib import md5
 
+from decorator import decorator
 from tg import config
 
-from hashlib import md5
-from decorator import decorator
-
-from kallithea import CELERY_ON, CELERY_EAGER
+from kallithea import CELERY_EAGER, CELERY_ON
+from kallithea.lib.pidlock import DaemonLock, LockHeld
 from kallithea.lib.utils2 import safe_str
-from kallithea.lib.pidlock import DaemonLock, LockHeld
-from kallithea.model.base import init_model
 from kallithea.model import meta
 
 
@@ -104,7 +102,7 @@
 def locked_task(func):
     def __wrapper(func, *fargs, **fkwargs):
         lockkey = __get_lockkey(func, *fargs, **fkwargs)
-        lockkey_path = config['app_conf']['cache_dir']
+        lockkey_path = config.get('cache_dir') or config['app_conf']['cache_dir']  # Backward compatibility for TurboGears < 2.4
 
         log.info('running task with lockkey %s', lockkey)
         try:
--- a/kallithea/lib/celerylib/tasks.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/celerylib/tasks.py	Sun Jan 05 04:07:51 2020 +0100
@@ -26,28 +26,26 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+import logging
 import os
-import traceback
-import logging
 import rfc822
-
+import traceback
+from collections import OrderedDict
+from operator import itemgetter
 from time import mktime
-from operator import itemgetter
-from string import lower
 
 from tg import config
 
 from kallithea import CELERY_ON
 from kallithea.lib import celerylib
+from kallithea.lib.compat import json
 from kallithea.lib.helpers import person
+from kallithea.lib.hooks import log_create_repository
 from kallithea.lib.rcmail.smtp_mailer import SmtpMailer
 from kallithea.lib.utils import action_logger
 from kallithea.lib.utils2 import str2bool
 from kallithea.lib.vcs.utils import author_email
-from kallithea.lib.compat import json, OrderedDict
-from kallithea.lib.hooks import log_create_repository
-
-from kallithea.model.db import Statistics, RepoGroup, Repository, User
+from kallithea.model.db import RepoGroup, Repository, Statistics, User
 
 
 __all__ = ['whoosh_index', 'get_commits_stats', 'send_email']
@@ -75,7 +73,7 @@
     DBS = celerylib.get_session()
     lockkey = celerylib.__get_lockkey('get_commits_stats', repo_name, ts_min_y,
                             ts_max_y)
-    lockkey_path = config['app_conf']['cache_dir']
+    lockkey_path = config.get('cache_dir') or config['app_conf']['cache_dir']  # Backward compatibility for TurboGears < 2.4
 
     log.info('running task with lockkey %s', lockkey)
 
@@ -99,7 +97,7 @@
             return True
 
         skip_date_limit = True
-        parse_limit = int(config['app_conf'].get('commit_parse_limit'))
+        parse_limit = int(config.get('commit_parse_limit'))
         last_rev = None
         last_cs = None
         timegetter = itemgetter('time')
@@ -171,11 +169,11 @@
                 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
                     co_day_auth_aggr[akc(cs.author)] = {
                                         "label": akc(cs.author),
-                                        "data": [{"time":k,
-                                                 "commits":1,
-                                                 "added":len(cs.added),
-                                                 "changed":len(cs.changed),
-                                                 "removed":len(cs.removed),
+                                        "data": [{"time": k,
+                                                 "commits": 1,
+                                                 "added": len(cs.added),
+                                                 "changed": len(cs.changed),
+                                                 "removed": len(cs.removed),
                                                  }],
                                         "schema": ["commits"],
                                         }
@@ -349,7 +347,6 @@
     # repo creation defaults, private and repo_type are filled in form
     defs = Setting.get_default_repo_settings(strip_prefix=True)
     enable_statistics = defs.get('repo_enable_statistics')
-    enable_locking = defs.get('repo_enable_locking')
     enable_downloads = defs.get('repo_enable_downloads')
 
     try:
@@ -366,7 +363,6 @@
             copy_fork_permissions=copy_fork_permissions,
             copy_group_permissions=copy_group_permissions,
             enable_statistics=enable_statistics,
-            enable_locking=enable_locking,
             enable_downloads=enable_downloads,
             state=state
         )
@@ -490,15 +486,13 @@
     tip = repo.get_changeset()
     code_stats = {}
 
-    def aggregate(cs):
-        for f in cs[2]:
-            ext = lower(f.extension)
-            if ext in LANGUAGES_EXTENSIONS_MAP.keys() and not f.is_binary:
+    for _topnode, _dirnodes, filenodes in tip.walk('/'):
+        for filenode in filenodes:
+            ext = filenode.extension.lower()
+            if ext in LANGUAGES_EXTENSIONS_MAP.keys() and not filenode.is_binary:
                 if ext in code_stats:
                     code_stats[ext] += 1
                 else:
                     code_stats[ext] = 1
 
-    map(aggregate, tip.walk('/'))
-
     return code_stats or {}
--- a/kallithea/lib/celerypylons/__init__.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/celerypylons/__init__.py	Sun Jan 05 04:07:51 2020 +0100
@@ -14,11 +14,11 @@
 mandatory settings.
 """
 
-import os
-import warnings
-
+import celery
+import celery.result as result
 import tg
-import celery
+from celery.bin import worker
+from celery.task import task
 
 
 def celery_config(config):
@@ -56,7 +56,3 @@
 # Create celery app from the TurboGears configuration file
 app = celery.Celery()
 app.config_from_object(celery_config(tg.config))
-
-import celery.result as result
-from celery.task import task
-from celery.bin import worker
--- a/kallithea/lib/colored_formatter.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/colored_formatter.py	Sun Jan 05 04:07:51 2020 +0100
@@ -14,6 +14,7 @@
 
 import logging
 
+
 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38)
 
 # Sequences
--- a/kallithea/lib/compat.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/compat.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,317 +27,31 @@
 """
 
 
-import sys
+import functools
 import os
-import functools
+import sys
+
+#==============================================================================
+# Hybrid property/method
+#==============================================================================
+from sqlalchemy.ext.hybrid import hybrid_property
+#==============================================================================
+# OrderedSet
+#==============================================================================
+from sqlalchemy.util import OrderedSet
 
 #==============================================================================
 # json
 #==============================================================================
 from kallithea.lib.ext_json import json
 
+
 # alias for formatted json
 formatted_json = functools.partial(json.dumps, indent=4, sort_keys=True)
 
 
-#==============================================================================
-# unittest
-#==============================================================================
-if sys.version_info >= (2, 7):
-    import unittest
-else:
-    import unittest2 as unittest
-
-
-#==============================================================================
-# OrderedDict - Python 2.7 could perhaps use collections.OrderedDict
-#==============================================================================
-
-# Python Software Foundation License
-
-
-# XXX: it feels like using the class with "is" and "is not" instead of "==" and
-# "!=" should be faster.
-class _Nil(object):
-
-    def __repr__(self):
-        return "nil"
-
-    def __eq__(self, other):
-        if (isinstance(other, _Nil)):
-            return True
-        else:
-            return NotImplemented
-
-    def __ne__(self, other):
-        if (isinstance(other, _Nil)):
-            return False
-        else:
-            return NotImplemented
-
-
-_nil = _Nil()
 
 
-class OrderedDict(dict):
-    """Ordered dict data structure, with O(1) complexity for dict operations
-    that modify one element.
-
-    Overwriting values doesn't change their original sequential order.
-    """
-
-    def __init__(self, data=(), **kwds):
-        """This doesn't accept keyword initialization as normal dicts to avoid
-        a trap - inside a function or method the keyword args are accessible
-        only as a dict, without a defined order, so their original order is
-        lost.
-        """
-        if kwds:
-            raise TypeError("__init__() of ordered dict takes no keyword "
-                            "arguments to avoid an ordering trap.")
-        dict.__init__(self)
-        # If you give a normal dict, then the order of elements is undefined
-        if hasattr(data, "iteritems"):
-            for key, val in data.iteritems():
-                self[key] = val
-        else:
-            for key, val in data:
-                self[key] = val
-
-    # Double-linked list header
-    def _get_lh(self):
-        if not hasattr(self, '_lh'):
-            dict.__setattr__(self, '_lh', _nil)
-        return dict.__getattribute__(self, '_lh')
-
-    def _set_lh(self, val):
-        dict.__setattr__(self, '_lh', val)
-
-    lh = property(_get_lh, _set_lh)
-
-    # Double-linked list tail
-    def _get_lt(self):
-        if not hasattr(self, '_lt'):
-            dict.__setattr__(self, '_lt', _nil)
-        return dict.__getattribute__(self, '_lt')
-
-    def _set_lt(self, val):
-        dict.__setattr__(self, '_lt', val)
-
-    lt = property(_get_lt, _set_lt)
-
-    def __getitem__(self, key):
-        return dict.__getitem__(self, key)[1]
-
-    def __setitem__(self, key, val):
-        try:
-            dict.__getitem__(self, key)[1] = val
-        except KeyError:
-            new = [dict.__getattribute__(self, 'lt'), val, _nil]
-            dict.__setitem__(self, key, new)
-            if dict.__getattribute__(self, 'lt') == _nil:
-                dict.__setattr__(self, 'lh', key)
-            else:
-                dict.__getitem__(
-                    self, dict.__getattribute__(self, 'lt'))[2] = key
-            dict.__setattr__(self, 'lt', key)
-
-    def __delitem__(self, key):
-        pred, _, succ = dict.__getitem__(self, key)
-        if pred == _nil:
-            dict.__setattr__(self, 'lh', succ)
-        else:
-            dict.__getitem__(self, pred)[2] = succ
-        if succ == _nil:
-            dict.__setattr__(self, 'lt', pred)
-        else:
-            dict.__getitem__(self, succ)[0] = pred
-        dict.__delitem__(self, key)
-
-    def __contains__(self, key):
-        return key in self.keys()
-
-    def __len__(self):
-        return len(self.keys())
-
-    def __str__(self):
-        pairs = ("%r: %r" % (k, v) for k, v in self.iteritems())
-        return "{%s}" % ", ".join(pairs)
-
-    def __repr__(self):
-        if self:
-            pairs = ("(%r, %r)" % (k, v) for k, v in self.iteritems())
-            return "odict([%s])" % ", ".join(pairs)
-        else:
-            return "odict()"
-
-    def get(self, k, x=None):
-        if k in self:
-            return dict.__getitem__(self, k)[1]
-        else:
-            return x
-
-    def __iter__(self):
-        curr_key = dict.__getattribute__(self, 'lh')
-        while curr_key != _nil:
-            yield curr_key
-            curr_key = dict.__getitem__(self, curr_key)[2]
-
-    iterkeys = __iter__
-
-    def keys(self):
-        return list(self.iterkeys())
-
-    def itervalues(self):
-        curr_key = dict.__getattribute__(self, 'lh')
-        while curr_key != _nil:
-            _, val, curr_key = dict.__getitem__(self, curr_key)
-            yield val
-
-    def values(self):
-        return list(self.itervalues())
-
-    def iteritems(self):
-        curr_key = dict.__getattribute__(self, 'lh')
-        while curr_key != _nil:
-            _, val, next_key = dict.__getitem__(self, curr_key)
-            yield curr_key, val
-            curr_key = next_key
-
-    def items(self):
-        return list(self.iteritems())
-
-    def sort(self, cmp=None, key=None, reverse=False):
-        items = [(k, v) for k, v in self.items()]
-        if cmp is not None:
-            items = sorted(items, cmp=cmp)
-        elif key is not None:
-            items = sorted(items, key=key)
-        else:
-            items = sorted(items, key=lambda x: x[1])
-        if reverse:
-            items.reverse()
-        self.clear()
-        self.__init__(items)
-
-    def clear(self):
-        dict.clear(self)
-        dict.__setattr__(self, 'lh', _nil)
-        dict.__setattr__(self, 'lt', _nil)
-
-    def copy(self):
-        return self.__class__(self)
-
-    def update(self, data=(), **kwds):
-        if kwds:
-            raise TypeError("update() of ordered dict takes no keyword "
-                            "arguments to avoid an ordering trap.")
-        if hasattr(data, "iteritems"):
-            data = data.iteritems()
-        for key, val in data:
-            self[key] = val
-
-    def setdefault(self, k, x=None):
-        try:
-            return self[k]
-        except KeyError:
-            self[k] = x
-            return x
-
-    def pop(self, k, x=_nil):
-        try:
-            val = self[k]
-            del self[k]
-            return val
-        except KeyError:
-            if x == _nil:
-                raise
-            return x
-
-    def popitem(self):
-        try:
-            key = dict.__getattribute__(self, 'lt')
-            return key, self.pop(key)
-        except KeyError:
-            raise KeyError("'popitem(): ordered dictionary is empty'")
-
-    def riterkeys(self):
-        """To iterate on keys in reversed order.
-        """
-        curr_key = dict.__getattribute__(self, 'lt')
-        while curr_key != _nil:
-            yield curr_key
-            curr_key = dict.__getitem__(self, curr_key)[0]
-
-    __reversed__ = riterkeys
-
-    def rkeys(self):
-        """List of the keys in reversed order.
-        """
-        return list(self.riterkeys())
-
-    def ritervalues(self):
-        """To iterate on values in reversed order.
-        """
-        curr_key = dict.__getattribute__(self, 'lt')
-        while curr_key != _nil:
-            curr_key, val, _ = dict.__getitem__(self, curr_key)
-            yield val
-
-    def rvalues(self):
-        """List of the values in reversed order.
-        """
-        return list(self.ritervalues())
-
-    def riteritems(self):
-        """To iterate on (key, value) in reversed order.
-        """
-        curr_key = dict.__getattribute__(self, 'lt')
-        while curr_key != _nil:
-            pred_key, val, _ = dict.__getitem__(self, curr_key)
-            yield curr_key, val
-            curr_key = pred_key
-
-    def ritems(self):
-        """List of the (key, value) in reversed order.
-        """
-        return list(self.riteritems())
-
-    def firstkey(self):
-        if self:
-            return dict.__getattribute__(self, 'lh')
-        else:
-            raise KeyError("'firstkey(): ordered dictionary is empty'")
-
-    def lastkey(self):
-        if self:
-            return dict.__getattribute__(self, 'lt')
-        else:
-            raise KeyError("'lastkey(): ordered dictionary is empty'")
-
-    def as_dict(self):
-        return dict(self.items())
-
-    def _repr(self):
-        """_repr(): low level repr of the whole data contained in the odict.
-        Useful for debugging.
-        """
-        form = "odict low level repr lh,lt,data: %r, %r, %s"
-        return form % (dict.__getattribute__(self, 'lh'),
-                       dict.__getattribute__(self, 'lt'),
-                       dict.__repr__(self))
-
-
-#==============================================================================
-# OrderedSet
-#==============================================================================
-from sqlalchemy.util import OrderedSet
-
-
-#==============================================================================
-# Hybrid property/method
-#==============================================================================
-from sqlalchemy.ext.hybrid import hybrid_property
 
 
 #==============================================================================
--- a/kallithea/lib/db_manage.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/db_manage.py	Sun Jan 05 04:07:51 2020 +0100
@@ -26,29 +26,25 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+from __future__ import print_function
+
+import logging
 import os
 import sys
-import time
 import uuid
-import logging
+
+import alembic.command
+import alembic.config
 import sqlalchemy
-from os.path import dirname
+from sqlalchemy.engine import create_engine
 
-import alembic.config
-import alembic.command
-
-from kallithea.model.user import UserModel
 from kallithea.model.base import init_model
-from kallithea.model.db import User, Permission, Ui, \
-    Setting, UserToPerm, RepoGroup, \
-    UserRepoGroupToPerm, CacheInvalidation, Repository
-
-from sqlalchemy.engine import create_engine
+from kallithea.model.db import Permission, RepoGroup, Repository, Setting, Ui, User, UserRepoGroupToPerm, UserToPerm
+#from kallithea.model import meta
+from kallithea.model.meta import Base, Session
+from kallithea.model.permission import PermissionModel
 from kallithea.model.repo_group import RepoGroupModel
-#from kallithea.model import meta
-from kallithea.model.meta import Session, Base
-from kallithea.model.repo import RepoModel
-from kallithea.model.permission import PermissionModel
+from kallithea.model.user import UserModel
 
 
 log = logging.getLogger(__name__)
@@ -92,7 +88,7 @@
         else:
             destroy = self._ask_ok('Are you sure to destroy old database ? [y/n]')
         if not destroy:
-            print 'Nothing done.'
+            print('Nothing done.')
             sys.exit(0)
         if destroy:
             # drop and re-create old schemas
@@ -207,10 +203,10 @@
         else:
             log.info('creating admin and regular test users')
             from kallithea.tests.base import TEST_USER_ADMIN_LOGIN, \
-            TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, \
-            TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, \
-            TEST_USER_REGULAR_EMAIL, TEST_USER_REGULAR2_LOGIN, \
-            TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL
+                TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, \
+                TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, \
+                TEST_USER_REGULAR_EMAIL, TEST_USER_REGULAR2_LOGIN, \
+                TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL
 
             self.create_user(TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS,
                              TEST_USER_ADMIN_EMAIL, True)
@@ -240,12 +236,11 @@
         """Creates default settings"""
 
         for k, v, t in [
-            ('default_repo_enable_locking',  False, 'bool'),
             ('default_repo_enable_downloads', False, 'bool'),
             ('default_repo_enable_statistics', False, 'bool'),
             ('default_repo_private', False, 'bool'),
-            ('default_repo_type', 'hg', 'unicode')]:
-
+            ('default_repo_type', 'hg', 'unicode')
+        ]:
             if skip_existing and Setting.get_by_name(k) is not None:
                 log.debug('Skipping option %s', k)
                 continue
@@ -291,7 +286,7 @@
         for repo in Repository.query():
             repo.update_changeset_cache()
 
-    def config_prompt(self, test_repo_path='', retries=3):
+    def prompt_repo_root_path(self, test_repo_path='', retries=3):
         _path = self.cli_args.get('repos_location')
         if retries == 3:
             log.info('Setting up repositories config')
@@ -335,7 +330,7 @@
             if _path is not None:
                 sys.exit('Invalid repo path: %s' % _path)
             retries -= 1
-            return self.config_prompt(test_repo_path, retries) # recursing!!!
+            return self.prompt_repo_root_path(test_repo_path, retries) # recursing!!!
 
         real_path = os.path.normpath(os.path.realpath(path))
 
@@ -344,30 +339,23 @@
 
         return real_path
 
-    def create_settings(self, path):
-
+    def create_settings(self, repo_root_path):
         ui_config = [
-            ('web', 'allow_archive', 'gz zip bz2', True),
-            ('web', 'baseurl', '/', True),
-            ('paths', '/', path, True),
+            ('paths', '/', repo_root_path, True),
             #('phases', 'publish', 'false', False)
             ('hooks', Ui.HOOK_UPDATE, 'hg update >&2', False),
             ('hooks', Ui.HOOK_REPO_SIZE, 'python:kallithea.lib.hooks.repo_size', True),
-            ('hooks', Ui.HOOK_PUSH_LOG, 'python:kallithea.lib.hooks.log_push_action', True),
-            ('hooks', Ui.HOOK_PUSH_LOCK, 'python:kallithea.lib.hooks.push_lock_handling', True),
-            ('hooks', Ui.HOOK_PULL_LOG, 'python:kallithea.lib.hooks.log_pull_action', True),
-            ('hooks', Ui.HOOK_PULL_LOCK, 'python:kallithea.lib.hooks.pull_lock_handling', True),
             ('extensions', 'largefiles', '', True),
-            ('largefiles', 'usercache', os.path.join(path, '.cache', 'largefiles'), True),
+            ('largefiles', 'usercache', os.path.join(repo_root_path, '.cache', 'largefiles'), True),
             ('extensions', 'hgsubversion', '', False),
             ('extensions', 'hggit', '', False),
         ]
-        for section, key, value, active in ui_config:
-            ui_conf = Ui()
-            setattr(ui_conf, 'ui_section', section)
-            setattr(ui_conf, 'ui_key', key)
-            setattr(ui_conf, 'ui_value', value)
-            setattr(ui_conf, 'ui_active', active)
+        for ui_section, ui_key, ui_value, ui_active in ui_config:
+            ui_conf = Ui(
+                ui_section=ui_section,
+                ui_key=ui_key,
+                ui_value=ui_value,
+                ui_active=ui_active)
             self.sa.add(ui_conf)
 
         settings = [
@@ -383,7 +371,7 @@
             ('use_gravatar', True, 'bool'),
             ('gravatar_url', User.DEFAULT_GRAVATAR_URL, 'unicode'),
             ('clone_uri_tmpl', Repository.DEFAULT_CLONE_URI, 'unicode'),
-            ('update_url', Setting.DEFAULT_UPDATE_URL, 'unicode'),
+            ('clone_ssh_tmpl', Repository.DEFAULT_CLONE_SSH, 'unicode'),
         ]
         for key, val, type_ in settings:
             sett = Setting(key, val, type_)
@@ -392,7 +380,7 @@
         self.create_auth_plugin_options()
         self.create_default_options()
 
-        log.info('created ui config')
+        log.info('Populated Ui and Settings defaults')
 
     def create_user(self, username, password, email='', admin=False):
         log.info('creating user %s', username)
--- a/kallithea/lib/diffs.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/diffs.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,23 +25,24 @@
 :copyright: (c) 2013 RhodeCode GmbH, and others.
 :license: GPLv3, see LICENSE.md for more details.
 """
-import re
 import difflib
 import logging
+import re
 
 from tg.i18n import ugettext as _
 
 from kallithea.lib import helpers as h
+from kallithea.lib.utils2 import safe_unicode
+from kallithea.lib.vcs.backends.base import EmptyChangeset
 from kallithea.lib.vcs.exceptions import VCSError
 from kallithea.lib.vcs.nodes import FileNode, SubModuleNode
-from kallithea.lib.vcs.backends.base import EmptyChangeset
-from kallithea.lib.utils2 import safe_unicode
+
 
 log = logging.getLogger(__name__)
 
 
 def _safe_id(idstring):
-    """Make a string safe for including in an id attribute.
+    r"""Make a string safe for including in an id attribute.
 
     The HTML spec says that id attributes 'must begin with
     a letter ([A-Za-z]) and may be followed by any number
--- a/kallithea/lib/exceptions.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/exceptions.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,11 +25,6 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
-from webob.exc import HTTPClientError
-
-from kallithea.lib.utils2 import safe_str
-
-
 class LdapUsernameError(Exception):
     pass
 
@@ -71,24 +66,6 @@
     pass
 
 
-class HTTPLockedRC(HTTPClientError):
-    """
-    Special Exception For locked Repos in Kallithea, the return code can
-    be overwritten by _code keyword argument passed into constructors
-    """
-    code = 423
-    title = explanation = 'Repository Locked'
-
-    def __init__(self, reponame, username, *args, **kwargs):
-        from kallithea import CONFIG
-        from kallithea.lib.utils2 import safe_int
-        _code = CONFIG.get('lock_ret_code')
-        self.code = safe_int(_code, self.code)
-        self.title = self.explanation = safe_str(
-            'Repository `%s` locked by user `%s`' % (reponame, username))
-        super(HTTPLockedRC, self).__init__(*args, **kwargs)
-
-
 class IMCCommitError(Exception):
     pass
 
--- a/kallithea/lib/ext_json.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/ext_json.py	Sun Jan 05 04:07:51 2020 +0100
@@ -5,9 +5,10 @@
 """
 
 import datetime
+import decimal
 import functools
-import decimal
-import json # is re-exported after monkey patching
+import json  # is re-exported after monkey patching
+
 
 __all__ = ['json']
 
--- a/kallithea/lib/helpers.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/helpers.py	Sun Jan 05 04:07:51 2020 +0100
@@ -19,35 +19,44 @@
 """
 import hashlib
 import json
-import StringIO
 import logging
+import random
 import re
+import StringIO
+import textwrap
 import urlparse
-import textwrap
 
 from beaker.cache import cache_region
+from pygments import highlight as code_highlight
 from pygments.formatters.html import HtmlFormatter
-from pygments import highlight as code_highlight
 from tg.i18n import ugettext as _
-
-from webhelpers.html import literal, HTML, escape
-from webhelpers.html.tags import checkbox, end_form, hidden, link_to, \
-    select, submit, text, password, textarea, radio, form as insecure_form
-from webhelpers.number import format_byte_size
-from webhelpers.pylonslib import Flash as _Flash
-from webhelpers.pylonslib.secure_form import secure_form, authentication_token
-from webhelpers.text import chop_at, truncate, wrap_paragraphs
-from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
-    convert_boolean_attrs, NotGiven, _make_safe_id_component
+from webhelpers2.html import HTML, escape, literal
+from webhelpers2.html.tags import NotGiven, Option, Options, _input, _make_safe_id_component, checkbox, end_form
+from webhelpers2.html.tags import form as insecure_form
+from webhelpers2.html.tags import hidden, link_to, password, radio
+from webhelpers2.html.tags import select as webhelpers2_select
+from webhelpers2.html.tags import submit, text, textarea
+from webhelpers2.number import format_byte_size
+from webhelpers2.text import chop_at, truncate, wrap_paragraphs
 
 from kallithea.config.routing import url
 from kallithea.lib.annotate import annotate_highlight
+#==============================================================================
+# PERMS
+#==============================================================================
+from kallithea.lib.auth import HasPermissionAny, HasRepoGroupPermissionLevel, HasRepoPermissionLevel
+from kallithea.lib.markup_renderer import url_re
 from kallithea.lib.pygmentsutils import get_custom_lexer
-from kallithea.lib.utils2 import str2bool, safe_unicode, safe_str, \
-    time_to_datetime, AttributeDict, safe_int, MENTIONS_REGEX
-from kallithea.lib.markup_renderer import url_re
+from kallithea.lib.utils2 import MENTIONS_REGEX, AttributeDict
+from kallithea.lib.utils2 import age as _age
+from kallithea.lib.utils2 import credentials_filter, safe_int, safe_str, safe_unicode, str2bool, time_to_datetime
+from kallithea.lib.vcs.backends.base import BaseChangeset, EmptyChangeset
 from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError
-from kallithea.lib.vcs.backends.base import BaseChangeset, EmptyChangeset
+#==============================================================================
+# SCM FILTERS available via h.
+#==============================================================================
+from kallithea.lib.vcs.utils import author_email, author_name
+
 
 log = logging.getLogger(__name__)
 
@@ -144,17 +153,41 @@
     return s
 
 
-def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
-    """
-    Reset button
-    """
-    _set_input_attrs(attrs, type, name, value)
-    _set_id_attr(attrs, id, name)
-    convert_boolean_attrs(attrs, ["disabled"])
-    return HTML.input(**attrs)
+def reset(name, value, id=NotGiven, **attrs):
+    """Create a reset button, similar to webhelpers2.html.tags.submit ."""
+    return _input("reset", name, value, id, attrs)
 
 
-reset = _reset
+def select(name, selected_values, options, id=NotGiven, **attrs):
+    """Convenient wrapper of webhelpers2 to let it accept options as a tuple list"""
+    if isinstance(options, list):
+        option_list = options
+        # Handle old value,label lists ... where value also can be value,label lists
+        options = Options()
+        for x in option_list:
+            if isinstance(x, tuple) and len(x) == 2:
+                value, label = x
+            elif isinstance(x, basestring):
+                value = label = x
+            else:
+                log.error('invalid select option %r', x)
+                raise
+            if isinstance(value, list):
+                og = options.add_optgroup(label)
+                for x in value:
+                    if isinstance(x, tuple) and len(x) == 2:
+                        group_value, group_label = x
+                    elif isinstance(x, basestring):
+                        group_value = group_label = x
+                    else:
+                        log.error('invalid select option %r', x)
+                        raise
+                    og.add_option(group_label, group_value)
+            else:
+                options.add_option(label, value)
+    return webhelpers2_select(name, selected_values, options, id=id, **attrs)
+
+
 safeid = _make_safe_id_component
 
 
@@ -386,7 +419,7 @@
 
 
 class _Message(object):
-    """A message returned by ``Flash.pop_messages()``.
+    """A message returned by ``pop_flash_messages()``.
 
     Converting the message to a string returns the message text. Instances
     also have the following attributes:
@@ -408,45 +441,53 @@
         return escape(safe_unicode(self.message))
 
 
-class Flash(_Flash):
-
-    def __call__(self, message, category=None, ignore_duplicate=False, logf=None):
-        """
-        Show a message to the user _and_ log it through the specified function
-
-        category: notice (default), warning, error, success
-        logf: a custom log function - such as log.debug
-
-        logf defaults to log.info, unless category equals 'success', in which
-        case logf defaults to log.debug.
-        """
-        if logf is None:
-            logf = log.info
-            if category == 'success':
-                logf = log.debug
-
-        logf('Flash %s: %s', category, message)
-
-        super(Flash, self).__call__(message, category, ignore_duplicate)
-
-    def pop_messages(self):
-        """Return all accumulated messages and delete them from the session.
-
-        The return value is a list of ``Message`` objects.
-        """
-        from tg import session
-        messages = session.pop(self.session_key, [])
-        session.save()
-        return [_Message(*m) for m in messages]
+def _session_flash_messages(append=None, clear=False):
+    """Manage a message queue in tg.session: return the current message queue
+    after appending the given message, and possibly clearing the queue."""
+    key = 'flash'
+    from tg import session
+    if key in session:
+        flash_messages = session[key]
+    else:
+        if append is None:  # common fast path - also used for clearing empty queue
+            return []  # don't bother saving
+        flash_messages = []
+        session[key] = flash_messages
+    if append is not None and append not in flash_messages:
+        flash_messages.append(append)
+    if clear:
+        session.pop(key, None)
+    session.save()
+    return flash_messages
 
 
-flash = Flash()
+def flash(message, category=None, logf=None):
+    """
+    Show a message to the user _and_ log it through the specified function
+
+    category: notice (default), warning, error, success
+    logf: a custom log function - such as log.debug
 
-#==============================================================================
-# SCM FILTERS available via h.
-#==============================================================================
-from kallithea.lib.vcs.utils import author_name, author_email
-from kallithea.lib.utils2 import credentials_filter, age as _age
+    logf defaults to log.info, unless category equals 'success', in which
+    case logf defaults to log.debug.
+    """
+    if logf is None:
+        logf = log.info
+        if category == 'success':
+            logf = log.debug
+
+    logf('Flash %s: %s', category, message)
+
+    _session_flash_messages(append=(category, message))
+
+
+def pop_flash_messages():
+    """Return all accumulated messages and delete them from the session.
+
+    The return value is a list of ``Message`` objects.
+    """
+    return [_Message(*m) for m in _session_flash_messages(clear=True)]
+
 
 age = lambda x, y=False: _age(x, y)
 capitalize = lambda x: x.capitalize()
@@ -500,13 +541,16 @@
     return _type == 'hg'
 
 
-@cache_region('long_term', 'user_or_none')
-def user_or_none(author):
-    """Try to match email part of VCS committer string with a local user - or return None"""
-    from kallithea.model.db import User
+@cache_region('long_term', 'user_attr_or_none')
+def user_attr_or_none(author, show_attr):
+    """Try to match email part of VCS committer string with a local user and return show_attr
+    - or return None if user not found"""
     email = author_email(author)
     if email:
-        return User.get_by_email(email, cache=True) # cache will only use sql_cache_short
+        from kallithea.model.db import User
+        user = User.get_by_email(email, cache=True) # cache will only use sql_cache_short
+        if user is not None:
+            return getattr(user, show_attr)
     return None
 
 
@@ -515,9 +559,9 @@
     Return primary email of user, email part of the specified author name, or None."""
     if not author:
         return None
-    user = user_or_none(author)
-    if user is not None:
-        return user.email # always use main email address - not necessarily the one used to find user
+    email = user_attr_or_none(author, 'email')
+    if email is not None:
+        return email # always use user's main email address - not necessarily the one used to find user
 
     # extract email from the commit string
     email = author_email(author)
@@ -532,16 +576,13 @@
     """Find the user identified by 'author', return one of the users attributes,
     default to the username attribute, None if there is no user"""
     from kallithea.model.db import User
-    # attr to return from fetched user
-    person_getter = lambda usr: getattr(usr, show_attr)
-
     # if author is already an instance use it for extraction
     if isinstance(author, User):
-        return person_getter(author)
+        return getattr(author, show_attr)
 
-    user = user_or_none(author)
-    if user is not None:
-        return person_getter(user)
+    value = user_attr_or_none(author, show_attr)
+    if value is not None:
+        return value
 
     # Still nothing?  Just pass back the author name if any, else the email
     return author_name(author) or email(author)
@@ -753,52 +794,52 @@
 
     # action : translated str, callback(extractor), icon
     action_map = {
-    'user_deleted_repo':           (_('[deleted] repository'),
-                                    None, 'icon-trashcan'),
-    'user_created_repo':           (_('[created] repository'),
-                                    None, 'icon-plus'),
-    'user_created_fork':           (_('[created] repository as fork'),
-                                    None, 'icon-fork'),
-    'user_forked_repo':            (_('[forked] repository'),
-                                    get_fork_name, 'icon-fork'),
-    'user_updated_repo':           (_('[updated] repository'),
-                                    None, 'icon-pencil'),
-    'user_downloaded_archive':      (_('[downloaded] archive from repository'),
-                                    get_archive_name, 'icon-download-cloud'),
-    'admin_deleted_repo':          (_('[delete] repository'),
-                                    None, 'icon-trashcan'),
-    'admin_created_repo':          (_('[created] repository'),
-                                    None, 'icon-plus'),
-    'admin_forked_repo':           (_('[forked] repository'),
-                                    None, 'icon-fork'),
-    'admin_updated_repo':          (_('[updated] repository'),
-                                    None, 'icon-pencil'),
-    'admin_created_user':          (_('[created] user'),
-                                    get_user_name, 'icon-user'),
-    'admin_updated_user':          (_('[updated] user'),
-                                    get_user_name, 'icon-user'),
-    'admin_created_users_group':   (_('[created] user group'),
-                                    get_users_group, 'icon-pencil'),
-    'admin_updated_users_group':   (_('[updated] user group'),
-                                    get_users_group, 'icon-pencil'),
-    'user_commented_revision':     (_('[commented] on revision in repository'),
-                                    get_cs_links, 'icon-comment'),
-    'user_commented_pull_request': (_('[commented] on pull request for'),
-                                    get_pull_request, 'icon-comment'),
-    'user_closed_pull_request':    (_('[closed] pull request for'),
-                                    get_pull_request, 'icon-ok'),
-    'push':                        (_('[pushed] into'),
-                                    get_cs_links, 'icon-move-up'),
-    'push_local':                  (_('[committed via Kallithea] into repository'),
-                                    get_cs_links, 'icon-pencil'),
-    'push_remote':                 (_('[pulled from remote] into repository'),
-                                    get_cs_links, 'icon-move-up'),
-    'pull':                        (_('[pulled] from'),
-                                    None, 'icon-move-down'),
-    'started_following_repo':      (_('[started following] repository'),
-                                    None, 'icon-heart'),
-    'stopped_following_repo':      (_('[stopped following] repository'),
-                                    None, 'icon-heart-empty'),
+        'user_deleted_repo':           (_('[deleted] repository'),
+                                        None, 'icon-trashcan'),
+        'user_created_repo':           (_('[created] repository'),
+                                        None, 'icon-plus'),
+        'user_created_fork':           (_('[created] repository as fork'),
+                                        None, 'icon-fork'),
+        'user_forked_repo':            (_('[forked] repository'),
+                                        get_fork_name, 'icon-fork'),
+        'user_updated_repo':           (_('[updated] repository'),
+                                        None, 'icon-pencil'),
+        'user_downloaded_archive':      (_('[downloaded] archive from repository'),
+                                        get_archive_name, 'icon-download-cloud'),
+        'admin_deleted_repo':          (_('[delete] repository'),
+                                        None, 'icon-trashcan'),
+        'admin_created_repo':          (_('[created] repository'),
+                                        None, 'icon-plus'),
+        'admin_forked_repo':           (_('[forked] repository'),
+                                        None, 'icon-fork'),
+        'admin_updated_repo':          (_('[updated] repository'),
+                                        None, 'icon-pencil'),
+        'admin_created_user':          (_('[created] user'),
+                                        get_user_name, 'icon-user'),
+        'admin_updated_user':          (_('[updated] user'),
+                                        get_user_name, 'icon-user'),
+        'admin_created_users_group':   (_('[created] user group'),
+                                        get_users_group, 'icon-pencil'),
+        'admin_updated_users_group':   (_('[updated] user group'),
+                                        get_users_group, 'icon-pencil'),
+        'user_commented_revision':     (_('[commented] on revision in repository'),
+                                        get_cs_links, 'icon-comment'),
+        'user_commented_pull_request': (_('[commented] on pull request for'),
+                                        get_pull_request, 'icon-comment'),
+        'user_closed_pull_request':    (_('[closed] pull request for'),
+                                        get_pull_request, 'icon-ok'),
+        'push':                        (_('[pushed] into'),
+                                        get_cs_links, 'icon-move-up'),
+        'push_local':                  (_('[committed via Kallithea] into repository'),
+                                        get_cs_links, 'icon-pencil'),
+        'push_remote':                 (_('[pulled from remote] into repository'),
+                                        get_cs_links, 'icon-move-up'),
+        'pull':                        (_('[pulled] from'),
+                                        None, 'icon-move-down'),
+        'started_following_repo':      (_('[started following] repository'),
+                                        None, 'icon-heart'),
+        'stopped_following_repo':      (_('[stopped following] repository'),
+                                        None, 'icon-heart-empty'),
     }
 
     action_str = action_map.get(action, action)
@@ -830,14 +871,6 @@
     return [lambda: literal(action), action_params_func, action_parser_icon]
 
 
-
-#==============================================================================
-# PERMS
-#==============================================================================
-from kallithea.lib.auth import HasPermissionAny, \
-    HasRepoPermissionLevel, HasRepoGroupPermissionLevel
-
-
 #==============================================================================
 # GRAVATAR URL
 #==============================================================================
@@ -905,7 +938,7 @@
         return default
 
     parsed_url = urlparse.urlparse(url.current(qualified=True))
-    url = (c.visual.gravatar_url or User.DEFAULT_GRAVATAR_URL ) \
+    url = (c.visual.gravatar_url or User.DEFAULT_GRAVATAR_URL) \
                .replace('{email}', email_address) \
                .replace('{md5email}', hashlib.md5(safe_str(email_address).lower()).hexdigest()) \
                .replace('{netloc}', parsed_url.netloc) \
@@ -1061,7 +1094,7 @@
                 return '<div class="label label-meta" data-tag="see">see =&gt; %s</div>' % seen
             license = match_obj.group('license')
             if license:
-                return '<div class="label label-meta" data-tag="license"><a href="http:\/\/www.opensource.org/licenses/%s">%s</a></div>' % (license, license)
+                return '<div class="label label-meta" data-tag="license"><a href="http://www.opensource.org/licenses/%s">%s</a></div>' % (license, license)
             tagtype = match_obj.group('tagtype')
             if tagtype:
                 tagvalue = match_obj.group('tagvalue')
@@ -1273,11 +1306,22 @@
     return '%s - %s' % (s, e)
 
 
+session_csrf_secret_name = "_session_csrf_secret_token"
+
+def session_csrf_secret_token():
+    """Return (and create) the current session's CSRF protection token."""
+    from tg import session
+    if not session_csrf_secret_name in session:
+        session[session_csrf_secret_name] = str(random.getrandbits(128))
+        session.save()
+    return session[session_csrf_secret_name]
+
 def form(url, method="post", **attrs):
-    """Like webhelpers.html.tags.form but automatically using secure_form with
-    authentication_token for POST. authentication_token is thus never leaked
-    in the URL."""
+    """Like webhelpers.html.tags.form , but automatically adding
+    session_csrf_secret_token for POST. The secret is thus never leaked in GET
+    URLs.
+    """
+    form = insecure_form(url, method, **attrs)
     if method.lower() == 'get':
-        return insecure_form(url, method=method, **attrs)
-    # webhelpers will turn everything but GET into POST
-    return secure_form(url, method=method, **attrs)
+        return form
+    return form + HTML.div(hidden(session_csrf_secret_name, session_csrf_secret_token()), style="display: none;")
--- a/kallithea/lib/hooks.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/hooks.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,18 +25,17 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+import binascii
 import os
 import time
-import binascii
 
-from kallithea.lib.vcs.utils.hgcompat import nullrev, revrange
 from kallithea.lib import helpers as h
-from kallithea.lib.utils import action_logger
+from kallithea.lib.exceptions import UserCreationError
+from kallithea.lib.utils import action_logger, make_ui, setup_cache_regions
+from kallithea.lib.utils2 import get_hook_environment, safe_str, safe_unicode
 from kallithea.lib.vcs.backends.base import EmptyChangeset
-from kallithea.lib.exceptions import HTTPLockedRC, UserCreationError
-from kallithea.lib.utils import make_ui, setup_cache_regions
-from kallithea.lib.utils2 import safe_str, safe_unicode, _extract_extras
-from kallithea.model.db import Repository, User, Ui
+from kallithea.lib.vcs.utils.hgcompat import revrange
+from kallithea.model.db import Repository, User
 
 
 def _get_scm_size(alias, root_path):
@@ -78,48 +77,14 @@
     ui.status(msg)
 
 
-def push_lock_handling(ui, repo, **kwargs):
-    """Pre push function, currently used to ban pushing when repository is locked.
-
-    Called as Mercurial hook prechangegroup.push_lock_handling or from the Git pre-receive hook calling handle_git_pre_receive.
-    """
-    ex = _extract_extras()
-
-    usr = User.get_by_username(ex.username)
-    if ex.locked_by[0] and usr.user_id != int(ex.locked_by[0]):
-        locked_by = User.get(ex.locked_by[0]).username
-        # this exception is interpreted in git/hg middlewares and based
-        # on that proper return code is server to client
-        _http_ret = HTTPLockedRC(ex.repository, locked_by)
-        if str(_http_ret.code).startswith('2'):
-            # 2xx Codes don't raise exceptions
-            ui.status(safe_str(_http_ret.title))
-        else:
-            raise _http_ret
-
-
-def pull_lock_handling(ui, repo, **kwargs):
-    """Called as Mercurial hook preoutgoing.pull_lock_handling or from Kallithea before invoking Git"""
-    # pre pull function ...
-    ex = _extract_extras()
-    if ex.locked_by[0]:
-        locked_by = User.get(ex.locked_by[0]).username
-        # this exception is interpreted in git/hg middlewares and based
-        # on that proper return code is server to client
-        _http_ret = HTTPLockedRC(ex.repository, locked_by)
-        if str(_http_ret.code).startswith('2'):
-            # 2xx Codes don't raise exceptions
-            ui.status(safe_str(_http_ret.title))
-        else:
-            raise _http_ret
-
-
 def log_pull_action(ui, repo, **kwargs):
-    """Logs user last pull action, and also handle locking
+    """Logs user last pull action
 
     Called as Mercurial hook outgoing.pull_logger or from Kallithea before invoking Git.
+
+    Does *not* use the action from the hook environment but is always 'pull'.
     """
-    ex = _extract_extras()
+    ex = get_hook_environment()
 
     user = User.get_by_username(ex.username)
     action = 'pull'
@@ -132,57 +97,35 @@
         kw.update(ex)
         callback(**kw)
 
-    if ex.make_lock is not None and ex.make_lock:
-        Repository.lock(Repository.get_by_repo_name(ex.repository), user.user_id)
-        #msg = 'Made lock on repo `%s`' % repository
-        #ui.status(msg)
-
-    if ex.locked_by[0]:
-        locked_by = User.get(ex.locked_by[0]).username
-        _http_ret = HTTPLockedRC(ex.repository, locked_by)
-        if str(_http_ret.code).startswith('2'):
-            # 2xx Codes don't raise exceptions
-            ui.status(safe_str(_http_ret.title))
     return 0
 
 
-def log_push_action(ui, repo, **kwargs):
+def log_push_action(ui, repo, node, node_last, **kwargs):
     """
-    Register that changes have been pushed - log it *and* invalidate caches.
-    Note: It is not only logging, but also the side effect invalidating cahes!
-    The function should perhaps be renamed.
-
-    Called as Mercurial hook changegroup.push_logger or from the Git
-    post-receive hook calling handle_git_post_receive ... or from scm _handle_push.
+    Entry point for Mercurial hook changegroup.push_logger.
 
-    Revisions are passed in different hack-ish ways.
-    """
-    ex = _extract_extras()
-
-    action_tmpl = ex.action + ':%s'
-    revs = []
-    if ex.scm == 'hg':
-        node = kwargs['node']
+    The pushed changesets is given by the revset 'node:node_last'.
 
-        def get_revs(repo, rev_opt):
-            if rev_opt:
-                revs = revrange(repo, rev_opt)
+    Note: This hook is not only logging, but also the side effect invalidating
+    cahes! The function should perhaps be renamed.
+    """
+    _h = binascii.hexlify
+    revs = [_h(repo[r].node()) for r in revrange(repo, [node + ':' + node_last])]
+    process_pushed_raw_ids(revs)
+    return 0
 
-                if len(revs) == 0:
-                    return (nullrev, nullrev)
-                return max(revs), min(revs)
-            else:
-                return len(repo) - 1, 0
 
-        stop, start = get_revs(repo, [node + ':'])
-        _h = binascii.hexlify
-        revs = [_h(repo[r].node()) for r in xrange(start, stop + 1)]
-    elif ex.scm == 'git':
-        revs = kwargs.get('_git_revs', [])
-        if '_git_revs' in kwargs:
-            kwargs.pop('_git_revs')
+def process_pushed_raw_ids(revs):
+    """
+    Register that changes have been added to the repo - log the action *and* invalidate caches.
 
-    action = action_tmpl % ','.join(revs)
+    Called from  Mercurial changegroup.push_logger calling hook log_push_action,
+    or from the Git post-receive hook calling handle_git_post_receive ...
+    or from scm _handle_push.
+    """
+    ex = get_hook_environment()
+
+    action = '%s:%s' % (ex.action, ','.join(revs))
     action_logger(ex.username, action, ex.repository, ex.ip, commit=True)
 
     from kallithea.model.scm import ScmModel
@@ -196,19 +139,6 @@
         kw.update(ex)
         callback(**kw)
 
-    if ex.make_lock is not None and not ex.make_lock:
-        Repository.unlock(Repository.get_by_repo_name(ex.repository))
-        ui.status(safe_str('Released lock on repo `%s`\n' % ex.repository))
-
-    if ex.locked_by[0]:
-        locked_by = User.get(ex.locked_by[0]).username
-        _http_ret = HTTPLockedRC(ex.repository, locked_by)
-        if str(_http_ret.code).startswith('2'):
-            # 2xx Codes don't raise exceptions
-            ui.status(safe_str(_http_ret.title))
-
-    return 0
-
 
 def log_create_repository(repository_dict, created_by, **kwargs):
     """
@@ -281,7 +211,6 @@
      'active',
      'password',
      'emails',
-     'inherit_default_permissions'
 
     """
     from kallithea import EXTENSIONS
@@ -354,7 +283,6 @@
      'active',
      'password',
      'emails',
-     'inherit_default_permissions'
 
     """
     from kallithea import EXTENSIONS
@@ -379,7 +307,7 @@
     from kallithea.config.environment import load_environment
     from kallithea.model.base import init_model
 
-    extras = _extract_extras()
+    extras = get_hook_environment()
     ini_file_path = extras['config']
     #logging.config.fileConfig(ini_file_path) # Note: we are in a different process - don't use configured logging
     app_conf = appconfig('config:%s' % ini_file_path)
@@ -400,15 +328,13 @@
         raise OSError('Repository %s not found in database'
                       % (safe_str(repo_path)))
 
-    baseui = make_ui('db')
+    baseui = make_ui()
     return baseui, repo
 
 
 def handle_git_pre_receive(repo_path, git_stdin_lines):
     """Called from Git pre-receive hook"""
-    baseui, repo = _hook_environment(repo_path)
-    scm_repo = repo.scm_instance
-    push_lock_handling(baseui, scm_repo)
+    # Currently unused. TODO: remove?
     return 0
 
 
@@ -419,53 +345,59 @@
     # the post push hook should never use the cached instance
     scm_repo = repo.scm_instance_no_cache()
 
-    _hooks = dict(baseui.configitems('hooks')) or {}
-    # if push hook is enabled via web interface
-    if _hooks.get(Ui.HOOK_PUSH_LOG):
-        rev_data = []
-        for l in git_stdin_lines:
-            old_rev, new_rev, ref = l.strip().split(' ')
-            _ref_data = ref.split('/')
-            if _ref_data[1] in ['tags', 'heads']:
-                rev_data.append({'old_rev': old_rev,
-                                 'new_rev': new_rev,
-                                 'ref': ref,
-                                 'type': _ref_data[1],
-                                 'name': '/'.join(_ref_data[2:])})
+    rev_data = []
+    for l in git_stdin_lines:
+        old_rev, new_rev, ref = l.strip().split(' ')
+        _ref_data = ref.split('/')
+        if _ref_data[1] in ['tags', 'heads']:
+            rev_data.append({'old_rev': old_rev,
+                             'new_rev': new_rev,
+                             'ref': ref,
+                             'type': _ref_data[1],
+                             'name': '/'.join(_ref_data[2:])})
 
-        git_revs = []
-        for push_ref in rev_data:
-            _type = push_ref['type']
-            if _type == 'heads':
-                if push_ref['old_rev'] == EmptyChangeset().raw_id:
-                    # update the symbolic ref if we push new repo
-                    if scm_repo.is_empty():
-                        scm_repo._repo.refs.set_symbolic_ref('HEAD',
-                                            'refs/heads/%s' % push_ref['name'])
+    git_revs = []
+    for push_ref in rev_data:
+        _type = push_ref['type']
+        if _type == 'heads':
+            if push_ref['old_rev'] == EmptyChangeset().raw_id:
+                # update the symbolic ref if we push new repo
+                if scm_repo.is_empty():
+                    scm_repo._repo.refs.set_symbolic_ref('HEAD',
+                                        'refs/heads/%s' % push_ref['name'])
 
-                    # build exclude list without the ref
-                    cmd = ['for-each-ref', '--format=%(refname)', 'refs/heads/*']
-                    stdout, stderr = scm_repo.run_git_command(cmd)
-                    ref = push_ref['ref']
-                    heads = [head for head in stdout.splitlines() if head != ref]
-                    # now list the git revs while excluding from the list
-                    cmd = ['log', push_ref['new_rev'], '--reverse', '--pretty=format:%H']
-                    cmd.append('--not')
-                    cmd.extend(heads) # empty list is ok
-                    stdout, stderr = scm_repo.run_git_command(cmd)
-                    git_revs += stdout.splitlines()
+                # build exclude list without the ref
+                cmd = ['for-each-ref', '--format=%(refname)', 'refs/heads/*']
+                stdout, stderr = scm_repo.run_git_command(cmd)
+                ref = push_ref['ref']
+                heads = [head for head in stdout.splitlines() if head != ref]
+                # now list the git revs while excluding from the list
+                cmd = ['log', push_ref['new_rev'], '--reverse', '--pretty=format:%H']
+                cmd.append('--not')
+                cmd.extend(heads) # empty list is ok
+                stdout, stderr = scm_repo.run_git_command(cmd)
+                git_revs += stdout.splitlines()
 
-                elif push_ref['new_rev'] == EmptyChangeset().raw_id:
-                    # delete branch case
-                    git_revs += ['delete_branch=>%s' % push_ref['name']]
-                else:
-                    cmd = ['log', '%(old_rev)s..%(new_rev)s' % push_ref,
-                           '--reverse', '--pretty=format:%H']
-                    stdout, stderr = scm_repo.run_git_command(cmd)
-                    git_revs += stdout.splitlines()
+            elif push_ref['new_rev'] == EmptyChangeset().raw_id:
+                # delete branch case
+                git_revs += ['delete_branch=>%s' % push_ref['name']]
+            else:
+                cmd = ['log', '%(old_rev)s..%(new_rev)s' % push_ref,
+                       '--reverse', '--pretty=format:%H']
+                stdout, stderr = scm_repo.run_git_command(cmd)
+                git_revs += stdout.splitlines()
+
+        elif _type == 'tags':
+            git_revs += ['tag=>%s' % push_ref['name']]
 
-            elif _type == 'tags':
-                git_revs += ['tag=>%s' % push_ref['name']]
+    process_pushed_raw_ids(git_revs)
+
+    return 0
+
 
-        log_push_action(baseui, scm_repo, _git_revs=git_revs)
-    return 0
+# Almost exactly like Mercurial contrib/hg-ssh:
+def rejectpush(ui, **kwargs):
+    """Mercurial hook to be installed as pretxnopen and prepushkey for read-only repos"""
+    ex = get_hook_environment()
+    ui.warn((b"Push access to %r denied\n") % safe_str(ex.repository))
+    return 1
--- a/kallithea/lib/indexers/__init__.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/indexers/__init__.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,19 +25,23 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+import logging
 import os
 import sys
-import logging
 from os.path import dirname
 
+from whoosh.analysis import IDTokenizer, LowercaseFilter, RegexTokenizer
+from whoosh.fields import BOOLEAN, DATETIME, ID, NUMERIC, STORED, TEXT, FieldType, Schema
+from whoosh.formats import Characters
+from whoosh.highlight import ContextFragmenter, HtmlFormatter
+from whoosh.highlight import highlight as whoosh_highlight
+
+from kallithea.lib.utils2 import LazyProperty
+
+
 # Add location of top level folder to sys.path
 sys.path.append(dirname(dirname(dirname(os.path.realpath(__file__)))))
 
-from whoosh.analysis import RegexTokenizer, LowercaseFilter, IDTokenizer
-from whoosh.fields import TEXT, ID, STORED, NUMERIC, BOOLEAN, Schema, FieldType, DATETIME
-from whoosh.formats import Characters
-from whoosh.highlight import highlight as whoosh_highlight, HtmlFormatter, ContextFragmenter
-from kallithea.lib.utils2 import LazyProperty
 
 log = logging.getLogger(__name__)
 
--- a/kallithea/lib/indexers/daemon.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/indexers/daemon.py	Sun Jan 05 04:07:51 2020 +0100
@@ -26,33 +26,31 @@
 """
 
 
+import logging
 import os
 import sys
-import logging
 import traceback
-
+from os.path import dirname
 from shutil import rmtree
 from time import mktime
 
-from os.path import dirname
+from whoosh.index import create_in, exists_in, open_dir
+from whoosh.qparser import QueryParser
+
+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, safe_unicode
+from kallithea.lib.vcs.exceptions import ChangesetError, NodeDoesNotExistError, RepositoryError
+from kallithea.model.db import Repository
+from kallithea.model.scm import ScmModel
+
 
 # Add location of top level folder to sys.path
 project_path = dirname(dirname(dirname(dirname(os.path.realpath(__file__)))))
 sys.path.append(project_path)
 
-from kallithea.config.conf import INDEX_EXTENSIONS, INDEX_FILENAMES
-from kallithea.model.scm import ScmModel
-from kallithea.model.db import Repository
-from kallithea.lib.utils2 import safe_unicode, safe_str
-from kallithea.lib.indexers import SCHEMA, IDX_NAME, CHGSETS_SCHEMA, \
-    CHGSET_IDX_NAME
 
-from kallithea.lib.vcs.exceptions import ChangesetError, RepositoryError, \
-    NodeDoesNotExistError
 
-from whoosh.index import create_in, open_dir, exists_in
-from whoosh.query import *
-from whoosh.qparser import QueryParser
 
 log = logging.getLogger('whoosh_indexer')
 
--- a/kallithea/lib/inifile.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/inifile.py	Sun Jan 05 04:07:51 2020 +0100
@@ -21,8 +21,8 @@
 """
 
 import logging
+import os
 import re
-import os
 
 import mako.template
 
@@ -141,7 +141,7 @@
             )*
         )
         ''',
-        process_section, ini_lines, flags=re.MULTILINE|re.VERBOSE) \
+        process_section, ini_lines, flags=re.MULTILINE | re.VERBOSE) \
         + \
         ''.join(
             '\n' + sectionname + '\n' + ''.join('%s = %s\n' % (key, value) for key, value in sorted(section_settings.items()))
--- a/kallithea/lib/ipaddr.py	Sat Aug 24 21:48:43 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1902 +0,0 @@
-# Copyright 2007 Google Inc.
-#  Licensed to PSF under a Contributor Agreement.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# permissions and limitations under the License.
-
-"""A fast, lightweight IPv4/IPv6 manipulation library in Python.
-
-This library is used to create/poke/manipulate IPv4 and IPv6 addresses
-and networks.
-
-"""
-
-__version__ = 'trunk'
-
-import struct
-
-IPV4LENGTH = 32
-IPV6LENGTH = 128
-
-
-class AddressValueError(ValueError):
-    """A Value Error related to the address."""
-
-
-class NetmaskValueError(ValueError):
-    """A Value Error related to the netmask."""
-
-
-def IPAddress(address, version=None):
-    """Take an IP string/int and return an object of the correct type.
-
-    Args:
-        address: A string or integer, the IP address.  Either IPv4 or
-          IPv6 addresses may be supplied; integers less than 2**32 will
-          be considered to be IPv4 by default.
-        version: An Integer, 4 or 6. If set, don't try to automatically
-          determine what the IP address type is. important for things
-          like IPAddress(1), which could be IPv4, '0.0.0.1',  or IPv6,
-          '::1'.
-
-    Returns:
-        An IPv4Address or IPv6Address object.
-
-    Raises:
-        ValueError: if the string passed isn't either a v4 or a v6
-          address.
-
-    """
-    if version:
-        if version == 4:
-            return IPv4Address(address)
-        elif version == 6:
-            return IPv6Address(address)
-
-    try:
-        return IPv4Address(address)
-    except (AddressValueError, NetmaskValueError):
-        pass
-
-    try:
-        return IPv6Address(address)
-    except (AddressValueError, NetmaskValueError):
-        pass
-
-    raise ValueError('%r does not appear to be an IPv4 or IPv6 address' %
-                     address)
-
-
-def IPNetwork(address, version=None, strict=False):
-    """Take an IP string/int and return an object of the correct type.
-
-    Args:
-        address: A string or integer, the IP address.  Either IPv4 or
-          IPv6 addresses may be supplied; integers less than 2**32 will
-          be considered to be IPv4 by default.
-        version: An Integer, if set, don't try to automatically
-          determine what the IP address type is. important for things
-          like IPNetwork(1), which could be IPv4, '0.0.0.1/32', or IPv6,
-          '::1/128'.
-
-    Returns:
-        An IPv4Network or IPv6Network object.
-
-    Raises:
-        ValueError: if the string passed isn't either a v4 or a v6
-          address. Or if a strict network was requested and a strict
-          network wasn't given.
-
-    """
-    if version:
-        if version == 4:
-            return IPv4Network(address, strict)
-        elif version == 6:
-            return IPv6Network(address, strict)
-
-    try:
-        return IPv4Network(address, strict)
-    except (AddressValueError, NetmaskValueError):
-        pass
-
-    try:
-        return IPv6Network(address, strict)
-    except (AddressValueError, NetmaskValueError):
-        pass
-
-    raise ValueError('%r does not appear to be an IPv4 or IPv6 network' %
-                     address)
-
-
-def v4_int_to_packed(address):
-    """The binary representation of this address.
-
-    Args:
-        address: An integer representation of an IPv4 IP address.
-
-    Returns:
-        The binary representation of this address.
-
-    Raises:
-        ValueError: If the integer is too large to be an IPv4 IP
-          address.
-    """
-    if address > _BaseV4._ALL_ONES:
-        raise ValueError('Address too large for IPv4')
-    return Bytes(struct.pack('!I', address))
-
-
-def v6_int_to_packed(address):
-    """The binary representation of this address.
-
-    Args:
-        address: An integer representation of an IPv6 IP address.
-
-    Returns:
-        The binary representation of this address.
-    """
-    return Bytes(struct.pack('!QQ', address >> 64, address & (2 ** 64 - 1)))
-
-
-def _find_address_range(addresses):
-    """Find a sequence of addresses.
-
-    Args:
-        addresses: a list of IPv4 or IPv6 addresses.
-
-    Returns:
-        A tuple containing the first and last IP addresses in the sequence.
-
-    """
-    first = last = addresses[0]
-    for ip in addresses[1:]:
-        if ip._ip == last._ip + 1:
-            last = ip
-        else:
-            break
-    return (first, last)
-
-
-def _get_prefix_length(number1, number2, bits):
-    """Get the number of leading bits that are same for two numbers.
-
-    Args:
-        number1: an integer.
-        number2: another integer.
-        bits: the maximum number of bits to compare.
-
-    Returns:
-        The number of leading bits that are the same for two numbers.
-
-    """
-    for i in range(bits):
-        if number1 >> i == number2 >> i:
-            return bits - i
-    return 0
-
-
-def _count_righthand_zero_bits(number, bits):
-    """Count the number of zero bits on the right hand side.
-
-    Args:
-        number: an integer.
-        bits: maximum number of bits to count.
-
-    Returns:
-        The number of zero bits on the right hand side of the number.
-
-    """
-    if number == 0:
-        return bits
-    for i in range(bits):
-        if (number >> i) % 2:
-            return i
-
-
-def summarize_address_range(first, last):
-    """Summarize a network range given the first and last IP addresses.
-
-    Example:
-        >>> summarize_address_range(IPv4Address('1.1.1.0'),
-            IPv4Address('1.1.1.130'))
-        [IPv4Network('1.1.1.0/25'), IPv4Network('1.1.1.128/31'),
-        IPv4Network('1.1.1.130/32')]
-
-    Args:
-        first: the first IPv4Address or IPv6Address in the range.
-        last: the last IPv4Address or IPv6Address in the range.
-
-    Returns:
-        The address range collapsed to a list of IPv4Network's or
-        IPv6Network's.
-
-    Raise:
-        TypeError:
-            If the first and last objects are not IP addresses.
-            If the first and last objects are not the same version.
-        ValueError:
-            If the last object is not greater than the first.
-            If the version is not 4 or 6.
-
-    """
-    if not (isinstance(first, _BaseIP) and isinstance(last, _BaseIP)):
-        raise TypeError('first and last must be IP addresses, not networks')
-    if first.version != last.version:
-        raise TypeError("%s and %s are not of the same version" % (
-                str(first), str(last)))
-    if first > last:
-        raise ValueError('last IP address must be greater than first')
-
-    networks = []
-
-    if first.version == 4:
-        ip = IPv4Network
-    elif first.version == 6:
-        ip = IPv6Network
-    else:
-        raise ValueError('unknown IP version')
-
-    ip_bits = first._max_prefixlen
-    first_int = first._ip
-    last_int = last._ip
-    while first_int <= last_int:
-        nbits = _count_righthand_zero_bits(first_int, ip_bits)
-        current = None
-        while nbits >= 0:
-            addend = 2 ** nbits - 1
-            current = first_int + addend
-            nbits -= 1
-            if current <= last_int:
-                break
-        prefix = _get_prefix_length(first_int, current, ip_bits)
-        net = ip('%s/%d' % (str(first), prefix))
-        networks.append(net)
-        if current == ip._ALL_ONES:
-            break
-        first_int = current + 1
-        first = IPAddress(first_int, version=first._version)
-    return networks
-
-
-def _collapse_address_list_recursive(addresses):
-    """Loops through the addresses, collapsing concurrent netblocks.
-
-    Example:
-
-        ip1 = IPv4Network('1.1.0.0/24')
-        ip2 = IPv4Network('1.1.1.0/24')
-        ip3 = IPv4Network('1.1.2.0/24')
-        ip4 = IPv4Network('1.1.3.0/24')
-        ip5 = IPv4Network('1.1.4.0/24')
-        ip6 = IPv4Network('1.1.0.1/22')
-
-        _collapse_address_list_recursive([ip1, ip2, ip3, ip4, ip5, ip6]) ->
-          [IPv4Network('1.1.0.0/22'), IPv4Network('1.1.4.0/24')]
-
-        This shouldn't be called directly; it is called via
-          collapse_address_list([]).
-
-    Args:
-        addresses: A list of IPv4Network's or IPv6Network's
-
-    Returns:
-        A list of IPv4Network's or IPv6Network's depending on what we were
-        passed.
-
-    """
-    ret_array = []
-    optimized = False
-
-    for cur_addr in addresses:
-        if not ret_array:
-            ret_array.append(cur_addr)
-            continue
-        if cur_addr in ret_array[-1]:
-            optimized = True
-        elif cur_addr == ret_array[-1].supernet().subnet()[1]:
-            ret_array.append(ret_array.pop().supernet())
-            optimized = True
-        else:
-            ret_array.append(cur_addr)
-
-    if optimized:
-        return _collapse_address_list_recursive(ret_array)
-
-    return ret_array
-
-
-def collapse_address_list(addresses):
-    """Collapse a list of IP objects.
-
-    Example:
-        collapse_address_list([IPv4('1.1.0.0/24'), IPv4('1.1.1.0/24')]) ->
-          [IPv4('1.1.0.0/23')]
-
-    Args:
-        addresses: A list of IPv4Network or IPv6Network objects.
-
-    Returns:
-        A list of IPv4Network or IPv6Network objects depending on what we
-        were passed.
-
-    Raises:
-        TypeError: If passed a list of mixed version objects.
-
-    """
-    i = 0
-    addrs = []
-    ips = []
-    nets = []
-
-    # split IP addresses and networks
-    for ip in addresses:
-        if isinstance(ip, _BaseIP):
-            if ips and ips[-1]._version != ip._version:
-                raise TypeError("%s and %s are not of the same version" % (
-                        str(ip), str(ips[-1])))
-            ips.append(ip)
-        elif ip._prefixlen == ip._max_prefixlen:
-            if ips and ips[-1]._version != ip._version:
-                raise TypeError("%s and %s are not of the same version" % (
-                        str(ip), str(ips[-1])))
-            ips.append(ip.ip)
-        else:
-            if nets and nets[-1]._version != ip._version:
-                raise TypeError("%s and %s are not of the same version" % (
-                        str(ip), str(nets[-1])))
-            nets.append(ip)
-
-    # sort and dedup
-    ips = sorted(set(ips))
-    nets = sorted(set(nets))
-
-    while i < len(ips):
-        (first, last) = _find_address_range(ips[i:])
-        i = ips.index(last) + 1
-        addrs.extend(summarize_address_range(first, last))
-
-    return _collapse_address_list_recursive(sorted(
-        addrs + nets, key=_BaseNet._get_networks_key))
-
-
-# backwards compatibility
-CollapseAddrList = collapse_address_list
-
-
-# We need to distinguish between the string and packed-bytes representations
-# of an IP address.  For example, b'0::1' is the IPv4 address 48.58.58.49,
-# while '0::1' is an IPv6 address.
-#
-# In Python 3, the native 'bytes' type already provides this functionality,
-# so we use it directly.  For earlier implementations where bytes is not a
-# distinct type, we create a subclass of str to serve as a tag.
-#
-# Usage example (Python 2):
-#   ip = ipaddr.IPAddress(ipaddr.Bytes('xxxx'))
-#
-# Usage example (Python 3):
-#   ip = ipaddr.IPAddress(b'xxxx')
-try:
-    if bytes is str:
-        raise TypeError("bytes is not a distinct type")
-    Bytes = bytes
-except (NameError, TypeError):
-    class Bytes(str):
-        def __repr__(self):
-            return 'Bytes(%s)' % str.__repr__(self)
-
-
-def get_mixed_type_key(obj):
-    """Return a key suitable for sorting between networks and addresses.
-
-    Address and Network objects are not sortable by default; they're
-    fundamentally different so the expression
-
-        IPv4Address('1.1.1.1') <= IPv4Network('1.1.1.1/24')
-
-    doesn't make any sense.  There are some times however, where you may wish
-    to have ipaddr sort these for you anyway. If you need to do this, you
-    can use this function as the key= argument to sorted().
-
-    Args:
-      obj: either a Network or Address object.
-    Returns:
-      appropriate key.
-
-    """
-    if isinstance(obj, _BaseNet):
-        return obj._get_networks_key()
-    elif isinstance(obj, _BaseIP):
-        return obj._get_address_key()
-    return NotImplemented
-
-
-class _IPAddrBase(object):
-
-    """The mother class."""
-
-    def __index__(self):
-        return self._ip
-
-    def __int__(self):
-        return self._ip
-
-    def __hex__(self):
-        return hex(self._ip)
-
-    @property
-    def exploded(self):
-        """Return the longhand version of the IP address as a string."""
-        return self._explode_shorthand_ip_string()
-
-    @property
-    def compressed(self):
-        """Return the shorthand version of the IP address as a string."""
-        return str(self)
-
-
-class _BaseIP(_IPAddrBase):
-
-    """A generic IP object.
-
-    This IP class contains the version independent methods which are
-    used by single IP addresses.
-
-    """
-
-    def __eq__(self, other):
-        try:
-            return (self._ip == other._ip
-                    and self._version == other._version)
-        except AttributeError:
-            return NotImplemented
-
-    def __ne__(self, other):
-        eq = self.__eq__(other)
-        if eq is NotImplemented:
-            return NotImplemented
-        return not eq
-
-    def __le__(self, other):
-        gt = self.__gt__(other)
-        if gt is NotImplemented:
-            return NotImplemented
-        return not gt
-
-    def __ge__(self, other):
-        lt = self.__lt__(other)
-        if lt is NotImplemented:
-            return NotImplemented
-        return not lt
-
-    def __lt__(self, other):
-        if self._version != other._version:
-            raise TypeError('%s and %s are not of the same version' % (
-                    str(self), str(other)))
-        if not isinstance(other, _BaseIP):
-            raise TypeError('%s and %s are not of the same type' % (
-                    str(self), str(other)))
-        if self._ip != other._ip:
-            return self._ip < other._ip
-        return False
-
-    def __gt__(self, other):
-        if self._version != other._version:
-            raise TypeError('%s and %s are not of the same version' % (
-                    str(self), str(other)))
-        if not isinstance(other, _BaseIP):
-            raise TypeError('%s and %s are not of the same type' % (
-                    str(self), str(other)))
-        if self._ip != other._ip:
-            return self._ip > other._ip
-        return False
-
-    # Shorthand for Integer addition and subtraction. This is not
-    # meant to ever support addition/subtraction of addresses.
-    def __add__(self, other):
-        if not isinstance(other, int):
-            return NotImplemented
-        return IPAddress(int(self) + other, version=self._version)
-
-    def __sub__(self, other):
-        if not isinstance(other, int):
-            return NotImplemented
-        return IPAddress(int(self) - other, version=self._version)
-
-    def __repr__(self):
-        return '%s(%r)' % (self.__class__.__name__, str(self))
-
-    def __str__(self):
-        return self._string_from_ip_int(self._ip)
-
-    def __hash__(self):
-        return hash(hex(long(self._ip)))
-
-    def _get_address_key(self):
-        return (self._version, self)
-
-    @property
-    def version(self):
-        raise NotImplementedError('BaseIP has no version')
-
-
-class _BaseNet(_IPAddrBase):
-
-    """A generic IP object.
-
-    This IP class contains the version independent methods which are
-    used by networks.
-
-    """
-
-    def __init__(self, address):
-        self._cache = {}
-
-    def __repr__(self):
-        return '%s(%r)' % (self.__class__.__name__, str(self))
-
-    def iterhosts(self):
-        """Generate Iterator over usable hosts in a network.
-
-           This is like __iter__ except it doesn't return the network
-           or broadcast addresses.
-
-        """
-        cur = int(self.network) + 1
-        bcast = int(self.broadcast) - 1
-        while cur <= bcast:
-            cur += 1
-            yield IPAddress(cur - 1, version=self._version)
-
-    def __iter__(self):
-        cur = int(self.network)
-        bcast = int(self.broadcast)
-        while cur <= bcast:
-            cur += 1
-            yield IPAddress(cur - 1, version=self._version)
-
-    def __getitem__(self, n):
-        network = int(self.network)
-        broadcast = int(self.broadcast)
-        if n >= 0:
-            if network + n > broadcast:
-                raise IndexError
-            return IPAddress(network + n, version=self._version)
-        else:
-            n += 1
-            if broadcast + n < network:
-                raise IndexError
-            return IPAddress(broadcast + n, version=self._version)
-
-    def __lt__(self, other):
-        if self._version != other._version:
-            raise TypeError('%s and %s are not of the same version' % (
-                    str(self), str(other)))
-        if not isinstance(other, _BaseNet):
-            raise TypeError('%s and %s are not of the same type' % (
-                    str(self), str(other)))
-        if self.network != other.network:
-            return self.network < other.network
-        if self.netmask != other.netmask:
-            return self.netmask < other.netmask
-        return False
-
-    def __gt__(self, other):
-        if self._version != other._version:
-            raise TypeError('%s and %s are not of the same version' % (
-                    str(self), str(other)))
-        if not isinstance(other, _BaseNet):
-            raise TypeError('%s and %s are not of the same type' % (
-                    str(self), str(other)))
-        if self.network != other.network:
-            return self.network > other.network
-        if self.netmask != other.netmask:
-            return self.netmask > other.netmask
-        return False
-
-    def __le__(self, other):
-        gt = self.__gt__(other)
-        if gt is NotImplemented:
-            return NotImplemented
-        return not gt
-
-    def __ge__(self, other):
-        lt = self.__lt__(other)
-        if lt is NotImplemented:
-            return NotImplemented
-        return not lt
-
-    def __eq__(self, other):
-        try:
-            return (self._version == other._version
-                    and self.network == other.network
-                    and int(self.netmask) == int(other.netmask))
-        except AttributeError:
-            if isinstance(other, _BaseIP):
-                return (self._version == other._version
-                        and self._ip == other._ip)
-
-    def __ne__(self, other):
-        eq = self.__eq__(other)
-        if eq is NotImplemented:
-            return NotImplemented
-        return not eq
-
-    def __str__(self):
-        return  '%s/%s' % (str(self.ip),
-                           str(self._prefixlen))
-
-    def __hash__(self):
-        return hash(int(self.network) ^ int(self.netmask))
-
-    def __contains__(self, other):
-        # always false if one is v4 and the other is v6.
-        if self._version != other._version:
-            return False
-        # dealing with another network.
-        if isinstance(other, _BaseNet):
-            return (self.network <= other.network and
-                    self.broadcast >= other.broadcast)
-        # dealing with another address
-        else:
-            return (int(self.network) <= int(other._ip) <=
-                    int(self.broadcast))
-
-    def overlaps(self, other):
-        """Tell if self is partly contained in other."""
-        return self.network in other or self.broadcast in other or (
-            other.network in self or other.broadcast in self)
-
-    @property
-    def network(self):
-        x = self._cache.get('network')
-        if x is None:
-            x = IPAddress(self._ip & int(self.netmask), version=self._version)
-            self._cache['network'] = x
-        return x
-
-    @property
-    def broadcast(self):
-        x = self._cache.get('broadcast')
-        if x is None:
-            x = IPAddress(self._ip | int(self.hostmask), version=self._version)
-            self._cache['broadcast'] = x
-        return x
-
-    @property
-    def hostmask(self):
-        x = self._cache.get('hostmask')
-        if x is None:
-            x = IPAddress(int(self.netmask) ^ self._ALL_ONES,
-                          version=self._version)
-            self._cache['hostmask'] = x
-        return x
-
-    @property
-    def with_prefixlen(self):
-        return '%s/%d' % (str(self.ip), self._prefixlen)
-
-    @property
-    def with_netmask(self):
-        return '%s/%s' % (str(self.ip), str(self.netmask))
-
-    @property
-    def with_hostmask(self):
-        return '%s/%s' % (str(self.ip), str(self.hostmask))
-
-    @property
-    def numhosts(self):
-        """Number of hosts in the current subnet."""
-        return int(self.broadcast) - int(self.network) + 1
-
-    @property
-    def version(self):
-        raise NotImplementedError('BaseNet has no version')
-
-    @property
-    def prefixlen(self):
-        return self._prefixlen
-
-    def address_exclude(self, other):
-        """Remove an address from a larger block.
-
-        For example:
-
-            addr1 = IPNetwork('10.1.1.0/24')
-            addr2 = IPNetwork('10.1.1.0/26')
-            addr1.address_exclude(addr2) =
-                [IPNetwork('10.1.1.64/26'), IPNetwork('10.1.1.128/25')]
-
-        or IPv6:
-
-            addr1 = IPNetwork('::1/32')
-            addr2 = IPNetwork('::1/128')
-            addr1.address_exclude(addr2) = [IPNetwork('::0/128'),
-                IPNetwork('::2/127'),
-                IPNetwork('::4/126'),
-                IPNetwork('::8/125'),
-                ...
-                IPNetwork('0:0:8000::/33')]
-
-        Args:
-            other: An IPvXNetwork object of the same type.
-
-        Returns:
-            A sorted list of IPvXNetwork objects addresses which is self
-            minus other.
-
-        Raises:
-            TypeError: If self and other are of differing address
-              versions, or if other is not a network object.
-            ValueError: If other is not completely contained by self.
-
-        """
-        if not self._version == other._version:
-            raise TypeError("%s and %s are not of the same version" % (
-                str(self), str(other)))
-
-        if not isinstance(other, _BaseNet):
-            raise TypeError("%s is not a network object" % str(other))
-
-        if other not in self:
-            raise ValueError('%s not contained in %s' % (str(other),
-                                                         str(self)))
-        if other == self:
-            return []
-
-        ret_addrs = []
-
-        # Make sure we're comparing the network of other.
-        other = IPNetwork('%s/%s' % (str(other.network), str(other.prefixlen)),
-                   version=other._version)
-
-        s1, s2 = self.subnet()
-        while s1 != other and s2 != other:
-            if other in s1:
-                ret_addrs.append(s2)
-                s1, s2 = s1.subnet()
-            elif other in s2:
-                ret_addrs.append(s1)
-                s1, s2 = s2.subnet()
-            else:
-                # If we got here, there's a bug somewhere.
-                assert False, ('Error performing exclusion: '
-                               's1: %s s2: %s other: %s' %
-                               (str(s1), str(s2), str(other)))
-        if s1 == other:
-            ret_addrs.append(s2)
-        elif s2 == other:
-            ret_addrs.append(s1)
-        else:
-            # If we got here, there's a bug somewhere.
-            assert False, ('Error performing exclusion: s1: %s s2: %s other: %s'
-                           % (str(s1), str(s2), str(other)))
-
-        return sorted(ret_addrs, key=_BaseNet._get_networks_key)
-
-    def compare_networks(self, other):
-        """Compare two IP objects.
-
-        This is only concerned about the comparison of the integer
-        representation of the network addresses.  This means that the
-        host bits aren't considered at all in this method.  If you want
-        to compare host bits, you can easily enough do a
-        'HostA._ip < HostB._ip'
-
-        Args:
-            other: An IP object.
-
-        Returns:
-            If the IP versions of self and other are the same, returns:
-
-            -1 if self < other:
-              eg: IPv4('1.1.1.0/24') < IPv4('1.1.2.0/24')
-              IPv6('1080::200C:417A') < IPv6('1080::200B:417B')
-            0 if self == other
-              eg: IPv4('1.1.1.1/24') == IPv4('1.1.1.2/24')
-              IPv6('1080::200C:417A/96') == IPv6('1080::200C:417B/96')
-            1 if self > other
-              eg: IPv4('1.1.1.0/24') > IPv4('1.1.0.0/24')
-              IPv6('1080::1:200C:417A/112') >
-              IPv6('1080::0:200C:417A/112')
-
-            If the IP versions of self and other are different, returns:
-
-            -1 if self._version < other._version
-              eg: IPv4('10.0.0.1/24') < IPv6('::1/128')
-            1 if self._version > other._version
-              eg: IPv6('::1/128') > IPv4('255.255.255.0/24')
-
-        """
-        if self._version < other._version:
-            return -1
-        if self._version > other._version:
-            return 1
-        # self._version == other._version below here:
-        if self.network < other.network:
-            return -1
-        if self.network > other.network:
-            return 1
-        # self.network == other.network below here:
-        if self.netmask < other.netmask:
-            return -1
-        if self.netmask > other.netmask:
-            return 1
-        # self.network == other.network and self.netmask == other.netmask
-        return 0
-
-    def _get_networks_key(self):
-        """Network-only key function.
-
-        Returns an object that identifies this address' network and
-        netmask. This function is a suitable "key" argument for sorted()
-        and list.sort().
-
-        """
-        return (self._version, self.network, self.netmask)
-
-    def _ip_int_from_prefix(self, prefixlen=None):
-        """Turn the prefix length netmask into a int for comparison.
-
-        Args:
-            prefixlen: An integer, the prefix length.
-
-        Returns:
-            An integer.
-
-        """
-        if not prefixlen and prefixlen != 0:
-            prefixlen = self._prefixlen
-        return self._ALL_ONES ^ (self._ALL_ONES >> prefixlen)
-
-    def _prefix_from_ip_int(self, ip_int, mask=32):
-        """Return prefix length from the decimal netmask.
-
-        Args:
-            ip_int: An integer, the IP address.
-            mask: The netmask.  Defaults to 32.
-
-        Returns:
-            An integer, the prefix length.
-
-        """
-        while mask:
-            if ip_int & 1 == 1:
-                break
-            ip_int >>= 1
-            mask -= 1
-
-        return mask
-
-    def _ip_string_from_prefix(self, prefixlen=None):
-        """Turn a prefix length into a dotted decimal string.
-
-        Args:
-            prefixlen: An integer, the netmask prefix length.
-
-        Returns:
-            A string, the dotted decimal netmask string.
-
-        """
-        if not prefixlen:
-            prefixlen = self._prefixlen
-        return self._string_from_ip_int(self._ip_int_from_prefix(prefixlen))
-
-    def iter_subnets(self, prefixlen_diff=1, new_prefix=None):
-        """The subnets which join to make the current subnet.
-
-        In the case that self contains only one IP
-        (self._prefixlen == 32 for IPv4 or self._prefixlen == 128
-        for IPv6), return a list with just ourself.
-
-        Args:
-            prefixlen_diff: An integer, the amount the prefix length
-              should be increased by. This should not be set if
-              new_prefix is also set.
-            new_prefix: The desired new prefix length. This must be a
-              larger number (smaller prefix) than the existing prefix.
-              This should not be set if prefixlen_diff is also set.
-
-        Returns:
-            An iterator of IPv(4|6) objects.
-
-        Raises:
-            ValueError: The prefixlen_diff is too small or too large.
-                OR
-            prefixlen_diff and new_prefix are both set or new_prefix
-              is a smaller number than the current prefix (smaller
-              number means a larger network)
-
-        """
-        if self._prefixlen == self._max_prefixlen:
-            yield self
-            return
-
-        if new_prefix is not None:
-            if new_prefix < self._prefixlen:
-                raise ValueError('new prefix must be longer')
-            if prefixlen_diff != 1:
-                raise ValueError('cannot set prefixlen_diff and new_prefix')
-            prefixlen_diff = new_prefix - self._prefixlen
-
-        if prefixlen_diff < 0:
-            raise ValueError('prefix length diff must be > 0')
-        new_prefixlen = self._prefixlen + prefixlen_diff
-
-        if not self._is_valid_netmask(str(new_prefixlen)):
-            raise ValueError(
-                'prefix length diff %d is invalid for netblock %s' % (
-                    new_prefixlen, str(self)))
-
-        first = IPNetwork('%s/%s' % (str(self.network),
-                                     str(self._prefixlen + prefixlen_diff)),
-                         version=self._version)
-
-        yield first
-        current = first
-        while True:
-            broadcast = current.broadcast
-            if broadcast == self.broadcast:
-                return
-            new_addr = IPAddress(int(broadcast) + 1, version=self._version)
-            current = IPNetwork('%s/%s' % (str(new_addr), str(new_prefixlen)),
-                                version=self._version)
-
-            yield current
-
-    def masked(self):
-        """Return the network object with the host bits masked out."""
-        return IPNetwork('%s/%d' % (self.network, self._prefixlen),
-                         version=self._version)
-
-    def subnet(self, prefixlen_diff=1, new_prefix=None):
-        """Return a list of subnets, rather than an iterator."""
-        return list(self.iter_subnets(prefixlen_diff, new_prefix))
-
-    def supernet(self, prefixlen_diff=1, new_prefix=None):
-        """The supernet containing the current network.
-
-        Args:
-            prefixlen_diff: An integer, the amount the prefix length of
-              the network should be decreased by.  For example, given a
-              /24 network and a prefixlen_diff of 3, a supernet with a
-              /21 netmask is returned.
-
-        Returns:
-            An IPv4 network object.
-
-        Raises:
-            ValueError: If self.prefixlen - prefixlen_diff < 0. I.e., you have a
-              negative prefix length.
-                OR
-            If prefixlen_diff and new_prefix are both set or new_prefix is a
-              larger number than the current prefix (larger number means a
-              smaller network)
-
-        """
-        if self._prefixlen == 0:
-            return self
-
-        if new_prefix is not None:
-            if new_prefix > self._prefixlen:
-                raise ValueError('new prefix must be shorter')
-            if prefixlen_diff != 1:
-                raise ValueError('cannot set prefixlen_diff and new_prefix')
-            prefixlen_diff = self._prefixlen - new_prefix
-
-        if self.prefixlen - prefixlen_diff < 0:
-            raise ValueError(
-                'current prefixlen is %d, cannot have a prefixlen_diff of %d' %
-                (self.prefixlen, prefixlen_diff))
-        return IPNetwork('%s/%s' % (str(self.network),
-                                    str(self.prefixlen - prefixlen_diff)),
-                         version=self._version)
-
-    # backwards compatibility
-    Subnet = subnet
-    Supernet = supernet
-    AddressExclude = address_exclude
-    CompareNetworks = compare_networks
-    Contains = __contains__
-
-
-class _BaseV4(object):
-
-    """Base IPv4 object.
-
-    The following methods are used by IPv4 objects in both single IP
-    addresses and networks.
-
-    """
-
-    # Equivalent to 255.255.255.255 or 32 bits of 1's.
-    _ALL_ONES = (2 ** IPV4LENGTH) - 1
-    _DECIMAL_DIGITS = frozenset('0123456789')
-
-    def __init__(self, address):
-        self._version = 4
-        self._max_prefixlen = IPV4LENGTH
-
-    def _explode_shorthand_ip_string(self):
-        return str(self)
-
-    def _ip_int_from_string(self, ip_str):
-        """Turn the given IP string into an integer for comparison.
-
-        Args:
-            ip_str: A string, the IP ip_str.
-
-        Returns:
-            The IP ip_str as an integer.
-
-        Raises:
-            AddressValueError: if ip_str isn't a valid IPv4 Address.
-
-        """
-        octets = ip_str.split('.')
-        if len(octets) != 4:
-            raise AddressValueError(ip_str)
-
-        packed_ip = 0
-        for oc in octets:
-            try:
-                packed_ip = (packed_ip << 8) | self._parse_octet(oc)
-            except ValueError:
-                raise AddressValueError(ip_str)
-        return packed_ip
-
-    def _parse_octet(self, octet_str):
-        """Convert a decimal octet into an integer.
-
-        Args:
-            octet_str: A string, the number to parse.
-
-        Returns:
-            The octet as an integer.
-
-        Raises:
-            ValueError: if the octet isn't strictly a decimal from [0..255].
-
-        """
-        # Whitelist the characters, since int() allows a lot of bizarre stuff.
-        if not self._DECIMAL_DIGITS.issuperset(octet_str):
-            raise ValueError
-        octet_int = int(octet_str, 10)
-        # Disallow leading zeroes, because no clear standard exists on
-        # whether these should be interpreted as decimal or octal.
-        if octet_int > 255 or (octet_str[0] == '0' and len(octet_str) > 1):
-            raise ValueError
-        return octet_int
-
-    def _string_from_ip_int(self, ip_int):
-        """Turns a 32-bit integer into dotted decimal notation.
-
-        Args:
-            ip_int: An integer, the IP address.
-
-        Returns:
-            The IP address as a string in dotted decimal notation.
-
-        """
-        octets = []
-        for _ in xrange(4):
-            octets.insert(0, str(ip_int & 0xFF))
-            ip_int >>= 8
-        return '.'.join(octets)
-
-    @property
-    def max_prefixlen(self):
-        return self._max_prefixlen
-
-    @property
-    def packed(self):
-        """The binary representation of this address."""
-        return v4_int_to_packed(self._ip)
-
-    @property
-    def version(self):
-        return self._version
-
-    @property
-    def is_reserved(self):
-        """Test if the address is otherwise IETF reserved.
-
-         Returns:
-             A boolean, True if the address is within the
-             reserved IPv4 Network range.
-
-        """
-        return self in IPv4Network('240.0.0.0/4')
-
-    @property
-    def is_private(self):
-        """Test if this address is allocated for private networks.
-
-        Returns:
-            A boolean, True if the address is reserved per RFC 1918.
-
-        """
-        return (self in IPv4Network('10.0.0.0/8') or
-                self in IPv4Network('172.16.0.0/12') or
-                self in IPv4Network('192.168.0.0/16'))
-
-    @property
-    def is_multicast(self):
-        """Test if the address is reserved for multicast use.
-
-        Returns:
-            A boolean, True if the address is multicast.
-            See RFC 3171 for details.
-
-        """
-        return self in IPv4Network('224.0.0.0/4')
-
-    @property
-    def is_unspecified(self):
-        """Test if the address is unspecified.
-
-        Returns:
-            A boolean, True if this is the unspecified address as defined in
-            RFC 5735 3.
-
-        """
-        return self in IPv4Network('0.0.0.0')
-
-    @property
-    def is_loopback(self):
-        """Test if the address is a loopback address.
-
-        Returns:
-            A boolean, True if the address is a loopback per RFC 3330.
-
-        """
-        return self in IPv4Network('127.0.0.0/8')
-
-    @property
-    def is_link_local(self):
-        """Test if the address is reserved for link-local.
-
-        Returns:
-            A boolean, True if the address is link-local per RFC 3927.
-
-        """
-        return self in IPv4Network('169.254.0.0/16')
-
-
-class IPv4Address(_BaseV4, _BaseIP):
-
-    """Represent and manipulate single IPv4 Addresses."""
-
-    def __init__(self, address):
-
-        """
-        Args:
-            address: A string or integer representing the IP
-              '192.168.1.1'
-
-              Additionally, an integer can be passed, so
-              IPv4Address('192.168.1.1') == IPv4Address(3232235777).
-              or, more generally
-              IPv4Address(int(IPv4Address('192.168.1.1'))) ==
-                IPv4Address('192.168.1.1')
-
-        Raises:
-            AddressValueError: If ipaddr isn't a valid IPv4 address.
-
-        """
-        _BaseV4.__init__(self, address)
-
-        # Efficient constructor from integer.
-        if isinstance(address, (int, long)):
-            self._ip = address
-            if address < 0 or address > self._ALL_ONES:
-                raise AddressValueError(address)
-            return
-
-        # Constructing from a packed address
-        if isinstance(address, Bytes):
-            try:
-                self._ip, = struct.unpack('!I', address)
-            except struct.error:
-                raise AddressValueError(address)  # Wrong length.
-            return
-
-        # Assume input argument to be string or any object representation
-        # which converts into a formatted IP string.
-        addr_str = str(address)
-        self._ip = self._ip_int_from_string(addr_str)
-
-
-class IPv4Network(_BaseV4, _BaseNet):
-
-    """This class represents and manipulates 32-bit IPv4 networks.
-
-    Attributes: [examples for IPv4Network('1.2.3.4/27')]
-        ._ip: 16909060
-        .ip: IPv4Address('1.2.3.4')
-        .network: IPv4Address('1.2.3.0')
-        .hostmask: IPv4Address('0.0.0.31')
-        .broadcast: IPv4Address('1.2.3.31')
-        .netmask: IPv4Address('255.255.255.224')
-        .prefixlen: 27
-
-    """
-
-    # the valid octets for host and netmasks. only useful for IPv4.
-    _valid_mask_octets = set((255, 254, 252, 248, 240, 224, 192, 128, 0))
-
-    def __init__(self, address, strict=False):
-        """Instantiate a new IPv4 network object.
-
-        Args:
-            address: A string or integer representing the IP [& network].
-              '192.168.1.1/24'
-              '192.168.1.1/255.255.255.0'
-              '192.168.1.1/0.0.0.255'
-              are all functionally the same in IPv4. Similarly,
-              '192.168.1.1'
-              '192.168.1.1/255.255.255.255'
-              '192.168.1.1/32'
-              are also functionally equivalent. That is to say, failing to
-              provide a subnetmask will create an object with a mask of /32.
-
-              If the mask (portion after the / in the argument) is given in
-              dotted quad form, it is treated as a netmask if it starts with a
-              non-zero field (e.g. /255.0.0.0 == /8) and as a hostmask if it
-              starts with a zero field (e.g. 0.255.255.255 == /8), with the
-              single exception of an all-zero mask which is treated as a
-              netmask == /0. If no mask is given, a default of /32 is used.
-
-              Additionally, an integer can be passed, so
-              IPv4Network('192.168.1.1') == IPv4Network(3232235777).
-              or, more generally
-              IPv4Network(int(IPv4Network('192.168.1.1'))) ==
-                IPv4Network('192.168.1.1')
-
-            strict: A boolean. If true, ensure that we have been passed
-              A true network address, eg, 192.168.1.0/24 and not an
-              IP address on a network, eg, 192.168.1.1/24.
-
-        Raises:
-            AddressValueError: If ipaddr isn't a valid IPv4 address.
-            NetmaskValueError: If the netmask isn't valid for
-              an IPv4 address.
-            ValueError: If strict was True and a network address was not
-              supplied.
-
-        """
-        _BaseNet.__init__(self, address)
-        _BaseV4.__init__(self, address)
-
-        # Constructing from an integer or packed bytes.
-        if isinstance(address, (int, long, Bytes)):
-            self.ip = IPv4Address(address)
-            self._ip = self.ip._ip
-            self._prefixlen = self._max_prefixlen
-            self.netmask = IPv4Address(self._ALL_ONES)
-            return
-
-        # Assume input argument to be string or any object representation
-        # which converts into a formatted IP prefix string.
-        addr = str(address).split('/')
-
-        if len(addr) > 2:
-            raise AddressValueError(address)
-
-        self._ip = self._ip_int_from_string(addr[0])
-        self.ip = IPv4Address(self._ip)
-
-        if len(addr) == 2:
-            mask = addr[1].split('.')
-            if len(mask) == 4:
-                # We have dotted decimal netmask.
-                if self._is_valid_netmask(addr[1]):
-                    self.netmask = IPv4Address(self._ip_int_from_string(
-                            addr[1]))
-                elif self._is_hostmask(addr[1]):
-                    self.netmask = IPv4Address(
-                        self._ip_int_from_string(addr[1]) ^ self._ALL_ONES)
-                else:
-                    raise NetmaskValueError('%s is not a valid netmask'
-                                                     % addr[1])
-
-                self._prefixlen = self._prefix_from_ip_int(int(self.netmask))
-            else:
-                # We have a netmask in prefix length form.
-                if not self._is_valid_netmask(addr[1]):
-                    raise NetmaskValueError(addr[1])
-                self._prefixlen = int(addr[1])
-                self.netmask = IPv4Address(self._ip_int_from_prefix(
-                    self._prefixlen))
-        else:
-            self._prefixlen = self._max_prefixlen
-            self.netmask = IPv4Address(self._ip_int_from_prefix(
-                self._prefixlen))
-        if strict:
-            if self.ip != self.network:
-                raise ValueError('%s has host bits set' %
-                                 self.ip)
-        if self._prefixlen == (self._max_prefixlen - 1):
-            self.iterhosts = self.__iter__
-
-    def _is_hostmask(self, ip_str):
-        """Test if the IP string is a hostmask (rather than a netmask).
-
-        Args:
-            ip_str: A string, the potential hostmask.
-
-        Returns:
-            A boolean, True if the IP string is a hostmask.
-
-        """
-        bits = ip_str.split('.')
-        try:
-            parts = [int(x) for x in bits if int(x) in self._valid_mask_octets]
-        except ValueError:
-            return False
-        if len(parts) != len(bits):
-            return False
-        if parts[0] < parts[-1]:
-            return True
-        return False
-
-    def _is_valid_netmask(self, netmask):
-        """Verify that the netmask is valid.
-
-        Args:
-            netmask: A string, either a prefix or dotted decimal
-              netmask.
-
-        Returns:
-            A boolean, True if the prefix represents a valid IPv4
-            netmask.
-
-        """
-        mask = netmask.split('.')
-        if len(mask) == 4:
-            if [x for x in mask if int(x) not in self._valid_mask_octets]:
-                return False
-            if [y for idx, y in enumerate(mask) if idx > 0 and
-                y > mask[idx - 1]]:
-                return False
-            return True
-        try:
-            netmask = int(netmask)
-        except ValueError:
-            return False
-        return 0 <= netmask <= self._max_prefixlen
-
-    # backwards compatibility
-    IsRFC1918 = lambda self: self.is_private
-    IsMulticast = lambda self: self.is_multicast
-    IsLoopback = lambda self: self.is_loopback
-    IsLinkLocal = lambda self: self.is_link_local
-
-
-class _BaseV6(object):
-
-    """Base IPv6 object.
-
-    The following methods are used by IPv6 objects in both single IP
-    addresses and networks.
-
-    """
-
-    _ALL_ONES = (2 ** IPV6LENGTH) - 1
-    _HEXTET_COUNT = 8
-    _HEX_DIGITS = frozenset('0123456789ABCDEFabcdef')
-
-    def __init__(self, address):
-        self._version = 6
-        self._max_prefixlen = IPV6LENGTH
-
-    def _ip_int_from_string(self, ip_str):
-        """Turn an IPv6 ip_str into an integer.
-
-        Args:
-            ip_str: A string, the IPv6 ip_str.
-
-        Returns:
-            A long, the IPv6 ip_str.
-
-        Raises:
-            AddressValueError: if ip_str isn't a valid IPv6 Address.
-
-        """
-        parts = ip_str.split(':')
-
-        # An IPv6 address needs at least 2 colons (3 parts).
-        if len(parts) < 3:
-            raise AddressValueError(ip_str)
-
-        # If the address has an IPv4-style suffix, convert it to hexadecimal.
-        if '.' in parts[-1]:
-            ipv4_int = IPv4Address(parts.pop())._ip
-            parts.append('%x' % ((ipv4_int >> 16) & 0xFFFF))
-            parts.append('%x' % (ipv4_int & 0xFFFF))
-
-        # An IPv6 address can't have more than 8 colons (9 parts).
-        if len(parts) > self._HEXTET_COUNT + 1:
-            raise AddressValueError(ip_str)
-
-        # Disregarding the endpoints, find '::' with nothing in between.
-        # This indicates that a run of zeroes has been skipped.
-        try:
-            skip_index, = (
-                [i for i in xrange(1, len(parts) - 1) if not parts[i]] or
-                [None])
-        except ValueError:
-            # Can't have more than one '::'
-            raise AddressValueError(ip_str)
-
-        # parts_hi is the number of parts to copy from above/before the '::'
-        # parts_lo is the number of parts to copy from below/after the '::'
-        if skip_index is not None:
-            # If we found a '::', then check if it also covers the endpoints.
-            parts_hi = skip_index
-            parts_lo = len(parts) - skip_index - 1
-            if not parts[0]:
-                parts_hi -= 1
-                if parts_hi:
-                    raise AddressValueError(ip_str)  # ^: requires ^::
-            if not parts[-1]:
-                parts_lo -= 1
-                if parts_lo:
-                    raise AddressValueError(ip_str)  # :$ requires ::$
-            parts_skipped = self._HEXTET_COUNT - (parts_hi + parts_lo)
-            if parts_skipped < 1:
-                raise AddressValueError(ip_str)
-        else:
-            # Otherwise, allocate the entire address to parts_hi.  The endpoints
-            # could still be empty, but _parse_hextet() will check for that.
-            if len(parts) != self._HEXTET_COUNT:
-                raise AddressValueError(ip_str)
-            parts_hi = len(parts)
-            parts_lo = 0
-            parts_skipped = 0
-
-        try:
-            # Now, parse the hextets into a 128-bit integer.
-            ip_int = 0L
-            for i in xrange(parts_hi):
-                ip_int <<= 16
-                ip_int |= self._parse_hextet(parts[i])
-            ip_int <<= 16 * parts_skipped
-            for i in xrange(-parts_lo, 0):
-                ip_int <<= 16
-                ip_int |= self._parse_hextet(parts[i])
-            return ip_int
-        except ValueError:
-            raise AddressValueError(ip_str)
-
-    def _parse_hextet(self, hextet_str):
-        """Convert an IPv6 hextet string into an integer.
-
-        Args:
-            hextet_str: A string, the number to parse.
-
-        Returns:
-            The hextet as an integer.
-
-        Raises:
-            ValueError: if the input isn't strictly a hex number from [0..FFFF].
-
-        """
-        # Whitelist the characters, since int() allows a lot of bizarre stuff.
-        if not self._HEX_DIGITS.issuperset(hextet_str):
-            raise ValueError
-        if len(hextet_str) > 4:
-            raise ValueError
-        hextet_int = int(hextet_str, 16)
-        if hextet_int > 0xFFFF:
-            raise ValueError
-        return hextet_int
-
-    def _compress_hextets(self, hextets):
-        """Compresses a list of hextets.
-
-        Compresses a list of strings, replacing the longest continuous
-        sequence of "0" in the list with "" and adding empty strings at
-        the beginning or at the end of the string such that subsequently
-        calling ":".join(hextets) will produce the compressed version of
-        the IPv6 address.
-
-        Args:
-            hextets: A list of strings, the hextets to compress.
-
-        Returns:
-            A list of strings.
-
-        """
-        best_doublecolon_start = -1
-        best_doublecolon_len = 0
-        doublecolon_start = -1
-        doublecolon_len = 0
-        for index in range(len(hextets)):
-            if hextets[index] == '0':
-                doublecolon_len += 1
-                if doublecolon_start == -1:
-                    # Start of a sequence of zeros.
-                    doublecolon_start = index
-                if doublecolon_len > best_doublecolon_len:
-                    # This is the longest sequence of zeros so far.
-                    best_doublecolon_len = doublecolon_len
-                    best_doublecolon_start = doublecolon_start
-            else:
-                doublecolon_len = 0
-                doublecolon_start = -1
-
-        if best_doublecolon_len > 1:
-            best_doublecolon_end = (best_doublecolon_start +
-                                    best_doublecolon_len)
-            # For zeros at the end of the address.
-            if best_doublecolon_end == len(hextets):
-                hextets += ['']
-            hextets[best_doublecolon_start:best_doublecolon_end] = ['']
-            # For zeros at the beginning of the address.
-            if best_doublecolon_start == 0:
-                hextets = [''] + hextets
-
-        return hextets
-
-    def _string_from_ip_int(self, ip_int=None):
-        """Turns a 128-bit integer into hexadecimal notation.
-
-        Args:
-            ip_int: An integer, the IP address.
-
-        Returns:
-            A string, the hexadecimal representation of the address.
-
-        Raises:
-            ValueError: The address is bigger than 128 bits of all ones.
-
-        """
-        if not ip_int and ip_int != 0:
-            ip_int = int(self._ip)
-
-        if ip_int > self._ALL_ONES:
-            raise ValueError('IPv6 address is too large')
-
-        hex_str = '%032x' % ip_int
-        hextets = []
-        for x in range(0, 32, 4):
-            hextets.append('%x' % int(hex_str[x:x + 4], 16))
-
-        hextets = self._compress_hextets(hextets)
-        return ':'.join(hextets)
-
-    def _explode_shorthand_ip_string(self):
-        """Expand a shortened IPv6 address.
-
-        Args:
-            ip_str: A string, the IPv6 address.
-
-        Returns:
-            A string, the expanded IPv6 address.
-
-        """
-        if isinstance(self, _BaseNet):
-            ip_str = str(self.ip)
-        else:
-            ip_str = str(self)
-
-        ip_int = self._ip_int_from_string(ip_str)
-        parts = []
-        for i in xrange(self._HEXTET_COUNT):
-            parts.append('%04x' % (ip_int & 0xFFFF))
-            ip_int >>= 16
-        parts.reverse()
-        if isinstance(self, _BaseNet):
-            return '%s/%d' % (':'.join(parts), self.prefixlen)
-        return ':'.join(parts)
-
-    @property
-    def max_prefixlen(self):
-        return self._max_prefixlen
-
-    @property
-    def packed(self):
-        """The binary representation of this address."""
-        return v6_int_to_packed(self._ip)
-
-    @property
-    def version(self):
-        return self._version
-
-    @property
-    def is_multicast(self):
-        """Test if the address is reserved for multicast use.
-
-        Returns:
-            A boolean, True if the address is a multicast address.
-            See RFC 2373 2.7 for details.
-
-        """
-        return self in IPv6Network('ff00::/8')
-
-    @property
-    def is_reserved(self):
-        """Test if the address is otherwise IETF reserved.
-
-        Returns:
-            A boolean, True if the address is within one of the
-            reserved IPv6 Network ranges.
-
-        """
-        return (self in IPv6Network('::/8') or
-                self in IPv6Network('100::/8') or
-                self in IPv6Network('200::/7') or
-                self in IPv6Network('400::/6') or
-                self in IPv6Network('800::/5') or
-                self in IPv6Network('1000::/4') or
-                self in IPv6Network('4000::/3') or
-                self in IPv6Network('6000::/3') or
-                self in IPv6Network('8000::/3') or
-                self in IPv6Network('A000::/3') or
-                self in IPv6Network('C000::/3') or
-                self in IPv6Network('E000::/4') or
-                self in IPv6Network('F000::/5') or
-                self in IPv6Network('F800::/6') or
-                self in IPv6Network('FE00::/9'))
-
-    @property
-    def is_unspecified(self):
-        """Test if the address is unspecified.
-
-        Returns:
-            A boolean, True if this is the unspecified address as defined in
-            RFC 2373 2.5.2.
-
-        """
-        return self._ip == 0 and getattr(self, '_prefixlen', 128) == 128
-
-    @property
-    def is_loopback(self):
-        """Test if the address is a loopback address.
-
-        Returns:
-            A boolean, True if the address is a loopback address as defined in
-            RFC 2373 2.5.3.
-
-        """
-        return self._ip == 1 and getattr(self, '_prefixlen', 128) == 128
-
-    @property
-    def is_link_local(self):
-        """Test if the address is reserved for link-local.
-
-        Returns:
-            A boolean, True if the address is reserved per RFC 4291.
-
-        """
-        return self in IPv6Network('fe80::/10')
-
-    @property
-    def is_site_local(self):
-        """Test if the address is reserved for site-local.
-
-        Note that the site-local address space has been deprecated by RFC 3879.
-        Use is_private to test if this address is in the space of unique local
-        addresses as defined by RFC 4193.
-
-        Returns:
-            A boolean, True if the address is reserved per RFC 3513 2.5.6.
-
-        """
-        return self in IPv6Network('fec0::/10')
-
-    @property
-    def is_private(self):
-        """Test if this address is allocated for private networks.
-
-        Returns:
-            A boolean, True if the address is reserved per RFC 4193.
-
-        """
-        return self in IPv6Network('fc00::/7')
-
-    @property
-    def ipv4_mapped(self):
-        """Return the IPv4 mapped address.
-
-        Returns:
-            If the IPv6 address is a v4 mapped address, return the
-            IPv4 mapped address. Return None otherwise.
-
-        """
-        if (self._ip >> 32) != 0xFFFF:
-            return None
-        return IPv4Address(self._ip & 0xFFFFFFFF)
-
-    @property
-    def teredo(self):
-        """Tuple of embedded teredo IPs.
-
-        Returns:
-            Tuple of the (server, client) IPs or None if the address
-            doesn't appear to be a teredo address (doesn't start with
-            2001::/32)
-
-        """
-        if (self._ip >> 96) != 0x20010000:
-            return None
-        return (IPv4Address((self._ip >> 64) & 0xFFFFFFFF),
-                IPv4Address(~self._ip & 0xFFFFFFFF))
-
-    @property
-    def sixtofour(self):
-        """Return the IPv4 6to4 embedded address.
-
-        Returns:
-            The IPv4 6to4-embedded address if present or None if the
-            address doesn't appear to contain a 6to4 embedded address.
-
-        """
-        if (self._ip >> 112) != 0x2002:
-            return None
-        return IPv4Address((self._ip >> 80) & 0xFFFFFFFF)
-
-
-class IPv6Address(_BaseV6, _BaseIP):
-
-    """Represent and manipulate single IPv6 Addresses.
-    """
-
-    def __init__(self, address):
-        """Instantiate a new IPv6 address object.
-
-        Args:
-            address: A string or integer representing the IP
-
-              Additionally, an integer can be passed, so
-              IPv6Address('2001:4860::') ==
-                IPv6Address(42541956101370907050197289607612071936L).
-              or, more generally
-              IPv6Address(IPv6Address('2001:4860::')._ip) ==
-                IPv6Address('2001:4860::')
-
-        Raises:
-            AddressValueError: If address isn't a valid IPv6 address.
-
-        """
-        _BaseV6.__init__(self, address)
-
-        # Efficient constructor from integer.
-        if isinstance(address, (int, long)):
-            self._ip = address
-            if address < 0 or address > self._ALL_ONES:
-                raise AddressValueError(address)
-            return
-
-        # Constructing from a packed address
-        if isinstance(address, Bytes):
-            try:
-                hi, lo = struct.unpack('!QQ', address)
-            except struct.error:
-                raise AddressValueError(address)  # Wrong length.
-            self._ip = (hi << 64) | lo
-            return
-
-        # Assume input argument to be string or any object representation
-        # which converts into a formatted IP string.
-        addr_str = str(address)
-        if not addr_str:
-            raise AddressValueError('')
-
-        self._ip = self._ip_int_from_string(addr_str)
-
-
-class IPv6Network(_BaseV6, _BaseNet):
-
-    """This class represents and manipulates 128-bit IPv6 networks.
-
-    Attributes: [examples for IPv6('2001:658:22A:CAFE:200::1/64')]
-        .ip: IPv6Address('2001:658:22a:cafe:200::1')
-        .network: IPv6Address('2001:658:22a:cafe::')
-        .hostmask: IPv6Address('::ffff:ffff:ffff:ffff')
-        .broadcast: IPv6Address('2001:658:22a:cafe:ffff:ffff:ffff:ffff')
-        .netmask: IPv6Address('ffff:ffff:ffff:ffff::')
-        .prefixlen: 64
-
-    """
-
-    def __init__(self, address, strict=False):
-        """Instantiate a new IPv6 Network object.
-
-        Args:
-            address: A string or integer representing the IPv6 network or the IP
-              and prefix/netmask.
-              '2001:4860::/128'
-              '2001:4860:0000:0000:0000:0000:0000:0000/128'
-              '2001:4860::'
-              are all functionally the same in IPv6.  That is to say,
-              failing to provide a subnetmask will create an object with
-              a mask of /128.
-
-              Additionally, an integer can be passed, so
-              IPv6Network('2001:4860::') ==
-                IPv6Network(42541956101370907050197289607612071936L).
-              or, more generally
-              IPv6Network(IPv6Network('2001:4860::')._ip) ==
-                IPv6Network('2001:4860::')
-
-            strict: A boolean. If true, ensure that we have been passed
-              A true network address, eg, 192.168.1.0/24 and not an
-              IP address on a network, eg, 192.168.1.1/24.
-
-        Raises:
-            AddressValueError: If address isn't a valid IPv6 address.
-            NetmaskValueError: If the netmask isn't valid for
-              an IPv6 address.
-            ValueError: If strict was True and a network address was not
-              supplied.
-
-        """
-        _BaseNet.__init__(self, address)
-        _BaseV6.__init__(self, address)
-
-        # Constructing from an integer or packed bytes.
-        if isinstance(address, (int, long, Bytes)):
-            self.ip = IPv6Address(address)
-            self._ip = self.ip._ip
-            self._prefixlen = self._max_prefixlen
-            self.netmask = IPv6Address(self._ALL_ONES)
-            return
-
-        # Assume input argument to be string or any object representation
-        # which converts into a formatted IP prefix string.
-        addr = str(address).split('/')
-
-        if len(addr) > 2:
-            raise AddressValueError(address)
-
-        self._ip = self._ip_int_from_string(addr[0])
-        self.ip = IPv6Address(self._ip)
-
-        if len(addr) == 2:
-            if self._is_valid_netmask(addr[1]):
-                self._prefixlen = int(addr[1])
-            else:
-                raise NetmaskValueError(addr[1])
-        else:
-            self._prefixlen = self._max_prefixlen
-
-        self.netmask = IPv6Address(self._ip_int_from_prefix(self._prefixlen))
-
-        if strict:
-            if self.ip != self.network:
-                raise ValueError('%s has host bits set' %
-                                 self.ip)
-        if self._prefixlen == (self._max_prefixlen - 1):
-            self.iterhosts = self.__iter__
-
-    def _is_valid_netmask(self, prefixlen):
-        """Verify that the netmask/prefixlen is valid.
-
-        Args:
-            prefixlen: A string, the netmask in prefix length format.
-
-        Returns:
-            A boolean, True if the prefix represents a valid IPv6
-            netmask.
-
-        """
-        try:
-            prefixlen = int(prefixlen)
-        except ValueError:
-            return False
-        return 0 <= prefixlen <= self._max_prefixlen
-
-    @property
-    def with_netmask(self):
-        return self.with_prefixlen
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/lib/locale.py	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,49 @@
+# -*- 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 logging
+import os
+import sys
+
+
+log = logging.getLogger(__name__)
+
+def current_locale_is_valid():
+    """Verify that things work when Dulwich passes unicode paths to the file system layer.
+
+    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;)
+    except UnicodeEncodeError:
+        log.error("Cannot encode Unicode paths to file system encoding %r", sys.getfilesystemencoding())
+        for var in ['LC_ALL', 'LC_CTYPE', 'LANG']:
+            if var in os.environ:
+                val = os.environ[var]
+                log.error("Note: Environment variable %s is %r - perhaps change it to some other value from 'locale -a', like 'C.UTF-8' or 'en_US.UTF-8'", var, val)
+                break
+        else:
+            log.error("Note: No locale setting found in environment variables - perhaps set LC_CTYPE to some value from 'locale -a', like 'C.UTF-8' or 'en_US.UTF-8'")
+        return False
+    return True
+
+def get_current_locale():
+    """Return the current locale based on environment variables.
+    There does not seem to be a good (and functional) way to get it via Python.
+    """
+    for var in ['LC_ALL', 'LC_CTYPE', 'LANG']:
+        val = os.environ.get(var)
+        if val:
+            log.debug('Determined current locale via environment variable %s (%s)', var, val)
+            return val
+    return None
--- a/kallithea/lib/markup_renderer.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/markup_renderer.py	Sun Jan 05 04:07:51 2020 +0100
@@ -26,14 +26,15 @@
 """
 
 
+import logging
 import re
-import logging
 import traceback
 
+import bleach
 import markdown as markdown_mod
-import bleach
 
-from kallithea.lib.utils2 import safe_unicode, MENTIONS_REGEX
+from kallithea.lib.utils2 import MENTIONS_REGEX, safe_unicode
+
 
 log = logging.getLogger(__name__)
 
@@ -49,24 +50,22 @@
     RST_PAT = re.compile(r're?st', re.IGNORECASE)
     PLAIN_PAT = re.compile(r'readme', re.IGNORECASE)
 
-    def _detect_renderer(self, source, filename):
+    @classmethod
+    def _detect_renderer(cls, source, filename):
         """
         runs detection of what renderer should be used for generating html
         from a markup language
 
         filename can be also explicitly a renderer name
-
-        :param source:
-        :param filename:
         """
 
-        if self.MARKDOWN_PAT.findall(filename):
-            return self.markdown
-        elif self.RST_PAT.findall(filename):
-            return self.rst
-        elif self.PLAIN_PAT.findall(filename):
-            return self.rst
-        return self.plain
+        if cls.MARKDOWN_PAT.findall(filename):
+            return cls.markdown
+        elif cls.RST_PAT.findall(filename):
+            return cls.rst
+        elif cls.PLAIN_PAT.findall(filename):
+            return cls.rst
+        return cls.plain
 
     @classmethod
     def _flavored_markdown(cls, text):
@@ -91,7 +90,7 @@
         def italic_callback(matchobj):
             s = matchobj.group(0)
             if list(s).count('_') >= 2:
-                return s.replace('_', '\_')
+                return s.replace('_', r'\_')
             return s
         text = re.sub(r'^(?! {4}|\t)\w+_\w+_\w[\w_]*', italic_callback, text)
 
@@ -112,17 +111,28 @@
 
         return text
 
-    def render(self, source, filename=None):
+    @classmethod
+    def render(cls, source, filename=None):
         """
         Renders a given filename using detected renderer
         it detects renderers based on file extension or mimetype.
         At last it will just do a simple html replacing new lines with <br/>
 
-        :param file_name:
-        :param source:
+        >>> MarkupRenderer.render('''<img id="a" style="margin-top:-1000px;color:red" src="http://example.com/test.jpg">''', '.md')
+        u'<p><img id="a" src="http://example.com/test.jpg" style="color: red;"></p>'
+        >>> MarkupRenderer.render('''<img class="c d" src="file://localhost/test.jpg">''', 'b.mkd')
+        u'<p><img class="c d"></p>'
+        >>> MarkupRenderer.render('''<a href="foo">foo</a>''', 'c.mkdn')
+        u'<p><a href="foo">foo</a></p>'
+        >>> MarkupRenderer.render('''<script>alert(1)</script>''', 'd.mdown')
+        u'&lt;script&gt;alert(1)&lt;/script&gt;'
+        >>> MarkupRenderer.render('''<div onclick="alert(2)">yo</div>''', 'markdown')
+        u'<div>yo</div>'
+        >>> MarkupRenderer.render('''<a href="javascript:alert(3)">yo</a>''', 'md')
+        u'<p><a>yo</a></p>'
         """
 
-        renderer = self._detect_renderer(source, filename)
+        renderer = cls._detect_renderer(source, filename)
         readme_data = renderer(source)
         # Allow most HTML, while preventing XSS issues:
         # no <script> tags, no onclick attributes, no javascript
@@ -154,21 +164,32 @@
     @classmethod
     def markdown(cls, source, safe=True, flavored=False):
         """
-        Convert Markdown (possibly GitHub Flavored) to XSS safe HTML, possibly
-        with "safe" fall-back to plaintext.
+        Convert Markdown (possibly GitHub Flavored) to INSECURE HTML, possibly
+        with "safe" fall-back to plaintext. Output from this method should be sanitized before use.
 
         >>> MarkupRenderer.markdown('''<img id="a" style="margin-top:-1000px;color:red" src="http://example.com/test.jpg">''')
-        u'<p><img id="a" src="http://example.com/test.jpg" style="color: red;"></p>'
+        u'<p><img id="a" style="margin-top:-1000px;color:red" src="http://example.com/test.jpg"></p>'
         >>> MarkupRenderer.markdown('''<img class="c d" src="file://localhost/test.jpg">''')
-        u'<p><img class="c d"></p>'
+        u'<p><img class="c d" src="file://localhost/test.jpg"></p>'
         >>> MarkupRenderer.markdown('''<a href="foo">foo</a>''')
         u'<p><a href="foo">foo</a></p>'
         >>> MarkupRenderer.markdown('''<script>alert(1)</script>''')
-        u'&lt;script&gt;alert(1)&lt;/script&gt;'
+        u'<script>alert(1)</script>'
         >>> MarkupRenderer.markdown('''<div onclick="alert(2)">yo</div>''')
-        u'<div>yo</div>'
+        u'<div onclick="alert(2)">yo</div>'
         >>> MarkupRenderer.markdown('''<a href="javascript:alert(3)">yo</a>''')
-        u'<p><a>yo</a></p>'
+        u'<p><a href="javascript:alert(3)">yo</a></p>'
+        >>> MarkupRenderer.markdown('''## Foo''')
+        u'<h2>Foo</h2>'
+        >>> print MarkupRenderer.markdown('''
+        ...     #!/bin/bash
+        ...     echo "hello"
+        ... ''')
+        <table class="code-highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
+        2</pre></div></td><td class="code"><div class="code-highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
+        <span class="nb">echo</span> <span class="s2">&quot;hello&quot;</span>
+        </pre></div>
+        </td></tr></table>
         """
         source = safe_unicode(source)
         try:
@@ -176,8 +197,8 @@
                 source = cls._flavored_markdown(source)
             return markdown_mod.markdown(
                 source,
-                extensions=['codehilite', 'extra'],
-                extension_configs={'codehilite': {'css_class': 'code-highlight'}})
+                extensions=['markdown.extensions.codehilite', 'markdown.extensions.extra'],
+                extension_configs={'markdown.extensions.codehilite': {'css_class': 'code-highlight'}})
         except Exception:
             log.error(traceback.format_exc())
             if safe:
@@ -222,6 +243,6 @@
 
         def wrapp(match_obj):
             uname = match_obj.groups()[0]
-            return '\ **@%(uname)s**\ ' % {'uname': uname}
+            return r'\ **@%(uname)s**\ ' % {'uname': uname}
         mention_hl = MENTIONS_REGEX.sub(wrapp, source).strip()
         return cls.rst(mention_hl)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/lib/middleware/permanent_repo_url.py	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,38 @@
+# -*- 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.permanent_repo_url
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+middleware to handle permanent repo URLs, replacing PATH_INFO '/_123/yada' with
+'/name/of/repo/yada' after looking 123 up in the database.
+"""
+
+
+from kallithea.lib.utils import fix_repo_id_name, safe_str
+
+
+class PermanentRepoUrl(object):
+
+    def __init__(self, app, config):
+        self.application = app
+        self.config = config
+
+    def __call__(self, environ, start_response):
+        path_info = environ['PATH_INFO']
+        if path_info.startswith('/'): # it must
+            path_info = '/' + safe_str(fix_repo_id_name(path_info[1:]))
+            environ['PATH_INFO'] = path_info
+
+        return self.application(environ, start_response)
--- a/kallithea/lib/middleware/pygrack.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/middleware/pygrack.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,16 +25,17 @@
 This file was forked by the Kallithea project in July 2014.
 """
 
+import logging
 import os
 import socket
-import logging
 import traceback
 
 from webob import Request, Response, exc
 
 import kallithea
+from kallithea.lib.utils2 import safe_unicode
 from kallithea.lib.vcs import subprocessio
-from kallithea.lib.utils2 import safe_unicode
+
 
 log = logging.getLogger(__name__)
 
@@ -70,7 +71,7 @@
     git_folder_signature = set(['config', 'head', 'info', 'objects', 'refs'])
     commands = ['git-upload-pack', 'git-receive-pack']
 
-    def __init__(self, repo_name, content_path, extras):
+    def __init__(self, repo_name, content_path):
         files = set([f.lower() for f in os.listdir(content_path)])
         if not (self.git_folder_signature.intersection(files)
                 == self.git_folder_signature):
@@ -79,7 +80,6 @@
         self.valid_accepts = ['application/x-%s-result' %
                               c for c in self.commands]
         self.repo_name = repo_name
-        self.extras = extras
 
     def _get_fixedpath(self, path):
         """
@@ -201,7 +201,7 @@
 
 class GitDirectory(object):
 
-    def __init__(self, repo_root, repo_name, extras):
+    def __init__(self, repo_root, repo_name):
         repo_location = os.path.join(repo_root, repo_name)
         if not os.path.isdir(repo_location):
             raise OSError(repo_location)
@@ -209,22 +209,21 @@
         self.content_path = repo_location
         self.repo_name = repo_name
         self.repo_location = repo_location
-        self.extras = extras
 
     def __call__(self, environ, start_response):
         content_path = self.content_path
         try:
-            app = GitRepository(self.repo_name, content_path, self.extras)
+            app = GitRepository(self.repo_name, content_path)
         except (AssertionError, OSError):
             content_path = os.path.join(content_path, '.git')
             if os.path.isdir(content_path):
-                app = GitRepository(self.repo_name, content_path, self.extras)
+                app = GitRepository(self.repo_name, content_path)
             else:
                 return exc.HTTPNotFound()(environ, start_response)
         return app(environ, start_response)
 
 
-def make_wsgi_app(repo_name, repo_root, extras):
+def make_wsgi_app(repo_name, repo_root):
     from dulwich.web import LimitedInputFilter, GunzipFilter
-    app = GitDirectory(repo_root, repo_name, extras)
+    app = GitDirectory(repo_root, repo_name)
     return GunzipFilter(LimitedInputFilter(app))
--- a/kallithea/lib/middleware/sessionmiddleware.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/middleware/sessionmiddleware.py	Sun Jan 05 04:07:51 2020 +0100
@@ -23,8 +23,8 @@
 Original Beaker SessionMiddleware class written by Ben Bangert
 """
 
+from beaker.middleware import SessionMiddleware
 from beaker.session import SessionObject
-from beaker.middleware import SessionMiddleware
 
 
 class SecureSessionMiddleware(SessionMiddleware):
--- a/kallithea/lib/middleware/simplegit.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/middleware/simplegit.py	Sun Jan 05 04:07:51 2020 +0100
@@ -28,191 +28,72 @@
 """
 
 
-import os
+import logging
 import re
-import logging
-import traceback
 
-from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \
-    HTTPNotAcceptable
-from kallithea.model.db import Ui
+from kallithea.lib.base import BaseVCSController
+from kallithea.lib.hooks import log_pull_action
+from kallithea.lib.middleware.pygrack import make_wsgi_app
+from kallithea.lib.utils import make_ui
+from kallithea.lib.utils2 import safe_unicode
+from kallithea.model.db import Repository
 
-from kallithea.lib.utils2 import safe_str, safe_unicode, fix_PATH, get_server_url, \
-    _set_extras
-from kallithea.lib.base import BaseVCSController, check_locking_state
-from kallithea.lib.utils import make_ui, is_valid_repo
-from kallithea.lib.exceptions import HTTPLockedRC
-from kallithea.lib.hooks import pull_lock_handling
 
 log = logging.getLogger(__name__)
 
 
-GIT_PROTO_PAT = re.compile(r'^/(.+)/(info/refs|git-upload-pack|git-receive-pack)')
+GIT_PROTO_PAT = re.compile(r'^/(.+)/(info/refs|git-upload-pack|git-receive-pack)$')
 
 
-def is_git(environ):
-    path_info = environ['PATH_INFO']
-    isgit_path = GIT_PROTO_PAT.match(path_info)
-    log.debug('pathinfo: %s detected as Git %s',
-        path_info, isgit_path is not None
-    )
-    return isgit_path
+cmd_mapping = {
+    'git-receive-pack': 'push',
+    'git-upload-pack': 'pull',
+}
 
 
 class SimpleGit(BaseVCSController):
 
-    _git_stored_op = 'pull' # most recent kind of command
-
-    def _handle_request(self, environ, start_response):
-        if not is_git(environ):
-            return self.application(environ, start_response)
-
-        ip_addr = self._get_ip_addr(environ)
-        # skip passing error to error controller
-        environ['pylons.status_code_redirect'] = True
+    scm_alias = 'git'
 
-        #======================================================================
-        # EXTRACT REPOSITORY NAME FROM ENV
-        #======================================================================
-        try:
-            str_repo_name = self.__get_repository(environ)
-            repo_name = safe_unicode(str_repo_name)
-            log.debug('Extracted repo name is %s', repo_name)
-        except Exception as e:
-            log.error('error extracting repo_name: %r', e)
-            return HTTPInternalServerError()(environ, start_response)
-
-        # quick check if that dir exists...
-        if not is_valid_repo(repo_name, self.basepath, 'git'):
-            return HTTPNotFound()(environ, start_response)
-
-        #======================================================================
-        # GET ACTION PULL or PUSH
-        #======================================================================
-        action = self.__get_action(environ)
+    @classmethod
+    def parse_request(cls, environ):
+        path_info = environ.get('PATH_INFO', '')
+        m = GIT_PROTO_PAT.match(path_info)
+        if m is None:
+            return None
 
-        #======================================================================
-        # CHECK PERMISSIONS
-        #======================================================================
-        user, response_app = self._authorize(environ, start_response, action, repo_name, ip_addr)
-        if response_app is not None:
-            return response_app(environ, start_response)
+        class parsed_request(object):
+            # See https://git-scm.com/book/en/v2/Git-Internals-Transfer-Protocols#_the_smart_protocol
+            repo_name = safe_unicode(m.group(1).rstrip('/'))
+            cmd = m.group(2)
 
-        # extras are injected into Mercurial UI object and later available
-        # in hooks executed by Kallithea
-        from kallithea import CONFIG
-        server_url = get_server_url(environ)
-        extras = {
-            'ip': ip_addr,
-            'username': user.username,
-            'action': action,
-            'repository': repo_name,
-            'scm': 'git',
-            'config': CONFIG['__file__'],
-            'server_url': server_url,
-            'make_lock': None,
-            'locked_by': [None, None]
-        }
-
-        #===================================================================
-        # GIT REQUEST HANDLING
-        #===================================================================
-        repo_path = os.path.join(safe_str(self.basepath), str_repo_name)
-        log.debug('Repository path is %s', repo_path)
-
-        if not user.is_default_user:
-            log.debug('Checking locking on repository')
-            make_lock, locked, locked_by = check_locking_state(action, repo_name, user)
-            # store the make_lock for later evaluation in hooks
-            extras.update({'make_lock': make_lock,
-                           'locked_by': locked_by})
-
-        fix_PATH()
-        log.debug('HOOKS extras is %s', extras)
-        baseui = make_ui('db')
-        _set_extras(extras or {})
+            query_string = environ['QUERY_STRING']
+            if cmd == 'info/refs' and query_string.startswith('service='):
+                service = query_string.split('=', 1)[1]
+                action = cmd_mapping.get(service)
+            else:
+                service = None
+                action = cmd_mapping.get(cmd)
 
-        try:
-            self._handle_githooks(repo_name, action, baseui, environ)
-            log.info('%s action on Git repo "%s" by "%s" from %s',
-                     action, str_repo_name, safe_str(user.username), ip_addr)
-            app = self.__make_app(repo_name, repo_path, extras)
-            return app(environ, start_response)
-        except HTTPLockedRC as e:
-            log.debug('Locked, response %s: %s', e.code, e.title)
-            return e(environ, start_response)
-        except Exception:
-            log.error(traceback.format_exc())
-            return HTTPInternalServerError()(environ, start_response)
-
-    def __make_app(self, repo_name, repo_path, extras):
-        """
-        Make an wsgi application using dulserver
-
-        :param repo_name: name of the repository
-        :param repo_path: full path to the repository
-        """
+        return parsed_request
 
-        from kallithea.lib.middleware.pygrack import make_wsgi_app
-        app = make_wsgi_app(
-            repo_root=safe_str(self.basepath),
-            repo_name=safe_unicode(repo_name),
-            extras=extras,
-        )
-        return app
-
-    def __get_repository(self, environ):
+    def _make_app(self, parsed_request):
         """
-        Gets repository name out of PATH_INFO header
-
-        :param environ: environ where PATH_INFO is stored
+        Return a pygrack wsgi application.
         """
-        try:
-            environ['PATH_INFO'] = self._get_by_id(environ['PATH_INFO'])
-            repo_name = GIT_PROTO_PAT.match(environ['PATH_INFO']).group(1)
-        except Exception:
-            log.error(traceback.format_exc())
-            raise
+        pygrack_app = make_wsgi_app(parsed_request.repo_name, self.basepath)
 
-        return repo_name
-
-    def __get_action(self, environ):
-        """
-        Maps Git request commands into a pull or push command.
-
-        :param environ:
-        """
-        service = environ['QUERY_STRING'].split('=')
+        def wrapper_app(environ, start_response):
+            if (parsed_request.cmd == 'info/refs' and
+                parsed_request.service == 'git-upload-pack'
+            ):
+                baseui = make_ui()
+                repo = Repository.get_by_repo_name(parsed_request.repo_name)
+                scm_repo = repo.scm_instance
+                # Run hooks, like Mercurial outgoing.pull_logger does
+                log_pull_action(ui=baseui, repo=scm_repo._repo)
+            # Note: push hooks are handled by post-receive hook
 
-        if len(service) > 1:
-            service_cmd = service[1]
-            mapping = {
-                'git-receive-pack': 'push',
-                'git-upload-pack': 'pull',
-            }
-            op = mapping[service_cmd]
-            self._git_stored_op = op
-            # try to fallback to stored variable as we don't know if the last
-            # operation is pull/push
-        return self._git_stored_op
+            return pygrack_app(environ, start_response)
 
-    def _handle_githooks(self, repo_name, action, baseui, environ):
-        """
-        Handles pull action, push is handled by post-receive hook
-        """
-        from kallithea.lib.hooks import log_pull_action
-        service = environ['QUERY_STRING'].split('=')
-
-        if len(service) < 2:
-            return
-
-        from kallithea.model.db import Repository
-        _repo = Repository.get_by_repo_name(repo_name)
-        _repo = _repo.scm_instance
-
-        _hooks = dict(baseui.configitems('hooks')) or {}
-        if action == 'pull':
-            # stupid git, emulate pre-pull hook !
-            pull_lock_handling(ui=baseui, repo=_repo._repo)
-        if action == 'pull' and _hooks.get(Ui.HOOK_PULL_LOG):
-            log_pull_action(ui=baseui, repo=_repo._repo)
+        return wrapper_app
--- a/kallithea/lib/middleware/simplehg.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/middleware/simplehg.py	Sun Jan 05 04:07:51 2020 +0100
@@ -28,42 +28,19 @@
 """
 
 
+import logging
 import os
-import logging
-import traceback
 import urllib
 
-from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \
-    HTTPNotAcceptable, HTTPBadRequest
+from kallithea.lib.base import BaseVCSController
+from kallithea.lib.utils import make_ui
+from kallithea.lib.utils2 import safe_str, safe_unicode
+from kallithea.lib.vcs.utils.hgcompat import hgweb_mod
 
-from kallithea.lib.utils2 import safe_str, safe_unicode, fix_PATH, get_server_url, \
-    _set_extras
-from kallithea.lib.base import BaseVCSController, check_locking_state
-from kallithea.lib.utils import make_ui, is_valid_repo, ui_sections
-from kallithea.lib.vcs.utils.hgcompat import RepoError, hgweb_mod
-from kallithea.lib.exceptions import HTTPLockedRC
 
 log = logging.getLogger(__name__)
 
 
-def is_mercurial(environ):
-    """
-    Returns True if request's target is mercurial server - header
-    ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
-    """
-    http_accept = environ.get('HTTP_ACCEPT')
-    path_info = environ['PATH_INFO']
-    if http_accept and http_accept.startswith('application/mercurial'):
-        ishg_path = True
-    else:
-        ishg_path = False
-
-    log.debug('pathinfo: %s detected as Mercurial %s',
-        path_info, ishg_path
-    )
-    return ishg_path
-
-
 def get_header_hgarg(environ):
     """Decode the special Mercurial encoding of big requests over multiple headers.
     >>> get_header_hgarg({})
@@ -82,205 +59,90 @@
     return ''.join(chunks)
 
 
+cmd_mapping = {
+    # 'batch' is not in this list - it is handled explicitly
+    'between': 'pull',
+    'branches': 'pull',
+    'branchmap': 'pull',
+    'capabilities': 'pull',
+    'changegroup': 'pull',
+    'changegroupsubset': 'pull',
+    'changesetdata': 'pull',
+    'clonebundles': 'pull',
+    'debugwireargs': 'pull',
+    'filedata': 'pull',
+    'getbundle': 'pull',
+    'getlfile': 'pull',
+    'heads': 'pull',
+    'hello': 'pull',
+    'known': 'pull',
+    'lheads': 'pull',
+    'listkeys': 'pull',
+    'lookup': 'pull',
+    'manifestdata': 'pull',
+    'narrow_widen': 'pull',
+    'protocaps': 'pull',
+    'statlfile': 'pull',
+    'stream_out': 'pull',
+    'pushkey': 'push',
+    'putlfile': 'push',
+    'unbundle': 'push',
+    }
+
+
 class SimpleHg(BaseVCSController):
 
-    def _handle_request(self, environ, start_response):
-        if not is_mercurial(environ):
-            return self.application(environ, start_response)
-
-        ip_addr = self._get_ip_addr(environ)
-        # skip passing error to error controller
-        environ['pylons.status_code_redirect'] = True
-
-        #======================================================================
-        # EXTRACT REPOSITORY NAME FROM ENV
-        #======================================================================
-        try:
-            str_repo_name = self.__get_repository(environ)
-            repo_name = safe_unicode(str_repo_name)
-            log.debug('Extracted repo name is %s', repo_name)
-        except Exception as e:
-            log.error('error extracting repo_name: %r', e)
-            return HTTPInternalServerError()(environ, start_response)
+    scm_alias = 'hg'
 
-        # quick check if that dir exists...
-        if not is_valid_repo(repo_name, self.basepath, 'hg'):
-            return HTTPNotFound()(environ, start_response)
+    @classmethod
+    def parse_request(cls, environ):
+        http_accept = environ.get('HTTP_ACCEPT', '')
+        if not http_accept.startswith('application/mercurial'):
+            return None
+        path_info = environ.get('PATH_INFO', '')
+        if not path_info.startswith('/'): # it must!
+            return None
 
-        #======================================================================
-        # GET ACTION PULL or PUSH
-        #======================================================================
-        try:
-            action = self.__get_action(environ)
-        except HTTPBadRequest as e:
-            return e(environ, start_response)
+        class parsed_request(object):
+            repo_name = safe_unicode(path_info[1:].rstrip('/'))
 
-        #======================================================================
-        # CHECK PERMISSIONS
-        #======================================================================
-        user, response_app = self._authorize(environ, start_response, action, repo_name, ip_addr)
-        if response_app is not None:
-            return response_app(environ, start_response)
+            query_string = environ['QUERY_STRING']
 
-        # extras are injected into Mercurial UI object and later available
-        # in hooks executed by Kallithea
-        from kallithea import CONFIG
-        server_url = get_server_url(environ)
-        extras = {
-            'ip': ip_addr,
-            'username': user.username,
-            'action': action,
-            'repository': repo_name,
-            'scm': 'hg',
-            'config': CONFIG['__file__'],
-            'server_url': server_url,
-            'make_lock': None,
-            'locked_by': [None, None]
-        }
-        #======================================================================
-        # MERCURIAL REQUEST HANDLING
-        #======================================================================
-        repo_path = os.path.join(safe_str(self.basepath), str_repo_name)
-        log.debug('Repository path is %s', repo_path)
+            action = None
+            for qry in query_string.split('&'):
+                parts = qry.split('=', 1)
+                if len(parts) == 2 and parts[0] == 'cmd':
+                    cmd = parts[1]
+                    if cmd == 'batch':
+                        hgarg = get_header_hgarg(environ)
+                        if not hgarg.startswith('cmds='):
+                            action = 'push' # paranoid and safe
+                            break
+                        action = 'pull'
+                        for cmd_arg in hgarg[5:].split(';'):
+                            cmd, _args = urllib.unquote_plus(cmd_arg).split(' ', 1)
+                            op = cmd_mapping.get(cmd, 'push')
+                            if op != 'pull':
+                                assert op == 'push'
+                                action = 'push'
+                                break
+                    else:
+                        action = cmd_mapping.get(cmd, 'push')
+                    break # only process one cmd
 
-        # A Mercurial HTTP server will see listkeys operations (bookmarks,
-        # phases and obsolescence marker) in a different request - we don't
-        # want to check locking on those
-        if environ['QUERY_STRING'] == 'cmd=listkeys':
-            pass
-        # CHECK LOCKING only if it's not ANONYMOUS USER
-        elif not user.is_default_user:
-            log.debug('Checking locking on repository')
-            make_lock, locked, locked_by = check_locking_state(action, repo_name, user)
-            # store the make_lock for later evaluation in hooks
-            extras.update({'make_lock': make_lock,
-                           'locked_by': locked_by})
-
-        fix_PATH()
-        log.debug('HOOKS extras is %s', extras)
-        baseui = make_ui('db')
-        self._augment_hgrc(repo_path, baseui)
-        _set_extras(extras or {})
+        return parsed_request
 
-        try:
-            log.info('%s action on Mercurial repo "%s" by "%s" from %s',
-                     action, str_repo_name, safe_str(user.username), ip_addr)
-            environ['REPO_NAME'] = str_repo_name # used by hgweb_mod.hgweb
-            app = self.__make_app(repo_path, baseui, extras)
-            return app(environ, start_response)
-        except RepoError as e:
-            if str(e).find('not found') != -1:
-                return HTTPNotFound()(environ, start_response)
-        except HTTPLockedRC as e:
-            # Before Mercurial 3.6, lock exceptions were caught here
-            log.debug('Locked, response %s: %s', e.code, e.title)
-            return e(environ, start_response)
-        except Exception:
-            log.error(traceback.format_exc())
-            return HTTPInternalServerError()(environ, start_response)
-
-    def __make_app(self, repo_name, baseui, extras):
-        """
-        Make an wsgi application using hgweb, and inject generated baseui
-        instance, additionally inject some extras into ui object
+    def _make_app(self, parsed_request):
         """
-        class HgWebWrapper(hgweb_mod.hgweb):
-            # Work-around for Mercurial 3.6+ causing lock exceptions to be
-            # thrown late
-            def _runwsgi(self, *args):
-                try:
-                    return super(HgWebWrapper, self)._runwsgi(*args)
-                except HTTPLockedRC as e:
-                    log.debug('Locked, response %s: %s', e.code, e.title)
-                    try:
-                        req, res, repo = args
-                        res.status = e.status
-                        res.headers['Content-Type'] = 'text/plain'
-                        res.setbodybytes('')
-                        return res.sendresponse()
-                    except ValueError: # wsgiresponse was introduced in Mercurial 4.6 (a88d68dc3ee8)
-                        req, repo = args
-                        req.respond(e.status, 'text/plain')
-                        return ''
-
-        return HgWebWrapper(repo_name, name=repo_name, baseui=baseui)
-
-    def __get_repository(self, environ):
-        """
-        Gets repository name out of PATH_INFO header
-
-        :param environ: environ where PATH_INFO is stored
-        """
-        try:
-            environ['PATH_INFO'] = self._get_by_id(environ['PATH_INFO'])
-            repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:])
-            if repo_name.endswith('/'):
-                repo_name = repo_name.rstrip('/')
-        except Exception:
-            log.error(traceback.format_exc())
-            raise
-
-        return repo_name
-
-    def __get_action(self, environ):
-        """
-        Maps Mercurial request commands into 'pull' or 'push'.
-
-        Raises HTTPBadRequest if the request environment doesn't look like a hg client.
+        Make an hgweb wsgi application.
         """
-        mapping = {
-            # 'batch' is not in this list - it is handled explicitly
-            'between': 'pull',
-            'branches': 'pull',
-            'branchmap': 'pull',
-            'capabilities': 'pull',
-            'changegroup': 'pull',
-            'changegroupsubset': 'pull',
-            'changesetdata': 'pull',
-            'clonebundles': 'pull',
-            'debugwireargs': 'pull',
-            'filedata': 'pull',
-            'getbundle': 'pull',
-            'getlfile': 'pull',
-            'heads': 'pull',
-            'hello': 'pull',
-            'known': 'pull',
-            'lheads': 'pull',
-            'listkeys': 'pull',
-            'lookup': 'pull',
-            'manifestdata': 'pull',
-            'narrow_widen': 'pull',
-            'protocaps': 'pull',
-            'statlfile': 'pull',
-            'stream_out': 'pull',
-            'pushkey': 'push',
-            'putlfile': 'push',
-            'unbundle': 'push',
-            }
-        for qry in environ['QUERY_STRING'].split('&'):
-            parts = qry.split('=', 1)
-            if len(parts) == 2 and parts[0] == 'cmd':
-                cmd = parts[1]
-                if cmd == 'batch':
-                    hgarg = get_header_hgarg(environ)
-                    if not hgarg.startswith('cmds='):
-                        return 'push' # paranoid and safe
-                    for cmd_arg in hgarg[5:].split(';'):
-                        cmd, _args = urllib.unquote_plus(cmd_arg).split(' ', 1)
-                        op = mapping.get(cmd, 'push')
-                        if op != 'pull':
-                            assert op == 'push'
-                            return 'push'
-                    return 'pull'
-                return mapping.get(cmd, 'push')
+        str_repo_name = safe_str(parsed_request.repo_name)
+        repo_path = os.path.join(safe_str(self.basepath), str_repo_name)
+        baseui = make_ui(repo_path=repo_path)
+        hgweb_app = hgweb_mod.hgweb(repo_path, name=str_repo_name, baseui=baseui)
 
-        # Note: the client doesn't get the helpful error message
-        raise HTTPBadRequest('Unable to detect pull/push action! Are you using non standard command or client?')
+        def wrapper_app(environ, start_response):
+            environ['REPO_NAME'] = str_repo_name # used by hgweb_mod.hgweb
+            return hgweb_app(environ, start_response)
 
-    def _augment_hgrc(self, repo_path, baseui):
-        """Augment baseui with config settings from the repo_path repo"""
-        hgrc = os.path.join(repo_path, '.hg', 'hgrc')
-        repoui = make_ui('file', hgrc)
-        for section in ui_sections:
-            for k, v in repoui.configitems(section):
-                baseui.setconfig(section, k, v)
+        return wrapper_app
--- a/kallithea/lib/middleware/wrapper.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/middleware/wrapper.py	Sun Jan 05 04:07:51 2020 +0100
@@ -15,7 +15,8 @@
 kallithea.lib.middleware.wrapper
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-request time measuring app
+Wrap app to measure request and response time ... all the way to the response
+WSGI iterator has been closed.
 
 This file was forked by the Kallithea project in July 2014.
 Original author and date, and relevant copyright and licensing information is below:
@@ -25,12 +26,61 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+import logging
 import time
-import logging
-from kallithea.lib.base import _get_ip_addr, _get_access_path
+
+from kallithea.lib.base import _get_access_path, _get_ip_addr
 from kallithea.lib.utils2 import safe_unicode
 
 
+log = logging.getLogger(__name__)
+
+
+class Meter:
+
+    def __init__(self, start_response):
+        self._start_response = start_response
+        self._start = time.time()
+        self._size = 0
+
+    def duration(self):
+        return time.time() - self._start
+
+    def start_response(self, status, response_headers, exc_info=None):
+        write = self._start_response(status, response_headers, exc_info)
+        def metered_write(s):
+            self.measure(s)
+            write(s)
+        return metered_write
+
+    def measure(self, chunk):
+        self._size += len(chunk)
+
+    def size(self):
+        return self._size
+
+
+class ResultIter:
+
+    def __init__(self, result, meter, description):
+        self._result_close = getattr(result, 'close', None) or (lambda: None)
+        self._next = iter(result).next
+        self._meter = meter
+        self._description = description
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        chunk = self._next()
+        self._meter.measure(chunk)
+        return chunk
+
+    def close(self):
+        self._result_close()
+        log.info("%s responded after %.3fs with %s bytes", self._description, self._meter.duration(), self._meter.size())
+
+
 class RequestWrapper(object):
 
     def __init__(self, app, config):
@@ -38,12 +88,13 @@
         self.config = config
 
     def __call__(self, environ, start_response):
-        start = time.time()
+        meter = Meter(start_response)
+        description = "Request from %s for %s" % (
+            _get_ip_addr(environ),
+            safe_unicode(_get_access_path(environ)),
+        )
         try:
-            return self.application(environ, start_response)
+            result = self.application(environ, meter.start_response)
         finally:
-            log = logging.getLogger('kallithea.' + self.__class__.__name__)
-            log.info('IP: %s Request to %s time: %.3fs' % (
-                _get_ip_addr(environ),
-                safe_unicode(_get_access_path(environ)), time.time() - start)
-            )
+            log.info("%s responding after %.3fs", description, meter.duration())
+        return ResultIter(result, meter, description)
--- a/kallithea/lib/page.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/page.py	Sun Jan 05 04:07:51 2020 +0100
@@ -17,9 +17,12 @@
 import logging
 import math
 import re
+
+from webhelpers2.html import HTML, literal
+from webhelpers.paginate import Page as _Page
+
 from kallithea.config.routing import url
-from webhelpers.html import literal, HTML
-from webhelpers.paginate import Page as _Page
+
 
 log = logging.getLogger(__name__)
 
@@ -123,7 +126,8 @@
         symbol_previous='<', symbol_next='>',
         link_attr=None,
         curpage_attr=None,
-        dotdot_attr=None, **kwargs):
+        dotdot_attr=None, **kwargs
+    ):
         self.curpage_attr = curpage_attr or {'class': 'active'}
         self.separator = separator
         self.pager_kwargs = kwargs
@@ -151,16 +155,16 @@
             'first_item': self.first_item,
             'last_item': self.last_item,
             'item_count': self.item_count,
-            'link_first': self.page > self.first_page and \
+            'link_first': self.page > self.first_page and
                     self._pagerlink(self.first_page, symbol_first) or '',
-            'link_last': self.page < self.last_page and \
+            'link_last': self.page < self.last_page and
                     self._pagerlink(self.last_page, symbol_last) or '',
-            'link_previous': HTML.li(self.previous_page and \
-                    self._pagerlink(self.previous_page, symbol_previous) \
+            'link_previous': HTML.li(self.previous_page and
+                    self._pagerlink(self.previous_page, symbol_previous)
                     or HTML.a(symbol_previous)),
-            'link_next': HTML.li(self.next_page and \
-                    self._pagerlink(self.next_page, symbol_next) \
-                    or HTML.a(symbol_next))
+            'link_next': HTML.li(self.next_page and
+                    self._pagerlink(self.next_page, symbol_next)
+                    or HTML.a(symbol_next)),
         })
 
         return literal(result)
@@ -190,7 +194,7 @@
         try:
             self.page = int(page)  # make it int() if we get it as a string
         except (ValueError, TypeError):
-            log.error("Invalid page value: %r" % page)
+            log.error("Invalid page value: %r", page)
             self.page = 1
 
         self.items_per_page = items_per_page
--- a/kallithea/lib/paster_commands/template.ini.mako	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/paster_commands/template.ini.mako	Sun Jan 05 04:07:51 2020 +0100
@@ -250,18 +250,6 @@
 <%text>## Kallithea url, ie. http[s]://kallithea.example.com/_admin/gists/<gistid></%text>
 gist_alias_url =
 
-<%text>## white list of API enabled controllers. This allows to add list of</%text>
-<%text>## controllers to which access will be enabled by api_key. eg: to enable</%text>
-<%text>## api access to raw_files put `FilesController:raw`, to enable access to patches</%text>
-<%text>## add `ChangesetController:changeset_patch`. This list should be "," separated</%text>
-<%text>## Syntax is <ControllerClass>:<function>. Check debug logs for generated names</%text>
-<%text>## Recommended settings below are commented out:</%text>
-api_access_controllers_whitelist =
-#    ChangesetController:changeset_patch,
-#    ChangesetController:changeset_raw,
-#    FilesController:raw,
-#    FilesController:archivefile
-
 <%text>## default encoding used to convert from and to unicode</%text>
 <%text>## can be also a comma separated list of encoding in case of mixed encodings</%text>
 default_encoding = utf-8
@@ -316,10 +304,6 @@
 <%text>## handling that. Set this variable to 403 to return HTTPForbidden</%text>
 auth_ret_code =
 
-<%text>## locking return code. When repository is locked return this HTTP code. 2XX</%text>
-<%text>## codes don't break the transactions while 4XX codes do</%text>
-lock_ret_code = 423
-
 <%text>## allows to change the repository location in settings page</%text>
 allow_repo_location_change = True
 
@@ -339,6 +323,34 @@
 #    CHANGELOG
 
 <%text>####################################</%text>
+<%text>###           SSH CONFIG        ####</%text>
+<%text>####################################</%text>
+
+<%text>## SSH is disabled by default, until an Administrator decides to enable it.</%text>
+ssh_enabled = false
+
+<%text>## File where users' SSH keys will be stored *if* ssh_enabled is true.</%text>
+#ssh_authorized_keys = /home/kallithea/.ssh/authorized_keys
+%if user_home_path:
+ssh_authorized_keys = ${user_home_path}/.ssh/authorized_keys
+%endif
+
+<%text>## Path to be used in ssh_authorized_keys file to invoke kallithea-cli with ssh-serve.</%text>
+#kallithea_cli_path = /srv/kallithea/venv/bin/kallithea-cli
+%if kallithea_cli_path:
+kallithea_cli_path = ${kallithea_cli_path}
+%endif
+
+<%text>## Locale to be used in the ssh-serve command.</%text>
+<%text>## This is needed because an SSH client may try to use its own locale</%text>
+<%text>## settings, which may not be available on the server.</%text>
+<%text>## See `locale -a` for valid values on this system.</%text>
+#ssh_locale = C.UTF-8
+%if ssh_locale:
+ssh_locale = ${ssh_locale}
+%endif
+
+<%text>####################################</%text>
 <%text>###        CELERY CONFIG        ####</%text>
 <%text>####################################</%text>
 
@@ -389,33 +401,32 @@
 
 <%text>## Name of session cookie. Should be unique for a given host and path, even when running</%text>
 <%text>## on different ports. Otherwise, cookie sessions will be shared and messed up.</%text>
-beaker.session.key = kallithea
+session.key = kallithea
 <%text>## Sessions should always only be accessible by the browser, not directly by JavaScript.</%text>
-beaker.session.httponly = true
+session.httponly = true
 <%text>## Session lifetime. 2592000 seconds is 30 days.</%text>
-beaker.session.timeout = 2592000
+session.timeout = 2592000
 
 <%text>## Server secret used with HMAC to ensure integrity of cookies.</%text>
-beaker.session.secret = ${uuid()}
+session.secret = ${uuid()}
 <%text>## Further, encrypt the data with AES.</%text>
-#beaker.session.encrypt_key = <key_for_encryption>
-#beaker.session.validate_key = <validation_key>
+#session.encrypt_key = <key_for_encryption>
+#session.validate_key = <validation_key>
 
 <%text>## Type of storage used for the session, current types are</%text>
 <%text>## dbm, file, memcached, database, and memory.</%text>
 
 <%text>## File system storage of session data. (default)</%text>
-#beaker.session.type = file
+#session.type = file
 
 <%text>## Cookie only, store all session data inside the cookie. Requires secure secrets.</%text>
-#beaker.session.type = cookie
+#session.type = cookie
 
 <%text>## Database storage of session data.</%text>
-#beaker.session.type = ext:database
-#beaker.session.sa.url = postgresql://postgres:qwe@localhost/kallithea
-#beaker.session.table_name = db_session
+#session.type = ext:database
+#session.sa.url = postgresql://postgres:qwe@localhost/kallithea
+#session.table_name = db_session
 
-%if error_aggregation_service == 'appenlight':
 <%text>############################</%text>
 <%text>## ERROR HANDLING SYSTEMS ##</%text>
 <%text>############################</%text>
@@ -427,6 +438,7 @@
 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>
@@ -553,7 +565,7 @@
 keys = root, routes, kallithea, sqlalchemy, tg, gearbox, beaker, templates, whoosh_indexer, werkzeug, backlash
 
 [handlers]
-keys = console, console_sql
+keys = console, console_color, console_color_sql, null
 
 [formatters]
 keys = generic, color_formatter, color_formatter_sql
@@ -565,67 +577,63 @@
 [logger_root]
 level = NOTSET
 handlers = console
+# For coloring based on log level:
+# handlers = console_color
 
 [logger_routes]
 level = WARN
 handlers =
 qualname = routes.middleware
 <%text>## "level = DEBUG" logs the route matched and routing variables.</%text>
-propagate = 1
 
 [logger_beaker]
 level = WARN
 handlers =
 qualname = beaker.container
-propagate = 1
 
 [logger_templates]
 level = WARN
 handlers =
 qualname = pylons.templating
-propagate = 1
 
 [logger_kallithea]
 level = WARN
 handlers =
 qualname = kallithea
-propagate = 1
 
 [logger_tg]
 level = WARN
 handlers =
 qualname = tg
-propagate = 1
 
 [logger_gearbox]
 level = WARN
 handlers =
 qualname = gearbox
-propagate = 1
 
 [logger_sqlalchemy]
 level = WARN
-handlers = console_sql
+handlers =
 qualname = sqlalchemy.engine
-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
 handlers =
 qualname = whoosh_indexer
-propagate = 1
 
 [logger_werkzeug]
 level = WARN
 handlers =
 qualname = werkzeug
-propagate = 1
 
 [logger_backlash]
 level = WARN
 handlers =
 qualname = backlash
-propagate = 1
 
 <%text>##############</%text>
 <%text>## HANDLERS ##</%text>
@@ -636,10 +644,21 @@
 args = (sys.stderr,)
 formatter = generic
 
-[handler_console_sql]
+[handler_console_color]
+# ANSI color coding based on log level
 class = StreamHandler
 args = (sys.stderr,)
-formatter = generic
+formatter = color_formatter
+
+[handler_console_color_sql]
+# ANSI color coding and pretty printing of SQL statements
+class = StreamHandler
+args = (sys.stderr,)
+formatter = color_formatter_sql
+
+[handler_null]
+class = NullHandler
+args = ()
 
 <%text>################</%text>
 <%text>## FORMATTERS ##</%text>
@@ -658,3 +677,21 @@
 class = kallithea.lib.colored_formatter.ColorFormatterSql
 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
 datefmt = %Y-%m-%d %H:%M:%S
+
+<%text>#################</%text>
+<%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
+
+[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.
--- a/kallithea/lib/pidlock.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/pidlock.py	Sun Jan 05 04:07:51 2020 +0100
@@ -12,9 +12,10 @@
 # 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
+from __future__ import print_function
+
 import errno
-
+import os
 from multiprocessing.util import Finalize
 
 from kallithea.lib.compat import kill
@@ -51,7 +52,7 @@
     def _on_finalize(lock, debug):
         if lock.held:
             if debug:
-                print 'lock held finalizing and running lock.release()'
+                print('lock held finalizing and running lock.release()')
             lock.release()
 
     def lock(self):
@@ -61,7 +62,7 @@
         """
         lockname = str(os.getpid())
         if self.debug:
-            print 'running lock'
+            print('running lock')
         self.trylock()
         self.makelock(lockname, self.pidfile)
         return True
@@ -69,7 +70,7 @@
     def trylock(self):
         running_pid = False
         if self.debug:
-            print 'checking for already running process'
+            print('checking for already running process')
         try:
             with open(self.pidfile, 'r') as f:
                 try:
@@ -78,8 +79,8 @@
                     running_pid = -1
 
             if self.debug:
-                print ('lock file present running_pid: %s, '
-                       'checking for execution' % (running_pid,))
+                print('lock file present running_pid: %s, '
+                      'checking for execution' % (running_pid,))
             # Now we check the PID from lock file matches to the current
             # process PID
             if running_pid:
@@ -89,13 +90,13 @@
                     if exc.errno in (errno.ESRCH, errno.EPERM):
                         print ("Lock File is there but"
                                " the program is not running")
-                        print "Removing lock file for the: %s" % running_pid
+                        print("Removing lock file for the: %s" % running_pid)
                         self.release()
                     else:
                         raise
                 else:
-                    print "You already have an instance of the program running"
-                    print "It is running as process %s" % running_pid
+                    print("You already have an instance of the program running")
+                    print("It is running as process %s" % running_pid)
                     raise LockHeld()
 
         except IOError as e:
@@ -106,21 +107,21 @@
         """releases the pid by removing the pidfile
         """
         if self.debug:
-            print 'trying to release the pidlock'
+            print('trying to release the pidlock')
 
         if self.callbackfn:
             #execute callback function on release
             if self.debug:
-                print 'executing callback function %s' % self.callbackfn
+                print('executing callback function %s' % self.callbackfn)
             self.callbackfn()
         try:
             if self.debug:
-                print 'removing pidfile %s' % self.pidfile
+                print('removing pidfile %s' % self.pidfile)
             os.remove(self.pidfile)
             self.held = False
         except OSError as e:
             if self.debug:
-                print 'removing pidfile failed %s' % e
+                print('removing pidfile failed %s' % e)
             pass
 
     def makelock(self, lockname, pidfile):
@@ -131,7 +132,7 @@
         :param pidfile: the file to write the pid in
         """
         if self.debug:
-            print 'creating a file %s and pid: %s' % (pidfile, lockname)
+            print('creating a file %s and pid: %s' % (pidfile, lockname))
 
         dir_, file_ = os.path.split(pidfile)
         if not os.path.isdir(dir_):
--- a/kallithea/lib/rcmail/message.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/rcmail/message.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,8 +1,6 @@
+from kallithea.lib.rcmail.exceptions import BadHeaders, InvalidMessage
 from kallithea.lib.rcmail.response import MailResponse
 
-from kallithea.lib.rcmail.exceptions import BadHeaders
-from kallithea.lib.rcmail.exceptions import InvalidMessage
-
 
 class Attachment(object):
     """
--- a/kallithea/lib/rcmail/response.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/rcmail/response.py	Sun Jan 05 04:07:51 2020 +0100
@@ -33,13 +33,14 @@
 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
 
+import mimetypes
 import os
-import mimetypes
 import string
 from email import encoders
 from email.charset import Charset
+from email.mime.base import MIMEBase
 from email.utils import parseaddr
-from email.mime.base import MIMEBase
+
 
 ADDRESS_HEADERS_WHITELIST = ['From', 'To', 'Delivered-To', 'Cc']
 DEFAULT_ENCODING = "utf-8"
--- a/kallithea/lib/rcmail/smtp_mailer.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/rcmail/smtp_mailer.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,11 +25,12 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
-import time
 import logging
 import smtplib
-from socket import sslerror
+import time
 from email.utils import formatdate
+from ssl import SSLError
+
 from kallithea.lib.rcmail.message import Message
 from kallithea.lib.rcmail.utils import DNS_NAME
 
@@ -100,6 +101,6 @@
 
         try:
             smtp_serv.quit()
-        except sslerror:
-            # sslerror is raised in tls connections on closing sometimes
+        except SSLError:
+            # SSL error might sometimes be raised in tls connections on closing
             smtp_serv.close()
--- a/kallithea/lib/recaptcha.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/recaptcha.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
+import json
 import urllib
 import urllib2
-import json
 
 
 class RecaptchaResponse(object):
@@ -51,7 +51,7 @@
 
     if not (isinstance(return_values, dict)):
         return RecaptchaResponse(is_valid=False, error_code='incorrect-captcha-sol')
-    elif (("success" in return_values) and ((return_values["success"] == True) or (return_values["success"] == "true"))):
+    elif (("success" in return_values) and ((return_values["success"] is True) or (return_values["success"] == "true"))):
         return RecaptchaResponse(is_valid=True)
     elif (("error-codes" in return_values) and isinstance(return_values["error-codes"], list) and (len(return_values["error-codes"]) > 0)):
         return RecaptchaResponse(is_valid=False, error_code=return_values["error-codes"][0])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/lib/ssh.py	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,117 @@
+# -*- coding: utf-8 -*-
+"""
+    kallithea.lib.ssh
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    :created_on: Dec 10, 2012
+    :author: ir4y
+    :copyright: (C) 2012 Ilya Beda <ir4y.ix@gmail.com>
+    :license: GPLv3, see COPYING for more details.
+"""
+# 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 binascii
+import logging
+import re
+
+from tg.i18n import ugettext as _
+
+
+log = logging.getLogger(__name__)
+
+
+class SshKeyParseError(Exception):
+    """Exception raised by parse_pub_key"""
+
+
+def parse_pub_key(ssh_key):
+    r"""Parse SSH public key string, raise SshKeyParseError or return decoded keytype, data and comment
+
+    >>> getfixture('doctest_mock_ugettext')
+    >>> parse_pub_key('')
+    Traceback (most recent call last):
+    ...
+    SshKeyParseError: SSH key is missing
+    >>> parse_pub_key('''AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ''')
+    Traceback (most recent call last):
+    ...
+    SshKeyParseError: Incorrect SSH key - it must have both a key type and a base64 part
+    >>> parse_pub_key('''abc AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ''')
+    Traceback (most recent call last):
+    ...
+    SshKeyParseError: Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'
+    >>> parse_pub_key('''ssh-rsa  AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ''')
+    Traceback (most recent call last):
+    ...
+    SshKeyParseError: Incorrect SSH key - failed to decode base64 part 'AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ'
+    >>> parse_pub_key('''ssh-rsa  AAAAB2NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ==''')
+    Traceback (most recent call last):
+    ...
+    SshKeyParseError: Incorrect SSH key - base64 part is not 'ssh-rsa' as claimed but 'csh-rsa'
+    >>> parse_pub_key('''ssh-rsa  AAAAB3NzaC1yc2EAAAA'LVGhpcyBpcyBmYWtlIQ''')
+    Traceback (most recent call last):
+    ...
+    SshKeyParseError: Incorrect SSH key - unexpected characters in base64 part "AAAAB3NzaC1yc2EAAAA'LVGhpcyBpcyBmYWtlIQ"
+    >>> parse_pub_key(''' ssh-rsa  AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ== and a comment
+    ... ''')
+    ('ssh-rsa', '\x00\x00\x00\x07ssh-rsa\x00\x00\x00\x0bThis is fake!', 'and a comment\n')
+    """
+    if not ssh_key:
+        raise SshKeyParseError(_("SSH key is missing"))
+
+    parts = ssh_key.split(None, 2)
+    if len(parts) < 2:
+        raise SshKeyParseError(_("Incorrect SSH key - it must have both a key type and a base64 part"))
+
+    keytype, keyvalue, comment = (parts + [''])[:3]
+    if keytype not in ('ssh-rsa', 'ssh-dss', 'ssh-ed25519'):
+        raise SshKeyParseError(_("Incorrect SSH key - it must start with 'ssh-(rsa|dss|ed25519)'"))
+
+    if re.search(r'[^a-zA-Z0-9+/=]', keyvalue):
+        raise SshKeyParseError(_("Incorrect SSH key - unexpected characters in base64 part %r") % keyvalue)
+
+    try:
+        decoded = keyvalue.decode('base64')
+    except binascii.Error:
+        raise SshKeyParseError(_("Incorrect SSH key - failed to decode base64 part %r") % keyvalue)
+
+    if not decoded.startswith('\x00\x00\x00\x07' + str(keytype) + '\x00'):
+        raise SshKeyParseError(_("Incorrect SSH key - base64 part is not %r as claimed but %r") % (str(keytype), str(decoded[4:].split('\0', 1)[0])))
+
+    return keytype, decoded, comment
+
+
+SSH_OPTIONS = 'no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding'
+
+
+def authorized_keys_line(kallithea_cli_path, config_file, key):
+    """
+    Return a line as it would appear in .authorized_keys
+
+    >>> from kallithea.model.db import UserSshKeys, User
+    >>> user = User(user_id=7, username='uu')
+    >>> key = UserSshKeys(user_ssh_key_id=17, user=user, description='test key')
+    >>> key.public_key='''ssh-rsa  AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ== and a comment'''
+    >>> authorized_keys_line('/srv/kallithea/venv/bin/kallithea-cli', '/srv/kallithea/my.ini', key)
+    'no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command="/srv/kallithea/venv/bin/kallithea-cli ssh-serve -c /srv/kallithea/my.ini 7 17" ssh-rsa AAAAB3NzaC1yc2EAAAALVGhpcyBpcyBmYWtlIQ==\\n'
+    """
+    try:
+        keytype, decoded, comment = parse_pub_key(key.public_key)
+    except SshKeyParseError:
+        return '# Invalid Kallithea SSH key: %s %s\n' % (key.user.user_id, key.user_ssh_key_id)
+    mimekey = decoded.encode('base64').replace('\n', '')
+    return '%s,command="%s ssh-serve -c %s %s %s" %s %s\n' % (
+        SSH_OPTIONS, kallithea_cli_path, config_file,
+        key.user.user_id, key.user_ssh_key_id,
+        keytype, mimekey)
--- a/kallithea/lib/timerproxy.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/timerproxy.py	Sun Jan 05 04:07:51 2020 +0100
@@ -12,10 +12,12 @@
 # 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 logging
 import time
-import logging
+
 from sqlalchemy.interfaces import ConnectionProxy
 
+
 log = logging.getLogger('timerproxy')
 
 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38)
--- a/kallithea/lib/utils.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/utils.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,28 +25,28 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+import datetime
+import logging
 import os
 import re
-import logging
-import datetime
+import sys
 import traceback
-import beaker
+from distutils.version import StrictVersion
 
-from tg import request, response
-from tg.i18n import ugettext as _
+import beaker
 from beaker.cache import _cache_decorate
-
-from kallithea.lib.vcs.utils.hgcompat import ui, config
-from kallithea.lib.vcs.utils.helpers import get_scm
-from kallithea.lib.vcs.exceptions import VCSError
+from tg.i18n import ugettext as _
 
 from kallithea.lib.exceptions import HgsubversionImportError
+from kallithea.lib.utils2 import get_current_authuser, safe_str, safe_unicode
+from kallithea.lib.vcs.exceptions import VCSError
+from kallithea.lib.vcs.utils.fakemod import create_module
+from kallithea.lib.vcs.utils.helpers import get_scm
+from kallithea.lib.vcs.utils.hgcompat import config, ui
 from kallithea.model import meta
-from kallithea.model.db import Repository, User, Ui, \
-    UserLog, RepoGroup, Setting, UserGroup
+from kallithea.model.db import RepoGroup, Repository, Setting, Ui, User, UserGroup, UserLog
 from kallithea.model.repo_group import RepoGroupModel
-from kallithea.lib.utils2 import safe_str, safe_unicode, get_current_authuser
-from kallithea.lib.vcs.utils.fakemod import create_module
+
 
 log = logging.getLogger(__name__)
 
@@ -78,29 +78,35 @@
     return None
 
 
-def _extract_id_from_repo_name(repo_name):
-    if repo_name.startswith('/'):
-        repo_name = repo_name.lstrip('/')
-    by_id_match = re.match(r'^_(\d{1,})', repo_name)
-    if by_id_match:
-        return by_id_match.groups()[0]
+def _get_permanent_id(s):
+    """Helper for decoding stable URLs with repo ID. For a string like '_123'
+    return 123.
+    """
+    by_id_match = re.match(r'^_(\d+)$', s)
+    if by_id_match is None:
+        return None
+    return int(by_id_match.group(1))
 
 
-def get_repo_by_id(repo_name):
+def fix_repo_id_name(path):
     """
-    Extracts repo_name by id from special urls. Example url is _11/repo_name
+    Rewrite repo_name for _<ID> permanent URLs.
 
-    :param repo_name:
-    :return: repo_name if matched else None
+    Given a path, if the first path element is like _<ID>, return the path with
+    this part expanded to the corresponding full repo name, else return the
+    provided path.
     """
-    _repo_id = _extract_id_from_repo_name(repo_name)
-    if _repo_id:
+    first, rest = path, ''
+    if '/' in path:
+        first, rest_ = path.split('/', 1)
+        rest = '/' + rest_
+    repo_id = _get_permanent_id(first)
+    if repo_id is not None:
         from kallithea.model.db import Repository
-        repo = Repository.get(_repo_id)
-        if repo:
-            # TODO: return repo instead of reponame? or would that be a layering violation?
-            return repo.repo_name
-    return None
+        repo = Repository.get(repo_id)
+        if repo is not None:
+            return repo.repo_name + rest
+    return path
 
 
 def action_logger(user, action, repo, ipaddr='', commit=False):
@@ -262,6 +268,7 @@
 
     :return True: if given path is a valid repository
     """
+    # TODO: paranoid security checks?
     full_path = os.path.join(safe_str(base_path), safe_str(repo_name))
 
     try:
@@ -315,15 +322,11 @@
                 'ui', 'web', ]
 
 
-def make_ui(read_from='file', path=None, clear_session=True):
+def make_ui(repo_path=None, clear_session=True):
     """
-    A function that will read python rc files or database
-    and make an mercurial ui object from read options
-
-    :param path: path to mercurial config file
-    :param read_from: read from 'file' or 'db'
+    Create an Mercurial 'ui' object based on database Ui settings, possibly
+    augmenting with content from a hgrc file.
     """
-
     baseui = ui.ui()
 
     # clean the baseui object
@@ -331,39 +334,39 @@
     baseui._ucfg = config.config()
     baseui._tcfg = config.config()
 
-    if read_from == 'file':
-        if not os.path.isfile(path):
-            log.debug('hgrc file is not present at %s, skipping...', path)
-            return baseui
-        log.debug('reading hgrc from %s', path)
-        cfg = config.config()
-        cfg.read(path)
-        for section in ui_sections:
-            for k, v in cfg.items(section):
-                log.debug('settings ui from file: [%s] %s=%s', section, k, v)
-                baseui.setconfig(safe_str(section), safe_str(k), safe_str(v))
-
-    elif read_from == 'db':
-        sa = meta.Session()
-        ret = sa.query(Ui).all()
+    sa = meta.Session()
+    for ui_ in sa.query(Ui).all():
+        if ui_.ui_active:
+            ui_val = '' if ui_.ui_value is None else safe_str(ui_.ui_value)
+            log.debug('config from db: [%s] %s=%r', ui_.ui_section,
+                      ui_.ui_key, ui_val)
+            baseui.setconfig(safe_str(ui_.ui_section), safe_str(ui_.ui_key),
+                             ui_val)
+    if clear_session:
+        meta.Session.remove()
 
-        hg_ui = ret
-        for ui_ in hg_ui:
-            if ui_.ui_active:
-                ui_val = '' if ui_.ui_value is None else safe_str(ui_.ui_value)
-                log.debug('settings ui from db: [%s] %s=%r', ui_.ui_section,
-                          ui_.ui_key, ui_val)
-                baseui.setconfig(safe_str(ui_.ui_section), safe_str(ui_.ui_key),
-                                 ui_val)
-        if clear_session:
-            meta.Session.remove()
+    # force set push_ssl requirement to False, Kallithea handles that
+    baseui.setconfig('web', 'push_ssl', False)
+    baseui.setconfig('web', 'allow_push', '*')
+    # prevent interactive questions for ssh password / passphrase
+    ssh = baseui.config('ui', 'ssh', default='ssh')
+    baseui.setconfig('ui', 'ssh', '%s -oBatchMode=yes -oIdentitiesOnly=yes' % ssh)
+    # push / pull hooks
+    baseui.setconfig('hooks', 'changegroup.kallithea_log_push_action', 'python:kallithea.lib.hooks.log_push_action')
+    baseui.setconfig('hooks', 'outgoing.kallithea_log_pull_action', 'python:kallithea.lib.hooks.log_pull_action')
 
-        # force set push_ssl requirement to False, Kallithea handles that
-        baseui.setconfig('web', 'push_ssl', False)
-        baseui.setconfig('web', 'allow_push', '*')
-        # prevent interactive questions for ssh password / passphrase
-        ssh = baseui.config('ui', 'ssh', default='ssh')
-        baseui.setconfig('ui', 'ssh', '%s -oBatchMode=yes -oIdentitiesOnly=yes' % ssh)
+    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 = config.config()
+            cfg.read(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(safe_str(section), safe_str(k), safe_str(v))
+        else:
+            log.debug('hgrc file is not present at %s, skipping...', hgrc_path)
 
     return baseui
 
@@ -410,10 +413,10 @@
     from kallithea.config import conf
 
     log.debug('adding extra into INDEX_EXTENSIONS')
-    conf.INDEX_EXTENSIONS.extend(re.split('\s+', config.get('index.extensions', '')))
+    conf.INDEX_EXTENSIONS.extend(re.split(r'\s+', config.get('index.extensions', '')))
 
     log.debug('adding extra into INDEX_FILENAMES')
-    conf.INDEX_FILENAMES.extend(re.split('\s+', config.get('index.filenames', '')))
+    conf.INDEX_FILENAMES.extend(re.split(r'\s+', config.get('index.filenames', '')))
 
 
 def map_groups(path):
@@ -481,7 +484,6 @@
     # creation defaults
     defs = Setting.get_default_repo_settings(strip_prefix=True)
     enable_statistics = defs.get('repo_enable_statistics')
-    enable_locking = defs.get('repo_enable_locking')
     enable_downloads = defs.get('repo_enable_downloads')
     private = defs.get('repo_private')
 
@@ -503,7 +505,6 @@
                 description=desc,
                 repo_group=getattr(group, 'group_id', None),
                 owner=user,
-                enable_locking=enable_locking,
                 enable_downloads=enable_downloads,
                 enable_statistics=enable_statistics,
                 private=private,
@@ -577,38 +578,49 @@
 # MISC
 #==============================================================================
 
+git_req_ver = StrictVersion('1.7.4')
+
 def check_git_version():
     """
-    Checks what version of git is installed in system, and issues a warning
+    Checks what version of git is installed on the system, and raise a system exit
     if it's too old for Kallithea to work properly.
     """
     from kallithea import BACKENDS
     from kallithea.lib.vcs.backends.git.repository import GitRepository
     from kallithea.lib.vcs.conf import settings
-    from distutils.version import StrictVersion
 
     if 'git' not in BACKENDS:
         return None
 
+    if not settings.GIT_EXECUTABLE_PATH:
+        log.warning('No git executable configured - check "git_path" in the ini file.')
+        return None
+
     stdout, stderr = GitRepository._run_git_command(['--version'], _bare=True,
                                                     _safe=True)
 
-    m = re.search("\d+.\d+.\d+", stdout)
+    if stderr:
+        log.warning('Error/stderr from "%s --version": %r', settings.GIT_EXECUTABLE_PATH, stderr)
+
+    m = re.search(r"\d+.\d+.\d+", stdout)
     if m:
         ver = StrictVersion(m.group(0))
+        log.debug('Git executable: "%s", version %s (parsed from: "%s")',
+                  settings.GIT_EXECUTABLE_PATH, ver, stdout.strip())
+        if ver < git_req_ver:
+            log.error('Kallithea detected %s version %s, which is too old '
+                      'for the system to function properly. '
+                      'Please upgrade to version %s or later. '
+                      'If you strictly need Mercurial repositories, you can '
+                      'clear the "git_path" setting in the ini file.',
+                      settings.GIT_EXECUTABLE_PATH, ver, git_req_ver)
+            log.error("Terminating ...")
+            sys.exit(1)
     else:
         ver = StrictVersion('0.0.0')
-
-    req_ver = StrictVersion('1.7.4')
+        log.warning('Error finding version number in "%s --version" stdout: %r',
+                    settings.GIT_EXECUTABLE_PATH, stdout.strip())
 
-    log.debug('Git executable: "%s" version %s detected: %s',
-              settings.GIT_EXECUTABLE_PATH, ver, stdout)
-    if stderr:
-        log.warning('Error detecting git version: %r', stderr)
-    elif ver < req_ver:
-        log.warning('Kallithea detected git version %s, which is too old '
-                    'for the system to function properly. '
-                    'Please upgrade to version %s or later.' % (ver, req_ver))
     return ver
 
 
--- a/kallithea/lib/utils2.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/utils2.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,23 +27,23 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+from __future__ import print_function
 
-import os
-import re
-import sys
-import time
-import uuid
-import datetime
-import urllib
 import binascii
+import datetime
+import os
+import pwd
+import re
+import time
+import urllib
 
-import webob
 import urlobject
-from webhelpers.text import collapse, remove_formatting, strip_tags
+from tg.i18n import ugettext as _
+from tg.i18n import ungettext
+from webhelpers2.text import collapse, remove_formatting, strip_tags
 
-from tg.i18n import ugettext as _, ungettext
+from kallithea.lib.compat import json
 from kallithea.lib.vcs.utils.lazy import LazyProperty
-from kallithea.lib.compat import json
 
 
 def str2bool(_str):
@@ -101,13 +101,13 @@
     from string import replace
 
     if mode == 0:
-            line = replace(line, '\r\n', '\n')
-            line = replace(line, '\r', '\n')
+        line = replace(line, '\r\n', '\n')
+        line = replace(line, '\r', '\n')
     elif mode == 1:
-            line = replace(line, '\r\n', '\r')
-            line = replace(line, '\n', '\r')
+        line = replace(line, '\r\n', '\r')
+        line = replace(line, '\n', '\r')
     elif mode == 2:
-            line = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", line)
+        line = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", line)
     return line
 
 
@@ -305,7 +305,8 @@
     month_lengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
     if deltas['day'] < 0:
         if prevdate.month == 2 and (prevdate.year % 4 == 0 and
-            (prevdate.year % 100 != 0 or prevdate.year % 400 == 0)):
+            (prevdate.year % 100 != 0 or prevdate.year % 400 == 0)
+        ):
             deltas['day'] += 29
         else:
             deltas['day'] += month_lengths[prevdate.month - 1]
@@ -411,28 +412,31 @@
     return ''.join(uri)
 
 
-def get_clone_url(uri_tmpl, qualified_home_url, repo_name, repo_id, **override):
-    parsed_url = urlobject.URLObject(qualified_home_url)
-    decoded_path = safe_unicode(urllib.unquote(parsed_url.path.rstrip('/')))
+def get_clone_url(clone_uri_tmpl, prefix_url, repo_name, repo_id, username=None):
+    parsed_url = urlobject.URLObject(prefix_url)
+    prefix = safe_unicode(urllib.unquote(parsed_url.path.rstrip('/')))
+    try:
+        system_user = pwd.getpwuid(os.getuid()).pw_name
+    except Exception: # TODO: support all systems - especially Windows
+        system_user = 'kallithea' # hardcoded default value ...
     args = {
         'scheme': parsed_url.scheme,
-        'user': '',
-        'netloc': parsed_url.netloc+decoded_path,  # path if we use proxy-prefix
-        'prefix': decoded_path,
+        'user': safe_unicode(urllib.quote(safe_str(username or ''))),
+        'netloc': parsed_url.netloc + prefix,  # like "hostname:port/prefix" (with optional ":port" and "/prefix")
+        'prefix': prefix, # undocumented, empty or starting with /
         'repo': repo_name,
-        'repoid': str(repo_id)
+        'repoid': str(repo_id),
+        'system_user': safe_unicode(system_user),
+        'hostname': parsed_url.hostname,
     }
-    args.update(override)
-    args['user'] = urllib.quote(safe_str(args['user']))
-
-    for k, v in args.items():
-        uri_tmpl = uri_tmpl.replace('{%s}' % k, v)
+    url = re.sub('{([^{}]+)}', lambda m: args.get(m.group(1), m.group(0)), clone_uri_tmpl)
 
     # remove leading @ sign if it's present. Case of empty user
-    url_obj = urlobject.URLObject(uri_tmpl)
-    url = url_obj.with_netloc(url_obj.netloc.lstrip('@'))
+    url_obj = urlobject.URLObject(url)
+    if not url_obj.username:
+        url_obj = url_obj.with_username(None)
 
-    return safe_unicode(url)
+    return safe_unicode(url_obj)
 
 
 def get_changeset_safe(repo, rev):
@@ -448,7 +452,7 @@
     from kallithea.lib.vcs.backends.base import EmptyChangeset
     if not isinstance(repo, BaseRepository):
         raise Exception('You must pass an Repository '
-                        'object as first argument got %s', type(repo))
+                        'object as first argument got %s' % type(repo))
 
     try:
         cs = repo.get_changeset(rev)
@@ -483,7 +487,7 @@
     Returns list of (possible) usernames @mentioned in given text.
 
     >>> extract_mentioned_usernames('@1-2.a_X,@1234 not@not @ddd@not @n @ee @ff @gg, @gg;@hh @n\n@zz,')
-    ['1-2.a_X', '1234', 'ddd', 'ee', 'ff', 'gg', 'hh', 'zz']
+    ['1-2.a_X', '1234', 'ddd', 'ee', 'ff', 'gg', 'gg', 'hh', 'zz']
     """
     return MENTIONS_REGEX.findall(text)
 
@@ -506,21 +510,6 @@
     __delattr__ = dict.__delitem__
 
 
-def fix_PATH(os_=None):
-    """
-    Get current active python path, and append it to PATH variable to fix issues
-    of subprocess calls and different python versions
-    """
-    if os_ is None:
-        import os
-    else:
-        os = os_
-
-    cur_path = os.path.split(sys.executable)[0]
-    if not os.environ['PATH'].startswith(cur_path):
-        os.environ['PATH'] = '%s:%s' % (cur_path, os.environ['PATH'])
-
-
 def obfuscate_url_pw(engine):
     from sqlalchemy.engine import url as sa_url
     from sqlalchemy.exc import ArgumentError
@@ -533,24 +522,23 @@
     return str(_url)
 
 
-def get_server_url(environ):
-    req = webob.Request(environ)
-    return req.host_url + req.script_name
-
+def get_hook_environment():
+    """
+    Get hook context by deserializing the global KALLITHEA_EXTRAS environment
+    variable.
 
-def _extract_extras():
+    Called early in Git out-of-process hooks to get .ini config path so the
+    basic environment can be configured properly. Also used in all hooks to get
+    information about the action that triggered it.
     """
-    Extracts the Kallithea extras data from os.environ, and wraps it into named
-    AttributeDict object
-    """
+
     try:
         extras = json.loads(os.environ['KALLITHEA_EXTRAS'])
     except KeyError:
         raise Exception("Environment variable KALLITHEA_EXTRAS not found")
 
     try:
-        for k in ['username', 'repository', 'locked_by', 'scm', 'make_lock',
-                  'action', 'ip']:
+        for k in ['username', 'repository', 'scm', 'action', 'ip']:
             extras[k]
     except KeyError:
         raise Exception('Missing key %s in KALLITHEA_EXTRAS %s' % (k, extras))
@@ -558,7 +546,24 @@
     return AttributeDict(extras)
 
 
-def _set_extras(extras):
+def set_hook_environment(username, ip_addr, repo_name, repo_alias, action=None):
+    """Prepare global context for running hooks by serializing data in the
+    global KALLITHEA_EXTRAS environment variable.
+
+    Most importantly, this allow Git hooks to do proper logging and updating of
+    caches after pushes.
+
+    Must always be called before anything with hooks are invoked.
+    """
+    from kallithea import CONFIG
+    extras = {
+        'ip': ip_addr, # used in log_push/pull_action action_logger
+        'username': username,
+        'action': action or 'push_local', # used in log_push_action_raw_ids action_logger
+        'repository': repo_name,
+        'scm': repo_alias, # used to pick hack in log_push_action_raw_ids
+        'config': CONFIG['__file__'], # used by git hook to read config
+    }
     os.environ['KALLITHEA_EXTRAS'] = json.dumps(extras)
 
 
@@ -676,7 +681,7 @@
     slug = remove_formatting(value)
     slug = strip_tags(slug)
 
-    for c in """`?=[]\;'"<>,/~!@#$%^&*()+{}|: """:
+    for c in r"""`?=[]\;'"<>,/~!@#$%^&*()+{}|: """:
         slug = slug.replace(c, '-')
     slug = recursive_replace(slug, '-')
     slug = collapse(slug, '-')
@@ -693,4 +698,4 @@
         retries = retries - 1
         if retries < 0:
             raise IOError
-        print complaint
+        print(complaint)
--- a/kallithea/lib/vcs/__init__.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/__init__.py	Sun Jan 05 04:07:51 2020 +0100
@@ -19,9 +19,8 @@
     'VCSError', 'RepositoryError', 'ChangesetError'
 ]
 
-import sys
-from kallithea.lib.vcs.backends import get_repo, get_backend
-from kallithea.lib.vcs.exceptions import VCSError, RepositoryError, ChangesetError
+from kallithea.lib.vcs.backends import get_backend, get_repo
+from kallithea.lib.vcs.exceptions import ChangesetError, RepositoryError, VCSError
 
 
 def get_version():
--- a/kallithea/lib/vcs/backends/__init__.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/backends/__init__.py	Sun Jan 05 04:07:51 2020 +0100
@@ -10,11 +10,12 @@
 """
 import os
 from pprint import pformat
+
 from kallithea.lib.vcs.conf import settings
 from kallithea.lib.vcs.exceptions import VCSError
 from kallithea.lib.vcs.utils.helpers import get_scm
+from kallithea.lib.vcs.utils.imports import import_class
 from kallithea.lib.vcs.utils.paths import abspath
-from kallithea.lib.vcs.utils.imports import import_class
 
 
 def get_repo(path=None, alias=None, create=False):
--- a/kallithea/lib/vcs/backends/base.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/backends/base.py	Sun Jan 05 04:07:51 2020 +0100
@@ -12,16 +12,12 @@
 import datetime
 import itertools
 
-from kallithea.lib.vcs.utils import author_name, author_email, safe_unicode
-from kallithea.lib.vcs.utils.lazy import LazyProperty
+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.utils import author_email, author_name, safe_unicode
 from kallithea.lib.vcs.utils.helpers import get_dict_for_attrs
-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.utils.lazy import LazyProperty
 
 
 class BaseRepository(object):
--- a/kallithea/lib/vcs/backends/git/__init__.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/backends/git/__init__.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,6 +1,6 @@
-from .repository import GitRepository
 from .changeset import GitChangeset
 from .inmemory import GitInMemoryChangeset
+from .repository import GitRepository
 from .workdir import GitWorkdir
 
 
--- a/kallithea/lib/vcs/backends/git/changeset.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/backends/git/changeset.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,23 +1,17 @@
 import re
+from io import BytesIO
 from itertools import chain
+from subprocess import PIPE, Popen
+
 from dulwich import objects
 from dulwich.config import ConfigFile
-from subprocess import Popen, PIPE
-from io import BytesIO
 
-from kallithea.lib.vcs.conf import settings
 from kallithea.lib.vcs.backends.base import BaseChangeset, EmptyChangeset
-from kallithea.lib.vcs.exceptions import (
-    RepositoryError, ChangesetError, NodeDoesNotExistError, VCSError,
-    ChangesetDoesNotExistError, ImproperArchiveTypeError
-)
+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 (
-    FileNode, DirNode, NodeKind, RootNode, SubModuleNode,
-    ChangedFileNodesGenerator, AddedFileNodesGenerator, RemovedFileNodesGenerator
-)
-from kallithea.lib.vcs.utils import (
-    safe_unicode, safe_str, safe_int, date_fromtimestamp
-)
+    AddedFileNodesGenerator, ChangedFileNodesGenerator, DirNode, FileNode, NodeKind, RemovedFileNodesGenerator, RootNode, SubModuleNode)
+from kallithea.lib.vcs.utils import date_fromtimestamp, safe_int, safe_str, safe_unicode
 from kallithea.lib.vcs.utils.lazy import LazyProperty
 
 
@@ -364,7 +358,7 @@
         allowed_kinds = settings.ARCHIVE_SPECS.keys()
         if kind not in allowed_kinds:
             raise ImproperArchiveTypeError('Archive kind not supported use one'
-                'of %s', allowed_kinds)
+                'of %s' % allowed_kinds)
 
         if prefix is None:
             prefix = '%s-%s' % (self.repository.name, self.short_id)
--- a/kallithea/lib/vcs/backends/git/inmemory.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/backends/git/inmemory.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,8 +1,10 @@
-import time
 import datetime
 import posixpath
 import stat
+import time
+
 from dulwich import objects
+
 from kallithea.lib.vcs.backends.base import BaseInMemoryChangeset
 from kallithea.lib.vcs.exceptions import RepositoryError
 from kallithea.lib.vcs.utils import safe_str
@@ -93,7 +95,8 @@
             new_trees.append(parent)
             # Update ancestors
             for parent, tree, path in reversed([(a[1], b[1], b[0]) for a, b in
-                zip(ancestors, ancestors[1:])]):
+                zip(ancestors, ancestors[1:])]
+            ):
                 parent[path] = stat.S_IFDIR, tree.id
                 object_store.add_object(tree)
 
--- a/kallithea/lib/vcs/backends/git/repository.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/backends/git/repository.py	Sun Jan 05 04:07:51 2020 +0100
@@ -9,41 +9,36 @@
     :copyright: (c) 2010-2011 by Marcin Kuzminski, Lukasz Balcerzak.
 """
 
+import errno
+import logging
 import os
+import posixpath
 import re
 import time
-import errno
 import urllib
 import urllib2
-import logging
-import posixpath
+from collections import OrderedDict
 
+from dulwich.config import ConfigFile
 from dulwich.objects import Tag
-from dulwich.repo import Repo, NotGitRepository
-from dulwich.config import ConfigFile
+from dulwich.repo import NotGitRepository, Repo
 
 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.utils import safe_str, safe_unicode, makedate, date_fromtimestamp
+    BranchDoesNotExistError, ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError, TagAlreadyExistError, TagDoesNotExistError)
+from kallithea.lib.vcs.utils import date_fromtimestamp, makedate, safe_str, safe_unicode
+from kallithea.lib.vcs.utils.hgcompat import hg_url, httpbasicauthhandler, httpdigestauthhandler
 from kallithea.lib.vcs.utils.lazy import LazyProperty
-from kallithea.lib.vcs.utils.ordered_dict import OrderedDict
 from kallithea.lib.vcs.utils.paths import abspath, get_user_home
 
-from kallithea.lib.vcs.utils.hgcompat import (
-    hg_url, httpbasicauthhandler, httpdigestauthhandler
-)
-
 from .changeset import GitChangeset
 from .inmemory import GitInMemoryChangeset
 from .workdir import GitWorkdir
 
-SHA_PATTERN = re.compile(r'^[[0-9a-fA-F]{12}|[0-9a-fA-F]{40}]$')
+
+SHA_PATTERN = re.compile(r'^([0-9a-fA-F]{12}|[0-9a-fA-F]{40})$')
 
 log = logging.getLogger(__name__)
 
@@ -149,7 +144,10 @@
             else:
                 raise RepositoryError(tb_err)
 
-        return ''.join(p.output), ''.join(p.error)
+        try:
+            return ''.join(p.output), ''.join(p.error)
+        finally:
+            p.close()
 
     def run_git_command(self, cmd):
         opts = {}
@@ -283,7 +281,8 @@
 
         is_bstr = isinstance(revision, (str, unicode))
         if ((is_bstr and revision.isdigit() and len(revision) < 12)
-            or isinstance(revision, int) or is_null(revision)):
+            or isinstance(revision, int) or is_null(revision)
+        ):
             try:
                 revision = self.revisions[int(revision)]
             except IndexError:
@@ -321,7 +320,7 @@
     def _get_archives(self, archive_name='tip'):
 
         for i in [('zip', '.zip'), ('gz', '.tar.gz'), ('bz2', '.tar.bz2')]:
-                yield {"type": i[0], "extension": i[1], "node": archive_name}
+            yield {"type": i[0], "extension": i[1], "node": archive_name}
 
     def _get_url(self, url):
         """
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/lib/vcs/backends/git/ssh.py	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,83 @@
+# -*- 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 logging
+import os
+
+from kallithea.lib.hooks import log_pull_action
+from kallithea.lib.utils import make_ui
+from kallithea.lib.utils2 import safe_str, safe_unicode
+from kallithea.lib.vcs.backends.ssh import BaseSshHandler
+
+
+log = logging.getLogger(__name__)
+
+
+class GitSshHandler(BaseSshHandler):
+    vcs_type = 'git'
+
+    @classmethod
+    def make(cls, ssh_command_parts):
+        r"""
+        >>> import shlex
+
+        >>> GitSshHandler.make(shlex.split("git-upload-pack '/foo bar'")).repo_name
+        u'foo bar'
+        >>> GitSshHandler.make(shlex.split("git-upload-pack '/foo bar'")).verb
+        'git-upload-pack'
+        >>> GitSshHandler.make(shlex.split(" git-upload-pack /blåbærgrød ")).repo_name # might not be necessary to support no quoting ... but we can
+        u'bl\xe5b\xe6rgr\xf8d'
+        >>> GitSshHandler.make(shlex.split('''git-upload-pack "/foo'bar"''')).repo_name
+        u"foo'bar"
+        >>> GitSshHandler.make(shlex.split("git-receive-pack '/foo'")).repo_name
+        u'foo'
+        >>> GitSshHandler.make(shlex.split("git-receive-pack '/foo'")).verb
+        'git-receive-pack'
+
+        >>> GitSshHandler.make(shlex.split("/bin/git-upload-pack '/foo'")) # ssh-serve will report 'SSH command %r is not supported'
+        >>> GitSshHandler.make(shlex.split('''git-upload-pack /foo bar''')) # ssh-serve will report 'SSH command %r is not supported'
+        >>> shlex.split("git-upload-pack '/foo'bar' x") # ssh-serve will report: Error parsing SSH command "...": No closing quotation
+        Traceback (most recent call last):
+        ValueError: No closing quotation
+        >>> GitSshHandler.make(shlex.split('hg -R foo serve --stdio')) # not handled here
+        """
+        if (len(ssh_command_parts) == 2 and
+            ssh_command_parts[0] in ['git-upload-pack', 'git-receive-pack'] and
+            ssh_command_parts[1].startswith('/')
+        ):
+            return cls(safe_unicode(ssh_command_parts[1][1:]), ssh_command_parts[0])
+
+        return None
+
+    def __init__(self, repo_name, verb):
+        self.repo_name = repo_name
+        self.verb = verb
+
+    def _serve(self):
+        if self.verb == 'git-upload-pack': # action 'pull'
+            # base class called set_hook_environment - action is hardcoded to 'pull'
+            log_pull_action(ui=make_ui(), repo=self.db_repo.scm_instance._repo)
+        else: # probably verb 'git-receive-pack', action 'push'
+            if not self.allow_push:
+                self.exit('Push access to %r denied' % safe_str(self.repo_name))
+            # Note: push logging is handled by Git post-receive hook
+
+        # git shell is not a real shell but use shell inspired quoting *inside* the argument.
+        # Per https://github.com/git/git/blob/v2.22.0/quote.c#L12 :
+        # The path must be "'" quoted, but "'" and "!" must exit the quoting and be "\" escaped
+        quoted_abspath = "'%s'" % self.db_repo.repo_full_path.replace("'", r"'\''").replace("!", r"'\!'")
+        newcmd = ['git', 'shell', '-c', "%s %s" % (self.verb, quoted_abspath)]
+        log.debug('Serving: %s', newcmd)
+        os.execvp(newcmd[0], newcmd)
+        self.exit("Failed to exec 'git' as %s" % newcmd)
--- a/kallithea/lib/vcs/backends/git/workdir.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/backends/git/workdir.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,7 +1,7 @@
 import re
+
 from kallithea.lib.vcs.backends.base import BaseWorkdir
-from kallithea.lib.vcs.exceptions import RepositoryError
-from kallithea.lib.vcs.exceptions import BranchDoesNotExistError
+from kallithea.lib.vcs.exceptions import BranchDoesNotExistError, RepositoryError
 
 
 class GitWorkdir(BaseWorkdir):
--- a/kallithea/lib/vcs/backends/hg/__init__.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/backends/hg/__init__.py	Sun Jan 05 04:07:51 2020 +0100
@@ -9,9 +9,9 @@
     :copyright: (c) 2010-2011 by Marcin Kuzminski, Lukasz Balcerzak.
 """
 
-from .repository import MercurialRepository
 from .changeset import MercurialChangeset
 from .inmemory import MercurialInMemoryChangeset
+from .repository import MercurialRepository
 from .workdir import MercurialWorkdir
 
 
--- a/kallithea/lib/vcs/backends/hg/changeset.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/backends/hg/changeset.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,22 +1,15 @@
 import os
 import posixpath
 
+from kallithea.lib.vcs.backends.base import BaseChangeset
 from kallithea.lib.vcs.conf import settings
-from kallithea.lib.vcs.backends.base import BaseChangeset
-from kallithea.lib.vcs.exceptions import (
-    ChangesetDoesNotExistError, ChangesetError, ImproperArchiveTypeError,
-    NodeDoesNotExistError, VCSError
-)
+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.utils import safe_str, safe_unicode, date_fromtimestamp
+    AddedFileNodesGenerator, ChangedFileNodesGenerator, DirNode, FileNode, NodeKind, RemovedFileNodesGenerator, RootNode, SubModuleNode)
+from kallithea.lib.vcs.utils import date_fromtimestamp, safe_str, safe_unicode
+from kallithea.lib.vcs.utils.hgcompat import archival, hex, obsutil
 from kallithea.lib.vcs.utils.lazy import LazyProperty
 from kallithea.lib.vcs.utils.paths import get_dirs_for_path
-from kallithea.lib.vcs.utils.hgcompat import archival, hex
-
-from mercurial import obsolete
 
 
 class MercurialChangeset(BaseChangeset):
@@ -88,13 +81,7 @@
 
     @LazyProperty
     def successors(self):
-        try:
-            # This works starting from Mercurial 4.3: the function `successorssets` was moved to the mercurial.obsutil module and gained the `closest` parameter.
-            from mercurial import obsutil
-            successors = obsutil.successorssets(self._ctx._repo, self._ctx.node(), closest=True)
-        except ImportError:
-            # fallback for older versions
-            successors = obsolete.successorssets(self._ctx._repo, self._ctx.node())
+        successors = 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)
@@ -104,19 +91,7 @@
 
     @LazyProperty
     def predecessors(self):
-        try:
-            # This works starting from Mercurial 4.3: the function `closestpredecessors` was added.
-            from mercurial import obsutil
-            return [hex(n)[:12] for n in obsutil.closestpredecessors(self._ctx._repo, self._ctx.node())]
-        except ImportError:
-            # fallback for older versions
-            predecessors = set()
-            nm = self._ctx._repo.changelog.nodemap
-            for p in self._ctx._repo.obsstore.precursors.get(self._ctx.node(), ()):
-                pr = nm.get(p[0])
-                if pr is not None:
-                    predecessors.add(hex(p[0])[:12])
-            return predecessors
+        return [hex(n)[:12] for n in obsutil.closestpredecessors(self._ctx._repo, self._ctx.node())]
 
     @LazyProperty
     def bookmarks(self):
@@ -320,10 +295,7 @@
         try:
             annotation_lines = [(annotateline.fctx, annotateline.text) for annotateline in annotations]
         except AttributeError: # annotateline was introduced in Mercurial 4.6 (b33b91ca2ec2)
-            try:
-                annotation_lines = [(aline.fctx, l) for aline, l in annotations]
-            except AttributeError: # aline.fctx was introduced in Mercurial 4.4
-                annotation_lines = [(aline[0], l) for aline, l in annotations]
+            annotation_lines = [(aline.fctx, l) for aline, l in annotations]
         for i, (fctx, l) in enumerate(annotation_lines):
             sha = fctx.hex()
             yield (i + 1, sha, lambda sha=sha, l=l: self.repository.get_changeset(sha), l)
@@ -348,7 +320,7 @@
         allowed_kinds = settings.ARCHIVE_SPECS.keys()
         if kind not in allowed_kinds:
             raise ImproperArchiveTypeError('Archive kind not supported use one'
-                'of %s', allowed_kinds)
+                'of %s' % allowed_kinds)
 
         if stream is None:
             raise VCSError('You need to pass in a valid stream for filling'
--- a/kallithea/lib/vcs/backends/hg/inmemory.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/backends/hg/inmemory.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,10 +1,8 @@
 import datetime
-import errno
 
 from kallithea.lib.vcs.backends.base import BaseInMemoryChangeset
 from kallithea.lib.vcs.exceptions import RepositoryError
-
-from kallithea.lib.vcs.utils.hgcompat import memfilectx, memctx, hex, tolocal
+from kallithea.lib.vcs.utils.hgcompat import hex, memctx, memfilectx, tolocal
 
 
 class MercurialInMemoryChangeset(BaseInMemoryChangeset):
@@ -57,7 +55,7 @@
                               if not node.is_binary else node.content),
                         islink=False,
                         isexec=node.is_executable,
-                        copied=False)
+                        copysource=False)
 
             # or changed
             for node in self.changed:
@@ -67,7 +65,7 @@
                               if not node.is_binary else node.content),
                         islink=False,
                         isexec=node.is_executable,
-                        copied=False)
+                        copysource=False)
 
             raise RepositoryError("Given path haven't been marked as added,"
                                   "changed or removed (%s)" % path)
--- a/kallithea/lib/vcs/backends/hg/repository.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/backends/hg/repository.py	Sun Jan 05 04:07:51 2020 +0100
@@ -9,35 +9,28 @@
     :copyright: (c) 2010-2011 by Marcin Kuzminski, Lukasz Balcerzak.
 """
 
+import datetime
+import logging
 import os
 import time
 import urllib
 import urllib2
-import logging
-import datetime
+from collections import OrderedDict
 
 from kallithea.lib.vcs.backends.base import BaseRepository, CollectionGenerator
-
 from kallithea.lib.vcs.exceptions import (
-    BranchDoesNotExistError, ChangesetDoesNotExistError, EmptyRepositoryError,
-    RepositoryError, VCSError, TagAlreadyExistError, TagDoesNotExistError
-)
-from kallithea.lib.vcs.utils import (
-    author_email, author_name, date_fromtimestamp, makedate, safe_unicode, safe_str,
-)
+    BranchDoesNotExistError, ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError, TagAlreadyExistError, TagDoesNotExistError, VCSError)
+from kallithea.lib.vcs.utils import author_email, author_name, date_fromtimestamp, makedate, safe_str, safe_unicode
+from kallithea.lib.vcs.utils.hgcompat import (
+    Abort, RepoError, RepoLookupError, clone, diffopts, get_contact, hex, hg_url, httpbasicauthhandler, httpdigestauthhandler, httppeer, localrepo, match_exact, nullid, patch, peer, scmutil, sshpeer, tag, ui)
 from kallithea.lib.vcs.utils.lazy import LazyProperty
-from kallithea.lib.vcs.utils.ordered_dict import OrderedDict
 from kallithea.lib.vcs.utils.paths import abspath
-from kallithea.lib.vcs.utils.hgcompat import (
-    ui, nullid, match, patch, diffopts, clone, get_contact,
-    localrepo, RepoLookupError, Abort, RepoError, hex, scmutil, hg_url,
-    httpbasicauthhandler, httpdigestauthhandler, peer, httppeer, sshpeer, tag
-)
 
 from .changeset import MercurialChangeset
 from .inmemory import MercurialInMemoryChangeset
 from .workdir import MercurialWorkdir
 
+
 log = logging.getLogger(__name__)
 
 
@@ -264,7 +257,7 @@
             self.get_changeset(rev1)
         self.get_changeset(rev2)
         if path:
-            file_filter = match(self.path, '', [path], exact=True)
+            file_filter = match_exact(path)
         else:
             file_filter = None
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/lib/vcs/backends/hg/ssh.py	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,72 @@
+# -*- 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 logging
+
+from mercurial import hg
+
+from kallithea.lib.utils import make_ui
+from kallithea.lib.utils2 import safe_str, safe_unicode
+from kallithea.lib.vcs.backends.ssh import BaseSshHandler
+
+
+try:
+    from mercurial.wireprotoserver import sshserver
+except ImportError:
+    from mercurial.sshserver import sshserver # moved in Mercurial 4.6 (1bf5263fe5cc)
+
+
+
+log = logging.getLogger(__name__)
+
+
+class MercurialSshHandler(BaseSshHandler):
+    vcs_type = 'hg'
+
+    @classmethod
+    def make(cls, ssh_command_parts):
+        r"""
+        >>> import shlex
+
+        >>> MercurialSshHandler.make(shlex.split('hg -R "foo bar" serve --stdio')).repo_name
+        u'foo bar'
+        >>> MercurialSshHandler.make(shlex.split(' hg -R blåbærgrød serve --stdio ')).repo_name
+        u'bl\xe5b\xe6rgr\xf8d'
+        >>> MercurialSshHandler.make(shlex.split('''hg -R 'foo"bar' serve --stdio''')).repo_name
+        u'foo"bar'
+
+        >>> MercurialSshHandler.make(shlex.split('/bin/hg -R "foo" serve --stdio'))
+        >>> MercurialSshHandler.make(shlex.split('''hg -R "foo"bar" serve --stdio''')) # ssh-serve will report: Error parsing SSH command "...": invalid syntax
+        Traceback (most recent call last):
+        ValueError: No closing quotation
+        >>> MercurialSshHandler.make(shlex.split('git-upload-pack "/foo"')) # not handled here
+        """
+        if ssh_command_parts[:2] == ['hg', '-R'] and ssh_command_parts[3:] == ['serve', '--stdio']:
+            return cls(safe_unicode(ssh_command_parts[2]))
+
+        return None
+
+    def __init__(self, repo_name):
+        self.repo_name = repo_name
+
+    def _serve(self):
+        # Note: we want a repo with config based on .hg/hgrc and can thus not use self.db_repo.scm_instance._repo.ui
+        baseui = make_ui(repo_path=self.db_repo.repo_full_path)
+        if not self.allow_push:
+            baseui.setconfig('hooks', 'pretxnopen._ssh_reject', 'python:kallithea.lib.hooks.rejectpush')
+            baseui.setconfig('hooks', 'prepushkey._ssh_reject', 'python:kallithea.lib.hooks.rejectpush')
+
+        repo = hg.repository(baseui, safe_str(self.db_repo.repo_full_path))
+        log.debug("Starting Mercurial sshserver for %s", self.db_repo.repo_full_path)
+        sshserver(baseui, repo).serve_forever()
--- a/kallithea/lib/vcs/backends/hg/workdir.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/backends/hg/workdir.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,6 +1,5 @@
 from kallithea.lib.vcs.backends.base import BaseWorkdir
 from kallithea.lib.vcs.exceptions import BranchDoesNotExistError
-
 from kallithea.lib.vcs.utils.hgcompat import hg_merge
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/lib/vcs/backends/ssh.py	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,106 @@
+# -*- 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/>.
+
+"""
+vcs.backends.ssh
+~~~~~~~~~~~~~~~~~
+
+SSH backend for all available SCMs
+"""
+
+import datetime
+import logging
+import sys
+
+from kallithea.lib.auth import AuthUser, HasPermissionAnyMiddleware
+from kallithea.lib.utils2 import safe_str, set_hook_environment
+from kallithea.model.db import Repository, User, UserSshKeys
+from kallithea.model.meta import Session
+
+
+log = logging.getLogger(__name__)
+
+
+class BaseSshHandler(object):
+    # Protocol for setting properties:
+    # Set by sub class:
+    #   vcs_type: 'hg' or 'git'
+    # Set by make() / __init__():
+    #   repo_name: requested repo name - only validated by serve()
+    # Set by serve() - must not be accessed before:
+    #   db_repo: repository db object
+    #   authuser: user that has been authenticated - like request.authuser ... which isn't used here
+    #   allow_push: false for read-only access to the repo
+
+    # Set defaults, in case .exit should be called early
+    vcs_type = None
+    repo_name = None
+
+    @staticmethod
+    def make(ssh_command):
+        """Factory function. Given a command as invoked over SSH (and preserved
+        in SSH_ORIGINAL_COMMAND when run as authorized_keys command), return a
+        handler if the command looks ok, else return None.
+        """
+        raise NotImplementedError
+
+    def serve(self, user_id, key_id, client_ip):
+        """Verify basic sanity of the repository, and that the user is
+        valid and has access - then serve the native VCS protocol for
+        repository access."""
+        dbuser = User.get(user_id)
+        if dbuser is None:
+            self.exit('User %r not found' % user_id)
+        self.authuser = AuthUser.make(dbuser=dbuser, ip_addr=client_ip)
+        log.info('Authorized user %s from SSH %s trusting user id %s and key id %s for %r', dbuser, client_ip, user_id, key_id, self.repo_name)
+        if self.authuser is None: # not ok ... but already kind of authenticated by SSH ... but not really not authorized ...
+            self.exit('User %s from %s cannot be authorized' % (dbuser.username, client_ip))
+
+        ssh_key = UserSshKeys.get(key_id)
+        if ssh_key is None:
+            self.exit('SSH key %r not found' % key_id)
+        ssh_key.last_seen = datetime.datetime.now()
+        Session().commit()
+
+        if HasPermissionAnyMiddleware('repository.write',
+                                      'repository.admin')(self.authuser, self.repo_name):
+            self.allow_push = True
+        elif HasPermissionAnyMiddleware('repository.read')(self.authuser, self.repo_name):
+            self.allow_push = False
+        else:
+            self.exit('Access to %r denied' % safe_str(self.repo_name))
+
+        self.db_repo = Repository.get_by_repo_name(self.repo_name)
+        if self.db_repo is None:
+            self.exit("Repository '%s' not found" % self.repo_name)
+        assert self.db_repo.repo_name == self.repo_name
+
+        # Set global hook environment up for 'push' actions.
+        # If pull actions should be served, the actual hook invocation will be
+        # hardcoded to 'pull' when log_pull_action is invoked (directly on Git,
+        # or through the Mercurial 'outgoing' hook).
+        # For push actions, the action in global hook environment is used (in
+        # handle_git_post_receive when it is called as Git post-receive hook,
+        # or in log_push_action through the Mercurial 'changegroup' hook).
+        set_hook_environment(self.authuser.username, client_ip, self.repo_name, self.vcs_type, 'push')
+        return self._serve()
+
+    def _serve(self):
+        """Serve the native protocol for repository access."""
+        raise NotImplementedError
+
+    def exit(self, error):
+        log.info('abort serving %s %s: %s', self.vcs_type, self.repo_name, error)
+        sys.stderr.write('abort: %s\n' % error)
+        sys.exit(1)
--- a/kallithea/lib/vcs/conf/settings.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/conf/settings.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,8 +1,10 @@
 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')
--- a/kallithea/lib/vcs/nodes.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/nodes.py	Sun Jan 05 04:07:51 2020 +0100
@@ -9,14 +9,14 @@
     :copyright: (c) 2010-2011 by Marcin Kuzminski, Lukasz Balcerzak.
 """
 
-import stat
+import mimetypes
 import posixpath
-import mimetypes
+import stat
 
 from kallithea.lib.vcs.backends.base import EmptyChangeset
 from kallithea.lib.vcs.exceptions import NodeError, RemovedFileNodeError
+from kallithea.lib.vcs.utils import safe_str, safe_unicode
 from kallithea.lib.vcs.utils.lazy import LazyProperty
-from kallithea.lib.vcs.utils import safe_unicode, safe_str
 
 
 class NodeKind:
--- a/kallithea/lib/vcs/subprocessio.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/subprocessio.py	Sun Jan 05 04:07:51 2020 +0100
@@ -22,9 +22,9 @@
 along with git_http_backend.py Project.
 If not, see <http://www.gnu.org/licenses/>.
 """
+import collections
 import os
 import subprocess
-import collections
 import threading
 
 
@@ -205,9 +205,6 @@
         except (GeneratorExit, StopIteration):
             pass
 
-    def __del__(self):
-        self.close()
-
     ####################
     # Threaded reader's infrastructure.
     ####################
@@ -367,13 +364,15 @@
         # Else, we are happy.
         returncode = _p.poll()
         if (returncode is not None # process has terminated
-            and returncode != 0): # and it failed
+            and returncode != 0
+        ): # and it failed
             bg_out.stop()
             out = ''.join(bg_out)
             bg_err.stop()
             err = ''.join(bg_err)
             if (err.strip() == 'fatal: The remote end hung up unexpectedly' and
-                out.startswith('0034shallow ')):
+                out.startswith('0034shallow ')
+            ):
                 # hack inspired by https://github.com/schacon/grack/pull/7
                 bg_out = iter([out])
                 _p = None
@@ -395,7 +394,8 @@
         if self.process:
             returncode = self.process.poll()
             if (returncode is not None # process has terminated
-                and returncode != 0): # and it failed
+                and returncode != 0
+            ): # and it failed
                 self.output.stop()
                 self.error.stop()
                 err = ''.join(self.error)
@@ -423,6 +423,3 @@
             os.close(self.inputstream)
         except:
             pass
-
-    def __del__(self):
-        self.close()
--- a/kallithea/lib/vcs/utils/__init__.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/utils/__init__.py	Sun Jan 05 04:07:51 2020 +0100
@@ -3,9 +3,9 @@
 output. It also includes some internal helpers.
 """
 
-import time
 import datetime
 import re
+import time
 
 
 def makedate():
--- a/kallithea/lib/vcs/utils/annotate.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/utils/annotate.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,7 +1,7 @@
 import StringIO
 
+from pygments import highlight
 from pygments.formatters import HtmlFormatter
-from pygments import highlight
 
 from kallithea.lib.vcs.exceptions import VCSError
 from kallithea.lib.vcs.nodes import FileNode
@@ -62,7 +62,8 @@
         self.order = order or ('ls', 'annotate', 'code')
         headers = options.pop('headers', None)
         if headers and not ('ls' in headers and 'annotate' in headers and
-            'code' in headers):
+            'code' in headers
+        ):
             raise ValueError("If headers option dict is specified it must "
                 "all 'ls', 'annotate' and 'code' keys")
         self.headers = headers
--- a/kallithea/lib/vcs/utils/compat.py	Sat Aug 24 21:48:43 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-"""
-Various utilities to work with Python < 2.7.
-
-Those utilities may be deleted once ``vcs`` stops support for older Python
-versions.
-"""
-
-import sys
-import array
-
-if sys.version_info >= (2, 7):
-    unittest = __import__('unittest')
-else:
-    unittest = __import__('unittest2')
--- a/kallithea/lib/vcs/utils/helpers.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/utils/helpers.py	Sun Jan 05 04:07:51 2020 +0100
@@ -3,16 +3,15 @@
 """
 from __future__ import division
 
+import datetime
+import os
 import re
-import os
 import time
-import datetime
-from subprocess import Popen, PIPE
 
-from kallithea.lib.vcs.exceptions import VCSError
-from kallithea.lib.vcs.exceptions import RepositoryError
+from kallithea.lib.vcs.exceptions import RepositoryError, VCSError
 from kallithea.lib.vcs.utils.paths import abspath
 
+
 ALIASES = ['hg', 'git']
 
 
@@ -52,7 +51,7 @@
         raise VCSError('More than one [%s] scm found at given path %s'
                        % (', '.join((x[0] for x in found_scms)), path))
 
-    if len(found_scms) is 0:
+    if len(found_scms) == 0:
         raise VCSError('No scm found at given path %s' % path)
 
     return found_scms[0]
@@ -221,15 +220,3 @@
     for attr in attrs:
         data[attr] = getattr(obj, attr)
     return data
-
-
-def get_total_seconds(timedelta):
-    """
-    Backported for Python 2.5.
-
-    See http://docs.python.org/library/datetime.html.
-    """
-    return ((timedelta.microseconds + (
-            timedelta.seconds +
-            timedelta.days * 24 * 60 * 60
-        ) * 10**6) / 10**6)
--- a/kallithea/lib/vcs/utils/hgcompat.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/utils/hgcompat.py	Sun Jan 05 04:07:51 2020 +0100
@@ -2,42 +2,33 @@
 Mercurial libs compatibility
 """
 
+# Mercurial 5.0 550a172a603b renamed memfilectx argument `copied` to `copysource`
+import inspect
+
 import mercurial
-from mercurial import demandimport
-# patch demandimport, due to bug in mercurial when it always triggers demandimport.enable()
-demandimport.enable = lambda *args, **kwargs: 1
-from mercurial import archival, merge as hg_merge, patch, ui
-from mercurial import discovery
-from mercurial import localrepo
-from mercurial import unionrepo
-from mercurial import scmutil
-from mercurial import config
-from mercurial import tags as tagsmod
-from mercurial import httppeer
-from mercurial import sshpeer
+from mercurial import archival, config, demandimport, discovery, httppeer, localrepo
+from mercurial import merge as hg_merge
+from mercurial import obsutil, patch, scmutil, sshpeer, ui, unionrepo
 from mercurial.commands import clone, nullid, pull
 from mercurial.context import memctx, memfilectx
-from mercurial.error import RepoError, RepoLookupError, Abort
+from mercurial.discovery import findcommonoutgoing
+from mercurial.encoding import tolocal
+from mercurial.error import Abort, RepoError, RepoLookupError
+from mercurial.hg import peer
 from mercurial.hgweb import hgweb_mod
 from mercurial.hgweb.common import get_contact
+from mercurial.match import exact as match_exact
 from mercurial.match import match
 from mercurial.mdiff import diffopts
-from mercurial.node import hex
-from mercurial.encoding import tolocal
-from mercurial.discovery import findcommonoutgoing
-from mercurial.hg import peer
+from mercurial.node import hex, nullrev
+from mercurial.scmutil import revrange
+from mercurial.tags import tag
+from mercurial.url import httpbasicauthhandler, httpdigestauthhandler
 from mercurial.util import url as hg_url
-from mercurial.scmutil import revrange
-from mercurial.node import nullrev
-from mercurial.url import httpbasicauthhandler, httpdigestauthhandler
 
 
-# Mercurial 4.5 8a0cac20a1ad introduced an extra memctx changectx argument
-# - introduce an optional wrapper factory that doesn't pass it on
-import inspect
-if inspect.getargspec(memfilectx.__init__).args[2] != 'changectx':
-    __org_memfilectx = memfilectx
-    memfilectx = lambda repo, changectx, *args, **kwargs: __org_memfilectx(repo, *args, **kwargs)
+# patch demandimport, due to bug in mercurial when it always triggers demandimport.enable()
+demandimport.enable = lambda *args, **kwargs: 1
 
 
 # workaround for 3.3 94ac64bcf6fe and not calling largefiles reposetup correctly
@@ -45,10 +36,12 @@
 # 3.5 7699d3212994 added the invariant that repo.lfstatus must exist before hitting overridearchive
 localrepo.localrepository.lfstatus = False
 
-# Mercurial 4.2 moved tag from localrepo to the tags module
-def tag(repo, *args):
-    try:
-        tag_f  = tagsmod.tag
-    except AttributeError:
-        return repo.tag(*args)
-    tag_f(repo, *args)
+if inspect.getargspec(memfilectx.__init__).args[7] != 'copysource':
+    assert inspect.getargspec(memfilectx.__init__).args[7] == 'copied', inspect.getargspec(memfilectx.__init__).args
+    __org_memfilectx_ = memfilectx
+    memfilectx = lambda repo, changectx, path, data, islink=False, isexec=False, copysource=None: \
+        __org_memfilectx_(repo, changectx, path, data, islink=islink, isexec=isexec, copied=copysource)
+
+# Mercurial 5.0 dropped exact argument for match in 635a12c53ea6, and 0531dff73d0b made the exact function stable with a single parameter
+if inspect.getargspec(match_exact).args[0] != 'files':
+    match_exact = lambda path: match(None, '', [path], exact=True)
--- a/kallithea/lib/vcs/utils/imports.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/utils/imports.py	Sun Jan 05 04:07:51 2020 +0100
@@ -16,12 +16,6 @@
     splitted = class_path.split('.')
     mod_path = '.'.join(splitted[:-1])
     class_name = splitted[-1]
-    try:
-        class_mod = __import__(mod_path, {}, {}, [class_name])
-    except ImportError as err:
-        msg = "There was problem while trying to import backend class. " \
-            "Original error was:\n%s" % err
-        raise VCSError(msg)
+    class_mod = __import__(mod_path, {}, {}, [class_name])
     cls = getattr(class_mod, class_name)
-
     return cls
--- a/kallithea/lib/vcs/utils/lockfiles.py	Sat Aug 24 21:48:43 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-import os
-
-
-class LockFile(object):
-    """Provides methods to obtain, check for, and release a file based lock which
-    should be used to handle concurrent access to the same file.
-
-    As we are a utility class to be derived from, we only use protected methods.
-
-    Locks will automatically be released on destruction"""
-    __slots__ = ("_file_path", "_owns_lock")
-
-    def __init__(self, file_path):
-        self._file_path = file_path
-        self._owns_lock = False
-
-    def __del__(self):
-        self._release_lock()
-
-    def _lock_file_path(self):
-        """:return: Path to lockfile"""
-        return "%s.lock" % (self._file_path)
-
-    def _has_lock(self):
-        """:return: True if we have a lock and if the lockfile still exists
-        :raise AssertionError: if our lock-file does not exist"""
-        if not self._owns_lock:
-            return False
-
-        return True
-
-    def _obtain_lock_or_raise(self):
-        """Create a lock file as flag for other instances, mark our instance as lock-holder
-
-        :raise IOError: if a lock was already present or a lock file could not be written"""
-        if self._has_lock():
-            return
-        lock_file = self._lock_file_path()
-        if os.path.isfile(lock_file):
-            raise IOError("Lock for file %r did already exist, delete %r in case the lock is illegal" % (self._file_path, lock_file))
-
-        try:
-            fd = os.open(lock_file, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0)
-            os.close(fd)
-        except OSError as e:
-            raise IOError(str(e))
-
-        self._owns_lock = True
-
-    def _obtain_lock(self):
-        """The default implementation will raise if a lock cannot be obtained.
-        Subclasses may override this method to provide a different implementation"""
-        return self._obtain_lock_or_raise()
-
-    def _release_lock(self):
-        """Release our lock if we have one"""
-        if not self._has_lock():
-            return
-
-        # if someone removed our file beforehand, lets just flag this issue
-        # instead of failing, to make it more usable.
-        lfp = self._lock_file_path()
-        try:
-            # on bloody windows, the file needs write permissions to be removable.
-            # Why ...
-            if os.name == 'nt':
-                os.chmod(lfp, 0777)
-            # END handle win32
-            os.remove(lfp)
-        except OSError:
-            pass
-        self._owns_lock = False
--- a/kallithea/lib/vcs/utils/ordered_dict.py	Sat Aug 24 21:48:43 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-"""Ordered dict implementation"""
-from UserDict import DictMixin
-
-
-class OrderedDict(dict, DictMixin):
-
-    def __init__(self, *args, **kwds):
-        if len(args) > 1:
-            raise TypeError('expected at most 1 arguments, got %d' % len(args))
-        try:
-            self.__end
-        except AttributeError:
-            self.clear()
-        self.update(*args, **kwds)
-
-    def clear(self):
-        self.__end = end = []
-        end += [None, end, end]         # sentinel node for doubly linked list
-        self.__map = {}                 # key --> [key, prev, next]
-        dict.clear(self)
-
-    def __setitem__(self, key, value):
-        if key not in self:
-            end = self.__end
-            curr = end[1]
-            curr[2] = end[1] = self.__map[key] = [key, curr, end]
-        dict.__setitem__(self, key, value)
-
-    def __delitem__(self, key):
-        dict.__delitem__(self, key)
-        key, prev, next = self.__map.pop(key)
-        prev[2] = next
-        next[1] = prev
-
-    def __iter__(self):
-        end = self.__end
-        curr = end[2]
-        while curr is not end:
-            yield curr[0]
-            curr = curr[2]
-
-    def __reversed__(self):
-        end = self.__end
-        curr = end[1]
-        while curr is not end:
-            yield curr[0]
-            curr = curr[1]
-
-    def popitem(self, last=True):
-        if not self:
-            raise KeyError('dictionary is empty')
-        if last:
-            key = reversed(self).next()
-        else:
-            key = iter(self).next()
-        value = self.pop(key)
-        return key, value
-
-    def __reduce__(self):
-        items = [[k, self[k]] for k in self]
-        tmp = self.__map, self.__end
-        del self.__map, self.__end
-        inst_dict = vars(self).copy()
-        self.__map, self.__end = tmp
-        if inst_dict:
-            return (self.__class__, (items,), inst_dict)
-        return self.__class__, (items,)
-
-    def keys(self):
-        return list(self)
-
-    setdefault = DictMixin.setdefault
-    update = DictMixin.update
-    pop = DictMixin.pop
-    values = DictMixin.values
-    items = DictMixin.items
-    iterkeys = DictMixin.iterkeys
-    itervalues = DictMixin.itervalues
-    iteritems = DictMixin.iteritems
-
-    def __repr__(self):
-        if not self:
-            return '%s()' % (self.__class__.__name__,)
-        return '%s(%r)' % (self.__class__.__name__, self.items())
-
-    def copy(self):
-        return self.__class__(self)
-
-    @classmethod
-    def fromkeys(cls, iterable, value=None):
-        d = cls()
-        for key in iterable:
-            d[key] = value
-        return d
-
-    def __eq__(self, other):
-        if isinstance(other, OrderedDict):
-            return len(self) == len(other) and self.items() == other.items()
-        return dict.__eq__(self, other)
-
-    def __ne__(self, other):
-        return not self == other
--- a/kallithea/lib/vcs/utils/paths.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/utils/paths.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,5 +1,6 @@
 import os
 
+
 abspath = lambda * p: os.path.abspath(os.path.join(*p))
 
 
--- a/kallithea/lib/vcs/utils/progressbar.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/lib/vcs/utils/progressbar.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,10 +1,12 @@
 # encoding: UTF-8
-import sys
+
+from __future__ import print_function
+
 import datetime
 import string
+import sys
 
 from kallithea.lib.vcs.utils.filesize import filesizeformat
-from kallithea.lib.vcs.utils.helpers import get_total_seconds
 
 
 class ProgressBarError(Exception):
@@ -87,7 +89,7 @@
             current_time = datetime.datetime.now()
         if self.step == 0:
             return datetime.timedelta()
-        total_seconds = get_total_seconds(self.get_total_time())
+        total_seconds = self.get_total_time().total_seconds()
         eta_seconds = total_seconds * self.steps / self.step - total_seconds
         return datetime.timedelta(seconds=int(eta_seconds))
 
@@ -113,7 +115,7 @@
         if step is None:
             step = self.step
         if total_seconds is None:
-            total_seconds = get_total_seconds(self.get_total_time())
+            total_seconds = self.get_total_time().total_seconds()
         if step <= 0 or total_seconds <= 0:
             speed = '-'
         else:
@@ -355,54 +357,54 @@
 def main():
     import time
 
-    print "Standard progress bar..."
+    print("Standard progress bar...")
     bar = ProgressBar(30)
     for x in xrange(1, 31):
-            bar.render(x)
-            time.sleep(0.02)
+        bar.render(x)
+        time.sleep(0.02)
     bar.stream.write('\n')
-    print
+    print()
 
-    print "Empty bar..."
+    print("Empty bar...")
     bar = ProgressBar(50)
     bar.render(0)
-    print
-    print
+    print()
+    print()
 
-    print "Colored bar..."
+    print("Colored bar...")
     bar = ColoredProgressBar(20)
     for x in bar:
         time.sleep(0.01)
-    print
+    print()
 
-    print "Animated char bar..."
+    print("Animated char bar...")
     bar = AnimatedProgressBar(20)
     for x in bar:
         time.sleep(0.01)
-    print
+    print()
 
-    print "Animated + colored char bar..."
+    print("Animated + colored char bar...")
     bar = AnimatedColoredProgressBar(20)
     for x in bar:
         time.sleep(0.01)
-    print
+    print()
 
-    print "Bar only ..."
+    print("Bar only ...")
     bar = BarOnlyProgressBar(20)
     for x in bar:
         time.sleep(0.01)
-    print
+    print()
 
-    print "Colored, longer bar-only, eta, total time ..."
+    print("Colored, longer bar-only, eta, total time ...")
     bar = BarOnlyColoredProgressBar(40)
     bar.width = 60
     bar.elements += ['time', 'eta']
     for x in bar:
         time.sleep(0.01)
-    print
-    print
+    print()
+    print()
 
-    print "File transfer bar, breaks after 2 seconds ..."
+    print("File transfer bar, breaks after 2 seconds ...")
     total_bytes = 1024 * 1024 * 2
     bar = ProgressBar(total_bytes)
     bar.width = 50
@@ -414,9 +416,8 @@
         now = datetime.datetime.now()
         if now - bar.started >= datetime.timedelta(seconds=2):
             break
-    print
-    print
-
+    print()
+    print()
 
 
 if __name__ == '__main__':
--- a/kallithea/model/api_key.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/api_key.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,13 +25,14 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+import logging
 import time
-import logging
 
 from kallithea.lib.utils2 import generate_api_key
 from kallithea.model.db import User, UserApiKeys
 from kallithea.model.meta import Session
 
+
 log = logging.getLogger(__name__)
 
 
--- a/kallithea/model/base.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/base.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,8 +27,10 @@
 
 
 import logging
+
+from kallithea.lib.utils2 import obfuscate_url_pw
 from kallithea.model import meta
-from kallithea.lib.utils2 import obfuscate_url_pw
+
 
 log = logging.getLogger(__name__)
 
--- a/kallithea/model/changeset_status.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/changeset_status.py	Sun Jan 05 04:07:51 2020 +0100
@@ -26,9 +26,11 @@
 """
 
 import logging
+
 from sqlalchemy.orm import joinedload
 
-from kallithea.model.db import ChangesetStatus, PullRequest, Repository, User, Session
+from kallithea.model.db import ChangesetStatus, PullRequest, Repository, Session, User
+
 
 log = logging.getLogger(__name__)
 
--- a/kallithea/model/comment.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/comment.py	Sun Jan 05 04:07:51 2020 +0100
@@ -26,16 +26,16 @@
 """
 
 import logging
-
-from tg.i18n import ugettext as _
 from collections import defaultdict
 
-from kallithea.lib.utils2 import extract_mentioned_users, safe_unicode
+from tg.i18n import ugettext as _
+
 from kallithea.lib import helpers as h
-from kallithea.model.db import ChangesetComment, User, \
-    PullRequest, Repository
+from kallithea.lib.utils2 import extract_mentioned_users, safe_unicode
+from kallithea.model.db import ChangesetComment, PullRequest, Repository, User
+from kallithea.model.meta import Session
 from kallithea.model.notification import NotificationModel
-from kallithea.model.meta import Session
+
 
 log = logging.getLogger(__name__)
 
@@ -82,7 +82,7 @@
                 revision=revision,
                 anchor='comment-%s' % comment.comment_id)
             subj = safe_unicode(
-                h.link_to('Re changeset: %(desc)s %(line)s' % \
+                h.link_to('Re changeset: %(desc)s %(line)s' %
                           {'desc': desc, 'line': line},
                           comment_url)
             )
--- a/kallithea/model/db.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/db.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,38 +25,36 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+import collections
+import datetime
+import functools
+import hashlib
+import logging
 import os
 import time
-import logging
-import datetime
 import traceback
-import hashlib
-import collections
-import functools
-
+
+import ipaddr
 import sqlalchemy
+from beaker.cache import cache_region, region_invalidate
 from sqlalchemy import *
 from sqlalchemy.ext.hybrid import hybrid_property
-from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
-from beaker.cache import cache_region, region_invalidate
+from sqlalchemy.orm import class_mapper, joinedload, relationship, validates
+from tg.i18n import lazy_ugettext as _
 from webob.exc import HTTPNotFound
 
-from tg.i18n import lazy_ugettext as _
-
+import kallithea
+from kallithea.lib.caching_query import FromCache
+from kallithea.lib.compat import json
 from kallithea.lib.exceptions import DefaultUserException
+from kallithea.lib.utils2 import Optional, aslist, get_changeset_safe, get_clone_url, remove_prefix, safe_int, safe_str, safe_unicode, 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.lib.vcs.backends.base import EmptyChangeset
-
-from kallithea.lib.utils2 import str2bool, safe_str, get_changeset_safe, \
-    safe_unicode, remove_prefix, time_to_datetime, aslist, Optional, safe_int, \
-    get_clone_url, urlreadable
-from kallithea.lib.compat import json
-from kallithea.lib.caching_query import FromCache
-
 from kallithea.model.meta import Base, Session
 
+
 URL_SEP = '/'
 log = logging.getLogger(__name__)
 
@@ -325,7 +323,6 @@
     def get_server_info(cls):
         import pkg_resources
         import platform
-        import kallithea
         from kallithea.lib.utils import check_git_version
         mods = [(p.project_name, p.version) for p in pkg_resources.working_set]
         info = {
@@ -351,10 +348,6 @@
 
     HOOK_UPDATE = 'changegroup.update'
     HOOK_REPO_SIZE = 'changegroup.repo_size'
-    HOOK_PUSH_LOG = 'changegroup.push_logger'
-    HOOK_PUSH_LOCK = 'prechangegroup.push_lock_handling'
-    HOOK_PULL_LOG = 'outgoing.pull_logger'
-    HOOK_PULL_LOCK = 'preoutgoing.pull_lock_handling'
 
     ui_id = Column(Integer(), primary_key=True)
     ui_section = Column(String(255), nullable=False)
@@ -379,18 +372,14 @@
     @classmethod
     def get_builtin_hooks(cls):
         q = cls.query()
-        q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE,
-                                     cls.HOOK_PUSH_LOG, cls.HOOK_PUSH_LOCK,
-                                     cls.HOOK_PULL_LOG, cls.HOOK_PULL_LOCK]))
+        q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE]))
         q = q.filter(cls.ui_section == 'hooks')
         return q.all()
 
     @classmethod
     def get_custom_hooks(cls):
         q = cls.query()
-        q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE,
-                                      cls.HOOK_PUSH_LOG, cls.HOOK_PUSH_LOCK,
-                                      cls.HOOK_PULL_LOG, cls.HOOK_PULL_LOCK]))
+        q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE]))
         q = q.filter(cls.ui_section == 'hooks')
         return q.all()
 
@@ -434,7 +423,6 @@
     extern_type = Column(String(255), nullable=True) # FIXME: not nullable?
     extern_name = Column(String(255), nullable=True) # FIXME: not nullable?
     api_key = Column(String(255), nullable=False)
-    inherit_default_permissions = Column(Boolean(), nullable=False, default=True)
     created_on = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
     _user_data = Column("user_data", LargeBinary(), nullable=True)  # JSON data # FIXME: not nullable?
 
@@ -458,6 +446,7 @@
     user_emails = relationship('UserEmailMap', cascade='all')
     # extra API keys
     user_api_keys = relationship('UserApiKeys', cascade='all')
+    ssh_keys = relationship('UserSshKeys', cascade='all')
 
     @hybrid_property
     def email(self):
@@ -607,6 +596,8 @@
             _res = UserApiKeys.query().filter_by(api_key=api_key, is_expired=False).first()
             if _res:
                 res = _res.user
+        if res is None or not res.active or res.is_default_user:
+            return None
         return res
 
     @classmethod
@@ -713,7 +704,6 @@
         Index('uak_api_key_expires_idx', 'api_key', 'expires'),
         _table_args_default_dict,
     )
-    __mapper_args__ = {}
 
     user_api_key_id = Column(Integer(), primary_key=True)
     user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=False)
@@ -735,7 +725,6 @@
         Index('uem_email_idx', 'email'),
         _table_args_default_dict,
     )
-    __mapper_args__ = {}
 
     email_id = Column(Integer(), primary_key=True)
     user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=False)
@@ -765,7 +754,6 @@
         UniqueConstraint('user_id', 'ip_addr'),
         _table_args_default_dict,
     )
-    __mapper_args__ = {}
 
     ip_id = Column(Integer(), primary_key=True)
     user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=False)
@@ -775,7 +763,6 @@
 
     @classmethod
     def _get_ip_range(cls, ip_addr):
-        from kallithea.lib import ipaddr
         net = ipaddr.IPNetwork(address=ip_addr)
         return [str(net.network), str(net.broadcast)]
 
@@ -828,7 +815,6 @@
     users_group_name = Column(Unicode(255), nullable=False, unique=True)
     user_group_description = Column(Unicode(10000), nullable=True) # FIXME: not nullable?
     users_group_active = Column(Boolean(), nullable=False)
-    inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, default=True)
     owner_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
     created_on = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
     _group_data = Column("group_data", LargeBinary(), nullable=True)  # JSON data # FIXME: not nullable?
@@ -974,7 +960,7 @@
     )
 
     DEFAULT_CLONE_URI = '{scheme}://{user}@{netloc}/{repo}'
-    DEFAULT_CLONE_URI_ID = '{scheme}://{user}@{netloc}/_{repoid}'
+    DEFAULT_CLONE_SSH = 'ssh://{system_user}@{hostname}/{repo}'
 
     STATE_CREATED = u'repo_state_created'
     STATE_PENDING = u'repo_state_pending'
@@ -985,7 +971,7 @@
     repo_state = Column(String(255), nullable=False)
 
     clone_uri = Column(String(255), nullable=True) # FIXME: not nullable?
-    repo_type = Column(String(255), nullable=False)
+    repo_type = Column(String(255), nullable=False) # 'hg' or 'git'
     owner_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
     private = Column(Boolean(), nullable=False)
     enable_statistics = Column("statistics", Boolean(), nullable=False, default=True)
@@ -994,8 +980,6 @@
     created_on = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
     updated_on = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
     _landing_revision = Column("landing_revision", String(255), nullable=False)
-    enable_locking = Column(Boolean(), nullable=False, default=False)
-    _locked = Column("locked", String(255), nullable=True) # FIXME: not nullable?
     _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) # JSON data # FIXME: not nullable?
 
     fork_id = Column(Integer(), ForeignKey('repositories.repo_id'), nullable=True)
@@ -1047,21 +1031,6 @@
         self._landing_revision = val
 
     @hybrid_property
-    def locked(self):
-        # always should return [user_id, timelocked]
-        if self._locked:
-            _lock_info = self._locked.split(':')
-            return int(_lock_info[0]), _lock_info[1]
-        return [None, None]
-
-    @locked.setter
-    def locked(self, val):
-        if val and isinstance(val, (list, tuple)):
-            self._locked = ':'.join(map(str, val))
-        else:
-            self._locked = None
-
-    @hybrid_property
     def changeset_cache(self):
         try:
             cs_cache = json.loads(self._changeset_cache) # might raise on bad data
@@ -1221,7 +1190,7 @@
         Creates an db based ui object for this repository
         """
         from kallithea.lib.utils import make_ui
-        return make_ui('db', clear_session=False)
+        return make_ui(clear_session=False)
 
     @classmethod
     def is_valid(cls, repo_name):
@@ -1254,13 +1223,8 @@
             owner=repo.owner.username,
             fork_of=repo.fork.repo_name if repo.fork else None,
             enable_statistics=repo.enable_statistics,
-            enable_locking=repo.enable_locking,
             enable_downloads=repo.enable_downloads,
             last_changeset=repo.changeset_cache,
-            locked_by=User.get(self.locked[0]).get_api_data() \
-                if self.locked[0] else None,
-            locked_date=time_to_datetime(self.locked[1]) \
-                if self.locked[1] else None
         )
         if with_revision_names:
             scm_repo = repo.scm_instance_no_cache()
@@ -1279,22 +1243,6 @@
 
         return data
 
-    @classmethod
-    def lock(cls, repo, user_id, lock_time=None):
-        if lock_time is not None:
-            lock_time = time.time()
-        repo.locked = [user_id, lock_time]
-        Session().commit()
-
-    @classmethod
-    def unlock(cls, repo):
-        repo.locked = None
-        Session().commit()
-
-    @classmethod
-    def getlock(cls, repo):
-        return repo.locked
-
     @property
     def last_db_change(self):
         return self.updated_on
@@ -1309,34 +1257,22 @@
                 clone_uri = url_obj.with_password('*****')
         return clone_uri
 
-    def clone_url(self, **override):
+    def clone_url(self, clone_uri_tmpl, with_id=False, username=None):
+        if '{repo}' not in clone_uri_tmpl and '_{repoid}' not in clone_uri_tmpl:
+            log.error("Configured clone_uri_tmpl %r has no '{repo}' or '_{repoid}' and cannot toggle to use repo id URLs", clone_uri_tmpl)
+        elif with_id:
+            clone_uri_tmpl = clone_uri_tmpl.replace('{repo}', '_{repoid}')
+        else:
+            clone_uri_tmpl = clone_uri_tmpl.replace('_{repoid}', '{repo}')
+
         import kallithea.lib.helpers as h
-        qualified_home_url = h.canonical_url('home')
-
-        uri_tmpl = None
-        if 'with_id' in override:
-            uri_tmpl = self.DEFAULT_CLONE_URI_ID
-            del override['with_id']
-
-        if 'uri_tmpl' in override:
-            uri_tmpl = override['uri_tmpl']
-            del override['uri_tmpl']
-
-        # we didn't override our tmpl from **overrides
-        if not uri_tmpl:
-            uri_tmpl = self.DEFAULT_CLONE_URI
-            try:
-                from tg import tmpl_context as c
-                uri_tmpl = c.clone_uri_tmpl
-            except AttributeError:
-                # in any case if we call this outside of request context,
-                # ie, not having tmpl_context set up
-                pass
-
-        return get_clone_url(uri_tmpl=uri_tmpl,
-                             qualified_home_url=qualified_home_url,
+        prefix_url = h.canonical_url('home')
+
+        return get_clone_url(clone_uri_tmpl=clone_uri_tmpl,
+                             prefix_url=prefix_url,
                              repo_name=self.repo_name,
-                             repo_id=self.repo_id, **override)
+                             repo_id=self.repo_id,
+                             username=username)
 
     def set_state(self, state):
         self.repo_state = state
@@ -1516,7 +1452,6 @@
     __table_args__ = (
         _table_args_default_dict,
     )
-    __mapper_args__ = {'order_by': 'group_name'} # TODO: Deprecated as of SQLAlchemy 1.1.
 
     SEP = ' &raquo; '
 
@@ -1524,7 +1459,6 @@
     group_name = Column(Unicode(255), nullable=False, unique=True) # full path
     parent_group_id = Column('group_parent_id', Integer(), ForeignKey('groups.group_id'), nullable=True)
     group_description = Column(Unicode(10000), nullable=False)
-    enable_locking = Column(Boolean(), nullable=False, default=False)
     owner_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
     created_on = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
 
@@ -1557,7 +1491,7 @@
     @classmethod
     def _generate_choice(cls, repo_group):
         """Return tuple with group_id and name as html literal"""
-        from webhelpers.html import literal
+        from webhelpers2.html import literal
         if repo_group is None:
             return (-1, u'-- %s --' % _('top level'))
         return repo_group.group_id, literal(cls.SEP.join(repo_group.full_path_splitted))
@@ -1699,7 +1633,7 @@
         _table_args_default_dict,
     )
 
-    PERMS = [
+    PERMS = (
         ('hg.admin', _('Kallithea Administrator')),
 
         ('repository.none', _('Default user has no access to new repositories')),
@@ -1738,10 +1672,10 @@
 
         ('hg.extern_activate.manual', _('Manual activation of external account')),
         ('hg.extern_activate.auto', _('Automatic activation of external account')),
-    ]
+    )
 
     # definition of system default permissions for DEFAULT user
-    DEFAULT_USER_PERMISSIONS = [
+    DEFAULT_USER_PERMISSIONS = (
         'repository.read',
         'group.read',
         'usergroup.read',
@@ -1750,7 +1684,7 @@
         'hg.fork.repository',
         'hg.register.manual_activate',
         'hg.extern_activate.auto',
-    ]
+    )
 
     # defines which permissions are more important higher the more important
     # Weight defines which permissions are more important.
@@ -1781,7 +1715,17 @@
         'hg.fork.repository': 1,
 
         'hg.create.none': 0,
-        'hg.create.repository': 1
+        'hg.create.repository': 1,
+
+        'hg.create.write_on_repogroup.false': 0,
+        'hg.create.write_on_repogroup.true': 1,
+
+        'hg.register.none': 0,
+        'hg.register.manual_activate': 1,
+        'hg.register.auto_activate': 2,
+
+        'hg.extern_activate.manual': 0,
+        'hg.extern_activate.auto': 1,
     }
 
     permission_id = Column(Integer(), primary_key=True)
@@ -2133,7 +2077,6 @@
         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 .
         """
-        import kallithea
         prefix = kallithea.CONFIG.get('instance_id', '')
         return "%s%s" % (prefix, key)
 
@@ -2411,6 +2354,7 @@
         return self.__json__()
 
     def __json__(self):
+        clone_uri_tmpl = kallithea.CONFIG.get('clone_uri_tmpl') or Repository.DEFAULT_CLONE_URI
         return dict(
             pull_request_id=self.pull_request_id,
             url=self.url(),
@@ -2419,7 +2363,7 @@
             owner=self.owner.username,
             title=self.title,
             description=self.description,
-            org_repo_url=self.org_repo.clone_url(),
+            org_repo_url=self.org_repo.clone_url(clone_uri_tmpl=clone_uri_tmpl),
             org_ref_parts=self.org_ref_parts,
             other_ref_parts=self.other_ref_parts,
             status=self.status,
@@ -2520,7 +2464,6 @@
         return cls.query().filter(cls.gist_access_id == gist_access_id).scalar()
 
     def gist_url(self):
-        import kallithea
         alias_url = kallithea.CONFIG.get('gist_alias_url')
         if alias_url:
             return alias_url.replace('{gistid}', self.gist_access_id)
@@ -2570,3 +2513,36 @@
         base_path = self.base_path()
         return get_repo(os.path.join(*map(safe_str,
                                           [base_path, self.gist_access_id])))
+
+
+class UserSshKeys(Base, BaseDbModel):
+    __tablename__ = 'user_ssh_keys'
+    __table_args__ = (
+        Index('usk_public_key_idx', 'public_key'),
+        Index('usk_fingerprint_idx', 'fingerprint'),
+        UniqueConstraint('fingerprint'),
+        _table_args_default_dict
+    )
+    __mapper_args__ = {}
+
+    user_ssh_key_id = Column(Integer(), primary_key=True)
+    user_id = Column(Integer(), ForeignKey('users.user_id'), nullable=False)
+    _public_key = Column('public_key', UnicodeText(), nullable=False)
+    description = Column(UnicodeText(), nullable=False)
+    fingerprint = Column(String(255), nullable=False, unique=True)
+    created_on = Column(DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
+    last_seen = Column(DateTime(timezone=False), nullable=True)
+
+    user = relationship('User')
+
+    @property
+    def public_key(self):
+        return self._public_key
+
+    @public_key.setter
+    def public_key(self, full_key):
+        # the full public key is too long to be suitable as database key - instead,
+        # use fingerprints similar to 'ssh-keygen -E sha256 -lf ~/.ssh/id_rsa.pub'
+        self._public_key = full_key
+        enc_key = full_key.split(" ")[1]
+        self.fingerprint = hashlib.sha256(enc_key.decode('base64')).digest().encode('base64').replace('\n', '').rstrip('=')
--- a/kallithea/model/forms.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/forms.py	Sun Jan 05 04:07:51 2020 +0100
@@ -37,12 +37,12 @@
 
 import formencode
 from formencode import All
-
 from tg.i18n import ugettext as _
 
 from kallithea import BACKENDS
 from kallithea.model import validators as v
 
+
 log = logging.getLogger(__name__)
 
 
@@ -182,7 +182,6 @@
                                       testValueList=True,
                                       if_missing=None, not_empty=True),
                               v.Int(min=-1, not_empty=True))
-        enable_locking = v.StringBoolean(if_missing=False)
         chained_validators = [v.ValidRepoGroup(edit, old_data)]
 
     return _RepoGroupForm
@@ -264,7 +263,6 @@
 
         repo_enable_statistics = v.StringBoolean(if_missing=False)
         repo_enable_downloads = v.StringBoolean(if_missing=False)
-        repo_enable_locking = v.StringBoolean(if_missing=False)
 
         if edit:
             owner = All(v.UnicodeString(not_empty=True), v.ValidRepoUser())
@@ -373,6 +371,7 @@
         use_gravatar = v.StringBoolean(if_missing=False)
         gravatar_url = v.UnicodeString(min=3)
         clone_uri_tmpl = v.UnicodeString(min=3)
+        clone_ssh_tmpl = v.UnicodeString()
 
     return _ApplicationVisualisationForm
 
@@ -387,8 +386,6 @@
         )
         hooks_changegroup_update = v.StringBoolean(if_missing=False)
         hooks_changegroup_repo_size = v.StringBoolean(if_missing=False)
-        hooks_changegroup_push_logger = v.StringBoolean(if_missing=False)
-        hooks_outgoing_pull_logger = v.StringBoolean(if_missing=False)
 
         extensions_largefiles = v.StringBoolean(if_missing=False)
         extensions_hgsubversion = v.StringBoolean(if_missing=False)
@@ -428,7 +425,6 @@
     class _CustomDefaultPermissionsForm(formencode.Schema):
         filter_extra_fields = True
         allow_extra_fields = True
-        inherit_default_permissions = v.StringBoolean(if_missing=False)
 
         create_repo_perm = v.StringBoolean(if_missing=False)
         create_user_group_perm = v.StringBoolean(if_missing=False)
@@ -447,7 +443,6 @@
         default_repo_private = v.StringBoolean(if_missing=False)
         default_repo_enable_statistics = v.StringBoolean(if_missing=False)
         default_repo_enable_downloads = v.StringBoolean(if_missing=False)
-        default_repo_enable_locking = v.StringBoolean(if_missing=False)
 
     return _DefaultsForm
 
--- a/kallithea/model/gist.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/gist.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,20 +25,20 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+import logging
 import os
 import random
+import shutil
 import time
-import logging
 import traceback
-import shutil
 
-from kallithea.lib.utils2 import safe_unicode, safe_int, \
-    time_to_datetime, AttributeDict
 from kallithea.lib.compat import json
+from kallithea.lib.utils2 import AttributeDict, safe_int, safe_unicode, time_to_datetime
 from kallithea.model.db import Gist, Session, User
 from kallithea.model.repo import RepoModel
 from kallithea.model.scm import ScmModel
 
+
 log = logging.getLogger(__name__)
 
 GIST_STORE_LOC = '.rc_gist_store'
@@ -97,7 +97,7 @@
         cs = repo.scm_instance.get_changeset(revision)
         return cs, [n for n in cs.get_node('/')]
 
-    def create(self, description, owner, gist_mapping,
+    def create(self, description, owner, ip_addr, gist_mapping,
                gist_type=Gist.GIST_PUBLIC, lifetime=-1):
         """
 
@@ -159,7 +159,9 @@
             scm_instance_no_cache=lambda: repo,
         ))
         ScmModel().create_nodes(
-            user=owner.user_id, repo=fake_repo,
+            user=owner.user_id,
+            ip_addr=ip_addr,
+            repo=fake_repo,
             message=message,
             nodes=processed_mapping,
             trigger_push_hook=False
@@ -181,7 +183,7 @@
             log.error(traceback.format_exc())
             raise
 
-    def update(self, gist, description, owner, gist_mapping, gist_type,
+    def update(self, gist, description, owner, ip_addr, gist_mapping, gist_type,
                lifetime):
         gist = Gist.guess_instance(gist)
         gist_repo = gist.scm_instance
@@ -226,6 +228,7 @@
 
         ScmModel().update_nodes(
             user=owner.user_id,
+            ip_addr=ip_addr,
             repo=fake_repo,
             message=message,
             nodes=gist_mapping_op,
--- a/kallithea/model/meta.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/meta.py	Sun Jan 05 04:07:51 2020 +0100
@@ -14,9 +14,9 @@
 """
 SQLAlchemy Metadata and Session object
 """
+from beaker import cache
 from sqlalchemy.ext.declarative import declarative_base
 from sqlalchemy.orm import scoped_session, sessionmaker
-from beaker import cache
 
 from kallithea.lib import caching_query
 
--- a/kallithea/model/notification.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/notification.py	Sun Jan 05 04:07:51 2020 +0100
@@ -28,17 +28,16 @@
 
 import datetime
 import logging
-import traceback
 
-from tg import tmpl_context as c, app_globals
+from tg import app_globals
+from tg import tmpl_context as c
 from tg.i18n import ugettext as _
-from sqlalchemy.orm import joinedload, subqueryload
 
 import kallithea
 from kallithea.lib import helpers as h
 from kallithea.lib.utils2 import safe_unicode
 from kallithea.model.db import User
-from kallithea.model.meta import Session
+
 
 log = logging.getLogger(__name__)
 
--- a/kallithea/model/permission.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/permission.py	Sun Jan 05 04:07:51 2020 +0100
@@ -31,9 +31,9 @@
 
 from sqlalchemy.exc import DatabaseError
 
-from kallithea.model.db import Permission, Session, User, \
-    UserToPerm, UserRepoToPerm, UserRepoGroupToPerm, UserUserGroupToPerm
 from kallithea.lib.utils2 import str2bool
+from kallithea.model.db import Permission, Session, User, UserRepoGroupToPerm, UserRepoToPerm, UserToPerm, UserUserGroupToPerm
+
 
 log = logging.getLogger(__name__)
 
--- a/kallithea/model/pull_request.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/pull_request.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,21 +25,18 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+import datetime
 import logging
-import datetime
 import re
 
 from tg import request
 from tg.i18n import ugettext as _
 
-from sqlalchemy.orm import joinedload
-
+from kallithea.lib import helpers as h
+from kallithea.lib.utils2 import extract_mentioned_users, safe_str, safe_unicode
+from kallithea.model.db import ChangesetStatus, PullRequest, PullRequestReviewer, User
 from kallithea.model.meta import Session
-from kallithea.lib import helpers as h
-from kallithea.model.db import PullRequest, PullRequestReviewer, \
-    ChangesetStatus, User
 from kallithea.model.notification import NotificationModel
-from kallithea.lib.utils2 import extract_mentioned_users, safe_str, safe_unicode
 
 
 log = logging.getLogger(__name__)
@@ -73,7 +70,7 @@
                                       h.canonical_hostname())]
         subject = safe_unicode(
             h.link_to(
-              _('%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s') % \
+              _('%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s') %
                 {'user': user.username,
                  'pr_title': pr.title,
                  'pr_nice_id': pr.nice_id()},
@@ -175,7 +172,8 @@
         object.
         """
         if (h.HasRepoPermissionLevel('read')(org_repo.repo_name) and
-            h.HasRepoPermissionLevel('read')(other_repo.repo_name)):
+            h.HasRepoPermissionLevel('read')(other_repo.repo_name)
+        ):
             return True
 
         return False
@@ -361,8 +359,8 @@
             else:
                 infos.append(_('This iteration is based on another %s revision and there is no simple diff.') % other_ref_name)
         else:
-           infos.append(_('No changes found on %s %s since previous iteration.') % (org_ref_type, org_ref_name))
-           # TODO: fail?
+            infos.append(_('No changes found on %s %s since previous iteration.') % (org_ref_type, org_ref_name))
+            # TODO: fail?
 
         try:
             title, old_v = re.match(r'(.*)\(v(\d+)\)\s*$', title).groups()
--- a/kallithea/model/repo.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/repo.py	Sun Jan 05 04:07:51 2020 +0100
@@ -26,29 +26,24 @@
 
 """
 
+import logging
 import os
 import shutil
-import logging
 import traceback
 from datetime import datetime
-from sqlalchemy.orm import subqueryload
 
 import kallithea.lib.utils2
-from kallithea.lib.utils import make_ui, is_valid_repo_uri
-from kallithea.lib.vcs.backends import get_backend
-from kallithea.lib.utils2 import LazyProperty, safe_str, safe_unicode, \
-    remove_prefix, obfuscate_url_pw, get_current_authuser
-from kallithea.lib.caching_query import FromCache
-from kallithea.lib.hooks import log_delete_repository
-
-from kallithea.model.db import Repository, UserRepoToPerm, UserGroupRepoToPerm, \
-    UserRepoGroupToPerm, UserGroupRepoGroupToPerm, User, Permission, Session, \
-    Statistics, UserGroup, Ui, RepoGroup, RepositoryField
-
 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.model.scm import UserGroupList
+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, safe_str, safe_unicode
+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)
+
 
 log = logging.getLogger(__name__)
 
@@ -236,7 +231,7 @@
         defaults['repo_group'] = repo_info.group_id
 
         for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
-                         (1, 'repo_description'), (1, 'repo_enable_locking'),
+                         (1, 'repo_description'),
                          (1, 'repo_landing_rev'), (0, 'clone_uri'),
                          (1, 'repo_private'), (1, 'repo_enable_statistics')]:
             attr = k
@@ -284,7 +279,6 @@
             log.debug('Updating repo %s with params:%s', cur_repo, kwargs)
             for k in ['repo_enable_downloads',
                       'repo_description',
-                      'repo_enable_locking',
                       'repo_landing_rev',
                       'repo_private',
                       'repo_enable_statistics',
@@ -296,7 +290,7 @@
                 # clone_uri is modified - if given a value, check it is valid
                 if clone_uri != '':
                     # will raise exception on error
-                    is_valid_repo_uri(cur_repo.repo_type, clone_uri, make_ui('db', clear_session=False))
+                    is_valid_repo_uri(cur_repo.repo_type, clone_uri, make_ui(clear_session=False))
                 cur_repo.clone_uri = clone_uri
 
             if 'repo_name' in kwargs:
@@ -332,7 +326,7 @@
                      private=False, clone_uri=None, repo_group=None,
                      landing_rev='rev:tip', fork_of=None,
                      copy_fork_permissions=False, enable_statistics=False,
-                     enable_locking=False, enable_downloads=False,
+                     enable_downloads=False,
                      copy_group_permissions=False, state=Repository.STATE_PENDING):
         """
         Create repository inside database with PENDING state. This should only be
@@ -366,17 +360,13 @@
             new_repo.private = private
             if clone_uri:
                 # will raise exception on error
-                is_valid_repo_uri(repo_type, clone_uri, make_ui('db', clear_session=False))
+                is_valid_repo_uri(repo_type, clone_uri, make_ui(clear_session=False))
             new_repo.clone_uri = clone_uri
             new_repo.landing_rev = landing_rev
 
             new_repo.enable_statistics = enable_statistics
-            new_repo.enable_locking = enable_locking
             new_repo.enable_downloads = enable_downloads
 
-            if repo_group:
-                new_repo.enable_locking = repo_group.enable_locking
-
             if fork_of:
                 parent_repo = fork_of
                 new_repo.fork = parent_repo
@@ -671,7 +661,7 @@
         backend = get_backend(repo_type)
 
         if repo_type == 'hg':
-            baseui = make_ui('db', clear_session=False)
+            baseui = make_ui(clear_session=False)
             # patch and reset hooks section of UI config to not run any
             # hooks on creating remote repo
             for k, v in baseui.configitems('hooks'):
--- a/kallithea/model/repo_group.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/repo_group.py	Sun Jan 05 04:07:51 2020 +0100
@@ -26,17 +26,16 @@
 """
 
 
+import datetime
+import logging
 import os
-import logging
+import shutil
 import traceback
-import shutil
-import datetime
 
 import kallithea.lib.utils2
 from kallithea.lib.utils2 import LazyProperty
+from kallithea.model.db import Permission, RepoGroup, Repository, Session, Ui, User, UserGroup, UserGroupRepoGroupToPerm, UserRepoGroupToPerm
 
-from kallithea.model.db import RepoGroup, Session, Ui, UserRepoGroupToPerm, \
-    User, Permission, UserGroupRepoGroupToPerm, UserGroup, Repository
 
 log = logging.getLogger(__name__)
 
@@ -287,8 +286,6 @@
                 repo_group.group_description = repo_group_args['group_description']
             if 'parent_group_id' in repo_group_args:
                 repo_group.parent_group_id = repo_group_args['parent_group_id']
-            if 'enable_locking' in repo_group_args:
-                repo_group.enable_locking = repo_group_args['enable_locking']
 
             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
@@ -302,24 +299,22 @@
             Session().add(repo_group)
 
             # iterate over all members of this groups and do fixes
-            # set locking if given
             # if obj is a repoGroup also fix the name of the group according
             # to the parent
             # if obj is a Repo fix it's name
             # this can be potentially heavy operation
             for obj in repo_group.recursive_groups_and_repos():
                 # set the value from it's parent
-                obj.enable_locking = repo_group.enable_locking
                 if isinstance(obj, RepoGroup):
                     new_name = obj.get_new_name(obj.name)
-                    log.debug('Fixing group %s to new name %s' \
+                    log.debug('Fixing group %s to new name %s'
                                 % (obj.group_name, new_name))
                     obj.group_name = new_name
                 elif isinstance(obj, Repository):
                     # we need to get all repositories from this new group and
                     # rename them accordingly to new group path
                     new_name = obj.get_new_name(obj.just_name)
-                    log.debug('Fixing repo %s to new name %s' \
+                    log.debug('Fixing repo %s to new name %s'
                                 % (obj.repo_name, new_name))
                     obj.repo_name = new_name
 
--- a/kallithea/model/repo_permission.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/repo_permission.py	Sun Jan 05 04:07:51 2020 +0100
@@ -24,8 +24,9 @@
 """
 
 import logging
-from kallithea.model.db import User, UserRepoToPerm, UserGroupRepoToPerm, \
-    Permission, Repository, Session
+
+from kallithea.model.db import Permission, Repository, Session, User, UserGroupRepoToPerm, UserRepoToPerm
+
 
 log = logging.getLogger(__name__)
 
--- a/kallithea/model/scm.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/scm.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,38 +25,31 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+import cStringIO
+import logging
 import os
-import sys
 import posixpath
 import re
-import time
+import sys
 import traceback
-import logging
-import cStringIO
+
 import pkg_resources
-
-from sqlalchemy import func
 from tg.i18n import ugettext as _
 
 import kallithea
+from kallithea import BACKENDS
+from kallithea.lib.auth import HasPermissionAny, HasRepoGroupPermissionLevel, HasRepoPermissionLevel, HasUserGroupPermissionLevel
+from kallithea.lib.exceptions import IMCCommitError, NonRelativePathError
+from kallithea.lib.hooks import process_pushed_raw_ids
+from kallithea.lib.utils import action_logger, get_filesystem_repos, make_ui
+from kallithea.lib.utils2 import safe_str, safe_unicode, set_hook_environment
 from kallithea.lib.vcs import get_backend
+from kallithea.lib.vcs.backends.base import EmptyChangeset
 from kallithea.lib.vcs.exceptions import RepositoryError
+from kallithea.lib.vcs.nodes import FileNode
 from kallithea.lib.vcs.utils.lazy import LazyProperty
-from kallithea.lib.vcs.nodes import FileNode
-from kallithea.lib.vcs.backends.base import EmptyChangeset
+from kallithea.model.db import PullRequest, RepoGroup, Repository, Session, Ui, User, UserFollowing, UserLog
 
-from kallithea import BACKENDS
-from kallithea.lib import helpers as h
-from kallithea.lib.utils2 import safe_str, safe_unicode, get_server_url, \
-    _set_extras
-from kallithea.lib.auth import HasRepoPermissionLevel, HasRepoGroupPermissionLevel, \
-    HasUserGroupPermissionLevel, HasPermissionAny, HasPermissionAny
-from kallithea.lib.utils import get_filesystem_repos, make_ui, \
-    action_logger
-from kallithea.model.db import Repository, Session, Ui, CacheInvalidation, \
-    UserFollowing, UserLog, User, RepoGroup, PullRequest
-from kallithea.lib.hooks import log_push_action
-from kallithea.lib.exceptions import NonRelativePathError, IMCCommitError
 
 log = logging.getLogger(__name__)
 
@@ -178,7 +171,7 @@
 
         log.info('scanning for repositories in %s', repos_path)
 
-        baseui = make_ui('db')
+        baseui = make_ui()
         repos = {}
 
         for name, path in get_filesystem_repos(repos_path):
@@ -223,9 +216,10 @@
 
         :param repo_name: the repo for which caches should be marked invalid
         """
-        CacheInvalidation.set_invalidate(repo_name)
+        log.debug("Marking %s as invalidated and update cache", repo_name)
         repo = Repository.get_by_repo_name(repo_name)
         if repo is not None:
+            repo.set_invalidate()
             repo.update_changeset_cache()
 
     def toggle_following_repo(self, follow_repo_id, user_id):
@@ -280,7 +274,7 @@
             log.error(traceback.format_exc())
             raise
 
-    def is_following_repo(self, repo_name, user_id, cache=False):
+    def is_following_repo(self, repo_name, user_id):
         r = Repository.query() \
             .filter(Repository.repo_name == repo_name).scalar()
 
@@ -290,7 +284,7 @@
 
         return f is not None
 
-    def is_following_user(self, username, user_id, cache=False):
+    def is_following_user(self, username, user_id):
         u = User.get_by_username(username)
 
         f = UserFollowing.query() \
@@ -328,48 +322,19 @@
         repo.fork = fork
         return repo
 
-    def _handle_rc_scm_extras(self, username, repo_name, repo_alias,
-                              action=None):
-        from kallithea import CONFIG
-        from kallithea.lib.base import _get_ip_addr
-        try:
-            from tg import request
-            environ = request.environ
-        except TypeError:
-            # we might use this outside of request context, let's fake the
-            # environ data
-            from webob import Request
-            environ = Request.blank('').environ
-        extras = {
-            'ip': _get_ip_addr(environ),
-            'username': username,
-            'action': action or 'push_local',
-            'repository': repo_name,
-            'scm': repo_alias,
-            'config': CONFIG['__file__'],
-            'server_url': get_server_url(environ),
-            'make_lock': None,
-            'locked_by': [None, None]
-        }
-        _set_extras(extras)
+    def _handle_push(self, repo, username, ip_addr, action, repo_name, revisions):
+        """
+        Handle that the repository has changed.
+        Adds an action log entry with the new revisions, and the head revision
+        cache and in-memory caches are invalidated/updated.
 
-    def _handle_push(self, repo, username, action, repo_name, revisions):
-        """
-        Triggers push action hooks
-
-        :param repo: SCM repo
         :param username: username who pushes
         :param action: push/push_local/push_remote
         :param repo_name: name of repo
         :param revisions: list of revisions that we pushed
         """
-        self._handle_rc_scm_extras(username, repo_name, repo_alias=repo.alias, action=action)
-        _scm_repo = repo._repo
-        # trigger push hook
-        if repo.alias == 'hg':
-            log_push_action(_scm_repo.ui, _scm_repo, node=revisions[0])
-        elif repo.alias == 'git':
-            log_push_action(None, _scm_repo, _git_revs=revisions)
+        set_hook_environment(username, ip_addr, repo_name, repo_alias=repo.alias, action=action)
+        process_pushed_raw_ids(revisions) # also calls mark_for_invalidation
 
     def _get_IMC_module(self, scm_type):
         """
@@ -388,7 +353,7 @@
         raise Exception('Invalid scm_type, must be one of hg,git got %s'
                         % (scm_type,))
 
-    def pull_changes(self, repo, username, clone_uri=None):
+    def pull_changes(self, repo, username, ip_addr, clone_uri=None):
         """
         Pull from "clone URL" or fork origin.
         """
@@ -404,24 +369,23 @@
             if repo.alias == 'git':
                 repo.fetch(clone_uri)
                 # git doesn't really have something like post-fetch action
-                # we fake that now. #TODO: extract fetched revisions somehow
-                # here
+                # we fake that now.
+                # TODO: extract fetched revisions ... somehow ...
                 self._handle_push(repo,
                                   username=username,
+                                  ip_addr=ip_addr,
                                   action='push_remote',
                                   repo_name=repo_name,
                                   revisions=[])
             else:
-                self._handle_rc_scm_extras(username, dbrepo.repo_name,
+                set_hook_environment(username, ip_addr, dbrepo.repo_name,
                                            repo.alias, action='push_remote')
                 repo.pull(clone_uri)
-
-            self.mark_for_invalidation(repo_name)
         except Exception:
             log.error(traceback.format_exc())
             raise
 
-    def commit_change(self, repo, repo_name, cs, user, author, message,
+    def commit_change(self, repo, repo_name, cs, user, ip_addr, author, message,
                       content, f_path):
         """
         Commit a change to a single file
@@ -446,12 +410,12 @@
                              parents=[cs], branch=cs.branch)
         except Exception as e:
             log.error(traceback.format_exc())
+            # clear caches - we also want a fresh object if commit fails
+            self.mark_for_invalidation(repo_name)
             raise IMCCommitError(str(e))
-        finally:
-            # always clear caches, if commit fails we want fresh object also
-            self.mark_for_invalidation(repo_name)
         self._handle_push(repo,
                           username=user.username,
+                          ip_addr=ip_addr,
                           action='push_local',
                           repo_name=repo_name,
                           revisions=[tip.raw_id])
@@ -493,7 +457,7 @@
 
         return _dirs, _files
 
-    def create_nodes(self, user, repo, message, nodes, parent_cs=None,
+    def create_nodes(self, user, ip_addr, repo, message, nodes, parent_cs=None,
                      author=None, trigger_push_hook=True):
         """
         Commits specified nodes to repo.
@@ -553,16 +517,18 @@
                          parents=parents,
                          branch=parent_cs.branch)
 
-        self.mark_for_invalidation(repo.repo_name)
         if trigger_push_hook:
             self._handle_push(scm_instance,
                               username=user.username,
+                              ip_addr=ip_addr,
                               action='push_local',
                               repo_name=repo.repo_name,
                               revisions=[tip.raw_id])
+        else:
+            self.mark_for_invalidation(repo.repo_name)
         return tip
 
-    def update_nodes(self, user, repo, message, nodes, parent_cs=None,
+    def update_nodes(self, user, ip_addr, repo, message, nodes, parent_cs=None,
                      author=None, trigger_push_hook=True):
         """
         Commits specified nodes to repo. Again.
@@ -613,15 +579,17 @@
                          parents=parents,
                          branch=parent_cs.branch)
 
-        self.mark_for_invalidation(repo.repo_name)
         if trigger_push_hook:
             self._handle_push(scm_instance,
                               username=user.username,
+                              ip_addr=ip_addr,
                               action='push_local',
                               repo_name=repo.repo_name,
                               revisions=[tip.raw_id])
+        else:
+            self.mark_for_invalidation(repo.repo_name)
 
-    def delete_nodes(self, user, repo, message, nodes, parent_cs=None,
+    def delete_nodes(self, user, ip_addr, repo, message, nodes, parent_cs=None,
                      author=None, trigger_push_hook=True):
         """
         Deletes specified nodes from repo.
@@ -672,13 +640,15 @@
                          parents=parents,
                          branch=parent_cs.branch)
 
-        self.mark_for_invalidation(repo.repo_name)
         if trigger_push_hook:
             self._handle_push(scm_instance,
                               username=user.username,
+                              ip_addr=ip_addr,
                               action='push_local',
                               repo_name=repo.repo_name,
                               revisions=[tip.raw_id])
+        else:
+            self.mark_for_invalidation(repo.repo_name)
         return tip
 
     def get_unread_journal(self):
@@ -695,7 +665,7 @@
         hist_l = []
         choices = []
         repo = self.__get_repo(repo)
-        hist_l.append(['rev:tip', _('latest tip')])
+        hist_l.append(('rev:tip', _('latest tip')))
         choices.append('rev:tip')
         if repo is None:
             return choices, hist_l
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/model/ssh_key.py	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,141 @@
+# -*- 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.ssh_key
+~~~~~~~~~~~~~~~~~~~~~~~
+
+SSH key model for Kallithea
+
+"""
+
+import errno
+import logging
+import os
+import stat
+import tempfile
+
+from tg import config
+from tg.i18n import ugettext as _
+
+from kallithea.lib import ssh
+from kallithea.lib.utils2 import safe_str, str2bool
+from kallithea.model.db import User, UserSshKeys
+from kallithea.model.meta import Session
+
+
+log = logging.getLogger(__name__)
+
+
+class SshKeyModelException(Exception):
+    """Exception raised by SshKeyModel methods to report errors"""
+
+
+class SshKeyModel(object):
+
+    def create(self, user, description, public_key):
+        """
+        :param user: user or user_id
+        :param description: description of SshKey
+        :param publickey: public key text
+        Will raise SshKeyModelException on errors
+        """
+        try:
+            keytype, pub, comment = ssh.parse_pub_key(public_key)
+        except ssh.SshKeyParseError as e:
+            raise SshKeyModelException(_('SSH key %r is invalid: %s') % (safe_str(public_key), e.message))
+        if not description.strip():
+            description = comment.strip()
+
+        user = User.guess_instance(user)
+
+        new_ssh_key = UserSshKeys()
+        new_ssh_key.user_id = user.user_id
+        new_ssh_key.description = description
+        new_ssh_key.public_key = public_key
+
+        for ssh_key in UserSshKeys.query().filter(UserSshKeys.fingerprint == new_ssh_key.fingerprint).all():
+            raise SshKeyModelException(_('SSH key %s is already used by %s') %
+                                       (new_ssh_key.fingerprint, ssh_key.user.username))
+
+        Session().add(new_ssh_key)
+
+        return new_ssh_key
+
+    def delete(self, public_key, user=None):
+        """
+        Deletes given public_key, if user is set it also filters the object for
+        deletion by given user.
+        Will raise SshKeyModelException on errors
+        """
+        ssh_key = UserSshKeys.query().filter(UserSshKeys._public_key == public_key)
+
+        if user:
+            user = User.guess_instance(user)
+            ssh_key = ssh_key.filter(UserSshKeys.user_id == user.user_id)
+
+        ssh_key = ssh_key.scalar()
+        if ssh_key is None:
+            raise SshKeyModelException(_('SSH key %r not found') % safe_str(public_key))
+        Session().delete(ssh_key)
+
+    def get_ssh_keys(self, user):
+        user = User.guess_instance(user)
+        user_ssh_keys = UserSshKeys.query() \
+            .filter(UserSshKeys.user_id == user.user_id).all()
+        return user_ssh_keys
+
+    def write_authorized_keys(self):
+        if not str2bool(config.get('ssh_enabled', False)):
+            log.error("Will not write SSH authorized_keys file - ssh_enabled is not configured")
+            return
+        authorized_keys = config.get('ssh_authorized_keys')
+        kallithea_cli_path = config.get('kallithea_cli_path', 'kallithea-cli')
+        if not authorized_keys:
+            log.error('Cannot write SSH authorized_keys file - ssh_authorized_keys is not configured')
+            return
+        log.info('Writing %s', authorized_keys)
+
+        authorized_keys_dir = os.path.dirname(authorized_keys)
+        try:
+            os.makedirs(authorized_keys_dir)
+            os.chmod(authorized_keys_dir, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR) # ~/.ssh/ must be 0700
+        except OSError as exception:
+            if exception.errno != errno.EEXIST:
+                raise
+        # Now, test that the directory is or was created in a readable way by previous.
+        if not (os.path.isdir(authorized_keys_dir) and
+                os.access(authorized_keys_dir, os.W_OK)):
+            raise Exception("Directory of authorized_keys cannot be written to so authorized_keys file %s cannot be written" % (authorized_keys))
+
+        # Make sure we don't overwrite a key file with important content
+        if os.path.exists(authorized_keys):
+            with open(authorized_keys) as f:
+                for l in f:
+                    if not l.strip() or l.startswith('#'):
+                        pass # accept empty lines and comments
+                    elif ssh.SSH_OPTIONS in l and ' ssh-serve ' in l:
+                        pass # Kallithea entries are ok to overwrite
+                    else:
+                        raise Exception("Safety check failed, found %r in %s - please review and remove it" % (l.strip(), authorized_keys))
+
+        fh, tmp_authorized_keys = tempfile.mkstemp('.authorized_keys', dir=os.path.dirname(authorized_keys))
+        with os.fdopen(fh, 'w') as f:
+            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)
--- a/kallithea/model/user.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/user.py	Sun Jan 05 04:07:51 2020 +0100
@@ -32,17 +32,14 @@
 import time
 import traceback
 
+from sqlalchemy.exc import DatabaseError
 from tg import config
 from tg.i18n import ugettext as _
 
-from sqlalchemy.exc import DatabaseError
-
-from kallithea.lib.utils2 import safe_unicode, generate_api_key, get_current_authuser
 from kallithea.lib.caching_query import FromCache
-from kallithea.model.db import Permission, User, UserToPerm, \
-    UserEmailMap, UserIpMap
-from kallithea.lib.exceptions import DefaultUserException, \
-    UserOwnsReposException
+from kallithea.lib.exceptions import DefaultUserException, UserOwnsReposException
+from kallithea.lib.utils2 import generate_api_key, get_current_authuser, safe_unicode
+from kallithea.model.db import Permission, User, UserEmailMap, UserIpMap, UserToPerm
 from kallithea.model.meta import Session
 
 
@@ -338,7 +335,7 @@
                 log.debug('password reset user %s found', user)
                 token = self.get_reset_password_token(user,
                                                       timestamp,
-                                                      h.authentication_token())
+                                                      h.session_csrf_secret_token())
                 # URL must be fully qualified; but since the token is locked to
                 # the current browser session, we must provide a URL with the
                 # current scheme and hostname, rather than the canonical_url.
@@ -371,8 +368,6 @@
                      timestamp=timestamp)
 
     def verify_reset_password_token(self, email, timestamp, token):
-        from kallithea.lib.celerylib import tasks
-        from kallithea.lib import auth
         import kallithea.lib.helpers as h
         user = User.get_by_email(email)
         if user is None:
@@ -391,7 +386,7 @@
 
         expected_token = self.get_reset_password_token(user,
                                                        timestamp,
-                                                       h.authentication_token())
+                                                       h.session_csrf_secret_token())
         log.debug('computed password reset token: %s', expected_token)
         log.debug('received password reset token: %s', token)
         return expected_token == token
--- a/kallithea/model/user_group.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/user_group.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,11 +27,10 @@
 import logging
 import traceback
 
-from kallithea.model.db import Session, UserGroupMember, UserGroup, \
-    UserGroupRepoToPerm, Permission, UserGroupToPerm, User, UserUserGroupToPerm, \
-    UserGroupUserGroupToPerm
-from kallithea.lib.exceptions import UserGroupsAssignedException, \
-    RepoGroupAssignmentError
+from kallithea.lib.exceptions import RepoGroupAssignmentError, UserGroupsAssignedException
+from kallithea.model.db import (
+    Permission, Session, User, UserGroup, UserGroupMember, UserGroupRepoToPerm, UserGroupToPerm, UserGroupUserGroupToPerm, UserUserGroupToPerm)
+
 
 log = logging.getLogger(__name__)
 
@@ -89,14 +88,14 @@
                         target_user_group=user_group, user_group=member, perm=perm
                     )
 
-    def get(self, user_group_id, cache=False):
+    def get(self, user_group_id):
         return UserGroup.get(user_group_id)
 
     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, case_insensitive)
+        return UserGroup.get_by_group_name(name, cache=cache, case_insensitive=case_insensitive)
 
     def create(self, name, description, owner, active=True, group_data=None):
         try:
@@ -167,6 +166,7 @@
             raise
 
     def add_user_to_group(self, user_group, user):
+        """Return True if user already is in the group - else return the new UserGroupMember"""
         user_group = UserGroup.guess_instance(user_group)
         user = User.guess_instance(user)
 
--- a/kallithea/model/validators.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/model/validators.py	Sun Jan 05 04:07:51 2020 +0100
@@ -15,28 +15,26 @@
 Set of generic validators
 """
 
+import logging
 import os
 import re
+from collections import defaultdict
+
 import formencode
-import logging
-from collections import defaultdict
+import ipaddr
+import sqlalchemy
+from formencode.validators import CIDR, Bool, Email, FancyValidator, Int, IPAddress, NotEmpty, Number, OneOf, Regex, Set, String, StringBoolean, UnicodeString
+from sqlalchemy import func
 from tg.i18n import ugettext as _
-from sqlalchemy import func
-from webhelpers.pylonslib.secure_form import authentication_token
-import sqlalchemy
 
-from formencode.validators import (
-    UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set,
-    NotEmpty, IPAddress, CIDR, String, FancyValidator
-)
+from kallithea.config.routing import ADMIN_PREFIX
+from kallithea.lib.auth import HasPermissionAny, HasRepoGroupPermissionLevel
 from kallithea.lib.compat import OrderedSet
-from kallithea.lib import ipaddr
+from kallithea.lib.exceptions import LdapImportError
 from kallithea.lib.utils import is_valid_repo_uri
-from kallithea.lib.utils2 import str2bool, aslist, repo_name_slug
-from kallithea.model.db import RepoGroup, Repository, UserGroup, User
-from kallithea.lib.exceptions import LdapImportError
-from kallithea.config.routing import ADMIN_PREFIX
-from kallithea.lib.auth import HasRepoGroupPermissionLevel, HasPermissionAny
+from kallithea.lib.utils2 import aslist, repo_name_slug, str2bool
+from kallithea.model.db import RepoGroup, Repository, User, UserGroup
+
 
 # silence warnings and pylint
 UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set, \
@@ -55,7 +53,7 @@
             missing_value=_('Value cannot be an empty list'),
         )
 
-        def _to_python(self, value, state):
+        def _convert_to_python(self, value, state):
             value = aslist(value, ',')
             seen = set()
             return [c for c in value if not (c in seen or seen.add(c))]
@@ -80,7 +78,7 @@
                   'alphanumeric character or underscore')
         }
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             if value in ['default', 'new_user']:
                 msg = self.message('system_invalid_username', state, username=value)
                 raise formencode.Invalid(msg, value, state)
@@ -112,7 +110,7 @@
             'invalid_username': _('Username %(username)s is not valid')
         }
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             try:
                 User.query().filter(User.active == True) \
                     .filter(User.username == value).one()
@@ -138,7 +136,7 @@
                   'with alphanumeric character')
         }
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             if value in ['default']:
                 msg = self.message('invalid_group', state)
                 raise formencode.Invalid(msg, value, state,
@@ -179,7 +177,7 @@
                 _('Repository with name "%(group_name)s" already exists')
         }
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             # TODO WRITE VALIDATIONS
             group_name = value.get('group_name')
             parent_group_id = value.get('parent_group_id')
@@ -235,7 +233,7 @@
                 _('Invalid characters (non-ascii) in password')
         }
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             try:
                 (value or '').decode('ascii')
             except UnicodeError:
@@ -250,7 +248,7 @@
             'invalid_password': _('Invalid old password')
         }
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             from kallithea.lib import auth_modules
             if auth_modules.authenticate(username, value, '') is None:
                 msg = self.message('invalid_password', state)
@@ -266,11 +264,11 @@
             'password_mismatch': _('Passwords do not match'),
         }
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             if value.get(password_field) != value[password_confirmation_field]:
                 msg = self.message('password_mismatch', state)
                 raise formencode.Invalid(msg, value, state,
-                     error_dict={password_field:msg, password_confirmation_field: msg}
+                     error_dict={password_field: msg, password_confirmation_field: msg}
                 )
     return _validator
 
@@ -281,7 +279,7 @@
             'invalid_auth': _(u'Invalid username or password'),
         }
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             from kallithea.lib import auth_modules
 
             password = value['password']
@@ -306,19 +304,6 @@
     return _validator
 
 
-def ValidAuthToken():
-    class _validator(formencode.validators.FancyValidator):
-        messages = {
-            'invalid_token': _('Token mismatch')
-        }
-
-        def validate_python(self, value, state):
-            if value != authentication_token():
-                msg = self.message('invalid_token', state)
-                raise formencode.Invalid(msg, value, state)
-    return _validator
-
-
 def ValidRepoName(edit=False, old_data=None):
     old_data = old_data or {}
 
@@ -334,7 +319,7 @@
                                    'already exists')
         }
 
-        def _to_python(self, value, state):
+        def _convert_to_python(self, value, state):
             repo_name = repo_name_slug(value.get('repo_name', ''))
             repo_group = value.get('repo_group')
             if repo_group:
@@ -355,7 +340,7 @@
             value['group_name'] = group_name
             return value
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             repo_name = value.get('repo_name')
             repo_name_full = value.get('repo_name_full')
             group_path = value.get('group_path')
@@ -380,17 +365,17 @@
                             error_dict=dict(repo_name=msg)
                         )
                 elif repo_group is not None:
-                        msg = self.message('same_group_exists', state,
-                                repo=repo_name)
-                        raise formencode.Invalid(msg, value, state,
-                            error_dict=dict(repo_name=msg)
-                        )
+                    msg = self.message('same_group_exists', state,
+                            repo=repo_name)
+                    raise formencode.Invalid(msg, value, state,
+                        error_dict=dict(repo_name=msg)
+                    )
                 elif repo is not None:
-                        msg = self.message('repository_exists', state,
-                                repo=repo.repo_name)
-                        raise formencode.Invalid(msg, value, state,
-                            error_dict=dict(repo_name=msg)
-                        )
+                    msg = self.message('repository_exists', state,
+                            repo=repo.repo_name)
+                    raise formencode.Invalid(msg, value, state,
+                        error_dict=dict(repo_name=msg)
+                    )
             return value
     return _validator
 
@@ -402,10 +387,10 @@
 def SlugifyName():
     class _validator(formencode.validators.FancyValidator):
 
-        def _to_python(self, value, state):
+        def _convert_to_python(self, value, state):
             return repo_name_slug(value)
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             pass
 
     return _validator
@@ -421,13 +406,13 @@
                                    'valid http, https, ssh, svn+http or svn+https URL'),
         }
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             repo_type = value.get('repo_type')
             url = value.get('clone_uri')
 
             if url and url != value.get('clone_uri_hidden'):
                 try:
-                    is_valid_repo_uri(repo_type, url, make_ui('db', clear_session=False))
+                    is_valid_repo_uri(repo_type, url, make_ui(clear_session=False))
                 except Exception:
                     log.exception('URL validation failed')
                     msg = self.message('clone_uri', state)
@@ -445,7 +430,7 @@
             'invalid_fork_type': _('Fork has to be the same type as parent')
         }
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             if old_data['repo_type'] != value:
                 msg = self.message('invalid_fork_type', state)
                 raise formencode.Invalid(msg, value, state,
@@ -463,13 +448,13 @@
                                         "in root location")
         }
 
-        def _to_python(self, value, state):
+        def _convert_to_python(self, value, state):
             # root location
             if value == -1:
                 return None
             return value
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             gr = RepoGroup.get(value)
             gr_name = gr.group_name if gr is not None else None # None means ROOT location
 
@@ -519,7 +504,7 @@
                 return None
             return value
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             gr = RepoGroup.get(value)
             gr_name = gr.group_name if gr is not None else None # None means ROOT location
 
@@ -598,11 +583,11 @@
             # update permissions
             for k, v, t in perms_new:
                 try:
-                    if t is 'user':
+                    if t == 'user':
                         self.user_db = User.query() \
                             .filter(User.active == True) \
                             .filter(User.username == k).one()
-                    if t is 'users_group':
+                    if t == 'users_group':
                         self.user_db = UserGroup.query() \
                             .filter(UserGroup.users_group_active == True) \
                             .filter(UserGroup.users_group_name == k).one()
@@ -619,13 +604,13 @@
 
 def ValidSettings():
     class _validator(formencode.validators.FancyValidator):
-        def _to_python(self, value, state):
+        def _convert_to_python(self, value, state):
             # settings  form for users that are not admin
             # can't edit certain parameters, it's extra backup if they mangle
             # with forms
 
             forbidden_params = [
-                'user', 'repo_type', 'repo_enable_locking',
+                'user', 'repo_type',
                 'repo_enable_downloads', 'repo_enable_statistics'
             ]
 
@@ -634,7 +619,7 @@
                     del value[param]
             return value
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             pass
     return _validator
 
@@ -645,7 +630,7 @@
             'invalid_path': _('This is not a valid path')
         }
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             if not os.path.isdir(value):
                 msg = self.message('invalid_path', state)
                 raise formencode.Invalid(msg, value, state,
@@ -662,10 +647,10 @@
             'email_taken': _('This email address is already in use')
         }
 
-        def _to_python(self, value, state):
+        def _convert_to_python(self, value, state):
             return value.lower()
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             if (old_data.get('email') or '').lower() != value:
                 user = User.get_by_email(value)
                 if user is not None:
@@ -682,10 +667,10 @@
             'non_existing_email': _('Email address "%(email)s" not found')
         }
 
-        def _to_python(self, value, state):
+        def _convert_to_python(self, value, state):
             return value.lower()
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             user = User.get_by_email(value)
             if user is None:
                 msg = self.message('non_existing_email', state, email=value)
@@ -702,7 +687,7 @@
 
         }
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             try:
                 import ldap
                 ldap  # pyflakes silence !
@@ -747,7 +732,7 @@
                     v += '/128'
             return v
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             try:
                 addr = value.strip()
                 # this raises an ValueError if address is not IPv4 or IPv6
@@ -766,7 +751,7 @@
                         'underscore, dash or numbers')
         )
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             if not re.match('[a-zA-Z0-9_-]+$', value):
                 raise formencode.Invalid(self.message('badFormat', state),
                                          value, state)
@@ -779,10 +764,10 @@
             badPath=_('Filename cannot be inside a directory')
         )
 
-        def _to_python(self, value, state):
+        def _convert_to_python(self, value, state):
             return value
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             if value != os.path.basename(value):
                 raise formencode.Invalid(self.message('badPath', state),
                                          value, state)
@@ -795,11 +780,11 @@
             import_duplicate=_('Plugins %(loaded)s and %(next_to_load)s both export the same name')
         )
 
-        def _to_python(self, value, state):
+        def _convert_to_python(self, value, state):
             # filter empty values
             return filter(lambda s: s not in [None, ''], value)
 
-        def validate_python(self, value, state):
+        def _validate_python(self, value, state):
             from kallithea.lib import auth_modules
             module_list = value
             unique_names = {}
--- a/kallithea/public/js/base.js	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/public/js/base.js	Sun Jan 05 04:07:51 2020 +0100
@@ -408,7 +408,7 @@
 };
 
 var ajaxPOST = function(url, postData, success, failure) {
-    postData['_authentication_token'] = _authentication_token;
+    postData['_session_csrf_secret_token'] = _session_csrf_secret_token;
     var postData = _toQueryString(postData);
     if(failure === undefined) {
         failure = function(jqXHR, textStatus, errorThrown) {
@@ -458,7 +458,7 @@
 
 var toggleFollowingRepo = function(target, follows_repository_id){
     var args = 'follows_repository_id=' + follows_repository_id;
-    args += '&amp;_authentication_token=' + _authentication_token;
+    args += '&amp;_session_csrf_secret_token=' + _session_csrf_secret_token;
     $.post(TOGGLE_FOLLOW_URL, args, function(data){
             _onSuccessFollow(target);
         });
@@ -466,7 +466,7 @@
 };
 
 var showRepoSize = function(target, repo_name){
-    var args = '_authentication_token=' + _authentication_token;
+    var args = '_session_csrf_secret_token=' + _session_csrf_secret_token;
 
     if(!$("#" + target).hasClass('loaded')){
         $("#" + target).html(_TM['Loading ...']);
--- a/kallithea/templates/about.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/about.html	Sun Jan 05 04:07:51 2020 +0100
@@ -71,6 +71,7 @@
   <li>Copyright &copy; 2016, timeless@gmail.com</li>
   <li>Copyright &copy; 2016, YFdyh000</li>
   <li>Copyright &copy; 2012&ndash;2013, 2015, Aras Pranckevičius</li>
+  <li>Copyright &copy; 2014&ndash;2015, Bradley M. Kuhn</li>
   <li>Copyright &copy; 2014&ndash;2015, Christian Oyarzun</li>
   <li>Copyright &copy; 2014&ndash;2015, Joseph Rivera</li>
   <li>Copyright &copy; 2014&ndash;2015, Sean Farley</li>
@@ -101,31 +102,47 @@
   <li>Copyright &copy; 2015, Tuux</li>
   <li>Copyright &copy; 2015, Viktar Palstsiuk</li>
   <li>Copyright &copy; 2014, Ante Ilic</li>
-  <li>Copyright &copy; 2014, Bradley M. Kuhn</li>
   <li>Copyright &copy; 2014, Calinou</li>
   <li>Copyright &copy; 2014, Daniel Anderson</li>
   <li>Copyright &copy; 2014, Henrik Stuart</li>
   <li>Copyright &copy; 2014, Ingo von Borstel</li>
+  <li>Copyright &copy; 2014, invision70</li>
   <li>Copyright &copy; 2014, Jelmer Vernooij</li>
   <li>Copyright &copy; 2014, Jim Hague</li>
   <li>Copyright &copy; 2014, Matt Fellows</li>
   <li>Copyright &copy; 2014, Max Roman</li>
   <li>Copyright &copy; 2014, Na'Tosha Bard</li>
   <li>Copyright &copy; 2014, Rasmus Selsmark</li>
+  <li>Copyright &copy; 2014, SkryabinD</li>
   <li>Copyright &copy; 2014, Tim Freund</li>
   <li>Copyright &copy; 2014, Travis Burtrum</li>
+  <li>Copyright &copy; 2014, whosaysni</li>
   <li>Copyright &copy; 2014, Zoltan Gyarmati</li>
   <li>Copyright &copy; 2010&ndash;2013, Marcin Kuźmiński</li>
   <li>Copyright &copy; 2010&ndash;2013, RhodeCode GmbH</li>
   <li>Copyright &copy; 2011, 2013, Aparkar</li>
+  <li>Copyright &copy; 2012&ndash;2013, Nemcio</li>
   <li>Copyright &copy; 2012&ndash;2013, xpol</li>
+  <li>Copyright &copy; 2013, Andrey Mivrenik</li>
+  <li>Copyright &copy; 2013, ArcheR</li>
   <li>Copyright &copy; 2013, Dennis Brakhane</li>
+  <li>Copyright &copy; 2013, gnustavo</li>
   <li>Copyright &copy; 2013, Grzegorz Rożniecki</li>
+  <li>Copyright &copy; 2013, Ilya Beda</li>
+  <li>Copyright &copy; 2013, ivlevdenis</li>
   <li>Copyright &copy; 2013, Jonathan Sternberg</li>
   <li>Copyright &copy; 2013, Leonardo Carneiro</li>
   <li>Copyright &copy; 2013, Magnus Ericmats</li>
   <li>Copyright &copy; 2013, Martin Vium</li>
+  <li>Copyright &copy; 2013, Mikhail Zholobov</li>
+  <li>Copyright &copy; 2013, mokeev1995</li>
+  <li>Copyright &copy; 2013, Ruslan Bekenev</li>
+  <li>Copyright &copy; 2013, shirou - しろう</li>
   <li>Copyright &copy; 2013, Simon Lopez</li>
+  <li>Copyright &copy; 2013, softforwinxp</li>
+  <li>Copyright &copy; 2013, stephanj</li>
+  <li>Copyright &copy; 2013, zhmylove</li>
+  <li>Copyright &copy; 2013, こいんとす</li>
   <li>Copyright &copy; 2011&ndash;2012, Augusto Herrmann</li>
   <li>Copyright &copy; 2012, Dan Sheridan</li>
   <li>Copyright &copy; 2012, H Waldo G</li>
--- a/kallithea/templates/admin/defaults/defaults.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/admin/defaults/defaults.html	Sun Jan 05 04:07:51 2020 +0100
@@ -55,14 +55,6 @@
             </div>
 
             <div class="form-group">
-                <label class="control-label" for="default_repo_enable_locking">${_('Enable locking')}:</label>
-                <div>
-                    ${h.checkbox('default_repo_enable_locking',value="True")}
-                    <span class="help-block">${_('Enable lock-by-pulling on repository.')}</span>
-                </div>
-            </div>
-
-            <div class="form-group">
                 <div class="buttons">
                     ${h.submit('save',_('Save'),class_="btn btn-default")}
                 </div>
--- a/kallithea/templates/admin/gists/edit.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/admin/gists/edit.html	Sun Jan 05 04:07:51 2020 +0100
@@ -153,7 +153,7 @@
                   // check for newer version.
                   $.ajax({
                     url: ${h.js(h.url('edit_gist_check_revision', gist_id=c.gist.gist_access_id))},
-                    data: {'revision': ${h.js(c.file_changeset.raw_id)}, '_authentication_token': _authentication_token},
+                    data: {'revision': ${h.js(c.file_changeset.raw_id)}, '_session_csrf_secret_token': _session_csrf_secret_token},
                     dataType: 'json',
                     type: 'POST',
                     success: function(data) {
--- a/kallithea/templates/admin/my_account/my_account.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/admin/my_account/my_account.html	Sun Jan 05 04:07:51 2020 +0100
@@ -25,6 +25,9 @@
             <li class="${'active' if c.active=='profile' else ''}"><a href="${h.url('my_account')}">${_('Profile')}</a></li>
             <li class="${'active' if c.active=='emails' else ''}"><a href="${h.url('my_account_emails')}">${_('Email Addresses')}</a></li>
             <li class="${'active' if c.active=='password' else ''}"><a href="${h.url('my_account_password')}">${_('Password')}</a></li>
+            %if c.ssh_enabled:
+              <li class="${'active' if c.active=='ssh_keys' else ''}"><a href="${h.url('my_account_ssh_keys')}">${_('SSH Keys')}</a></li>
+            %endif
             <li class="${'active' if c.active=='api_keys' else ''}"><a href="${h.url('my_account_api_keys')}">${_('API Keys')}</a></li>
             <li class="${'active' if c.active=='repos' else ''}"><a href="${h.url('my_account_repos')}">${_('Owned Repositories')}</a></li>
             <li class="${'active' if c.active=='watched' else ''}"><a href="${h.url('my_account_watched')}">${_('Watched Repositories')}</a></li>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/templates/admin/my_account/my_account_ssh_keys.html	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,71 @@
+<table class="table">
+    %if c.user_ssh_keys:
+        <tr>
+            <th>${_('Fingerprint')}</th>
+            <th>${_('Description')}</th>
+            <th>${_('Last Used')}</th>
+            <th>${_('Action')}</th>
+        </tr>
+        %for ssh_key in c.user_ssh_keys:
+          <tr>
+            <td>
+                ${ssh_key.fingerprint}
+            </td>
+            <td>
+                ${ssh_key.description}
+            </td>
+            <td>
+              %if ssh_key.last_seen:
+                ${h.fmt_date(ssh_key.last_seen)}
+              %else:
+                ${_('Never')}
+              %endif
+            </td>
+            <td>
+                ${h.form(url('my_account_ssh_keys_delete'))}
+                    ${h.hidden('del_public_key', ssh_key.public_key)}
+                    <button class="btn btn-danger btn-xs" type="submit"
+                            onclick="return confirm('${_('Confirm to remove this SSH key: %s') % ssh_key.fingerprint}');">
+                        <i class="icon-trashcan"></i>
+                        ${_('Remove')}
+                    </button>
+                ${h.end_form()}
+            </td>
+          </tr>
+        %endfor
+    %else:
+        <tr>
+            <td>
+                <div class="ip">${_('No SSH keys have been added')}</div>
+            </td>
+        </tr>
+    %endif
+</table>
+
+<div>
+    ${h.form(url('my_account_ssh_keys'))}
+    <div class="form">
+            <div class="form-group">
+                <label class="control-label">${_('New SSH key')}</label>
+            </div>
+            <div class="form-group">
+                <label class="control-label" for="public_key">${_('Public key')}:</label>
+                <div>
+                    ${h.textarea('public_key', '', class_='form-control', placeholder=_('Public key (contents of e.g. ~/.ssh/id_rsa.pub)'), cols=80, rows=5)}
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="control-label" for="description">${_('Description')}:</label>
+                <div>
+                    ${h.text('description', class_='form-control', placeholder=_('Description'))}
+                </div>
+            </div>
+            <div class="form-group">
+                <div class="buttons">
+                    ${h.submit('save', _('Add'), class_="btn btn-default")}
+                    ${h.reset('reset', _('Reset'), class_="btn btn-default")}
+                </div>
+            </div>
+    </div>
+    ${h.end_form()}
+</div>
--- a/kallithea/templates/admin/repo_groups/repo_group_edit_settings.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/admin/repo_groups/repo_group_edit_settings.html	Sun Jan 05 04:07:51 2020 +0100
@@ -23,14 +23,6 @@
         </div>
 
         <div class="form-group">
-            <label class="control-label" for="enable_locking">${_('Enable locking')}:</label>
-            <div>
-                ${h.checkbox('enable_locking',value="True")}
-                <span class="help-block">${_('Enable lock-by-pulling on group. This option will be applied to all other groups and repositories inside')}</span>
-            </div>
-        </div>
-
-        <div class="form-group">
             <div class="buttons">
                 ${h.submit('save',_('Save'),class_="btn btn-default")}
                 ${h.reset('reset',_('Reset'),class_="btn btn-default")}
--- a/kallithea/templates/admin/repos/repo_edit_advanced.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/admin/repos/repo_edit_advanced.html	Sun Jan 05 04:07:51 2020 +0100
@@ -39,32 +39,6 @@
 </div>
 ${h.end_form()}
 
-<h3>${_('Change Locking')}</h3>
-${h.form(url('edit_repo_advanced_locking', repo_name=c.repo_info.repo_name))}
-<div class="form">
-      %if c.repo_info.locked[0]:
-        ${h.hidden('set_unlock', '1')}
-        <button class="btn btn-default btn-sm" type="submit"
-                onclick="return confirm('${_('Confirm to unlock repository.')}');">
-            <i class="icon-lock-open-alt"></i>
-            ${_('Unlock Repository')}
-        </button>
-       ${_('Locked by %s on %s') % (h.person_by_id(c.repo_info.locked[0]),h.fmt_date(h.time_to_datetime(c.repo_info.locked[1])))}
-      %else:
-        ${h.hidden('set_lock', '1')}
-        <button class="btn btn-default btn-sm" type="submit"
-                onclick="return confirm('${_('Confirm to lock repository.')}');">
-            <i class="icon-lock"></i>
-            ${_('Lock Repository')}
-        </button>
-        ${_('Repository is not locked')}
-      %endif
-   <div class="text-muted">
-   ${_('Force locking on the repository. Works only when anonymous access is disabled. Triggering a pull locks the repository.  The user who is pulling locks the repository; only the user who pulled and locked it can unlock it by doing a push.')}
-   </div>
-</div>
-${h.end_form()}
-
 <h3>${_('Delete')}</h3>
 ${h.form(url('delete_repo', repo_name=c.repo_name))}
 <div class="form">
--- a/kallithea/templates/admin/repos/repo_edit_settings.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/admin/repos/repo_edit_settings.html	Sun Jan 05 04:07:51 2020 +0100
@@ -4,12 +4,17 @@
                 <label class="control-label" for="repo_name">${_('Name')}:</label>
                 <div>
                     ${h.text('repo_name',class_='form-control')}
-                    <span class="help-block">${_('Permanent Repository ID')}: `_${c.repo_info.repo_id}` <span><a id="show_more_clone_id" href="#">${_('What is that?')}</a></span></span>
-                    <span id="clone_id" class="help-block" style="display: none">
-                        ${_('URL by id')}: `${c.repo_info.clone_url(with_id=True)}`<br/>
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="control-label" for="permanent_url">${_('Permanent URL')}:</label>
+                <div>
+                    ${h.text('permanent_url',class_='form-control', readonly='1')}
+                    <span class="help-block">
                         ${_('''In case this repository is renamed or moved into another group the repository URL changes.
                                Using the above permanent URL guarantees that this repository always will be accessible on that URL.
-                               This is useful for CI systems, or any other cases that you need to hardcode the URL into a 3rd party service.''')}</span>
+                               This is useful for CI systems, or any other cases that you need to hardcode the URL into a 3rd party service.''')}
+                    </span>
                 </div>
             </div>
             <div class="form-group">
@@ -74,13 +79,6 @@
                     <span class="help-block">${_('Enable download menu on summary page.')}</span>
                 </div>
             </div>
-            <div class="form-group">
-                <label class="control-label" for="repo_enable_locking">${_('Enable locking')}:</label>
-                <div>
-                    ${h.checkbox('repo_enable_locking',value="True")}
-                    <span class="help-block">${_('Enable lock-by-pulling on repository.')}</span>
-                </div>
-            </div>
 
             %if c.visual.repository_fields:
               ## EXTRA FIELDS
@@ -107,11 +105,6 @@
 
 <script>
     $(document).ready(function(){
-        $('#show_more_clone_id').on('click', function(e){
-            $('#clone_id').show();
-            e.preventDefault();
-        });
-
         $('#repo_landing_rev').select2({
             'dropdownAutoWidth': true
         });
--- a/kallithea/templates/admin/settings/settings_system.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/admin/settings/settings_system.html	Sun Jan 05 04:07:51 2020 +0100
@@ -4,13 +4,12 @@
 
 <%
  elems = [
-    (_('Kallithea version'), h.literal('%s <b><span id="check_for_update" style="display:none">%s</span></b>') % (c.kallithea_version, _('Check for updates')), ''),
+    (_('Kallithea version'), c.kallithea_version, ''),
     (_('Kallithea configuration file'), c.ini['__file__'], ''),
     (_('Python version'), c.py_version, ''),
     (_('Platform'), c.platform, ''),
     (_('Git version'), c.git_version, ''),
     (_('Git path'), c.ini.get('git_path'), ''),
-    (_('Upgrade info endpoint'), h.literal('%s <br/><span class="text-muted">%s.</span>') % (c.update_url, _('Note: please make sure this server can access this URL')), ''),
  ]
 %>
 <dl class="dl-horizontal">
@@ -31,11 +30,3 @@
       %endfor
   </tbody>
 </table>
-
-<script>
-    $('#check_for_update').click(function(e){
-        var $update_notice = $('#update_notice');
-        $update_notice.show();
-        asynchtml(${h.js(h.url('admin_settings_system_update'))}, $update_notice);
-    });
-</script>
--- a/kallithea/templates/admin/settings/settings_vcs.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/admin/settings/settings_vcs.html	Sun Jan 05 04:07:51 2020 +0100
@@ -11,18 +11,6 @@
                     </div>
                     <div class="checkbox">
                         <label>
-                            ${h.checkbox('hooks_changegroup_push_logger','True')}
-                            ${_('Log user push commands')}
-                        </label>
-                    </div>
-                    <div class="checkbox">
-                        <label>
-                            ${h.checkbox('hooks_outgoing_pull_logger','True')}
-                            ${_('Log user pull commands')}
-                        </label>
-                    </div>
-                    <div class="checkbox">
-                        <label>
                             ${h.checkbox('hooks_changegroup_update','True')}
                             ${_('Update repository after push (hg update)')}
                         </label>
--- a/kallithea/templates/admin/settings/settings_visual.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/admin/settings/settings_visual.html	Sun Jan 05 04:07:51 2020 +0100
@@ -37,7 +37,7 @@
             </div>
 
             <div class="form-group">
-                <label class="control-label">${_('Clone URL')}:</label>
+                <label class="control-label">${_('HTTP Clone URL')}:</label>
                 <div>
                     ${h.text('clone_uri_tmpl', size=80, class_='form-control')}
                     <span class="help-block">${_('''Schema of clone URL construction eg. '{scheme}://{user}@{netloc}/{repo}'.
@@ -46,8 +46,19 @@
                                                     {user}   current user username,
                                                     {netloc} network location/server host of running Kallithea server,
                                                     {repo}   full repository name,
-                                                    {repoid} ID of repository, can be used to construct clone-by-id''')}</span>
+                                                    {repoid} ID of repository, can be used to construct clone-by-id,
+                                                    {system_user}  name of the Kallithea system user,
+                                                    {hostname}  server hostname
+                                                    ''')}
+                    </span>
                 </div>
+                %if c.ssh_enabled:
+                <label class="control-label">${_('SSH Clone URL')}:</label>
+                <div>
+                    ${h.text('clone_ssh_tmpl', size=80, class_='form-control')}
+                    <span class="help-block">${_('''Schema for constructing SSH clone URL, eg. 'ssh://{system_user}@{hostname}/{repo}'.''')}</span>
+                </div>
+                %endif
             </div>
 
             <div class="form-group">
--- a/kallithea/templates/admin/users/user_edit.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/admin/users/user_edit.html	Sun Jan 05 04:07:51 2020 +0100
@@ -28,6 +28,9 @@
       <ul class="nav nav-pills nav-stacked">
         <li class="${'active' if c.active=='profile' else ''}"><a href="${h.url('edit_user', id=c.user.user_id)}">${_('Profile')}</a></li>
         <li class="${'active' if c.active=='emails' else ''}"><a href="${h.url('edit_user_emails', id=c.user.user_id)}">${_('Emails')}</a></li>
+        %if c.ssh_enabled:
+          <li class="${'active' if c.active=='ssh_keys' else ''}"><a href="${h.url('edit_user_ssh_keys', id=c.user.user_id)}">${_('SSH Keys')}</a></li>
+        %endif
         <li class="${'active' if c.active=='api_keys' else ''}"><a href="${h.url('edit_user_api_keys', id=c.user.user_id)}">${_('API Keys')}</a></li>
         <li class="${'active' if c.active=='ips' else ''}"><a href="${h.url('edit_user_ips', id=c.user.user_id)}">${_('IP Whitelist')}</a></li>
         <li class="${'active' if c.active=='advanced' else ''}"><a href="${h.url('edit_user_advanced', id=c.user.user_id)}">${_('Advanced')}</a></li>
--- a/kallithea/templates/admin/users/user_edit_ips.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/admin/users/user_edit_ips.html	Sun Jan 05 04:07:51 2020 +0100
@@ -1,5 +1,5 @@
 <table class="table">
-    %if c.default_user_ip_map and c.inherit_default_ips:
+    %if c.default_user_ip_map:
         %for ip in c.default_user_ip_map:
           <tr>
             <td><div class="ip">${ip.ip_addr}</div></td>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/templates/admin/users/user_edit_ssh_keys.html	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,71 @@
+<table class="table">
+    %if c.user_ssh_keys:
+        <tr>
+            <th>${_('Fingerprint')}</th>
+            <th>${_('Description')}</th>
+            <th>${_('Last Used')}</th>
+            <th>${_('Action')}</th>
+        </tr>
+        %for ssh_key in c.user_ssh_keys:
+          <tr>
+            <td>
+                ${ssh_key.fingerprint}
+            </td>
+            <td>
+                ${ssh_key.description}
+            </td>
+            <td>
+              %if ssh_key.last_seen:
+                ${h.fmt_date(ssh_key.last_seen)}
+              %else:
+                ${_('Never')}
+              %endif
+            </td>
+            <td>
+                ${h.form(url('edit_user_ssh_keys_delete', id=c.user.user_id))}
+                    ${h.hidden('del_public_key', ssh_key.public_key)}
+                    <button class="btn btn-danger btn-xs" type="submit"
+                            onclick="return confirm('${_('Confirm to remove this SSH key: %s') % ssh_key.fingerprint}');">
+                        <i class="icon-trashcan"></i>
+                        ${_('Remove')}
+                    </button>
+                ${h.end_form()}
+            </td>
+          </tr>
+        %endfor
+    %else:
+        <tr>
+            <td>
+                <div class="ip">${_('No SSH keys have been added')}</div>
+            </td>
+        </tr>
+    %endif
+</table>
+
+<div>
+    ${h.form(url('edit_user_ssh_keys', id=c.user.user_id))}
+    <div class="form">
+            <div class="form-group">
+                <label class="control-label">${_('New SSH key')}</label>
+            </div>
+            <div class="form-group">
+                <label class="control-label" for="public_key">${_('Public key')}:</label>
+                <div>
+                    ${h.textarea('public_key', '', class_='form-control', placeholder=_('Public key (contents of e.g. ~/.ssh/id_rsa.pub)'), cols=80, rows=5)}
+                </div>
+            </div>
+            <div class="form-group">
+                <label class="control-label" for="description">${_('Description')}:</label>
+                <div>
+                    ${h.text('description', class_='form-control', placeholder=_('Description'))}
+                </div>
+            </div>
+            <div class="form-group">
+                <div class="buttons">
+                    ${h.submit('save', _('Add'), class_="btn btn-default")}
+                    ${h.reset('reset', _('Reset'), class_="btn btn-default")}
+                </div>
+            </div>
+    </div>
+    ${h.end_form()}
+</div>
--- a/kallithea/templates/base/base.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/base/base.html	Sun Jan 05 04:07:51 2020 +0100
@@ -159,13 +159,6 @@
 
               <li><a href="${h.url('search_repo',repo_name=c.repo_name)}"><i class="icon-search"></i>${_('Search')}</a></li>
 
-              %if h.HasRepoPermissionLevel('write')(c.repo_name) and c.db_repo.enable_locking:
-                %if c.db_repo.locked[0]:
-                  <li><a href="${h.url('toggle_locking', repo_name=c.repo_name)}"><i class="icon-lock"></i>${_('Unlock')}</a></li>
-                %else:
-                  <li><a href="${h.url('toggle_locking', repo_name=c.repo_name)}"><i class="icon-lock-open-alt"></i>${_('Lock')}</a></li>
-                %endif
-              %endif
               ## TODO: this check feels wrong, it would be better to have a check for permissions
               ## also it feels like a job for the controller
               %if request.authuser.username != 'default':
--- a/kallithea/templates/base/default_perms_box.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/base/default_perms_box.html	Sun Jan 05 04:07:51 2020 +0100
@@ -8,18 +8,6 @@
 ${h.form(form_url)}
     <div class="form">
             <div class="form-group">
-                <label class="control-label" for="inherit_default_permissions">${_('Inherit defaults')}:</label>
-                <div>
-                    ${h.checkbox('inherit_default_permissions',value=True)}
-                    <span class="help-block">
-                        ${(h.HTML(_('Select to inherit global settings, IP whitelist and permissions from the %s.'))
-                                % h.link_to(_('default permissions'), url('admin_permissions')))}
-                    </span>
-                </div>
-            </div>
-
-            <div id="inherit_overlay">
-            <div class="form-group">
                 <label class="control-label" for="create_repo_perm">${_('Create repositories')}:</label>
                 <div>
                     ${h.checkbox('create_repo_perm',value=True)}
@@ -49,8 +37,6 @@
                 </div>
             </div>
 
-            </div>
-
             <div class="form-group">
                 <div class="buttons">
                     ${h.submit('save',_('Save'),class_="btn btn-default")}
@@ -59,23 +45,4 @@
             </div>
     </div>
 ${h.end_form()}
-
-## JS
-<script>
-$(document).ready(function(e){
-    var show_custom_perms = function(inherit_default){
-        if(inherit_default){
-            $('#inherit_overlay').hide();
-        }else{
-            $('#inherit_overlay').show();
-        }
-    };
-
-    show_custom_perms($('#inherit_default_permissions').prop('checked'));
-    $('#inherit_default_permissions').change(function(){
-        show_custom_perms($('#inherit_default_permissions').prop('checked'));
-    });
-});
-</script>
-
 </%def>
--- a/kallithea/templates/base/flash_msg.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/base/flash_msg.html	Sun Jan 05 04:07:51 2020 +0100
@@ -1,5 +1,5 @@
 <div class="flash_msg">
-    <% messages = h.flash.pop_messages() %>
+    <% messages = h.pop_flash_messages() %>
     % if messages:
         <% alert_categories = {'warning': 'alert-warning', 'notice': 'alert-info', 'error': 'alert-danger', 'success': 'alert-success'} %>
         % for message in messages:
--- a/kallithea/templates/base/root.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/base/root.html	Sun Jan 05 04:07:51 2020 +0100
@@ -65,7 +65,7 @@
                 var REPO_NAME = ${h.js(c.repo_name)};
             %endif
 
-            var _authentication_token = ${h.js(h.authentication_token())};
+            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>
--- a/kallithea/templates/files/files.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/files/files.html	Sun Jan 05 04:07:51 2020 +0100
@@ -40,6 +40,7 @@
 var CACHE = {};
 var CACHE_EXPIRE = 5*60*1000; //cache for 5*60s
 //used to construct links from the search list
+var _repo_files_url = ${h.jshtml(h.url("files_home",repo_name=c.repo_name,revision='',f_path='').replace('//', '/'))};
 var url_base = ${h.js(h.url("files_home",repo_name=c.repo_name,revision='__REV__',f_path='__FPATH__'))};
 //send the nodelist request to this url
 var node_list_url = ${h.js(h.url("files_nodelist_home",repo_name=c.repo_name,revision='__REV__',f_path='__FPATH__'))};
@@ -57,15 +58,11 @@
             return true;
         }
 
-        var el = e.currentTarget;
-        var url = el.href;
-
-        var _base_url = ${h.jshtml(h.url("files_home",repo_name=c.repo_name,revision='',f_path=''))};
-        _base_url = _base_url.replace('//','/');
+        var url = e.currentTarget.href;
 
         //extract rev and the f_path from url.
-        parts = url.split(_base_url);
-        if(parts.length != 2){
+        var parts = url.split(_repo_files_url);
+        if (parts.length != 2) {
             return false;
         }
 
--- a/kallithea/templates/pullrequests/pullrequest_show.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/pullrequests/pullrequest_show.html	Sun Jan 05 04:07:51 2020 +0100
@@ -106,9 +106,9 @@
               <div>
                ## TODO: use cs_ranges[-1] or org_ref_parts[1] in both cases?
                %if h.is_hg(c.pull_request.org_repo):
-                 <span>hg pull ${c.pull_request.org_repo.clone_url()} -r ${h.short_id(c.cs_ranges[-1].raw_id)}</span>
+                 <span>hg pull ${c.pull_request.org_repo.clone_url(clone_uri_tmpl=c.clone_uri_tmpl)} -r ${h.short_id(c.cs_ranges[-1].raw_id)}</span>
                %elif h.is_git(c.pull_request.org_repo):
-                 <span>git pull ${c.pull_request.org_repo.clone_url()} ${c.pull_request.org_ref_parts[1]}</span>
+                 <span>git pull ${c.pull_request.org_repo.clone_url(clone_uri_tmpl=c.clone_uri_tmpl)} ${c.pull_request.org_ref_parts[1]}</span>
                %endif
               </div>
             %endif
@@ -167,7 +167,7 @@
                               </span>
                             %endfor
                           </div>
-                          <div class="message">${h.urlify_text(cs.message, c.repo_name)}</div>
+                          <div class="message">${h.urlify_text(cs.message.splitlines()[0], c.repo_name)}</div>
                         </td>
                       %endif
                     </tr>
--- a/kallithea/templates/summary/summary.html	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/templates/summary/summary.html	Sun Jan 05 04:07:51 2020 +0100
@@ -8,15 +8,6 @@
 <%def name="breadcrumbs_links()">
     ${_('Summary')}
 
-    ## locking icon
-    %if c.db_repo.enable_locking:
-     %if c.db_repo.locked[0]:
-       <span class="locking_locked icon-block" data-toggle="tooltip" title="${_('Repository locked by %s') % h.person_by_id(c.db_repo.locked[0])}"></span>
-     %else:
-       <span class="locking_unlocked icon-ok" data-toggle="tooltip" title="${_('Repository unlocked')}"></span>
-     %endif
-    %endif
-
     ##FORK
     %if c.db_repo.fork:
         - <i class="icon-fork"></i>${_('Fork of')} "<a href="${h.url('summary_home',repo_name=c.db_repo.fork.repo_name)}">${c.db_repo.fork.repo_name}</a>"
@@ -62,16 +53,33 @@
             <div class="form-group form-inline">
                 <label>${_('Clone URL')}:</label>
                 <div id="clone-url">
-                  <div id="clone_by_name" class="input-group">
+                  <div id="clone_by_name" class="input-group"
+                    %if c.ssh_repo_url:
+                        style="display:none"
+                    %endif
+                    >
                     <span class="input-group-addon">${self.repolabel(c.db_repo)}</span>
                     <input class="form-control" size="80" readonly="readonly" value="${c.clone_repo_url}"/>
-                    <span class="input-group-addon btn">${_('Show by ID')}</span>
+                    <span class="input-group-addon btn use-id">${_('Use ID')}</span>
+                    %if c.ssh_repo_url:
+                    <span class="input-group-addon btn use-ssh">${_('Use SSH')}</span>
+                    %endif
                   </div>
                   <div id="clone_by_id" class="input-group" style="display:none">
                     <span class="input-group-addon">${self.repolabel(c.db_repo)}</span>
                     <input class="form-control" size="80" readonly="readonly" value="${c.clone_repo_url_id}"/>
-                    <span class="input-group-addon btn">${_('Show by Name')}</span>
+                    <span class="input-group-addon btn use-name">${_('Use Name')}</span>
+                    %if c.ssh_repo_url:
+                    <span class="input-group-addon btn use-ssh">${_('Use SSH')}</span>
+                    %endif
                   </div>
+                  %if c.ssh_repo_url:
+                  <div id="clone_ssh" class="input-group">
+                    <span class="input-group-addon">${self.repolabel(c.db_repo)}</span>
+                    <input id="ssh_url" class="form-control" size="80" readonly="readonly" value="${c.ssh_repo_url}"/>
+                    <span class="input-group-addon btn use-name">${_('Use HTTP')}</span>
+                  </div>
+                  %endif
                 </div>
             </div>
 
@@ -96,7 +104,7 @@
 
             <div class="form-group">
               <label>${_('Download')}:</label>
-              <div>
+              <div class="form-inline">
                 %if len(c.db_repo_scm_instance.revisions) == 0:
                   ${_('There are no downloads yet')}
                 %elif not c.enable_downloads:
@@ -108,7 +116,7 @@
                     <span id="${'zip_link'}">
                         <a class="btn btn-default btn-sm" href="${h.url('files_archive_home',repo_name=c.db_repo.repo_name,fname='tip.zip')}"><i class="icon-file-zip"></i>${_('Download as zip')}</a>
                     </span>
-                    ${h.hidden('download_options')}
+                    ${h.hidden('download_options', class_='form-control')}
                     <span>
                       <label data-toggle="tooltip" title="${_('Check this to download archive with subrepos')}">
                           <input id="archive_subrepos" type="checkbox" name="subrepos" />
@@ -242,15 +250,24 @@
         }
     });
 
+    var $clone_url = $('#clone-url');
     var $clone_by_name = $('#clone_by_name');
     var $clone_by_id = $('#clone_by_id');
-    $clone_by_name.find('.btn').click(function(e){
-        $clone_by_name.hide();
-        $clone_by_id.show();
+    var $clone_ssh = $('#clone_ssh');
+    $clone_url.on('click', '.btn.use-name', function(e){
+        $clone_by_name.show();
+        $clone_by_id.hide();
+        $clone_ssh.hide();
     });
-    $clone_by_id.find('.btn').click(function(e){
+    $clone_url.on('click', '.btn.use-id', function(e){
+        $clone_by_id.show();
+        $clone_by_name.hide();
+        $clone_ssh.hide();
+    });
+    $clone_url.on('click', '.btn.use-ssh', function(e){
         $clone_by_id.hide();
-        $clone_by_name.show();
+        $clone_by_name.hide();
+        $clone_ssh.show();
     });
 
     var cache = {}
--- a/kallithea/tests/__init__.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/__init__.py	Sun Jan 05 04:07:51 2020 +0100
@@ -20,6 +20,7 @@
 
 import pytest
 
+
 if getattr(pytest, 'register_assert_rewrite', None):
     # make sure that all asserts under kallithea/tests benefit from advanced
     # assert reporting with pytest-3.0.0+, including api/api_base.py,
--- a/kallithea/tests/api/api_base.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/api/api_base.py	Sun Jan 05 04:07:51 2020 +0100
@@ -18,25 +18,24 @@
 
 import os
 import random
-import mock
 import re
 
+import mock
 import pytest
 
+from kallithea.lib.auth import AuthUser
+from kallithea.lib.compat import json
+from kallithea.model.changeset_status import ChangesetStatusModel
+from kallithea.model.db import ChangesetStatus, PullRequest, RepoGroup, Repository, Setting, Ui, User
+from kallithea.model.gist import GistModel
+from kallithea.model.meta import Session
+from kallithea.model.repo import RepoModel
+from kallithea.model.repo_group import RepoGroupModel
+from kallithea.model.scm import ScmModel
+from kallithea.model.user import UserModel
+from kallithea.model.user_group import UserGroupModel
 from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
-from kallithea.lib.compat import json
-from kallithea.lib.auth import AuthUser
-from kallithea.model.user import UserModel
-from kallithea.model.user_group import UserGroupModel
-from kallithea.model.repo import RepoModel
-from kallithea.model.repo_group import RepoGroupModel
-from kallithea.model.meta import Session
-from kallithea.model.scm import ScmModel
-from kallithea.model.gist import GistModel
-from kallithea.model.changeset_status import ChangesetStatusModel
-from kallithea.model.db import Repository, User, Setting, Ui, PullRequest, ChangesetStatus, RepoGroup
-from kallithea.lib.utils2 import time_to_datetime
 
 
 API_URL = '/_admin/api'
@@ -107,6 +106,7 @@
         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):
@@ -288,6 +288,8 @@
         r.clone_uri = os.path.join(Ui.get_by_key('paths', '/').ui_value, self.REPO)
         Session().commit()
 
+        pre_cached_tip = [repo.get_api_data()['last_changeset']['short_id'] for repo in Repository.query().filter(Repository.repo_name == repo_name)]
+
         id_, params = _build_data(self.apikey, 'pull',
                                   repoid=repo_name,)
         response = api_call(self, params)
@@ -296,8 +298,12 @@
                     'repository': repo_name}
         self._compare_ok(id_, expected, given=response.body)
 
+        post_cached_tip = [repo.get_api_data()['last_changeset']['short_id'] for repo in Repository.query().filter(Repository.repo_name == repo_name)]
+
         fixture.destroy_repo(repo_name)
 
+        assert pre_cached_tip != post_cached_tip
+
     def test_api_pull_fork(self):
         fork_name = u'fork'
         fixture.create_fork(self.REPO, fork_name)
@@ -386,205 +392,6 @@
         expected = "repository `%s` does not exist" % (self.REPO,)
         self._compare_error(id_, expected, given=response.body)
 
-    def test_api_lock_repo_lock_acquire(self):
-        try:
-            id_, params = _build_data(self.apikey, 'lock',
-                                      userid=TEST_USER_ADMIN_LOGIN,
-                                      repoid=self.REPO,
-                                      locked=True)
-            response = api_call(self, params)
-            expected = {
-                'repo': self.REPO, 'locked': True,
-                'locked_since': response.json['result']['locked_since'],
-                'locked_by': TEST_USER_ADMIN_LOGIN,
-                'lock_state_changed': True,
-                'msg': ('User `%s` set lock state for repo `%s` to `%s`'
-                        % (TEST_USER_ADMIN_LOGIN, self.REPO, True))
-            }
-            self._compare_ok(id_, expected, given=response.body)
-        finally:
-            # cleanup
-            Repository.unlock(RepoModel().get_by_repo_name(self.REPO))
-
-    def test_api_lock_repo_lock_acquire_by_non_admin(self):
-        repo_name = u'api_delete_me'
-        fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
-                            cur_user=self.TEST_USER_LOGIN)
-        try:
-            id_, params = _build_data(self.apikey_regular, 'lock',
-                                      repoid=repo_name,
-                                      locked=True)
-            response = api_call(self, params)
-            expected = {
-                'repo': repo_name,
-                'locked': True,
-                'locked_since': response.json['result']['locked_since'],
-                'locked_by': self.TEST_USER_LOGIN,
-                'lock_state_changed': True,
-                'msg': ('User `%s` set lock state for repo `%s` to `%s`'
-                        % (self.TEST_USER_LOGIN, repo_name, True))
-            }
-            self._compare_ok(id_, expected, given=response.body)
-        finally:
-            fixture.destroy_repo(repo_name)
-
-    def test_api_lock_repo_lock_acquire_non_admin_with_userid(self):
-        repo_name = u'api_delete_me'
-        fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
-                            cur_user=self.TEST_USER_LOGIN)
-        try:
-            id_, params = _build_data(self.apikey_regular, 'lock',
-                                      userid=TEST_USER_ADMIN_LOGIN,
-                                      repoid=repo_name,
-                                      locked=True)
-            response = api_call(self, params)
-            expected = 'userid is not the same as your user'
-            self._compare_error(id_, expected, given=response.body)
-        finally:
-            fixture.destroy_repo(repo_name)
-
-    def test_api_lock_repo_lock_acquire_non_admin_not_his_repo(self):
-        id_, params = _build_data(self.apikey_regular, 'lock',
-                                  repoid=self.REPO,
-                                  locked=True)
-        response = api_call(self, params)
-        expected = 'repository `%s` does not exist' % (self.REPO)
-        self._compare_error(id_, expected, given=response.body)
-
-    def test_api_lock_repo_lock_release(self):
-        id_, params = _build_data(self.apikey, 'lock',
-                                  userid=TEST_USER_ADMIN_LOGIN,
-                                  repoid=self.REPO,
-                                  locked=False)
-        response = api_call(self, params)
-        expected = {
-            'repo': self.REPO,
-            'locked': False,
-            'locked_since': None,
-            'locked_by': TEST_USER_ADMIN_LOGIN,
-            'lock_state_changed': True,
-            'msg': ('User `%s` set lock state for repo `%s` to `%s`'
-                    % (TEST_USER_ADMIN_LOGIN, self.REPO, False))
-        }
-        self._compare_ok(id_, expected, given=response.body)
-
-        # test_api_lock_repo_lock_optional_not_locked(self):
-        id_, params = _build_data(self.apikey, 'lock',
-                                  repoid=self.REPO)
-        response = api_call(self, params)
-        expected = {
-            'repo': self.REPO,
-            'locked': False,
-            'locked_since': None,
-            'locked_by': None,
-            'lock_state_changed': False,
-            'msg': ('Repo `%s` not locked.' % (self.REPO,))
-        }
-        self._compare_ok(id_, expected, given=response.body)
-
-    def test_api_lock_repo_lock_acquire_optional_userid(self):
-        try:
-            id_, params = _build_data(self.apikey, 'lock',
-                                      repoid=self.REPO,
-                                      locked=True)
-            response = api_call(self, params)
-            time_ = response.json['result']['locked_since']
-            expected = {
-                'repo': self.REPO,
-                'locked': True,
-                'locked_since': time_,
-                'locked_by': TEST_USER_ADMIN_LOGIN,
-                'lock_state_changed': True,
-                'msg': ('User `%s` set lock state for repo `%s` to `%s`'
-                        % (TEST_USER_ADMIN_LOGIN, self.REPO, True))
-            }
-
-            self._compare_ok(id_, expected, given=response.body)
-
-            # test_api_lock_repo_lock_optional_locked
-            id_, params = _build_data(self.apikey, 'lock',
-                                      repoid=self.REPO)
-            response = api_call(self, params)
-            time_ = response.json['result']['locked_since']
-            expected = {
-                'repo': self.REPO,
-                'locked': True,
-                'locked_since': time_,
-                'locked_by': TEST_USER_ADMIN_LOGIN,
-                'lock_state_changed': False,
-                'msg': ('Repo `%s` locked by `%s` on `%s`.'
-                        % (self.REPO, TEST_USER_ADMIN_LOGIN,
-                           json.dumps(time_to_datetime(time_))))
-            }
-            self._compare_ok(id_, expected, given=response.body)
-        finally:
-            # cleanup
-            Repository.unlock(RepoModel().get_by_repo_name(self.REPO))
-
-    @mock.patch.object(Repository, 'lock', crash)
-    def test_api_lock_error(self):
-        id_, params = _build_data(self.apikey, 'lock',
-                                  userid=TEST_USER_ADMIN_LOGIN,
-                                  repoid=self.REPO,
-                                  locked=True)
-        response = api_call(self, params)
-
-        expected = 'Error occurred locking repository `%s`' % self.REPO
-        self._compare_error(id_, expected, given=response.body)
-
-    def test_api_get_locks_regular_user(self):
-        id_, params = _build_data(self.apikey_regular, 'get_locks')
-        response = api_call(self, params)
-        expected = []
-        self._compare_ok(id_, expected, given=response.body)
-
-    def test_api_get_locks_with_userid_regular_user(self):
-        id_, params = _build_data(self.apikey_regular, 'get_locks',
-                                  userid=TEST_USER_ADMIN_LOGIN)
-        response = api_call(self, params)
-        expected = 'userid is not the same as your user'
-        self._compare_error(id_, expected, given=response.body)
-
-    def test_api_get_locks(self):
-        id_, params = _build_data(self.apikey, 'get_locks')
-        response = api_call(self, params)
-        expected = []
-        self._compare_ok(id_, expected, given=response.body)
-
-    def test_api_get_locks_with_one_locked_repo(self):
-        repo_name = u'api_delete_me'
-        repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
-                                   cur_user=self.TEST_USER_LOGIN)
-        Repository.lock(repo, User.get_by_username(self.TEST_USER_LOGIN).user_id)
-        try:
-            id_, params = _build_data(self.apikey, 'get_locks')
-            response = api_call(self, params)
-            expected = [repo.get_api_data()]
-            self._compare_ok(id_, expected, given=response.body)
-        finally:
-            fixture.destroy_repo(repo_name)
-
-    def test_api_get_locks_with_one_locked_repo_for_specific_user(self):
-        repo_name = u'api_delete_me'
-        repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
-                                   cur_user=self.TEST_USER_LOGIN)
-        Repository.lock(repo, User.get_by_username(self.TEST_USER_LOGIN).user_id)
-        try:
-            id_, params = _build_data(self.apikey, 'get_locks',
-                                      userid=self.TEST_USER_LOGIN)
-            response = api_call(self, params)
-            expected = [repo.get_api_data()]
-            self._compare_ok(id_, expected, given=response.body)
-        finally:
-            fixture.destroy_repo(repo_name)
-
-    def test_api_get_locks_with_userid(self):
-        id_, params = _build_data(self.apikey, 'get_locks',
-                                  userid=TEST_USER_REGULAR_LOGIN)
-        response = api_call(self, params)
-        expected = []
-        self._compare_ok(id_, expected, given=response.body)
-
     def test_api_create_existing_user(self):
         id_, params = _build_data(self.apikey, 'create_user',
                                   username=TEST_USER_ADMIN_LOGIN,
@@ -899,15 +706,23 @@
 
     def test_api_get_repo_by_non_admin_no_permission_to_repo(self):
         RepoModel().grant_user_permission(repo=self.REPO,
-                                          user=self.TEST_USER_LOGIN,
+                                          user=self.default_user_username,
                                           perm='repository.none')
+        try:
+            RepoModel().grant_user_permission(repo=self.REPO,
+                                              user=self.TEST_USER_LOGIN,
+                                              perm='repository.none')
 
-        id_, params = _build_data(self.apikey_regular, 'get_repo',
-                                  repoid=self.REPO)
-        response = api_call(self, params)
+            id_, params = _build_data(self.apikey_regular, 'get_repo',
+                                      repoid=self.REPO)
+            response = api_call(self, params)
 
-        expected = 'repository `%s` does not exist' % (self.REPO)
-        self._compare_error(id_, expected, given=response.body)
+            expected = 'repository `%s` does not exist' % (self.REPO)
+            self._compare_error(id_, expected, given=response.body)
+        finally:
+            RepoModel().grant_user_permission(repo=self.REPO,
+                                              user=self.default_user_username,
+                                              perm='repository.read')
 
     def test_api_get_repo_that_doesn_not_exist(self):
         id_, params = _build_data(self.apikey, 'get_repo',
@@ -1259,7 +1074,6 @@
         ('clone_uri', {'clone_uri': None}),
         ('landing_rev', {'landing_rev': 'branch:master'}),
         ('enable_statistics', {'enable_statistics': True}),
-        ('enable_locking', {'enable_locking': True}),
         ('enable_downloads', {'enable_downloads': True}),
         ('name', {'name': u'new_repo_name'}),
         ('repo_group', {'group': u'test_group_for_update'}),
@@ -1300,7 +1114,6 @@
         ('clone_uri', {'clone_uri': None}),
         ('landing_rev', {'landing_rev': 'branch:master'}),
         ('enable_statistics', {'enable_statistics': True}),
-        ('enable_locking', {'enable_locking': True}),
         ('enable_downloads', {'enable_downloads': True}),
         ('name', {'name': u'new_repo_name'}),
         ('repo_group', {'group': u'test_group_for_update'}),
@@ -1550,17 +1363,22 @@
 
     def test_api_fork_repo_non_admin_no_permission_to_fork(self):
         RepoModel().grant_user_permission(repo=self.REPO,
-                                          user=self.TEST_USER_LOGIN,
+                                          user=self.default_user_username,
                                           perm='repository.none')
-        fork_name = u'api-repo-fork'
-        id_, params = _build_data(self.apikey_regular, 'fork_repo',
-                                  repoid=self.REPO,
-                                  fork_name=fork_name,
-        )
-        response = api_call(self, params)
-        expected = 'repository `%s` does not exist' % (self.REPO)
-        self._compare_error(id_, expected, given=response.body)
-        fixture.destroy_repo(fork_name)
+        try:
+            fork_name = u'api-repo-fork'
+            id_, params = _build_data(self.apikey_regular, 'fork_repo',
+                                      repoid=self.REPO,
+                                      fork_name=fork_name,
+            )
+            response = api_call(self, params)
+            expected = 'repository `%s` does not exist' % (self.REPO)
+            self._compare_error(id_, expected, given=response.body)
+        finally:
+            RepoModel().grant_user_permission(repo=self.REPO,
+                                              user=self.default_user_username,
+                                              perm='repository.read')
+            fixture.destroy_repo(fork_name)
 
     @parametrize('name,perm', [
         ('read', 'repository.read'),
--- a/kallithea/tests/api/test_api_git.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/api/test_api_git.py	Sun Jan 05 04:07:51 2020 +0100
@@ -12,8 +12,8 @@
 # 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 kallithea.tests.base import TestController, GIT_REPO, GIT_TEST_REVISION
 from kallithea.tests.api.api_base import _BaseTestApi
+from kallithea.tests.base import GIT_REPO, GIT_TEST_REVISION, TestController
 
 
 class TestGitApi(_BaseTestApi, TestController):
--- a/kallithea/tests/api/test_api_hg.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/api/test_api_hg.py	Sun Jan 05 04:07:51 2020 +0100
@@ -12,8 +12,8 @@
 # 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 kallithea.tests.base import TestController, HG_REPO, HG_TEST_REVISION
 from kallithea.tests.api.api_base import _BaseTestApi
+from kallithea.tests.base import HG_REPO, HG_TEST_REVISION, TestController
 
 
 class TestHgApi(_BaseTestApi, TestController):
--- a/kallithea/tests/base.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/base.py	Sun Jan 05 04:07:51 2020 +0100
@@ -15,18 +15,15 @@
 import datetime
 import logging
 import os
-import pytest
 import re
 import tempfile
 import time
 
-from tg import config
+import pytest
 from webtest import TestApp
 
-from kallithea import model
+from kallithea.lib.utils2 import safe_str
 from kallithea.model.db import User
-from kallithea.model.meta import Session
-from kallithea.lib.utils2 import safe_str
 
 
 log = logging.getLogger(__name__)
@@ -45,8 +42,8 @@
     'HG_FORK', 'GIT_FORK', 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS',
     'TEST_USER_ADMIN_EMAIL', 'TEST_USER_REGULAR_LOGIN', 'TEST_USER_REGULAR_PASS',
     'TEST_USER_REGULAR_EMAIL', 'TEST_USER_REGULAR2_LOGIN',
-    'TEST_USER_REGULAR2_PASS', 'TEST_USER_REGULAR2_EMAIL', 'TEST_HG_REPO',
-    'TEST_HG_REPO_CLONE', 'TEST_HG_REPO_PULL', 'TEST_GIT_REPO',
+    'TEST_USER_REGULAR2_PASS', 'TEST_USER_REGULAR2_EMAIL', 'IP_ADDR',
+    'TEST_HG_REPO', 'TEST_HG_REPO_CLONE', 'TEST_HG_REPO_PULL', 'TEST_GIT_REPO',
     'TEST_GIT_REPO_CLONE', 'TEST_GIT_REPO_PULL', 'HG_REMOTE_REPO',
     'GIT_REMOTE_REPO', 'HG_TEST_REVISION', 'GIT_TEST_REVISION',
 ]
@@ -67,6 +64,8 @@
 TEST_USER_REGULAR2_PASS = 'test12'
 TEST_USER_REGULAR2_EMAIL = 'test_regular2@example.com'
 
+IP_ADDR = '127.0.0.127'
+
 HG_REPO = u'vcs_test_hg'
 GIT_REPO = u'vcs_test_git'
 
@@ -154,7 +153,8 @@
         self._logged_username = username
         response = self.app.post(url(controller='login', action='index'),
                                  {'username': username,
-                                  'password': password})
+                                  'password': password,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         if 'Invalid username or password' in response.body:
             pytest.fail('could not login using %s %s' % (username, password))
@@ -175,8 +175,8 @@
         user = user and user.username
         assert user == expected_username
 
-    def authentication_token(self):
-        return self.app.get(url('authentication_token')).body
+    def session_csrf_secret_token(self):
+        return self.app.get(url('session_csrf_secret_token')).body
 
     def checkSessionFlash(self, response, msg=None, skip=0, _matcher=lambda msg, m: msg in m):
         if 'flash' not in response.session:
--- a/kallithea/tests/conftest.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/conftest.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,28 +1,25 @@
+import logging
 import os
-import re
 import sys
-import logging
-import pkg_resources
 import time
 
 import formencode
-from paste.deploy import loadwsgi
-from routes.util import URLGenerator
+import pkg_resources
 import pytest
+from paste.deploy import loadwsgi
 from pytest_localserver.http import WSGIServer
+from routes.util import URLGenerator
+from tg.util.webtest import test_context
 
+import kallithea.tests.base  # FIXME: needed for setting testapp instance!!!
 from kallithea.controllers.root import RootController
 from kallithea.lib import inifile
 from kallithea.lib.utils import repo2db_mapper
-from kallithea.model.user import UserModel
+from kallithea.model.db import Setting, User, UserIpMap
 from kallithea.model.meta import Session
-from kallithea.model.db import Setting, User, UserIpMap
 from kallithea.model.scm import ScmModel
-from kallithea.tests.base import invalidate_all_caches, TEST_USER_REGULAR_LOGIN, TESTS_TMP_PATH, \
-    TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS
-import kallithea.tests.base # FIXME: needed for setting testapp instance!!!
-
-from tg.util.webtest import test_context
+from kallithea.model.user import UserModel
+from kallithea.tests.base import TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS, TEST_USER_REGULAR_LOGIN, TESTS_TMP_PATH, invalidate_all_caches
 
 
 def pytest_configure():
@@ -42,10 +39,14 @@
             'port': '4999',
         },
         '[app:main]': {
+            'ssh_enabled': 'true',
+            # Mainly to safeguard against accidentally overwriting the real one:
+            'ssh_authorized_keys': os.path.join(TESTS_TMP_PATH, 'authorized_keys'),
+            #'ssh_locale': 'C',
             'app_instance_uuid': 'test',
             'show_revision_number': 'true',
             'beaker.cache.sql_cache_short.expire': '1',
-            'beaker.session.secret': '{74e0cd75-b339-478b-b129-07dd221def1f}',
+            'session.secret': '{74e0cd75-b339-478b-b129-07dd221def1f}',
             #'i18n.lang': '',
         },
         '[handler_console]': {
@@ -154,6 +155,8 @@
 
     # IP permissions are cached, need to invalidate this cache explicitly
     invalidate_all_caches()
+    session = Session()
+    session.commit()
 
 
 @pytest.fixture
--- a/kallithea/tests/fixture.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/fixture.py	Sun Jan 05 04:07:51 2020 +0100
@@ -26,23 +26,23 @@
 from tg import request
 from tg.util.webtest import test_context
 
-from kallithea.model.db import Repository, User, RepoGroup, UserGroup, Gist, ChangesetStatus
-from kallithea.model.meta import Session
-from kallithea.model.repo import RepoModel
-from kallithea.model.user import UserModel
-from kallithea.model.repo_group import RepoGroupModel
-from kallithea.model.user_group import UserGroupModel
-from kallithea.model.gist import GistModel
-from kallithea.model.scm import ScmModel
-from kallithea.model.comment import ChangesetCommentsModel
-from kallithea.model.changeset_status import ChangesetStatusModel
-from kallithea.model.pull_request import CreatePullRequestAction#, CreatePullRequestIterationAction, PullRequestModel
 from kallithea.lib import helpers
 from kallithea.lib.auth import AuthUser
 from kallithea.lib.db_manage import DbManage
 from kallithea.lib.vcs.backends.base import EmptyChangeset
-from kallithea.tests.base import invalidate_all_caches, GIT_REPO, HG_REPO, \
-    TESTS_TMP_PATH, TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN, TEST_USER_ADMIN_EMAIL
+from kallithea.model.changeset_status import ChangesetStatusModel
+from kallithea.model.comment import ChangesetCommentsModel
+from kallithea.model.db import ChangesetStatus, Gist, RepoGroup, Repository, User, UserGroup
+from kallithea.model.gist import GistModel
+from kallithea.model.meta import Session
+from kallithea.model.pull_request import CreatePullRequestAction  # , CreatePullRequestIterationAction, PullRequestModel
+from kallithea.model.repo import RepoModel
+from kallithea.model.repo_group import RepoGroupModel
+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)
 
 
 log = logging.getLogger(__name__)
@@ -117,7 +117,6 @@
             parent_group_id=u'-1',
             perms_updates=[],
             perms_new=[],
-            enable_locking=False,
             recursive=False
         )
         defs.update(custom)
@@ -262,7 +261,7 @@
         }
         form_data.update(kwargs)
         gist = GistModel().create(
-            description=form_data['description'], owner=form_data['owner'],
+            description=form_data['description'], owner=form_data['owner'], ip_addr=IP_ADDR,
             gist_mapping=form_data['gist_mapping'], gist_type=form_data['gist_type'],
             lifetime=form_data['lifetime']
         )
@@ -303,7 +302,9 @@
                 }
             }
             cs = ScmModel().create_nodes(
-                user=TEST_USER_ADMIN_LOGIN, repo=repo,
+                user=TEST_USER_ADMIN_LOGIN,
+                ip_addr=IP_ADDR,
+                repo=repo,
                 message=message,
                 nodes=nodes,
                 parent_cs=_cs,
@@ -312,7 +313,9 @@
         else:
             cs = ScmModel().commit_change(
                 repo=repo.scm_instance, repo_name=repo.repo_name,
-                cs=parent, user=TEST_USER_ADMIN_LOGIN,
+                cs=parent,
+                user=TEST_USER_ADMIN_LOGIN,
+                ip_addr=IP_ADDR,
                 author=author,
                 message=message,
                 content=content,
@@ -365,7 +368,7 @@
                         tests=True)
     dbmanage.create_tables(override=True)
     # for tests dynamically set new root paths based on generated content
-    dbmanage.create_settings(dbmanage.config_prompt(repos_test_path))
+    dbmanage.create_settings(dbmanage.prompt_repo_root_path(repos_test_path))
     dbmanage.create_default_user()
     dbmanage.admin_prompt()
     dbmanage.create_permissions()
@@ -406,7 +409,7 @@
     """
 
     from kallithea.lib.indexers.daemon import WhooshIndexingDaemon
-    from kallithea.lib.pidlock import DaemonLock, LockHeld
+    from kallithea.lib.pidlock import DaemonLock
 
     index_location = os.path.join(config['index_dir'])
     if not os.path.exists(index_location):
--- a/kallithea/tests/functional/test_admin.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_admin.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,11 +1,13 @@
-import os
 import csv
 import datetime
-from kallithea.tests.base import *
+import os
+from os.path import dirname
+
+from kallithea.lib.utils2 import safe_unicode
 from kallithea.model.db import UserLog
 from kallithea.model.meta import Session
-from kallithea.lib.utils2 import safe_unicode
-from os.path import dirname
+from kallithea.tests.base import *
+
 
 FIXTURES = os.path.join(dirname(dirname(os.path.abspath(__file__))), 'fixtures')
 
--- a/kallithea/tests/functional/test_admin_auth_settings.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_admin_auth_settings.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,12 +1,12 @@
+from kallithea.model.db import Setting
 from kallithea.tests.base import *
-from kallithea.model.db import Setting
 
 
 class TestAuthSettingsController(TestController):
     def _enable_plugins(self, plugins_list):
         test_url = url(controller='admin/auth_settings',
                        action='auth_settings')
-        params={'auth_plugins': plugins_list, '_authentication_token': self.authentication_token()}
+        params={'auth_plugins': plugins_list, '_session_csrf_secret_token': self.session_csrf_secret_token()}
 
         for plugin in plugins_list.split(','):
             enable = plugin.partition('kallithea.lib.auth_modules.')[-1]
--- a/kallithea/tests/functional/test_admin_defaults.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_admin_defaults.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,5 +1,5 @@
+from kallithea.model.db import Setting
 from kallithea.tests.base import *
-from kallithea.model.db import Setting
 
 
 class TestDefaultsController(TestController):
@@ -10,38 +10,35 @@
         response.mustcontain('default_repo_private')
         response.mustcontain('default_repo_enable_statistics')
         response.mustcontain('default_repo_enable_downloads')
-        response.mustcontain('default_repo_enable_locking')
 
     def test_update_params_true_hg(self):
         self.log_user()
         params = {
-            'default_repo_enable_locking': True,
             'default_repo_enable_downloads': True,
             'default_repo_enable_statistics': True,
             'default_repo_private': True,
             'default_repo_type': 'hg',
-            '_authentication_token': self.authentication_token(),
+            '_session_csrf_secret_token': self.session_csrf_secret_token(),
         }
         response = self.app.post(url('defaults_update', id='default'), params=params)
         self.checkSessionFlash(response, 'Default settings updated successfully')
 
-        params.pop('_authentication_token')
+        params.pop('_session_csrf_secret_token')
         defs = Setting.get_default_repo_settings()
         assert params == defs
 
     def test_update_params_false_git(self):
         self.log_user()
         params = {
-            'default_repo_enable_locking': False,
             'default_repo_enable_downloads': False,
             'default_repo_enable_statistics': False,
             'default_repo_private': False,
             'default_repo_type': 'git',
-            '_authentication_token': self.authentication_token(),
+            '_session_csrf_secret_token': self.session_csrf_secret_token(),
         }
         response = self.app.post(url('defaults_update', id='default'), params=params)
         self.checkSessionFlash(response, 'Default settings updated successfully')
 
-        params.pop('_authentication_token')
+        params.pop('_session_csrf_secret_token')
         defs = Setting.get_default_repo_settings()
         assert params == defs
--- a/kallithea/tests/functional/test_admin_gists.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_admin_gists.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,7 +1,7 @@
-from kallithea.tests.base import *
+from kallithea.model.db import Gist, User
 from kallithea.model.gist import GistModel
 from kallithea.model.meta import Session
-from kallithea.model.db import User, Gist
+from kallithea.tests.base import *
 
 
 def _create_gist(f_name, content='some gist', lifetime=-1,
@@ -11,7 +11,7 @@
         f_name: {'content': content}
     }
     owner = User.get_by_username(owner)
-    gist = GistModel().create(description, owner=owner,
+    gist = GistModel().create(description, owner=owner, ip_addr=IP_ADDR,
                        gist_mapping=gist_mapping, gist_type=gist_type,
                        lifetime=lifetime)
     Session().commit()
@@ -56,7 +56,7 @@
     def test_create_missing_description(self):
         self.log_user()
         response = self.app.post(url('gists'),
-                                 params={'lifetime': -1, '_authentication_token': self.authentication_token()},
+                                 params={'lifetime': -1, '_session_csrf_secret_token': self.session_csrf_secret_token()},
                                  status=200)
 
         response.mustcontain('Missing value')
@@ -68,7 +68,7 @@
                                          'content': 'gist test',
                                          'filename': 'foo',
                                          'public': 'public',
-                                         '_authentication_token': self.authentication_token()},
+                                         '_session_csrf_secret_token': self.session_csrf_secret_token()},
                                  status=302)
         response = response.follow()
         response.mustcontain('added file: foo')
@@ -82,7 +82,7 @@
                                          'content': 'gist test',
                                          'filename': '/home/foo',
                                          'public': 'public',
-                                         '_authentication_token': self.authentication_token()},
+                                         '_session_csrf_secret_token': self.session_csrf_secret_token()},
                                  status=200)
         response.mustcontain('Filename cannot be inside a directory')
 
@@ -101,7 +101,7 @@
                                          'content': 'private gist test',
                                          'filename': 'private-foo',
                                          'private': 'private',
-                                         '_authentication_token': self.authentication_token()},
+                                         '_session_csrf_secret_token': self.session_csrf_secret_token()},
                                  status=302)
         response = response.follow()
         response.mustcontain('added file: private-foo<')
@@ -116,7 +116,7 @@
                                          'filename': 'foo-desc',
                                          'description': 'gist-desc',
                                          'public': 'public',
-                                         '_authentication_token': self.authentication_token()},
+                                         '_session_csrf_secret_token': self.session_csrf_secret_token()},
                                  status=302)
         response = response.follow()
         response.mustcontain('added file: foo-desc')
@@ -132,19 +132,19 @@
         self.log_user()
         gist = _create_gist('delete-me')
         response = self.app.post(url('gist_delete', gist_id=gist.gist_id),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
 
     def test_delete_normal_user_his_gist(self):
         self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
         gist = _create_gist('delete-me', owner=TEST_USER_REGULAR_LOGIN)
         response = self.app.post(url('gist_delete', gist_id=gist.gist_id),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
 
     def test_delete_normal_user_not_his_own_gist(self):
         self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
         gist = _create_gist('delete-me')
         response = self.app.post(url('gist_delete', gist_id=gist.gist_id), status=403,
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
 
     def test_show(self):
         gist = _create_gist('gist-show-me')
--- a/kallithea/tests/functional/test_admin_permissions.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_admin_permissions.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,12 +1,6 @@
-import time
-
 from kallithea.model.db import User, UserIpMap
-from kallithea.model.user import UserModel
-from kallithea.model.meta import Session
 from kallithea.tests.base import *
 
-from tg.util.webtest import test_context
-
 
 class TestAdminPermissionsController(TestController):
 
@@ -29,7 +23,7 @@
 
         response = self.app.post(url('edit_user_ips_update', id=default_user_id),
                                  params=dict(new_ip='0.0.0.0/24',
-                                 _authentication_token=self.authentication_token()))
+                                 _session_csrf_secret_token=self.session_csrf_secret_token()))
         invalidate_all_caches()
         response = self.app.get(url('admin_permissions_ips'),
                                 extra_environ={'REMOTE_ADDR': '0.0.0.1'})
@@ -43,7 +37,7 @@
 
         response = self.app.post(url('edit_user_ips_update', id=default_user_id),
                                  params=dict(new_ip='0.0.1.0/24',
-                                 _authentication_token=self.authentication_token()))
+                                 _session_csrf_secret_token=self.session_csrf_secret_token()))
         invalidate_all_caches()
 
         response = self.app.get(url('admin_permissions_ips'),
@@ -54,7 +48,7 @@
         x = UserIpMap.query().filter_by(ip_addr='0.0.1.0/24').first()
         response = self.app.post(url('edit_user_ips_delete', id=default_user_id),
                                  params=dict(del_ip_id=x.ip_id,
-                                             _authentication_token=self.authentication_token()))
+                                             _session_csrf_secret_token=self.session_csrf_secret_token()))
         invalidate_all_caches()
 
         response = self.app.get(url('admin_permissions_ips'),
@@ -65,7 +59,7 @@
         x = UserIpMap.query().filter_by(ip_addr='0.0.0.0/24').first()
         response = self.app.post(url('edit_user_ips_delete', id=default_user_id),
                                  params=dict(del_ip_id=x.ip_id,
-                                             _authentication_token=self.authentication_token()))
+                                             _session_csrf_secret_token=self.session_csrf_secret_token()))
         invalidate_all_caches()
 
         response = self.app.get(url('admin_permissions_ips'),
@@ -86,7 +80,7 @@
                 perm_new_member_1='repository.read',
                 perm_new_member_name_1=user.username,
                 perm_new_member_type_1='user',
-                _authentication_token=self.authentication_token()),
+                _session_csrf_secret_token=self.session_csrf_secret_token()),
             status=302)
 
         assert not response.location.endswith(url('edit_repo_perms_update', repo_name=HG_REPO))
@@ -97,7 +91,7 @@
             params=dict(
                 obj_type='user',
                 user_id=user.user_id,
-                _authentication_token=self.authentication_token()),
+                _session_csrf_secret_token=self.session_csrf_secret_token()),
             status=302)
 
         assert response.location.endswith(url('login_home', came_from=url('edit_repo_perms_revoke', repo_name=HG_REPO)))
@@ -111,7 +105,7 @@
                 perm_new_member_1='repository.read',
                 perm_new_member_name_1=user.username,
                 perm_new_member_type_1='user',
-                _authentication_token=self.authentication_token()),
+                _session_csrf_secret_token=self.session_csrf_secret_token()),
             status=302)
 
         assert response.location.endswith(url('edit_repo_perms_update', repo_name=HG_REPO))
@@ -121,6 +115,6 @@
             params=dict(
                 obj_type='user',
                 user_id=user.user_id,
-                _authentication_token=self.authentication_token()),
+                _session_csrf_secret_token=self.session_csrf_secret_token()),
             status=200)
         assert not response.body
--- a/kallithea/tests/functional/test_admin_repo_groups.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_admin_repo_groups.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,4 +1,3 @@
-from kallithea.model.db import Repository
 from kallithea.model.meta import Session
 from kallithea.model.repo_group import RepoGroupModel
 from kallithea.tests.base import TestController, url
@@ -15,12 +14,12 @@
         group_name = u'newgroup'
         response = self.app.post(url('repos_groups'),
                                  fixture._get_repo_group_create_params(group_name=group_name,
-                                                                 _authentication_token=self.authentication_token()))
+                                                                 _session_csrf_secret_token=self.session_csrf_secret_token()))
         # try to create repo group with swapped case
         swapped_group_name = group_name.swapcase()
         response = self.app.post(url('repos_groups'),
                                  fixture._get_repo_group_create_params(group_name=swapped_group_name,
-                                                                 _authentication_token=self.authentication_token()))
+                                                                 _session_csrf_secret_token=self.session_csrf_secret_token()))
         response.mustcontain('already exists')
 
         RepoGroupModel().delete(group_name)
--- a/kallithea/tests/functional/test_admin_repos.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_admin_repos.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,23 +1,22 @@
 # -*- coding: utf-8 -*-
 
 import os
-import mock
 import urllib
 
+import mock
 import pytest
-from sqlalchemy import func
 
 from kallithea.lib import vcs
 from kallithea.lib.utils2 import safe_str, safe_unicode
-from kallithea.model.db import Repository, RepoGroup, UserRepoToPerm, User, \
-    Permission, Ui
+from kallithea.model.db import Permission, RepoGroup, Repository, Ui, User, UserRepoToPerm
+from kallithea.model.meta import Session
+from kallithea.model.repo import RepoModel
+from kallithea.model.repo_group import RepoGroupModel
 from kallithea.model.user import UserModel
 from kallithea.tests.base import *
-from kallithea.model.repo_group import RepoGroupModel
-from kallithea.model.repo import RepoModel
-from kallithea.model.meta import Session, Base
 from kallithea.tests.fixture import Fixture, error_function
 
+
 fixture = Fixture()
 
 
@@ -53,7 +52,7 @@
                                                 repo_name=repo_name,
                                                 repo_type=self.REPO_TYPE,
                                                 repo_description=description,
-                                                _authentication_token=self.authentication_token()))
+                                                _session_csrf_secret_token=self.session_csrf_secret_token()))
         ## run the check page that triggers the flash message
         response = self.app.get(url('repo_check_home', repo_name=repo_name))
         assert response.json == {u'result': True}
@@ -91,7 +90,7 @@
                                                                  repo_name=repo_name,
                                                                  repo_type=self.REPO_TYPE,
                                                                  repo_description=description,
-                                                                 _authentication_token=self.authentication_token()))
+                                                                 _session_csrf_secret_token=self.session_csrf_secret_token()))
         # try to create repo with swapped case
         swapped_repo_name = repo_name.swapcase()
         response = self.app.post(url('repos'),
@@ -99,7 +98,7 @@
                                                                  repo_name=swapped_repo_name,
                                                                  repo_type=self.REPO_TYPE,
                                                                  repo_description=description,
-                                                                 _authentication_token=self.authentication_token()))
+                                                                 _session_csrf_secret_token=self.session_csrf_secret_token()))
         response.mustcontain('already exists')
 
         RepoModel().delete(repo_name)
@@ -124,7 +123,7 @@
                                                 repo_type=self.REPO_TYPE,
                                                 repo_description=description,
                                                 repo_group=gr.group_id,
-                                                _authentication_token=self.authentication_token()))
+                                                _session_csrf_secret_token=self.session_csrf_secret_token()))
         ## run the check page that triggers the flash message
         response = self.app.get(url('repo_check_home', repo_name=repo_name_full))
         assert response.json == {u'result': True}
@@ -163,7 +162,7 @@
     def test_create_in_group_without_needed_permissions(self):
         usr = self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
         # avoid spurious RepoGroup DetachedInstanceError ...
-        authentication_token = self.authentication_token()
+        session_csrf_secret_token = self.session_csrf_secret_token()
         # revoke
         user_model = UserModel()
         # disable fork and create on default user
@@ -201,7 +200,7 @@
                                                 repo_type=self.REPO_TYPE,
                                                 repo_description=description,
                                                 repo_group=gr.group_id,
-                                                _authentication_token=authentication_token))
+                                                _session_csrf_secret_token=session_csrf_secret_token))
 
         response.mustcontain('Invalid value')
 
@@ -215,7 +214,7 @@
                                                 repo_type=self.REPO_TYPE,
                                                 repo_description=description,
                                                 repo_group=gr_allowed.group_id,
-                                                _authentication_token=authentication_token))
+                                                _session_csrf_secret_token=session_csrf_secret_token))
 
         ## run the check page that triggers the flash message
         response = self.app.get(url('repo_check_home', repo_name=repo_name_full))
@@ -277,7 +276,7 @@
                                                 repo_description=description,
                                                 repo_group=gr.group_id,
                                                 repo_copy_permissions=True,
-                                                _authentication_token=self.authentication_token()))
+                                                _session_csrf_secret_token=self.session_csrf_secret_token()))
 
         ## run the check page that triggers the flash message
         response = self.app.get(url('repo_check_home', repo_name=repo_name_full))
@@ -329,7 +328,7 @@
                                                 repo_type=self.REPO_TYPE,
                                                 repo_description=description,
                                                 clone_uri='http://127.0.0.1/repo',
-                                                _authentication_token=self.authentication_token()))
+                                                _session_csrf_secret_token=self.session_csrf_secret_token()))
         response.mustcontain('Invalid repository URL')
 
     def test_create_remote_repo_wrong_clone_uri_hg_svn(self):
@@ -342,7 +341,7 @@
                                                 repo_type=self.REPO_TYPE,
                                                 repo_description=description,
                                                 clone_uri='svn+http://127.0.0.1/repo',
-                                                _authentication_token=self.authentication_token()))
+                                                _session_csrf_secret_token=self.session_csrf_secret_token()))
         response.mustcontain('Invalid repository URL')
 
     def test_delete(self):
@@ -354,7 +353,7 @@
                                                 repo_type=self.REPO_TYPE,
                                                 repo_name=repo_name,
                                                 repo_description=description,
-                                                _authentication_token=self.authentication_token()))
+                                                _session_csrf_secret_token=self.session_csrf_secret_token()))
         ## run the check page that triggers the flash message
         response = self.app.get(url('repo_check_home', repo_name=repo_name))
         self.checkSessionFlash(response,
@@ -379,7 +378,7 @@
             pytest.fail('no repo %s in filesystem' % repo_name)
 
         response = self.app.post(url('delete_repo', repo_name=repo_name),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         self.checkSessionFlash(response, 'Deleted repository %s' % (repo_name))
 
@@ -405,7 +404,7 @@
                                                 repo_name=repo_name,
                                                 repo_type=self.REPO_TYPE,
                                                 repo_description=description,
-                                                _authentication_token=self.authentication_token()))
+                                                _session_csrf_secret_token=self.session_csrf_secret_token()))
         ## run the check page that triggers the flash message
         response = self.app.get(url('repo_check_home', repo_name=repo_name))
         assert response.json == {u'result': True}
@@ -431,7 +430,7 @@
             pytest.fail('no repo %s in filesystem' % repo_name)
 
         response = self.app.post(url('delete_repo', repo_name=repo_name),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'Deleted repository %s' % (repo_name_unicode))
         response.follow()
 
@@ -449,7 +448,7 @@
 
     def test_delete_browser_fakeout(self):
         response = self.app.post(url('delete_repo', repo_name=self.REPO),
-                                 params=dict(_authentication_token=self.authentication_token()))
+                                 params=dict(_session_csrf_secret_token=self.session_csrf_secret_token()))
 
     def test_show(self):
         self.log_user()
@@ -471,7 +470,7 @@
                                                 repo_name=self.REPO,
                                                 repo_type=self.REPO_TYPE,
                                                 owner=TEST_USER_ADMIN_LOGIN,
-                                                _authentication_token=self.authentication_token()))
+                                                _session_csrf_secret_token=self.session_csrf_secret_token()))
         self.checkSessionFlash(response,
                                msg='Repository %s updated successfully' % (self.REPO))
         assert Repository.get_by_repo_name(self.REPO).private == True
@@ -486,7 +485,7 @@
                                                 repo_name=self.REPO,
                                                 repo_type=self.REPO_TYPE,
                                                 owner=TEST_USER_ADMIN_LOGIN,
-                                                _authentication_token=self.authentication_token()))
+                                                _session_csrf_secret_token=self.session_csrf_secret_token()))
         self.checkSessionFlash(response,
                                msg='Repository %s updated successfully' % (self.REPO))
         assert Repository.get_by_repo_name(self.REPO).private == False
@@ -514,7 +513,7 @@
         repo = Repository.get_by_repo_name(self.REPO)
         repo2 = Repository.get_by_repo_name(other_repo)
         response = self.app.post(url('edit_repo_advanced_fork', repo_name=self.REPO),
-                                params=dict(id_fork_of=repo2.repo_id, _authentication_token=self.authentication_token()))
+                                params=dict(id_fork_of=repo2.repo_id, _session_csrf_secret_token=self.session_csrf_secret_token()))
         repo = Repository.get_by_repo_name(self.REPO)
         repo2 = Repository.get_by_repo_name(other_repo)
         self.checkSessionFlash(response,
@@ -535,7 +534,7 @@
         repo = Repository.get_by_repo_name(self.REPO)
         repo2 = Repository.get_by_repo_name(self.OTHER_TYPE_REPO)
         response = self.app.post(url('edit_repo_advanced_fork', repo_name=self.REPO),
-                                params=dict(id_fork_of=repo2.repo_id, _authentication_token=self.authentication_token()))
+                                params=dict(id_fork_of=repo2.repo_id, _session_csrf_secret_token=self.session_csrf_secret_token()))
         repo = Repository.get_by_repo_name(self.REPO)
         repo2 = Repository.get_by_repo_name(self.OTHER_TYPE_REPO)
         self.checkSessionFlash(response,
@@ -545,7 +544,7 @@
         self.log_user()
         ## mark it as None
         response = self.app.post(url('edit_repo_advanced_fork', repo_name=self.REPO),
-                                params=dict(id_fork_of=None, _authentication_token=self.authentication_token()))
+                                params=dict(id_fork_of=None, _session_csrf_secret_token=self.session_csrf_secret_token()))
         repo = Repository.get_by_repo_name(self.REPO)
         repo2 = Repository.get_by_repo_name(self.OTHER_TYPE_REPO)
         self.checkSessionFlash(response,
@@ -557,7 +556,7 @@
         self.log_user()
         repo = Repository.get_by_repo_name(self.REPO)
         response = self.app.post(url('edit_repo_advanced_fork', repo_name=self.REPO),
-                                params=dict(id_fork_of=repo.repo_id, _authentication_token=self.authentication_token()))
+                                params=dict(id_fork_of=repo.repo_id, _session_csrf_secret_token=self.session_csrf_secret_token()))
         self.checkSessionFlash(response,
                                'An error occurred during this operation')
 
@@ -588,7 +587,7 @@
                                                 repo_name=repo_name,
                                                 repo_type=self.REPO_TYPE,
                                                 repo_description=description,
-                                                _authentication_token=self.authentication_token()))
+                                                _session_csrf_secret_token=self.session_csrf_secret_token()))
 
         response.mustcontain('<span class="error-message">Invalid value</span>')
 
@@ -606,7 +605,7 @@
                                                 repo_name=repo_name,
                                                 repo_type=self.REPO_TYPE,
                                                 repo_description=description,
-                                                _authentication_token=self.authentication_token()))
+                                                _session_csrf_secret_token=self.session_csrf_secret_token()))
 
         self.checkSessionFlash(response,
                                'Error creating repository %s' % repo_name)
--- a/kallithea/tests/functional/test_admin_settings.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_admin_settings.py	Sun Jan 05 04:07:51 2020 +0100
@@ -4,6 +4,7 @@
 from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 
+
 fixture = Fixture()
 
 
@@ -38,7 +39,7 @@
         response = self.app.post(url('admin_settings_hooks'),
                                 params=dict(new_hook_ui_key='test_hooks_1',
                                             new_hook_ui_value='cd %s' % TESTS_TMP_PATH,
-                                            _authentication_token=self.authentication_token()))
+                                            _session_csrf_secret_token=self.session_csrf_secret_token()))
 
         self.checkSessionFlash(response, 'Added new hook')
         response = response.follow()
@@ -51,7 +52,7 @@
                                 params=dict(hook_ui_key='test_hooks_1',
                                             hook_ui_value='old_value_of_hook_1',
                                             hook_ui_value_new='new_value_of_hook_1',
-                                            _authentication_token=self.authentication_token()))
+                                            _session_csrf_secret_token=self.session_csrf_secret_token()))
 
         response = response.follow()
         response.mustcontain('test_hooks_1')
@@ -62,7 +63,7 @@
         response = self.app.post(url('admin_settings_hooks'),
                                 params=dict(new_hook_ui_key='test_hooks_1',
                                             new_hook_ui_value='attempted_new_value',
-                                            _authentication_token=self.authentication_token()))
+                                            _session_csrf_secret_token=self.session_csrf_secret_token()))
 
         self.checkSessionFlash(response, 'Hook already exists')
         response = response.follow()
@@ -74,7 +75,7 @@
         response = self.app.post(url('admin_settings_hooks'),
                                 params=dict(new_hook_ui_key='test_hooks_2',
                                             new_hook_ui_value='cd %s2' % TESTS_TMP_PATH,
-                                            _authentication_token=self.authentication_token()))
+                                            _session_csrf_secret_token=self.session_csrf_secret_token()))
 
         self.checkSessionFlash(response, 'Added new hook')
         response = response.follow()
@@ -84,7 +85,7 @@
         hook_id = Ui.get_by_key('hooks', 'test_hooks_2').ui_id
         ## delete
         self.app.post(url('admin_settings_hooks'),
-                        params=dict(hook_id=hook_id, _authentication_token=self.authentication_token()))
+                        params=dict(hook_id=hook_id, _session_csrf_secret_token=self.session_csrf_secret_token()))
         response = self.app.get(url('admin_settings_hooks'))
         response.mustcontain(no=['test_hooks_2'])
         response.mustcontain(no=['cd %s2' % TESTS_TMP_PATH])
@@ -94,7 +95,7 @@
         response = self.app.post(url('admin_settings_hooks'),
                                 params=dict(new_hook_ui_key='changegroup.update',
                                             new_hook_ui_value='attempted_new_value',
-                                            _authentication_token=self.authentication_token()))
+                                            _session_csrf_secret_token=self.session_csrf_secret_token()))
 
         self.checkSessionFlash(response, 'Builtin hooks are read-only')
         response = response.follow()
@@ -120,7 +121,7 @@
                                  ga_code=new_ga_code,
                                  captcha_private_key='',
                                  captcha_public_key='',
-                                 _authentication_token=self.authentication_token(),
+                                 _session_csrf_secret_token=self.session_csrf_secret_token(),
                                  ))
 
         self.checkSessionFlash(response, 'Updated application settings')
@@ -141,7 +142,7 @@
                                  ga_code=new_ga_code,
                                  captcha_private_key='',
                                  captcha_public_key='',
-                                 _authentication_token=self.authentication_token(),
+                                 _session_csrf_secret_token=self.session_csrf_secret_token(),
                                  ))
 
         self.checkSessionFlash(response, 'Updated application settings')
@@ -161,7 +162,7 @@
                                  ga_code=new_ga_code,
                                  captcha_private_key='1234567890',
                                  captcha_public_key='1234567890',
-                                 _authentication_token=self.authentication_token(),
+                                 _session_csrf_secret_token=self.session_csrf_secret_token(),
                                  ))
 
         self.checkSessionFlash(response, 'Updated application settings')
@@ -181,7 +182,7 @@
                                  ga_code=new_ga_code,
                                  captcha_private_key='',
                                  captcha_public_key='1234567890',
-                                 _authentication_token=self.authentication_token(),
+                                 _session_csrf_secret_token=self.session_csrf_secret_token(),
                                  ))
 
         self.checkSessionFlash(response, 'Updated application settings')
@@ -203,7 +204,7 @@
                                  ga_code='',
                                  captcha_private_key='',
                                  captcha_public_key='',
-                                 _authentication_token=self.authentication_token(),
+                                 _session_csrf_secret_token=self.session_csrf_secret_token(),
                                 ))
 
             self.checkSessionFlash(response, 'Updated application settings')
--- a/kallithea/tests/functional/test_admin_user_groups.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_admin_user_groups.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,7 +1,8 @@
 # -*- coding: utf-8 -*-
+from kallithea.model.db import Permission, UserGroup, UserGroupToPerm
+from kallithea.model.meta import Session
 from kallithea.tests.base import *
-from kallithea.model.db import UserGroup, UserGroupToPerm, Permission
-from kallithea.model.meta import Session
+
 
 TEST_USER_GROUP = u'admins_test'
 
@@ -20,7 +21,7 @@
                                  {'users_group_name': users_group_name,
                                   'user_group_description': u'DESC',
                                   'active': True,
-                                  '_authentication_token': self.authentication_token()})
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
         response.follow()
 
         self.checkSessionFlash(response,
@@ -36,7 +37,7 @@
 
     def test_update_browser_fakeout(self):
         response = self.app.post(url('update_users_group', id=1),
-                                 params=dict(_authentication_token=self.authentication_token()))
+                                 params=dict(_session_csrf_secret_token=self.session_csrf_secret_token()))
 
     def test_delete(self):
         self.log_user()
@@ -45,7 +46,7 @@
                                  {'users_group_name': users_group_name,
                                   'user_group_description': u'DESC',
                                   'active': True,
-                                  '_authentication_token': self.authentication_token()})
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
         response.follow()
 
         self.checkSessionFlash(response,
@@ -55,7 +56,7 @@
             .filter(UserGroup.users_group_name == users_group_name).one()
 
         response = self.app.post(url('delete_users_group', id=gr.users_group_id),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         gr = Session().query(UserGroup) \
             .filter(UserGroup.users_group_name == users_group_name).scalar()
@@ -69,7 +70,7 @@
                                  {'users_group_name': users_group_name,
                                   'user_group_description': u'DESC',
                                   'active': True,
-                                  '_authentication_token': self.authentication_token()})
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
         response.follow()
 
         ug = UserGroup.get_by_group_name(users_group_name)
@@ -79,7 +80,7 @@
         response = self.app.post(url('edit_user_group_default_perms_update',
                                      id=ug.users_group_id),
                                  {'create_repo_perm': True,
-                                  '_authentication_token': self.authentication_token()})
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
         response.follow()
         ug = UserGroup.get_by_group_name(users_group_name)
         p = Permission.get_by_key('hg.create.repository')
@@ -97,7 +98,7 @@
         ## DISABLE REPO CREATE ON A GROUP
         response = self.app.post(
             url('edit_user_group_default_perms_update', id=ug.users_group_id),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         response.follow()
         ug = UserGroup.get_by_group_name(users_group_name)
@@ -118,7 +119,7 @@
         ug = UserGroup.get_by_group_name(users_group_name)
         ugid = ug.users_group_id
         response = self.app.post(url('delete_users_group', id=ug.users_group_id),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
         response = response.follow()
         gr = Session().query(UserGroup) \
             .filter(UserGroup.users_group_name == users_group_name).scalar()
@@ -138,7 +139,7 @@
                                  {'users_group_name': users_group_name,
                                   'user_group_description': u'DESC',
                                   'active': True,
-                                  '_authentication_token': self.authentication_token()})
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
         response.follow()
 
         ug = UserGroup.get_by_group_name(users_group_name)
@@ -147,7 +148,7 @@
         ## ENABLE REPO CREATE ON A GROUP
         response = self.app.post(url('edit_user_group_default_perms_update',
                                      id=ug.users_group_id),
-                                 {'fork_repo_perm': True, '_authentication_token': self.authentication_token()})
+                                 {'fork_repo_perm': True, '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         response.follow()
         ug = UserGroup.get_by_group_name(users_group_name)
@@ -165,7 +166,7 @@
 
         ## DISABLE REPO CREATE ON A GROUP
         response = self.app.post(url('edit_user_group_default_perms_update', id=ug.users_group_id),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         response.follow()
         ug = UserGroup.get_by_group_name(users_group_name)
@@ -185,7 +186,7 @@
         ug = UserGroup.get_by_group_name(users_group_name)
         ugid = ug.users_group_id
         response = self.app.post(url('delete_users_group', id=ug.users_group_id),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
         response = response.follow()
         gr = Session().query(UserGroup) \
                            .filter(UserGroup.users_group_name ==
@@ -201,4 +202,4 @@
 
     def test_delete_browser_fakeout(self):
         response = self.app.post(url('delete_users_group', id=1),
-                                 params=dict(_authentication_token=self.authentication_token()))
+                                 params=dict(_session_csrf_secret_token=self.session_csrf_secret_token()))
--- a/kallithea/tests/functional/test_admin_users.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_admin_users.py	Sun Jan 05 04:07:51 2020 +0100
@@ -12,21 +12,21 @@
 # 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 sqlalchemy.orm.exc import NoResultFound, ObjectDeletedError
+import pytest
+from sqlalchemy.orm.exc import NoResultFound
+from tg.util.webtest import test_context
+from webob.exc import HTTPNotFound
 
-import pytest
+from kallithea.controllers.admin.users import UsersController
+from kallithea.lib import helpers as h
+from kallithea.lib.auth import check_password
+from kallithea.model import validators
+from kallithea.model.db import Permission, RepoGroup, User, UserApiKeys, UserSshKeys
+from kallithea.model.meta import Session
+from kallithea.model.user import UserModel
 from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
-from kallithea.controllers.admin.users import UsersController
-from kallithea.model.db import User, Permission, UserIpMap, UserApiKeys
-from kallithea.lib.auth import check_password
-from kallithea.model.user import UserModel
-from kallithea.model import validators
-from kallithea.lib import helpers as h
-from kallithea.model.meta import Session
-from webob.exc import HTTPNotFound
 
-from tg.util.webtest import test_context
 
 fixture = Fixture()
 
@@ -39,11 +39,8 @@
     repo_group = fixture.create_repo_group(name=groupname, cur_user=username)
     yield user, repo_group
     # cleanup
-    try:
+    if RepoGroup.get_by_group_name(groupname):
         fixture.destroy_repo_group(repo_group)
-    except ObjectDeletedError:
-        # delete already succeeded in test body
-        pass
 
 
 class TestAdminUsersController(TestController):
@@ -79,7 +76,7 @@
              'extern_name': 'internal',
              'extern_type': 'internal',
              'email': email,
-             '_authentication_token': self.authentication_token()})
+             '_session_csrf_secret_token': self.session_csrf_secret_token()})
         # 302 Found
         # The resource was found at http://localhost/_admin/users/5/edit; you should be redirected automatically.
 
@@ -112,7 +109,7 @@
              'active': False,
              'lastname': lastname,
              'email': email,
-             '_authentication_token': self.authentication_token()})
+             '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         with test_context(self.app):
             msg = validators.ValidUsername(False, {})._messages['system_invalid_username']
@@ -169,10 +166,10 @@
             # special case since this user is not logged in yet his data is
             # not filled so we use creation data
 
-        params.update({'_authentication_token': self.authentication_token()})
+        params.update({'_session_csrf_secret_token': self.session_csrf_secret_token()})
         response = self.app.post(url('update_user', id=usr.user_id), params)
         self.checkSessionFlash(response, 'User updated successfully')
-        params.pop('_authentication_token')
+        params.pop('_session_csrf_secret_token')
 
         updated_user = User.get_by_username(self.test_user_1)
         updated_params = updated_user.get_api_data(True)
@@ -190,7 +187,7 @@
         new_user = Session().query(User) \
             .filter(User.username == username).one()
         response = self.app.post(url('delete_user', id=new_user.user_id),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         self.checkSessionFlash(response, 'Successfully deleted user')
 
@@ -205,29 +202,29 @@
         new_user = Session().query(User) \
             .filter(User.username == username).one()
         response = self.app.post(url('delete_user', id=new_user.user_id),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'User "%s" still '
                                'owns 1 repositories and cannot be removed. '
                                'Switch owners or remove those repositories: '
                                '%s' % (username, reponame))
 
         response = self.app.post(url('delete_repo', repo_name=reponame),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'Deleted repository %s' % reponame)
 
         response = self.app.post(url('delete_user', id=new_user.user_id),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'Successfully deleted user')
 
     def test_delete_repo_group_err(self, user_and_repo_group_fail):
-        self.log_user()
-        username = 'repogrouperr'
-        groupname = u'repogroup_fail'
+        new_user, repo_group = user_and_repo_group_fail
+        username = new_user.username
+        groupname = repo_group.group_name
 
-        new_user = Session().query(User) \
-            .filter(User.username == username).one()
+        self.log_user()
+
         response = self.app.post(url('delete_user', id=new_user.user_id),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'User "%s" still '
                                'owns 1 repository groups and cannot be removed. '
                                'Switch owners or remove those repository groups: '
@@ -238,11 +235,11 @@
         # response = self.app.get(url('repos_groups', id=rg.group_id))
 
         response = self.app.post(url('delete_repo_group', group_name=groupname),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'Removed repository group %s' % groupname)
 
         response = self.app.post(url('delete_user', id=new_user.user_id),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'Successfully deleted user')
 
     def test_delete_user_group_err(self):
@@ -256,7 +253,7 @@
         new_user = Session().query(User) \
             .filter(User.username == username).one()
         response = self.app.post(url('delete_user', id=new_user.user_id),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'User "%s" still '
                                'owns 1 user groups and cannot be removed. '
                                'Switch owners or remove those user groups: '
@@ -269,7 +266,7 @@
         fixture.destroy_user_group(ug.users_group_id)
 
         response = self.app.post(url('delete_user', id=new_user.user_id),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'Successfully deleted user')
 
     def test_edit(self):
@@ -295,7 +292,7 @@
 
             response = self.app.post(url('edit_user_perms_update', id=uid),
                                      params=dict(create_repo_perm=True,
-                                                 _authentication_token=self.authentication_token()))
+                                                 _session_csrf_secret_token=self.session_csrf_secret_token()))
 
             perm_none = Permission.get_by_key('hg.create.none')
             perm_create = Permission.get_by_key('hg.create.repository')
@@ -324,7 +321,7 @@
             assert UserModel().has_perm(user, perm_create) == False
 
             response = self.app.post(url('edit_user_perms_update', id=uid),
-                                     params=dict(_authentication_token=self.authentication_token()))
+                                     params=dict(_session_csrf_secret_token=self.session_csrf_secret_token()))
 
             perm_none = Permission.get_by_key('hg.create.none')
             perm_create = Permission.get_by_key('hg.create.repository')
@@ -354,7 +351,7 @@
 
             response = self.app.post(url('edit_user_perms_update', id=uid),
                                      params=dict(create_repo_perm=True,
-                                                 _authentication_token=self.authentication_token()))
+                                                 _session_csrf_secret_token=self.session_csrf_secret_token()))
 
             perm_none = Permission.get_by_key('hg.create.none')
             perm_create = Permission.get_by_key('hg.create.repository')
@@ -383,7 +380,7 @@
             assert UserModel().has_perm(user, perm_fork) == False
 
             response = self.app.post(url('edit_user_perms_update', id=uid),
-                                     params=dict(_authentication_token=self.authentication_token()))
+                                     params=dict(_session_csrf_secret_token=self.session_csrf_secret_token()))
 
             perm_none = Permission.get_by_key('hg.create.none')
             perm_create = Permission.get_by_key('hg.create.repository')
@@ -415,7 +412,7 @@
         user_id = user.user_id
 
         response = self.app.post(url('edit_user_ips_update', id=user_id),
-                                 params=dict(new_ip=ip, _authentication_token=self.authentication_token()))
+                                 params=dict(new_ip=ip, _session_csrf_secret_token=self.session_csrf_secret_token()))
 
         if failure:
             self.checkSessionFlash(response, 'Please enter a valid IPv4 or IPv6 address')
@@ -444,7 +441,7 @@
         response.mustcontain(ip_range)
 
         self.app.post(url('edit_user_ips_delete', id=user_id),
-                      params=dict(del_ip_id=new_ip_id, _authentication_token=self.authentication_token()))
+                      params=dict(del_ip_id=new_ip_id, _session_csrf_secret_token=self.session_csrf_secret_token()))
 
         response = self.app.get(url('edit_user_ips', id=user_id))
         response.mustcontain('All IP addresses are allowed')
@@ -470,7 +467,7 @@
         user_id = user.user_id
 
         response = self.app.post(url('edit_user_api_keys_update', id=user_id),
-                 {'description': desc, 'lifetime': lifetime, '_authentication_token': self.authentication_token()})
+                 {'description': desc, 'lifetime': lifetime, '_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'API key successfully created')
         try:
             response = response.follow()
@@ -488,7 +485,7 @@
         user_id = user.user_id
 
         response = self.app.post(url('edit_user_api_keys_update', id=user_id),
-                {'description': 'desc', 'lifetime': -1, '_authentication_token': self.authentication_token()})
+                {'description': 'desc', 'lifetime': -1, '_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'API key successfully created')
         response = response.follow()
 
@@ -497,7 +494,7 @@
         assert 1 == len(keys)
 
         response = self.app.post(url('edit_user_api_keys_delete', id=user_id),
-                 {'del_api_key': keys[0].api_key, '_authentication_token': self.authentication_token()})
+                 {'del_api_key': keys[0].api_key, '_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'API key successfully deleted')
         keys = UserApiKeys.query().filter(UserApiKeys.user_id == user_id).all()
         assert 0 == len(keys)
@@ -512,11 +509,59 @@
         response.mustcontain('Expires: Never')
 
         response = self.app.post(url('edit_user_api_keys_delete', id=user_id),
-                 {'del_api_key_builtin': api_key, '_authentication_token': self.authentication_token()})
+                 {'del_api_key_builtin': api_key, '_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'API key successfully reset')
         response = response.follow()
         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'
+
+        self.log_user()
+        user = User.get_by_username(TEST_USER_REGULAR_LOGIN)
+        user_id = user.user_id
+
+        response = self.app.post(url('edit_user_ssh_keys', id=user_id),
+                                 {'description': description,
+                                  'public_key': public_key,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
+        self.checkSessionFlash(response, 'SSH key %s successfully added' % fingerprint)
+
+        response = response.follow()
+        response.mustcontain(fingerprint)
+        ssh_key = UserSshKeys.query().filter(UserSshKeys.user_id == user_id).one()
+        assert ssh_key.fingerprint == fingerprint
+        assert ssh_key.description == description
+        Session().delete(ssh_key)
+        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'
+
+        self.log_user()
+        user = User.get_by_username(TEST_USER_REGULAR_LOGIN)
+        user_id = user.user_id
+
+        response = self.app.post(url('edit_user_ssh_keys', id=user_id),
+                                 {'description': description,
+                                  'public_key': public_key,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
+        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'
+
+        response = self.app.post(url('edit_user_ssh_keys_delete', id=user_id),
+                                 {'del_public_key': ssh_key.public_key,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
+        self.checkSessionFlash(response, 'SSH key successfully deleted')
+        keys = UserSshKeys.query().all()
+        assert 0 == len(keys)
+
 
 class TestAdminUsersController_unittest(TestController):
     """ Unit tests for the users controller """
@@ -561,13 +606,13 @@
         self.log_user()
         user = User.get_default_user()
         response = self.app.post(url('edit_user_api_keys_update', id=user.user_id),
-                 {'_authentication_token': self.authentication_token()}, status=404)
+                 {'_session_csrf_secret_token': self.session_csrf_secret_token()}, status=404)
 
     def test_delete_api_keys_default_user(self):
         self.log_user()
         user = User.get_default_user()
         response = self.app.post(url('edit_user_api_keys_delete', id=user.user_id),
-                 {'_authentication_token': self.authentication_token()}, status=404)
+                 {'_session_csrf_secret_token': self.session_csrf_secret_token()}, status=404)
 
     # Permissions
     def test_edit_perms_default_user(self):
@@ -579,7 +624,7 @@
         self.log_user()
         user = User.get_default_user()
         response = self.app.post(url('edit_user_perms_update', id=user.user_id),
-                 {'_authentication_token': self.authentication_token()}, status=404)
+                 {'_session_csrf_secret_token': self.session_csrf_secret_token()}, status=404)
 
     # Emails
     def test_edit_emails_default_user(self):
@@ -591,13 +636,13 @@
         self.log_user()
         user = User.get_default_user()
         response = self.app.post(url('edit_user_emails_update', id=user.user_id),
-                 {'_authentication_token': self.authentication_token()}, status=404)
+                 {'_session_csrf_secret_token': self.session_csrf_secret_token()}, status=404)
 
     def test_delete_emails_default_user(self):
         self.log_user()
         user = User.get_default_user()
         response = self.app.post(url('edit_user_emails_delete', id=user.user_id),
-                 {'_authentication_token': self.authentication_token()}, status=404)
+                 {'_session_csrf_secret_token': self.session_csrf_secret_token()}, status=404)
 
     # IP addresses
     # Add/delete of IP addresses for the default user is used to maintain
--- a/kallithea/tests/functional/test_changeset.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_changeset.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,5 +1,6 @@
 from kallithea.tests.base import *
 
+
 class TestChangesetController(TestController):
 
     def test_index(self):
--- a/kallithea/tests/functional/test_changeset_pullrequests_comments.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_changeset_pullrequests_comments.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,9 +1,9 @@
 import re
 
-from kallithea.tests.base import *
 from kallithea.model.changeset_status import ChangesetStatusModel
 from kallithea.model.db import ChangesetComment, PullRequest
 from kallithea.model.meta import Session
+from kallithea.tests.base import *
 
 
 class TestChangeSetCommentsController(TestController):
@@ -18,7 +18,7 @@
         rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
         text = u'general comment on changeset'
 
-        params = {'text': text, '_authentication_token': self.authentication_token()}
+        params = {'text': text, '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(url(controller='changeset', action='comment',
                                      repo_name=HG_REPO, revision=rev),
                                      params=params, extra_environ={'HTTP_X_PARTIAL_XHR': '1'})
@@ -43,7 +43,7 @@
         f_path = 'vcs/web/simplevcs/views/repository.py'
         line = 'n1'
 
-        params = {'text': text, 'f_path': f_path, 'line': line, '_authentication_token': self.authentication_token()}
+        params = {'text': text, 'f_path': f_path, 'line': line, '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(url(controller='changeset', action='comment',
                                      repo_name=HG_REPO, revision=rev),
                                      params=params, extra_environ={'HTTP_X_PARTIAL_XHR': '1'})
@@ -72,7 +72,7 @@
         rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
         text = u'@%s check CommentOnRevision' % TEST_USER_REGULAR_LOGIN
 
-        params = {'text': text, '_authentication_token': self.authentication_token()}
+        params = {'text': text, '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(url(controller='changeset', action='comment',
                                      repo_name=HG_REPO, revision=rev),
                                      params=params, extra_environ={'HTTP_X_PARTIAL_XHR': '1'})
@@ -96,7 +96,7 @@
         text = u'general comment on changeset'
 
         params = {'text': text, 'changeset_status': 'rejected',
-                '_authentication_token': self.authentication_token()}
+                '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(url(controller='changeset', action='comment',
                                      repo_name=HG_REPO, revision=rev),
                                      params=params, extra_environ={'HTTP_X_PARTIAL_XHR': '1'})
@@ -123,7 +123,7 @@
         rev = '27cd5cce30c96924232dffcd24178a07ffeb5dfc'
         text = u'general comment on changeset to be deleted'
 
-        params = {'text': text, '_authentication_token': self.authentication_token()}
+        params = {'text': text, '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(url(controller='changeset', action='comment',
                                      repo_name=HG_REPO, revision=rev),
                                      params=params, extra_environ={'HTTP_X_PARTIAL_XHR': '1'})
@@ -135,7 +135,7 @@
         self.app.post(url("changeset_comment_delete",
                                     repo_name=HG_REPO,
                                     comment_id=comment_id),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         comments = ChangesetComment.query().all()
         assert len(comments) == 0
@@ -165,7 +165,7 @@
                                   'other_ref': 'branch:default:96507bd11ecc815ebc6270fdf6db110928c09c1e',
                                   'pullrequest_title': 'title',
                                   'pullrequest_desc': 'description',
-                                  '_authentication_token': self.authentication_token(),
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
         pr_id = int(re.search('/pull-request/(\d+)/', response.location).group(1))
@@ -176,7 +176,7 @@
         pr_id = self._create_pr()
 
         text = u'general comment on pullrequest'
-        params = {'text': text, '_authentication_token': self.authentication_token()}
+        params = {'text': text, '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(url(controller='pullrequests', action='comment',
                                      repo_name=HG_REPO, pull_request_id=pr_id),
                                      params=params, extra_environ={'HTTP_X_PARTIAL_XHR': '1'})
@@ -204,7 +204,7 @@
         text = u'inline comment on changeset'
         f_path = 'vcs/web/simplevcs/views/repository.py'
         line = 'n1'
-        params = {'text': text, 'f_path': f_path, 'line': line, '_authentication_token': self.authentication_token()}
+        params = {'text': text, 'f_path': f_path, 'line': line, '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(url(controller='pullrequests', action='comment',
                                      repo_name=HG_REPO, pull_request_id=pr_id),
                                      params=params, extra_environ={'HTTP_X_PARTIAL_XHR': '1'})
@@ -232,7 +232,7 @@
         pr_id = self._create_pr()
 
         text = u'@%s check CommentOnRevision' % TEST_USER_REGULAR_LOGIN
-        params = {'text': text, '_authentication_token': self.authentication_token()}
+        params = {'text': text, '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(url(controller='pullrequests', action='comment',
                                      repo_name=HG_REPO, pull_request_id=pr_id),
                                      params=params, extra_environ={'HTTP_X_PARTIAL_XHR': '1'})
@@ -256,7 +256,7 @@
 
         text = u'general comment on pullrequest'
         params = {'text': text, 'changeset_status': 'rejected',
-                '_authentication_token': self.authentication_token()}
+                '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(url(controller='pullrequests', action='comment',
                                      repo_name=HG_REPO, pull_request_id=pr_id),
                                      params=params, extra_environ={'HTTP_X_PARTIAL_XHR': '1'})
@@ -286,7 +286,7 @@
         pr_id = self._create_pr()
 
         text = u'general comment on changeset to be deleted'
-        params = {'text': text, '_authentication_token': self.authentication_token()}
+        params = {'text': text, '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(url(controller='pullrequests', action='comment',
                                      repo_name=HG_REPO, pull_request_id=pr_id),
                                      params=params, extra_environ={'HTTP_X_PARTIAL_XHR': '1'})
@@ -298,7 +298,7 @@
         self.app.post(url("pullrequest_comment_delete",
                                     repo_name=HG_REPO,
                                     comment_id=comment_id),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         comments = ChangesetComment.query().all()
         assert len(comments) == 1
@@ -317,7 +317,7 @@
 
         text = u'general comment on pullrequest'
         params = {'text': text, 'save_close': 'close',
-                '_authentication_token': self.authentication_token()}
+                '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(url(controller='pullrequests', action='comment',
                                      repo_name=HG_REPO, pull_request_id=pr_id),
                                      params=params, extra_environ={'HTTP_X_PARTIAL_XHR': '1'})
@@ -340,7 +340,7 @@
 
         text = u'general comment on pullrequest'
         params = {'text': text, 'save_delete': 'delete',
-                '_authentication_token': self.authentication_token()}
+                '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(url(controller='pullrequests', action='comment',
                                      repo_name=HG_REPO, pull_request_id=pr_id),
                                      params=params, extra_environ={'HTTP_X_PARTIAL_XHR': '1'})
@@ -360,7 +360,7 @@
         # first close
         text = u'general comment on pullrequest'
         params = {'text': text, 'save_close': 'close',
-                '_authentication_token': self.authentication_token()}
+                '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(url(controller='pullrequests', action='comment',
                                      repo_name=HG_REPO, pull_request_id=pr_id),
                                      params=params, extra_environ={'HTTP_X_PARTIAL_XHR': '1'})
@@ -368,7 +368,7 @@
 
         # attempt delete, should fail
         params = {'text': text, 'save_delete': 'delete',
-                '_authentication_token': self.authentication_token()}
+                '_session_csrf_secret_token': self.session_csrf_secret_token()}
         response = self.app.post(url(controller='pullrequests', action='comment',
                                      repo_name=HG_REPO, pull_request_id=pr_id),
                                      params=params, extra_environ={'HTTP_X_PARTIAL_XHR': '1'}, status=403)
--- a/kallithea/tests/functional/test_compare.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_compare.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,9 +1,10 @@
 # -*- coding: utf-8 -*-
-from kallithea.tests.base import *
+from kallithea.model.meta import Session
 from kallithea.model.repo import RepoModel
-from kallithea.model.meta import Session
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 
+
 fixture = Fixture()
 
 
--- a/kallithea/tests/functional/test_compare_local.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_compare_local.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 from kallithea.tests.base import *
 
+
 class TestCompareController(TestController):
 
     def test_compare_tag_hg(self):
--- a/kallithea/tests/functional/test_feed.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_feed.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,5 +1,6 @@
 from kallithea.tests.base import *
 
+
 class TestFeedController(TestController):
 
     def test_rss(self):
--- a/kallithea/tests/functional/test_files.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_files.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,12 +1,13 @@
 # -*- coding: utf-8 -*-
-import os
+import mimetypes
 import posixpath
-import mimetypes
-from kallithea.tests.base import *
+
 from kallithea.model.db import Repository
 from kallithea.model.meta import Session
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 
+
 fixture = Fixture()
 
 ARCHIVE_SPECS = {
@@ -333,7 +334,7 @@
                                       revision='tip', f_path='/'),
                                  params={
                                     'content': '',
-                                    '_authentication_token': self.authentication_token(),
+                                    '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
 
@@ -346,7 +347,7 @@
                                       revision='tip', f_path='/'),
                                  params={
                                     'content': "foo",
-                                    '_authentication_token': self.authentication_token(),
+                                    '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
 
@@ -366,7 +367,7 @@
                                     'content': "foo",
                                     'filename': filename,
                                     'location': location,
-                                    '_authentication_token': self.authentication_token(),
+                                    '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
 
@@ -387,7 +388,7 @@
                                     'content': "foo",
                                     'filename': filename,
                                     'location': location,
-                                    '_authentication_token': self.authentication_token(),
+                                    '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
         try:
@@ -410,7 +411,7 @@
                                       revision='tip', f_path='/'),
                                  params={
                                      'content': '',
-                                     '_authentication_token': self.authentication_token(),
+                                     '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
         self.checkSessionFlash(response, 'No content')
@@ -422,7 +423,7 @@
                                       revision='tip', f_path='/'),
                                  params={
                                     'content': "foo",
-                                    '_authentication_token': self.authentication_token(),
+                                    '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
 
@@ -442,7 +443,7 @@
                                     'content': "foo",
                                     'filename': filename,
                                     'location': location,
-                                    '_authentication_token': self.authentication_token(),
+                                    '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
 
@@ -463,7 +464,7 @@
                                     'content': "foo",
                                     'filename': filename,
                                     'location': location,
-                                    '_authentication_token': self.authentication_token(),
+                                    '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
         try:
@@ -493,7 +494,7 @@
                                     'content': "def py():\n print 'hello'\n",
                                     'filename': filename,
                                     'location': location,
-                                    '_authentication_token': self.authentication_token(),
+                                    '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
         response.follow()
@@ -524,7 +525,7 @@
                                     'content': "def py():\n print 'hello'\n",
                                     'filename': filename,
                                     'location': location,
-                                    '_authentication_token': self.authentication_token(),
+                                    '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
         response.follow()
@@ -538,7 +539,7 @@
                                      params={
                                         'content': "def py():\n print 'hello world'\n",
                                         'message': 'i committed',
-                                        '_authentication_token': self.authentication_token(),
+                                        '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                      },
                                     status=302)
             self.checkSessionFlash(response, 'Successfully committed to %s'
@@ -567,7 +568,7 @@
                                     'content': "def py():\n print 'hello'\n",
                                     'filename': filename,
                                     'location': location,
-                                    '_authentication_token': self.authentication_token(),
+                                    '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
         response.follow()
@@ -598,7 +599,7 @@
                                     'content': "def py():\n print 'hello'\n",
                                     'filename': filename,
                                     'location': location,
-                                    '_authentication_token': self.authentication_token(),
+                                    '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
         response.follow()
@@ -612,7 +613,7 @@
                                      params={
                                         'content': "def py():\n print 'hello world'\n",
                                         'message': 'i committed',
-                                        '_authentication_token': self.authentication_token(),
+                                        '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                      },
                                     status=302)
             self.checkSessionFlash(response, 'Successfully committed to %s'
@@ -641,7 +642,7 @@
                                     'content': "def py():\n print 'hello'\n",
                                     'filename': filename,
                                     'location': location,
-                                    '_authentication_token': self.authentication_token(),
+                                    '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
         response.follow()
@@ -672,7 +673,7 @@
                                     'content': "def py():\n print 'hello'\n",
                                     'filename': filename,
                                     'location': location,
-                                    '_authentication_token': self.authentication_token(),
+                                    '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
         response.follow()
@@ -685,7 +686,7 @@
                                           f_path=posixpath.join(location, filename)),
                                      params={
                                         'message': 'i committed',
-                                        '_authentication_token': self.authentication_token(),
+                                        '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                      },
                                     status=302)
             self.checkSessionFlash(response,
@@ -714,7 +715,7 @@
                                     'content': "def py():\n print 'hello'\n",
                                     'filename': filename,
                                     'location': location,
-                                    '_authentication_token': self.authentication_token(),
+                                    '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
         response.follow()
@@ -745,7 +746,7 @@
                                     'content': "def py():\n print 'hello'\n",
                                     'filename': filename,
                                     'location': location,
-                                    '_authentication_token': self.authentication_token(),
+                                    '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
         response.follow()
@@ -758,7 +759,7 @@
                                           f_path=posixpath.join(location, filename)),
                                      params={
                                         'message': 'i committed',
-                                        '_authentication_token': self.authentication_token(),
+                                        '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                      },
                                     status=302)
             self.checkSessionFlash(response,
--- a/kallithea/tests/functional/test_forks.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_forks.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,16 +1,15 @@
 # -*- coding: utf-8 -*-
 
 import urllib
-import unittest
 
+from kallithea.lib.utils2 import safe_str, safe_unicode
+from kallithea.model.db import Repository, User
+from kallithea.model.meta import Session
+from kallithea.model.repo import RepoModel
+from kallithea.model.user import UserModel
 from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 
-from kallithea.lib.utils2 import safe_str, safe_unicode
-from kallithea.model.db import Repository
-from kallithea.model.repo import RepoModel
-from kallithea.model.user import UserModel
-from kallithea.model.meta import Session
 
 fixture = Fixture()
 
@@ -27,12 +26,12 @@
     def setup_method(self, method):
         self.username = u'forkuser'
         self.password = u'qweqwe'
-        self.u1 = fixture.create_user(self.username, password=self.password,
-                                      email=u'fork_king@example.com')
+        u1 = fixture.create_user(self.username, password=self.password, email=u'fork_king@example.com')
+        self.u1_id = u1.user_id
         Session().commit()
 
     def teardown_method(self, method):
-        Session().delete(self.u1)
+        fixture.destroy_user(self.u1_id)
         Session().commit()
 
     def test_index(self):
@@ -44,18 +43,22 @@
         response.mustcontain("""There are no forks yet""")
 
     def test_no_permissions_to_fork(self):
-        usr = self.log_user(TEST_USER_REGULAR_LOGIN,
-                            TEST_USER_REGULAR_PASS)['user_id']
-        user_model = UserModel()
-        user_model.revoke_perm(usr, 'hg.fork.repository')
-        user_model.grant_perm(usr, 'hg.fork.none')
-        u = UserModel().get(usr)
-        u.inherit_default_permissions = False
-        Session().commit()
-        # try create a fork
-        repo_name = self.REPO
-        self.app.post(url(controller='forks', action='fork_create',
-                          repo_name=repo_name), {'_authentication_token': self.authentication_token()}, status=403)
+        self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)['user_id']
+        try:
+            user_model = UserModel()
+            usr = User.get_default_user()
+            user_model.revoke_perm(usr, 'hg.fork.repository')
+            user_model.grant_perm(usr, 'hg.fork.none')
+            Session().commit()
+            # try create a fork
+            repo_name = self.REPO
+            self.app.post(url(controller='forks', action='fork_create',
+                              repo_name=repo_name), {'_session_csrf_secret_token': self.session_csrf_secret_token()}, status=403)
+        finally:
+            usr = User.get_default_user()
+            user_model.revoke_perm(usr, 'hg.fork.none')
+            user_model.grant_perm(usr, 'hg.fork.repository')
+            Session().commit()
 
     def test_index_with_fork(self):
         self.log_user()
@@ -73,7 +76,7 @@
             'description': description,
             'private': 'False',
             'landing_rev': 'rev:tip',
-            '_authentication_token': self.authentication_token()}
+            '_session_csrf_secret_token': self.session_csrf_secret_token()}
 
         self.app.post(url(controller='forks', action='fork_create',
                           repo_name=repo_name), creation_args)
@@ -87,7 +90,7 @@
 
         # remove this fork
         response = self.app.post(url('delete_repo', repo_name=fork_name),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
 
     def test_fork_create_into_group(self):
         self.log_user()
@@ -106,7 +109,7 @@
             'description': description,
             'private': 'False',
             'landing_rev': 'rev:tip',
-            '_authentication_token': self.authentication_token()}
+            '_session_csrf_secret_token': self.session_csrf_secret_token()}
         self.app.post(url(controller='forks', action='fork_create',
                           repo_name=repo_name), creation_args)
         repo = Repository.get_by_repo_name(fork_name_full)
@@ -150,7 +153,7 @@
             'description': 'unicode repo 1',
             'private': 'False',
             'landing_rev': 'rev:tip',
-            '_authentication_token': self.authentication_token()}
+            '_session_csrf_secret_token': self.session_csrf_secret_token()}
         self.app.post(url(controller='forks', action='fork_create',
                           repo_name=repo_name), creation_args)
         response = self.app.get(url(controller='forks', action='forks',
@@ -171,7 +174,7 @@
             'description': 'unicode repo 2',
             'private': 'False',
             'landing_rev': 'rev:tip',
-            '_authentication_token': self.authentication_token()}
+            '_session_csrf_secret_token': self.session_csrf_secret_token()}
         self.app.post(url(controller='forks', action='fork_create',
                           repo_name=fork_name), creation_args)
         response = self.app.get(url(controller='forks', action='forks',
@@ -182,9 +185,9 @@
 
         # remove these forks
         response = self.app.post(url('delete_repo', repo_name=fork_name_2),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
         response = self.app.post(url('delete_repo', repo_name=fork_name),
-            params={'_authentication_token': self.authentication_token()})
+            params={'_session_csrf_secret_token': self.session_csrf_secret_token()})
 
     def test_fork_create_and_permissions(self):
         self.log_user()
@@ -200,7 +203,7 @@
             'description': description,
             'private': 'False',
             'landing_rev': 'rev:tip',
-            '_authentication_token': self.authentication_token()}
+            '_session_csrf_secret_token': self.session_csrf_secret_token()}
         self.app.post(url(controller='forks', action='fork_create',
                           repo_name=repo_name), creation_args)
         repo = Repository.get_by_repo_name(self.REPO_FORK)
@@ -245,9 +248,12 @@
         response.mustcontain('<div>fork of vcs test</div>')
 
         # remove permissions
+        default_user = User.get_default_user()
         try:
             RepoModel().grant_user_permission(repo=forks[0],
                                               user=usr, perm='repository.none')
+            RepoModel().grant_user_permission(repo=forks[0],
+                                              user=default_user, perm='repository.none')
             Session().commit()
 
             # fork shouldn't be visible
@@ -258,6 +264,8 @@
         finally:
             RepoModel().grant_user_permission(repo=forks[0],
                                               user=usr, perm='repository.read')
+            RepoModel().grant_user_permission(repo=forks[0],
+                                              user=default_user, perm='repository.read')
             RepoModel().delete(repo=forks[0])
 
 
--- a/kallithea/tests/functional/test_home.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_home.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,12 +1,11 @@
 # -*- coding: utf-8 -*-
 import json
 
+from kallithea.model.meta import Session
+from kallithea.model.repo import RepoModel
+from kallithea.model.repo_group import RepoGroupModel
 from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
-from kallithea.model.meta import Session
-from kallithea.model.db import Repository
-from kallithea.model.repo import RepoModel
-from kallithea.model.repo_group import RepoGroupModel
 
 
 fixture = Fixture()
--- a/kallithea/tests/functional/test_journal.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_journal.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,5 +1,6 @@
+import datetime
+
 from kallithea.tests.base import *
-import datetime
 
 
 class TestJournalController(TestController):
--- a/kallithea/tests/functional/test_login.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_login.py	Sun Jan 05 04:07:51 2020 +0100
@@ -3,20 +3,19 @@
 import time
 import urlparse
 
-import mock
+from tg.util.webtest import test_context
 
-from kallithea.tests.base import *
-from kallithea.tests.fixture import Fixture
+from kallithea.lib import helpers as h
+from kallithea.lib.auth import check_password
 from kallithea.lib.utils2 import generate_api_key
-from kallithea.lib.auth import check_password
-from kallithea.lib import helpers as h
+from kallithea.model import validators
 from kallithea.model.api_key import ApiKeyModel
-from kallithea.model import validators
 from kallithea.model.db import User
 from kallithea.model.meta import Session
 from kallithea.model.user import UserModel
+from kallithea.tests.base import *
+from kallithea.tests.fixture import Fixture
 
-from tg.util.webtest import test_context
 
 fixture = Fixture()
 
@@ -31,7 +30,8 @@
     def test_login_admin_ok(self):
         response = self.app.post(url(controller='login', action='index'),
                                  {'username': TEST_USER_ADMIN_LOGIN,
-                                  'password': TEST_USER_ADMIN_PASS})
+                                  'password': TEST_USER_ADMIN_PASS,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
         assert response.status == '302 Found'
         self.assert_authenticated_user(response, TEST_USER_ADMIN_LOGIN)
 
@@ -41,7 +41,8 @@
     def test_login_regular_ok(self):
         response = self.app.post(url(controller='login', action='index'),
                                  {'username': TEST_USER_REGULAR_LOGIN,
-                                  'password': TEST_USER_REGULAR_PASS})
+                                  'password': TEST_USER_REGULAR_PASS,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         assert response.status == '302 Found'
         self.assert_authenticated_user(response, TEST_USER_REGULAR_LOGIN)
@@ -52,7 +53,8 @@
     def test_login_regular_email_ok(self):
         response = self.app.post(url(controller='login', action='index'),
                                  {'username': TEST_USER_REGULAR_EMAIL,
-                                  'password': TEST_USER_REGULAR_PASS})
+                                  'password': TEST_USER_REGULAR_PASS,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         assert response.status == '302 Found'
         self.assert_authenticated_user(response, TEST_USER_REGULAR_LOGIN)
@@ -65,7 +67,8 @@
         response = self.app.post(url(controller='login', action='index',
                                      came_from=test_came_from),
                                  {'username': TEST_USER_ADMIN_LOGIN,
-                                  'password': TEST_USER_ADMIN_PASS})
+                                  'password': TEST_USER_ADMIN_PASS,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
         assert response.status == '302 Found'
         response = response.follow()
 
@@ -76,7 +79,8 @@
         response = self.app.post(url(controller='login', action='index'),
                                  {'username': TEST_USER_REGULAR_LOGIN,
                                   'password': TEST_USER_REGULAR_PASS,
-                                  'remember': False})
+                                  'remember': False,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         assert 'Set-Cookie' in response.headers
         for cookie in response.headers.getall('Set-Cookie'):
@@ -86,7 +90,8 @@
         response = self.app.post(url(controller='login', action='index'),
                                  {'username': TEST_USER_REGULAR_LOGIN,
                                   'password': TEST_USER_REGULAR_PASS,
-                                  'remember': True})
+                                  'remember': True,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         assert 'Set-Cookie' in response.headers
         for cookie in response.headers.getall('Set-Cookie'):
@@ -95,7 +100,8 @@
     def test_logout(self):
         response = self.app.post(url(controller='login', action='index'),
                                  {'username': TEST_USER_REGULAR_LOGIN,
-                                  'password': TEST_USER_REGULAR_PASS})
+                                  'password': TEST_USER_REGULAR_PASS,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         # Verify that a login session has been established.
         response = self.app.get(url(controller='login', action='index'))
@@ -123,13 +129,15 @@
         response = self.app.post(url(controller='login', action='index',
                                      came_from=url_came_from),
                                  {'username': TEST_USER_ADMIN_LOGIN,
-                                  'password': TEST_USER_ADMIN_PASS},
+                                  'password': TEST_USER_ADMIN_PASS,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()},
                                  status=400)
 
     def test_login_short_password(self):
         response = self.app.post(url(controller='login', action='index'),
                                  {'username': TEST_USER_ADMIN_LOGIN,
-                                  'password': 'as'})
+                                  'password': 'as',
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
         assert response.status == '200 OK'
 
         response.mustcontain('Enter 3 characters or more')
@@ -137,14 +145,16 @@
     def test_login_wrong_username_password(self):
         response = self.app.post(url(controller='login', action='index'),
                                  {'username': 'error',
-                                  'password': 'test12'})
+                                  'password': 'test12',
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         response.mustcontain('Invalid username or password')
 
     def test_login_non_ascii(self):
         response = self.app.post(url(controller='login', action='index'),
                                  {'username': TEST_USER_REGULAR_LOGIN,
-                                  'password': 'blåbærgrød'})
+                                  'password': 'blåbærgrød',
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         response.mustcontain('>Invalid username or password<')
 
@@ -187,7 +197,8 @@
         response = self.app.post(url(controller='login', action='index',
                                      came_from=url('/_admin/users', **args)),
                                  {'username': TEST_USER_ADMIN_LOGIN,
-                                  'password': TEST_USER_ADMIN_PASS})
+                                  'password': TEST_USER_ADMIN_PASS,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
         assert response.status == '302 Found'
         for encoded in args_encoded:
             assert encoded in response.location
@@ -201,7 +212,8 @@
         response = self.app.post(url(controller='login', action='index',
                                      came_from=url('/_admin/users', **args)),
                                  {'username': 'error',
-                                  'password': 'test12'})
+                                  'password': 'test12',
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         response.mustcontain('Invalid username or password')
         came_from = urlparse.parse_qs(urlparse.urlparse(response.form.action).query)['came_from'][0]
@@ -223,7 +235,8 @@
                                              'password_confirmation': 'test12',
                                              'email': 'goodmail@example.com',
                                              'firstname': 'test',
-                                             'lastname': 'test'})
+                                             'lastname': 'test',
+                                             '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         with test_context(self.app):
             msg = validators.ValidUsername()._messages['username_exists']
@@ -237,7 +250,8 @@
                                              'password_confirmation': 'test12',
                                              'email': TEST_USER_ADMIN_EMAIL,
                                              'firstname': 'test',
-                                             'lastname': 'test'})
+                                             'lastname': 'test',
+                                             '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         with test_context(self.app):
             msg = validators.UniqSystemEmail()()._messages['email_taken']
@@ -250,7 +264,8 @@
                                              'password_confirmation': 'test12',
                                              'email': TEST_USER_ADMIN_EMAIL.title(),
                                              'firstname': 'test',
-                                             'lastname': 'test'})
+                                             'lastname': 'test',
+                                             '_session_csrf_secret_token': self.session_csrf_secret_token()})
         with test_context(self.app):
             msg = validators.UniqSystemEmail()()._messages['email_taken']
         response.mustcontain(msg)
@@ -262,7 +277,8 @@
                                              'password_confirmation': 'test',
                                              'email': 'goodmailm',
                                              'firstname': 'test',
-                                             'lastname': 'test'})
+                                             'lastname': 'test',
+                                             '_session_csrf_secret_token': self.session_csrf_secret_token()})
         assert response.status == '200 OK'
         response.mustcontain('An email address must contain a single @')
         response.mustcontain('Enter a value 6 characters long or more')
@@ -274,7 +290,8 @@
                                              'password_confirmation': 'test12',
                                              'email': 'goodmailm',
                                              'firstname': 'test',
-                                             'lastname': 'test'})
+                                             'lastname': 'test',
+                                             '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         response.mustcontain('An email address must contain a single @')
         response.mustcontain('Username may only contain '
@@ -290,7 +307,8 @@
                                              'password_confirmation': 'test12',
                                              'email': 'goodmailm',
                                              'firstname': 'test',
-                                             'lastname': 'test'})
+                                             'lastname': 'test',
+                                             '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         response.mustcontain('An email address must contain a single @')
         with test_context(self.app):
@@ -305,7 +323,8 @@
                                          'password_confirmation': 'ąćźżąśśśś',
                                          'email': 'goodmailm@test.plx',
                                          'firstname': 'test',
-                                         'lastname': 'test'})
+                                         'lastname': 'test',
+                                         '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         with test_context(self.app):
             msg = validators.ValidPassword()._messages['invalid_password']
@@ -318,7 +337,8 @@
                                              'password_confirmation': 'qwe123',
                                              'email': 'goodmailm@test.plxa',
                                              'firstname': 'test',
-                                             'lastname': 'test'})
+                                             'lastname': 'test',
+                                             '_session_csrf_secret_token': self.session_csrf_secret_token()})
         with test_context(self.app):
             msg = validators.ValidPasswordsMatch('password', 'password_confirmation')._messages['password_mismatch']
         response.mustcontain(msg)
@@ -337,7 +357,8 @@
                                              'email': email,
                                              'firstname': name,
                                              'lastname': lastname,
-                                             'admin': True})  # This should be overridden
+                                             'admin': True,
+                                             '_session_csrf_secret_token': self.session_csrf_secret_token()})  # This should be overridden
         assert response.status == '302 Found'
         self.checkSessionFlash(response, 'You have successfully registered with Kallithea')
 
@@ -358,8 +379,8 @@
         bad_email = 'username%wrongmail.org'
         response = self.app.post(
                         url(controller='login', action='password_reset'),
-                            {'email': bad_email, }
-        )
+                            {'email': bad_email,
+                             '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         response.mustcontain('An email address must contain a single @')
 
@@ -387,7 +408,8 @@
 
         response = self.app.post(url(controller='login',
                                      action='password_reset'),
-                                 {'email': email, })
+                                 {'email': email,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         self.checkSessionFlash(response, 'A password reset confirmation code has been sent')
 
@@ -404,6 +426,7 @@
                                   'password': "p@ssw0rd",
                                   'password_confirm': "p@ssw0rd",
                                   'token': token,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  })
         assert response.status == '200 OK'
         response.mustcontain('Invalid password reset token')
@@ -414,7 +437,7 @@
         # above, instead of being recalculated.
 
         token = UserModel().get_reset_password_token(
-            User.get_by_username(username), timestamp, self.authentication_token())
+            User.get_by_username(username), timestamp, self.session_csrf_secret_token())
 
         response = self.app.get(url(controller='login',
                                     action='password_reset_confirmation',
@@ -431,6 +454,7 @@
                                   'password': "p@ssw0rd",
                                   'password_confirm': "p@ssw0rd",
                                   'token': token,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  })
         assert response.status == '302 Found'
         self.checkSessionFlash(response, 'Successfully updated password')
@@ -441,10 +465,6 @@
     # API
     #==========================================================================
 
-    def _get_api_whitelist(self, values=None):
-        config = {'api_access_controllers_whitelist': values or []}
-        return config
-
     def _api_key_test(self, api_key, status):
         """Verifies HTTP status code for accessing an auth-requiring page,
         using the given api_key URL parameter as well as using the API key
@@ -476,45 +496,22 @@
         ('none', None, 302),
         ('empty_string', '', 403),
         ('fake_number', '123456', 403),
-        ('proper_api_key', True, 403)
-    ])
-    def test_access_not_whitelisted_page_via_api_key(self, test_name, api_key, code):
-        whitelist = self._get_api_whitelist([])
-        with mock.patch('kallithea.CONFIG', whitelist):
-            assert [] == whitelist['api_access_controllers_whitelist']
-            self._api_key_test(api_key, code)
-
-    @parametrize('test_name,api_key,code', [
-        ('none', None, 302),
-        ('empty_string', '', 403),
-        ('fake_number', '123456', 403),
         ('fake_not_alnum', 'a-z', 403),
         ('fake_api_key', '0123456789abcdef0123456789ABCDEF01234567', 403),
         ('proper_api_key', True, 200)
     ])
-    def test_access_whitelisted_page_via_api_key(self, test_name, api_key, code):
-        whitelist = self._get_api_whitelist(['ChangesetController:changeset_raw'])
-        with mock.patch('kallithea.CONFIG', whitelist):
-            assert ['ChangesetController:changeset_raw'] == whitelist['api_access_controllers_whitelist']
-            self._api_key_test(api_key, code)
+    def test_access_page_via_api_key(self, test_name, api_key, code):
+        self._api_key_test(api_key, code)
 
     def test_access_page_via_extra_api_key(self):
-        whitelist = self._get_api_whitelist(['ChangesetController:changeset_raw'])
-        with mock.patch('kallithea.CONFIG', whitelist):
-            assert ['ChangesetController:changeset_raw'] == whitelist['api_access_controllers_whitelist']
-
-            new_api_key = ApiKeyModel().create(TEST_USER_ADMIN_LOGIN, u'test')
-            Session().commit()
-            self._api_key_test(new_api_key.api_key, status=200)
+        new_api_key = ApiKeyModel().create(TEST_USER_ADMIN_LOGIN, u'test')
+        Session().commit()
+        self._api_key_test(new_api_key.api_key, status=200)
 
     def test_access_page_via_expired_api_key(self):
-        whitelist = self._get_api_whitelist(['ChangesetController:changeset_raw'])
-        with mock.patch('kallithea.CONFIG', whitelist):
-            assert ['ChangesetController:changeset_raw'] == whitelist['api_access_controllers_whitelist']
-
-            new_api_key = ApiKeyModel().create(TEST_USER_ADMIN_LOGIN, u'test')
-            Session().commit()
-            # patch the API key and make it expired
-            new_api_key.expires = 0
-            Session().commit()
-            self._api_key_test(new_api_key.api_key, status=403)
+        new_api_key = ApiKeyModel().create(TEST_USER_ADMIN_LOGIN, u'test')
+        Session().commit()
+        # patch the API key and make it expired
+        new_api_key.expires = 0
+        Session().commit()
+        self._api_key_test(new_api_key.api_key, status=403)
--- a/kallithea/tests/functional/test_my_account.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_my_account.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,13 +1,14 @@
 # -*- coding: utf-8 -*-
 
-from kallithea.model.db import User, UserFollowing, Repository, UserApiKeys
+from tg.util.webtest import test_context
+
+from kallithea.lib import helpers as h
+from kallithea.model.db import Repository, User, UserApiKeys, UserFollowing, UserSshKeys
+from kallithea.model.meta import Session
+from kallithea.model.user import UserModel
 from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
-from kallithea.lib import helpers as h
-from kallithea.model.user import UserModel
-from kallithea.model.meta import Session
 
-from tg.util.webtest import test_context
 
 fixture = Fixture()
 
@@ -54,7 +55,7 @@
         response = self.app.get(url('my_account_emails'))
         response.mustcontain('No additional emails specified')
         response = self.app.post(url('my_account_emails'),
-                                 {'new_email': TEST_USER_REGULAR_EMAIL, '_authentication_token': self.authentication_token()})
+                                 {'new_email': TEST_USER_REGULAR_EMAIL, '_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'This email address is already in use')
 
     def test_my_account_my_emails_add_missing_email_in_form(self):
@@ -62,7 +63,7 @@
         response = self.app.get(url('my_account_emails'))
         response.mustcontain('No additional emails specified')
         response = self.app.post(url('my_account_emails'),
-            {'_authentication_token': self.authentication_token()})
+            {'_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'Please enter an email address')
 
     def test_my_account_my_emails_add_remove(self):
@@ -71,7 +72,7 @@
         response.mustcontain('No additional emails specified')
 
         response = self.app.post(url('my_account_emails'),
-                                 {'new_email': 'barz@example.com', '_authentication_token': self.authentication_token()})
+                                 {'new_email': 'barz@example.com', '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         response = self.app.get(url('my_account_emails'))
 
@@ -84,7 +85,7 @@
         response.mustcontain('<input id="del_email_id" name="del_email_id" type="hidden" value="%s" />' % email_id)
 
         response = self.app.post(url('my_account_emails_delete'),
-                                 {'del_email_id': email_id, '_authentication_token': self.authentication_token()})
+                                 {'del_email_id': email_id, '_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'Removed email from user')
         response = self.app.get(url('my_account_emails'))
         response.mustcontain('No additional emails specified')
@@ -119,7 +120,7 @@
         params.update({'new_password': ''})
         params.update({'extern_type': 'internal'})
         params.update({'extern_name': self.test_user_1})
-        params.update({'_authentication_token': self.authentication_token()})
+        params.update({'_session_csrf_secret_token': self.session_csrf_secret_token()})
 
         params.update(attrs)
         response = self.app.post(url('my_account'), params)
@@ -148,7 +149,7 @@
             # my account cannot make you an admin !
             params['admin'] = False
 
-        params.pop('_authentication_token')
+        params.pop('_session_csrf_secret_token')
         assert params == updated_params
 
     def test_my_account_update_err_email_exists(self):
@@ -163,7 +164,7 @@
                                     firstname=u'NewName',
                                     lastname=u'NewLastname',
                                     email=new_email,
-                                    _authentication_token=self.authentication_token())
+                                    _session_csrf_secret_token=self.session_csrf_secret_token())
                                 )
 
         response.mustcontain('This email address is already in use')
@@ -180,7 +181,7 @@
                                             firstname=u'NewName',
                                             lastname=u'NewLastname',
                                             email=new_email,
-                                            _authentication_token=self.authentication_token()))
+                                            _session_csrf_secret_token=self.session_csrf_secret_token()))
 
         response.mustcontain('An email address must contain a single @')
         from kallithea.model import validators
@@ -206,7 +207,7 @@
         usr = self.log_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS)
         user = User.get(usr['user_id'])
         response = self.app.post(url('my_account_api_keys'),
-                                 {'description': desc, 'lifetime': lifetime, '_authentication_token': self.authentication_token()})
+                                 {'description': desc, 'lifetime': lifetime, '_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'API key successfully created')
         try:
             response = response.follow()
@@ -222,7 +223,7 @@
         usr = self.log_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS)
         user = User.get(usr['user_id'])
         response = self.app.post(url('my_account_api_keys'),
-                                 {'description': 'desc', 'lifetime': -1, '_authentication_token': self.authentication_token()})
+                                 {'description': 'desc', 'lifetime': -1, '_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'API key successfully created')
         response = response.follow()
 
@@ -231,7 +232,7 @@
         assert 1 == len(keys)
 
         response = self.app.post(url('my_account_api_keys_delete'),
-                 {'del_api_key': keys[0].api_key, '_authentication_token': self.authentication_token()})
+                 {'del_api_key': keys[0].api_key, '_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'API key successfully deleted')
         keys = UserApiKeys.query().all()
         assert 0 == len(keys)
@@ -245,7 +246,51 @@
         response.mustcontain('Expires: Never')
 
         response = self.app.post(url('my_account_api_keys_delete'),
-                 {'del_api_key_builtin': api_key, '_authentication_token': self.authentication_token()})
+                 {'del_api_key_builtin': api_key, '_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'API key successfully reset')
         response = response.follow()
         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'
+
+        self.log_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS)
+        response = self.app.post(url('my_account_ssh_keys'),
+                                 {'description': description,
+                                  'public_key': public_key,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
+        self.checkSessionFlash(response, 'SSH key %s successfully added' % fingerprint)
+
+        response = response.follow()
+        response.mustcontain(fingerprint)
+        user_id = response.session['authuser']['user_id']
+        ssh_key = UserSshKeys.query().filter(UserSshKeys.user_id == user_id).one()
+        assert ssh_key.fingerprint == fingerprint
+        assert ssh_key.description == description
+        Session().delete(ssh_key)
+        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'
+
+        self.log_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS)
+        response = self.app.post(url('my_account_ssh_keys'),
+                                 {'description': description,
+                                  'public_key': public_key,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
+        self.checkSessionFlash(response, 'SSH key %s successfully added' % fingerprint)
+        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'
+
+        response = self.app.post(url('my_account_ssh_keys_delete'),
+                                 {'del_public_key': ssh_key.public_key,
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token()})
+        self.checkSessionFlash(response, 'SSH key successfully deleted')
+        keys = UserSshKeys.query().all()
+        assert 0 == len(keys)
--- a/kallithea/tests/functional/test_pullrequests.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_pullrequests.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,14 +1,13 @@
 import re
+
 import pytest
 
-from tg.util.webtest import test_context
-
+from kallithea.controllers.pullrequests import PullrequestsController
+from kallithea.model.db import PullRequest, User
+from kallithea.model.meta import Session
 from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
-from kallithea.model.db import PullRequest, User
-from kallithea.model.meta import Session
 
-from kallithea.controllers.pullrequests import PullrequestsController
 
 fixture = Fixture()
 
@@ -30,7 +29,7 @@
                                   'other_ref': 'branch:default:96507bd11ecc815ebc6270fdf6db110928c09c1e',
                                   'pullrequest_title': 'title',
                                   'pullrequest_desc': 'description',
-                                  '_authentication_token': self.authentication_token(),
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
         response = response.follow()
@@ -49,7 +48,7 @@
                                   'other_ref': 'branch:default:96507bd11ecc815ebc6270fdf6db110928c09c1e',
                                   'pullrequest_title': 'title',
                                   'pullrequest_desc': 'description',
-                                  '_authentication_token': self.authentication_token(),
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
         response = response.follow()
@@ -69,7 +68,7 @@
                                   'other_ref': 'rev:94f45ed825a1:94f45ed825a113e61af7e141f44ca578374abef0',
                                   'pullrequest_title': 'title',
                                   'pullrequest_desc': 'description',
-                                  '_authentication_token': self.authentication_token(),
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
         response = response.follow()
@@ -92,7 +91,7 @@
                                   'other_ref': 'branch:default:96507bd11ecc815ebc6270fdf6db110928c09c1e',
                                   'pullrequest_title': 'title',
                                   'pullrequest_desc': 'description',
-                                  '_authentication_token': self.authentication_token(),
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                  status=302)
         pull_request1_id = re.search('/pull-request/(\d+)/', response.location).group(1)
@@ -106,7 +105,7 @@
                                   'pullrequest_title': 'title',
                                   'pullrequest_desc': 'description',
                                   'owner': TEST_USER_ADMIN_LOGIN,
-                                  '_authentication_token': self.authentication_token(),
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                   'review_members': [regular_user.user_id],
                                  },
                                  status=302)
@@ -124,7 +123,7 @@
                                   'pullrequest_title': 'Title',
                                   'pullrequest_desc': 'description',
                                   'owner': TEST_USER_ADMIN_LOGIN,
-                                  '_authentication_token': self.authentication_token(),
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                   'org_review_members': [admin_user.user_id], # fake - just to get some 'meanwhile' warning ... but it is also added ...
                                   'review_members': [regular_user2.user_id, admin_user.user_id],
                                  },
@@ -151,7 +150,7 @@
                                   'other_ref': 'branch:default:96507bd11ecc815ebc6270fdf6db110928c09c1e',
                                   'pullrequest_title': 'title',
                                   'pullrequest_desc': 'description',
-                                  '_authentication_token': self.authentication_token(),
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                 status=302)
         # location is of the form:
@@ -168,7 +167,7 @@
                                   'pullrequest_title': 'title',
                                   'pullrequest_desc': 'description',
                                   'owner': TEST_USER_ADMIN_LOGIN,
-                                  '_authentication_token': self.authentication_token(),
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                   'review_members': [str(invalid_user_id)],
                                  },
                                  status=400)
@@ -187,7 +186,7 @@
                                   'other_ref': 'branch:default:96507bd11ecc815ebc6270fdf6db110928c09c1e',
                                   'pullrequest_title': 'title',
                                   'pullrequest_desc': 'description',
-                                  '_authentication_token': self.authentication_token(),
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                  },
                                 status=302)
         # location is of the form:
@@ -203,7 +202,7 @@
                                   'pullrequest_title': 'title',
                                   'pullrequest_desc': 'description',
                                   'owner': TEST_USER_ADMIN_LOGIN,
-                                  '_authentication_token': self.authentication_token(),
+                                  '_session_csrf_secret_token': self.session_csrf_secret_token(),
                                   'review_members': [str(invalid_user_id)],
                                  },
                                  status=400)
@@ -235,7 +234,7 @@
                 'other_ref': 'branch:default:3d1091ee5a533b1f4577ec7d8a226bb315fb1336',
                 'pullrequest_title': 'title',
                 'pullrequest_desc': 'description',
-                '_authentication_token': self.authentication_token(),
+                '_session_csrf_secret_token': self.session_csrf_secret_token(),
             },
             status=302)
         pr1_id = int(re.search('/pull-request/(\d+)/', response.location).group(1))
@@ -254,7 +253,7 @@
                 'pullrequest_title': 'title',
                 'pullrequest_desc': 'description',
                 'owner': TEST_USER_REGULAR_LOGIN,
-                '_authentication_token': self.authentication_token(),
+                '_session_csrf_secret_token': self.session_csrf_secret_token(),
              },
              status=302)
         pr2_id = int(re.search('/pull-request/(\d+)/', response.location).group(1))
@@ -276,7 +275,7 @@
                 'pullrequest_title': 'title',
                 'pullrequest_desc': 'description',
                 'owner': TEST_USER_REGULAR_LOGIN,
-                '_authentication_token': self.authentication_token(),
+                '_session_csrf_secret_token': self.session_csrf_secret_token(),
              },
              status=302)
         pr3_id = int(re.search('/pull-request/(\d+)/', response.location).group(1))
--- a/kallithea/tests/functional/test_repo_groups.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_repo_groups.py	Sun Jan 05 04:07:51 2020 +0100
@@ -20,7 +20,7 @@
         # creation with form error
         response = self.app.post(url('repos_groups'),
                                          {'group_name': group_name,
-                                          '_authentication_token': self.authentication_token()})
+                                          '_session_csrf_secret_token': self.session_csrf_secret_token()})
         response.mustcontain('name="group_name" type="text" value="%s"' % group_name)
         response.mustcontain('<!-- for: group_description -->')
 
@@ -30,7 +30,7 @@
                                          'group_description': 'lala',
                                          'parent_group_id': '-1',
                                          'group_copy_permissions': 'True',
-                                          '_authentication_token': self.authentication_token()})
+                                          '_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'Created repository group %s' % group_name)
 
         # edit form
@@ -40,7 +40,7 @@
         # edit with form error
         response = self.app.post(url('update_repos_group', group_name=group_name),
                                          {'group_name': group_name,
-                                          '_authentication_token': self.authentication_token()})
+                                          '_session_csrf_secret_token': self.session_csrf_secret_token()})
         response.mustcontain('name="group_name" type="text" value="%s"' % group_name)
         response.mustcontain('<!-- for: group_description -->')
 
@@ -48,7 +48,7 @@
         response = self.app.post(url('update_repos_group', group_name=group_name),
                                          {'group_name': group_name,
                                          'group_description': 'lolo',
-                                          '_authentication_token': self.authentication_token()})
+                                          '_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'Updated repository group %s' % group_name)
         response = response.follow()
         response.mustcontain('name="group_name" type="text" value="%s"' % group_name)
@@ -69,7 +69,7 @@
 
         # delete
         response = self.app.post(url('delete_repo_group', group_name=group_name),
-                                 {'_authentication_token': self.authentication_token()})
+                                 {'_session_csrf_secret_token': self.session_csrf_secret_token()})
         self.checkSessionFlash(response, 'Removed repository group %s' % group_name)
 
     def test_new_by_regular_user(self):
--- a/kallithea/tests/functional/test_search.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_search.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,5 +1,5 @@
 import mock
-import os
+
 from kallithea.tests.base import *
 
 
@@ -16,10 +16,8 @@
         self.log_user()
 
         config_mock = {
-            'app_conf': {
-                # can be any existing dir that does not contain an actual index
-                'index_dir': str(tmpdir),
-            }
+            # can be any existing dir that does not contain an actual index
+            'index_dir': str(tmpdir),
         }
         with mock.patch('kallithea.controllers.search.config', config_mock):
             response = self.app.get(url(controller='search', action='index'),
--- a/kallithea/tests/functional/test_search_indexing.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_search_indexing.py	Sun Jan 05 04:07:51 2020 +0100
@@ -6,7 +6,8 @@
 from kallithea.model.repo import RepoModel
 from kallithea.model.repo_group import RepoGroupModel
 from kallithea.tests.base import *
-from kallithea.tests.fixture import create_test_index, Fixture
+from kallithea.tests.fixture import Fixture, create_test_index
+
 
 fixture = Fixture()
 
--- a/kallithea/tests/functional/test_summary.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/functional/test_summary.py	Sun Jan 05 04:07:51 2020 +0100
@@ -12,19 +12,29 @@
 # 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 pytest
+
+from kallithea.model.db import Repository
+from kallithea.model.meta import Session
+from kallithea.model.repo import RepoModel
+from kallithea.model.scm import ScmModel
 from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
-from kallithea.model.db import Repository
-from kallithea.model.repo import RepoModel
-from kallithea.model.meta import Session
-from kallithea.model.scm import ScmModel
+
 
 fixture = Fixture()
 
+@pytest.fixture
+def custom_settings(set_test_settings):
+    # overwrite DEFAULT_CLONE_SSH = 'ssh://{system_user}@{hostname}/{repo}'
+    set_test_settings(
+        ('clone_ssh_tmpl', 'ssh://ssh_user@ssh_hostname/{repo}', 'unicode'),
+        )
+
 
 class TestSummaryController(TestController):
 
-    def test_index_hg(self):
+    def test_index_hg(self, custom_settings):
         self.log_user()
         ID = Repository.get_by_repo_name(HG_REPO).repo_id
         response = self.app.get(url(controller='summary',
@@ -39,8 +49,7 @@
         response.mustcontain(
             """<i class="icon-globe">"""
         )
-
-        # clone url...
+        # clone URLs
         response.mustcontain(
             '''<input class="form-control" size="80" readonly="readonly" value="http://%s@localhost:80/%s"/>''' %
             (TEST_USER_ADMIN_LOGIN, HG_REPO)
@@ -49,8 +58,13 @@
             '''<input class="form-control" size="80" readonly="readonly" value="http://%s@localhost:80/_%s"/>''' %
             (TEST_USER_ADMIN_LOGIN, ID)
         )
+        response.mustcontain(
+            '''<input id="ssh_url" class="form-control" size="80" readonly="readonly" value="ssh://ssh_user@ssh_hostname/%s"/>''' %
+            (HG_REPO)
+        )
 
-    def test_index_git(self):
+
+    def test_index_git(self, custom_settings):
         self.log_user()
         ID = Repository.get_by_repo_name(GIT_REPO).repo_id
         response = self.app.get(url(controller='summary',
@@ -65,15 +79,19 @@
         response.mustcontain(
             """<i class="icon-globe">"""
         )
-
-        # clone url...
+        # clone URLs
         response.mustcontain(
             '''<input class="form-control" size="80" readonly="readonly" value="http://%s@localhost:80/%s"/>''' %
-            (TEST_USER_ADMIN_LOGIN, GIT_REPO))
+            (TEST_USER_ADMIN_LOGIN, GIT_REPO)
+        )
         response.mustcontain(
             '''<input class="form-control" size="80" readonly="readonly" value="http://%s@localhost:80/_%s"/>''' %
             (TEST_USER_ADMIN_LOGIN, ID)
         )
+        response.mustcontain(
+            '''<input id="ssh_url" class="form-control" size="80" readonly="readonly" value="ssh://ssh_user@ssh_hostname/%s"/>''' %
+            (GIT_REPO)
+        )
 
     def test_index_by_id_hg(self):
         self.log_user()
@@ -141,12 +159,12 @@
             '["rst", {"count": 16, "desc": ["Rst"]}], '
             '["css", {"count": 2, "desc": ["Css"]}], '
             '["sh", {"count": 2, "desc": ["Bash"]}], '
-            '["yml", {"count": 1, "desc": ["Yaml"]}], '
-            '["makefile", {"count": 1, "desc": ["Makefile", "Makefile"]}], '
+            '["bat", {"count": 1, "desc": ["Batch"]}], '
+            '["cfg", {"count": 1, "desc": ["Ini"]}], '
+            '["html", {"count": 1, "desc": ["EvoqueHtml", "Html"]}], '
+            '["ini", {"count": 1, "desc": ["Ini"]}], '
             '["js", {"count": 1, "desc": ["Javascript"]}], '
-            '["cfg", {"count": 1, "desc": ["Ini"]}], '
-            '["ini", {"count": 1, "desc": ["Ini"]}], '
-            '["html", {"count": 1, "desc": ["EvoqueHtml", "Html"]}]]'
+            '["makefile", {"count": 1, "desc": ["Makefile", "Makefile"]}]]',
         )
 
     def test_index_statistics(self):
@@ -174,12 +192,12 @@
             '["rst", {"count": 16, "desc": ["Rst"]}], '
             '["css", {"count": 2, "desc": ["Css"]}], '
             '["sh", {"count": 2, "desc": ["Bash"]}], '
-            '["makefile", {"count": 1, "desc": ["Makefile", "Makefile"]}], '
-            '["js", {"count": 1, "desc": ["Javascript"]}], '
+            '["bat", {"count": 1, "desc": ["Batch"]}], '
             '["cfg", {"count": 1, "desc": ["Ini"]}], '
+            '["html", {"count": 1, "desc": ["EvoqueHtml", "Html"]}], '
             '["ini", {"count": 1, "desc": ["Ini"]}], '
-            '["html", {"count": 1, "desc": ["EvoqueHtml", "Html"]}], '
-            '["bat", {"count": 1, "desc": ["Batch"]}]]'
+            '["js", {"count": 1, "desc": ["Javascript"]}], '
+            '["makefile", {"count": 1, "desc": ["Makefile", "Makefile"]}]]',
         )
 
     def test_index_statistics_git(self):
--- a/kallithea/tests/models/common.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/models/common.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,13 +1,10 @@
-from kallithea.tests.base import *
-from kallithea.tests.fixture import Fixture
-
-from kallithea.model.repo_group import RepoGroupModel
+from kallithea.lib.auth import AuthUser
+from kallithea.model.db import RepoGroup, Repository, User
+from kallithea.model.meta import Session
 from kallithea.model.repo import RepoModel
-from kallithea.model.db import RepoGroup, Repository, User
+from kallithea.model.repo_group import RepoGroupModel
 from kallithea.model.user import UserModel
-
-from kallithea.lib.auth import AuthUser
-from kallithea.model.meta import Session
+from kallithea.tests.fixture import Fixture
 
 
 fixture = Fixture()
--- a/kallithea/tests/models/test_changeset_status.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/models/test_changeset_status.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,6 +1,6 @@
-from kallithea.tests.base import *
 from kallithea.model.changeset_status import ChangesetStatusModel
 from kallithea.model.db import ChangesetStatus as CS
+from kallithea.tests.base import *
 
 
 class CSM(object): # ChangesetStatusMock
--- a/kallithea/tests/models/test_comments.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/models/test_comments.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,9 +1,10 @@
-from kallithea.tests.base import *
+import pytest
+from tg.util.webtest import test_context
+
 from kallithea.model.comment import ChangesetCommentsModel
 from kallithea.model.db import Repository
+from kallithea.tests.base import *
 
-import pytest
-from tg.util.webtest import test_context
 
 class TestComments(TestController):
 
--- a/kallithea/tests/models/test_diff_parsers.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/models/test_diff_parsers.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,8 +1,8 @@
+from kallithea.lib.diffs import BIN_FILENODE, CHMOD_FILENODE, COPIED_FILENODE, DEL_FILENODE, MOD_FILENODE, NEW_FILENODE, RENAMED_FILENODE, DiffProcessor
 from kallithea.tests.base import *
-from kallithea.lib.diffs import DiffProcessor, NEW_FILENODE, DEL_FILENODE, \
-    MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE
 from kallithea.tests.fixture import Fixture
 
+
 fixture = Fixture()
 
 
@@ -294,7 +294,6 @@
         for d in chunks[1]:
             l.append('%(action)-7s %(new_lineno)3s %(old_lineno)3s %(line)r\n' % d)
         s = ''.join(l)
-        print s
         assert s == r'''
 context ... ... u'@@ -51,6 +51,13 @@\n'
 unmod    51  51 u'<u>\t</u>begin();\n'
--- a/kallithea/tests/models/test_notifications.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/models/test_notifications.py	Sun Jan 05 04:07:51 2020 +0100
@@ -2,19 +2,16 @@
 import re
 
 import mock
-import routes.util
-
-from kallithea.tests.base import *
-from kallithea.lib import helpers as h
-from kallithea.model.db import User
-from kallithea.model.user import UserModel
-from kallithea.model.meta import Session
-from kallithea.model.notification import NotificationModel, EmailNotificationModel
+from tg.util.webtest import test_context
 
 import kallithea.lib.celerylib
 import kallithea.lib.celerylib.tasks
-
-from tg.util.webtest import test_context
+from kallithea.lib import helpers as h
+from kallithea.model.db import User
+from kallithea.model.meta import Session
+from kallithea.model.notification import EmailNotificationModel, NotificationModel
+from kallithea.model.user import UserModel
+from kallithea.tests.base import *
 
 
 class TestNotifications(TestController):
--- a/kallithea/tests/models/test_permissions.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/models/test_permissions.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,15 +1,13 @@
+from kallithea.lib.auth import AuthUser
+from kallithea.model.db import Permission, RepoGroup, User, UserGroupRepoGroupToPerm, UserToPerm
+from kallithea.model.meta import Session
+from kallithea.model.permission import PermissionModel
+from kallithea.model.repo import RepoModel
+from kallithea.model.repo_group import RepoGroupModel
+from kallithea.model.user import UserModel
+from kallithea.model.user_group import UserGroupModel
 from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
-from kallithea.model.repo_group import RepoGroupModel
-from kallithea.model.repo import RepoModel
-from kallithea.model.db import RepoGroup, User, UserGroupRepoGroupToPerm, \
-    Permission, UserToPerm
-from kallithea.model.user import UserModel
-
-from kallithea.model.meta import Session
-from kallithea.model.user_group import UserGroupModel
-from kallithea.lib.auth import AuthUser
-from kallithea.model.permission import PermissionModel
 
 
 fixture = Fixture()
@@ -132,29 +130,20 @@
         self.ug1 = fixture.create_user_group(u'G1')
         UserGroupModel().add_user_to_group(self.ug1, self.u1)
 
-        # set permission to lower
-        new_perm = 'repository.none'
-        RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, perm=new_perm)
+        # set user permission none
+        RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, perm='repository.none')
         Session().commit()
         u1_auth = AuthUser(user_id=self.u1.user_id)
-        assert u1_auth.permissions['repositories'][HG_REPO] == new_perm
+        assert u1_auth.permissions['repositories'][HG_REPO] == 'repository.read' # inherit from default user
 
-        # grant perm for group this should not override permission from user
-        # since it has explicitly set
-        new_perm_gr = 'repository.write'
+        # grant perm for group this should override permission from user
         RepoModel().grant_user_group_permission(repo=HG_REPO,
                                                  group_name=self.ug1,
-                                                 perm=new_perm_gr)
-        # check perms
+                                                 perm='repository.write')
+
+        # verify that user group permissions win
         u1_auth = AuthUser(user_id=self.u1.user_id)
-        perms = {
-            'repositories_groups': {},
-            'global': set(['hg.create.repository', 'repository.read',
-                           'hg.register.manual_activate']),
-            'repositories': {HG_REPO: 'repository.read'}
-        }
-        assert u1_auth.permissions['repositories'][HG_REPO] == new_perm
-        assert u1_auth.permissions['repositories_groups'] == perms['repositories_groups']
+        assert u1_auth.permissions['repositories'][HG_REPO] == 'repository.write'
 
     def test_propagated_permission_from_users_group(self):
         # make group
@@ -310,7 +299,7 @@
         u1_auth = AuthUser(user_id=self.u1.user_id)
         assert u1_auth.permissions['repositories_groups'] == {u'group1': u'group.read'}
 
-    def test_inherited_permissions_from_default_on_user_enabled(self):
+    def test_inherit_nice_permissions_from_default_user(self):
         user_model = UserModel()
         # enable fork and create on default user
         usr = 'default'
@@ -318,8 +307,6 @@
         user_model.grant_perm(usr, 'hg.create.repository')
         user_model.revoke_perm(usr, 'hg.fork.none')
         user_model.grant_perm(usr, 'hg.fork.repository')
-        # make sure inherit flag is turned on
-        self.u1.inherit_default_permissions = True
         Session().commit()
         u1_auth = AuthUser(user_id=self.u1.user_id)
         # this user will have inherited permissions from default user
@@ -329,7 +316,7 @@
                               'repository.read', 'group.read',
                               'usergroup.read', 'hg.create.write_on_repogroup.true'])
 
-    def test_inherited_permissions_from_default_on_user_disabled(self):
+    def test_inherit_sad_permissions_from_default_user(self):
         user_model = UserModel()
         # disable fork and create on default user
         usr = 'default'
@@ -337,8 +324,6 @@
         user_model.grant_perm(usr, 'hg.create.none')
         user_model.revoke_perm(usr, 'hg.fork.repository')
         user_model.grant_perm(usr, 'hg.fork.none')
-        # make sure inherit flag is turned on
-        self.u1.inherit_default_permissions = True
         Session().commit()
         u1_auth = AuthUser(user_id=self.u1.user_id)
         # this user will have inherited permissions from default user
@@ -348,7 +333,7 @@
                               'repository.read', 'group.read',
                               'usergroup.read', 'hg.create.write_on_repogroup.true'])
 
-    def test_non_inherited_permissions_from_default_on_user_enabled(self):
+    def test_inherit_more_permissions_from_default_user(self):
         user_model = UserModel()
         # enable fork and create on default user
         usr = 'default'
@@ -363,19 +348,18 @@
         user_model.revoke_perm(self.u1, 'hg.fork.repository')
         user_model.grant_perm(self.u1, 'hg.fork.none')
 
-        # make sure inherit flag is turned off
-        self.u1.inherit_default_permissions = False
         Session().commit()
         u1_auth = AuthUser(user_id=self.u1.user_id)
-        # this user will have non inherited permissions from he's
-        # explicitly set permissions
-        assert u1_auth.permissions['global'] == set(['hg.create.none', 'hg.fork.none',
+        # this user will have inherited more permissions from default user
+        assert u1_auth.permissions['global'] == set([
+                              'hg.create.repository',
+                              'hg.fork.repository',
                               'hg.register.manual_activate',
                               'hg.extern_activate.auto',
                               'repository.read', 'group.read',
                               'usergroup.read', 'hg.create.write_on_repogroup.true'])
 
-    def test_non_inherited_permissions_from_default_on_user_disabled(self):
+    def test_inherit_less_permissions_from_default_user(self):
         user_model = UserModel()
         # disable fork and create on default user
         usr = 'default'
@@ -390,25 +374,21 @@
         user_model.revoke_perm(self.u1, 'hg.fork.none')
         user_model.grant_perm(self.u1, 'hg.fork.repository')
 
-        # make sure inherit flag is turned off
-        self.u1.inherit_default_permissions = False
         Session().commit()
         u1_auth = AuthUser(user_id=self.u1.user_id)
-        # this user will have non inherited permissions from he's
-        # explicitly set permissions
-        assert u1_auth.permissions['global'] == set(['hg.create.repository', 'hg.fork.repository',
+        # this user will have inherited less permissions from default user
+        assert u1_auth.permissions['global'] == set([
+                              'hg.create.repository',
+                              'hg.fork.repository',
                               'hg.register.manual_activate',
                               'hg.extern_activate.auto',
                               'repository.read', 'group.read',
                               'usergroup.read', 'hg.create.write_on_repogroup.true'])
 
     def test_inactive_user_group_does_not_affect_global_permissions(self):
-        # Issue #138: Inactive User Groups affecting permissions
         # Add user to inactive user group, set specific permissions on user
-        # group and disable inherit-from-default. User permissions should still
-        # inherit from default.
+        # group and and verify it really is inactive.
         self.ug1 = fixture.create_user_group(u'G1')
-        self.ug1.inherit_default_permissions = False
         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})
@@ -438,12 +418,9 @@
                               'hg.create.write_on_repogroup.true'])
 
     def test_inactive_user_group_does_not_affect_global_permissions_inverse(self):
-        # Issue #138: Inactive User Groups affecting permissions
         # Add user to inactive user group, set specific permissions on user
-        # group and disable inherit-from-default. User permissions should still
-        # inherit from default.
+        # group and and verify it really is inactive.
         self.ug1 = fixture.create_user_group(u'G1')
-        self.ug1.inherit_default_permissions = False
         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})
@@ -474,7 +451,6 @@
 
     def test_inactive_user_group_does_not_affect_repo_permissions(self):
         self.ug1 = fixture.create_user_group(u'G1')
-        self.ug1.inherit_default_permissions = False
         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})
@@ -499,7 +475,6 @@
 
     def test_inactive_user_group_does_not_affect_repo_permissions_inverse(self):
         self.ug1 = fixture.create_user_group(u'G1')
-        self.ug1.inherit_default_permissions = False
         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})
@@ -524,7 +499,6 @@
 
     def test_inactive_user_group_does_not_affect_repo_group_permissions(self):
         self.ug1 = fixture.create_user_group(u'G1')
-        self.ug1.inherit_default_permissions = False
         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})
@@ -545,7 +519,6 @@
 
     def test_inactive_user_group_does_not_affect_repo_group_permissions_inverse(self):
         self.ug1 = fixture.create_user_group(u'G1')
-        self.ug1.inherit_default_permissions = False
         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})
@@ -566,7 +539,6 @@
 
     def test_inactive_user_group_does_not_affect_user_group_permissions(self):
         self.ug1 = fixture.create_user_group(u'G1')
-        self.ug1.inherit_default_permissions = False
         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})
@@ -588,7 +560,6 @@
 
     def test_inactive_user_group_does_not_affect_user_group_permissions_inverse(self):
         self.ug1 = fixture.create_user_group(u'G1')
-        self.ug1.inherit_default_permissions = False
         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})
--- a/kallithea/tests/models/test_repo_groups.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/models/test_repo_groups.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,15 +1,15 @@
 import os
+
 import pytest
 from sqlalchemy.exc import IntegrityError
 
+from kallithea.model.db import RepoGroup
+from kallithea.model.meta import Session
+from kallithea.model.repo import RepoModel
+from kallithea.model.repo_group import RepoGroupModel
 from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 
-from kallithea.model.repo_group import RepoGroupModel
-from kallithea.model.repo import RepoModel
-from kallithea.model.db import RepoGroup
-from kallithea.model.meta import Session
-
 
 fixture = Fixture()
 
@@ -52,9 +52,6 @@
         path = os.path.join(*path)
         return os.path.isdir(path)
 
-    def _check_folders(self):
-        print os.listdir(TESTS_TMP_PATH)
-
     def __delete_group(self, id_):
         RepoGroupModel().delete(id_)
 
--- a/kallithea/tests/models/test_repos.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/models/test_repos.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,11 +1,12 @@
 import pytest
-from kallithea.tests.base import *
 
+from kallithea.lib.exceptions import AttachedForksError
+from kallithea.model.db import Repository
 from kallithea.model.meta import Session
+from kallithea.model.repo import RepoModel
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
-from kallithea.model.repo import RepoModel
-from kallithea.model.db import Repository
-from kallithea.lib.exceptions import AttachedForksError
+
 
 fixture = Fixture()
 
--- a/kallithea/tests/models/test_settings.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/models/test_settings.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,5 +1,5 @@
+from kallithea.model.db import Setting
 from kallithea.model.meta import Session
-from kallithea.model.db import Setting
 
 
 name = 'spam-setting-name'
--- a/kallithea/tests/models/test_user_group_permissions_on_repo_groups.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/models/test_user_group_permissions_on_repo_groups.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,13 +1,12 @@
 import functools
 
+from kallithea.model.db import RepoGroup
+from kallithea.model.meta import Session
 from kallithea.model.repo_group import RepoGroupModel
-from kallithea.model.db import RepoGroup
-
-from kallithea.model.meta import Session
-from kallithea.tests.models.common import _create_project_tree, check_tree_perms, \
-    _get_perms, _check_expected_count, expected_count, _destroy_project_tree
 from kallithea.model.user_group import UserGroupModel
 from kallithea.tests.fixture import Fixture
+from kallithea.tests.models.common import _check_expected_count, _create_project_tree, _destroy_project_tree, _get_perms, check_tree_perms, expected_count
+
 
 fixture = Fixture()
 
@@ -129,14 +128,14 @@
     _check_expected_count(items, repo_items, expected_count(group, True))
 
     for name, perm in repo_items:
-        check_tree_perms(name, perm, group, 'repository.none')
+        check_tree_perms(name, perm, group, 'repository.none' if name.endswith('_private') else 'repository.read')
 
     for name, perm in items:
-        check_tree_perms(name, perm, group, 'group.none')
+        check_tree_perms(name, perm, group, 'group.read')
 
 
 def test_user_permissions_on_group_with_recursive_mode_deepest():
-    ## set permission to g0_3 group to none
+    ## set permission to g0/g0_1/g0_1_1 group to write
     recursive = 'all'
     group = u'g0/g0_1/g0_1_1'
     permissions_setup_func(group, 'group.write', recursive=recursive)
@@ -153,7 +152,7 @@
 
 
 def test_user_permissions_on_group_with_recursive_mode_only_with_repos():
-    ## set permission to g0_3 group to none
+    ## set permission to g0/g0_2 group to admin
     recursive = 'all'
     group = u'g0/g0_2'
     permissions_setup_func(group, 'group.admin', recursive=recursive)
@@ -208,4 +207,4 @@
         check_tree_perms(name, perm, group, 'repository.read')
 
     for name, perm in items:
-        check_tree_perms(name, perm, group, 'group.none')
+        check_tree_perms(name, perm, group, 'group.read')
--- a/kallithea/tests/models/test_user_groups.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/models/test_user_groups.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,11 +1,9 @@
 from kallithea.model.db import User, UserGroup
-
+from kallithea.model.meta import Session
+from kallithea.model.user_group import UserGroupModel
 from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 
-from kallithea.model.user_group import UserGroupModel
-from kallithea.model.meta import Session
-
 
 fixture = Fixture()
 
--- a/kallithea/tests/models/test_user_permissions_on_repo_groups.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/models/test_user_permissions_on_repo_groups.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,11 +1,9 @@
 import functools
 
+from kallithea.model.db import RepoGroup, Repository, User
+from kallithea.model.meta import Session
 from kallithea.model.repo_group import RepoGroupModel
-from kallithea.model.db import RepoGroup, Repository, User
-
-from kallithea.model.meta import Session
-from kallithea.tests.models.common import _create_project_tree, check_tree_perms, \
-    _get_perms, _check_expected_count, expected_count, _destroy_project_tree
+from kallithea.tests.models.common import _check_expected_count, _create_project_tree, _destroy_project_tree, _get_perms, check_tree_perms, expected_count
 
 
 test_u1_id = None
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/tests/models/test_user_ssh_keys.py	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,17 @@
+from kallithea.model.db import UserSshKeys
+from kallithea.tests.base import TestController
+from kallithea.tests.fixture import Fixture
+
+
+fixture = Fixture()
+
+public_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== kallithea@localhost'
+
+
+class TestUserSshKeys(TestController):
+
+    def test_fingerprint_generation(self):
+        key_model = UserSshKeys()
+        key_model.public_key = public_key
+        expected = 'Ke3oUCNJM87P0jJTb3D+e3shjceP2CqMpQKVd75E9I8'
+        assert expected == key_model.fingerprint
--- a/kallithea/tests/models/test_users.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/models/test_users.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,13 +1,13 @@
 import pytest
-from kallithea.tests.base import *
 
-from kallithea.model.db import User, UserGroup, UserGroupMember, UserEmailMap, \
-    Permission
+from kallithea.model.db import Permission, User, UserEmailMap, UserGroup, UserGroupMember
+from kallithea.model.meta import Session
 from kallithea.model.user import UserModel
-from kallithea.model.meta import Session
 from kallithea.model.user_group import UserGroupModel
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 
+
 fixture = Fixture()
 
 
--- a/kallithea/tests/other/test_auth_ldap.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/other/test_auth_ldap.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,8 +1,9 @@
+import uuid
+
+import pytest
+
 from kallithea.lib.auth_modules import auth_ldap, authenticate
-from kallithea.model.db import Setting, User
-from kallithea.model.meta import Session
-import uuid
-import pytest
+from kallithea.model.db import User
 
 
 @pytest.fixture
--- a/kallithea/tests/other/test_libs.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/other/test_libs.py	Sun Jan 05 04:07:51 2020 +0100
@@ -27,11 +27,14 @@
 
 import datetime
 import hashlib
+
 import mock
-from kallithea.tests.base import *
+from tg.util.webtest import test_context
+
 from kallithea.lib.utils2 import AttributeDict
 from kallithea.model.db import Repository
-from tg.util.webtest import test_context
+from kallithea.tests.base import *
+
 
 proto = 'http'
 TEST_URLS = [
@@ -267,26 +270,26 @@
                 grav = gravatar_url(email_address=em, size=24)
                 assert grav == 'https://example.com/%s/%s' % (_md5(em), 24)
 
-    @parametrize('tmpl,repo_name,overrides,prefix,expected', [
-        (Repository.DEFAULT_CLONE_URI, 'group/repo1', {}, '', 'http://vps1:8000/group/repo1'),
-        (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'username'}, '', 'http://username@vps1:8000/group/repo1'),
-        (Repository.DEFAULT_CLONE_URI, 'group/repo1', {}, '/prefix', 'http://vps1:8000/prefix/group/repo1'),
-        (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'user'}, '/prefix', 'http://user@vps1:8000/prefix/group/repo1'),
-        (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'username'}, '/prefix', 'http://username@vps1:8000/prefix/group/repo1'),
-        (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'user'}, '/prefix/', 'http://user@vps1:8000/prefix/group/repo1'),
-        (Repository.DEFAULT_CLONE_URI, 'group/repo1', {'user': 'username'}, '/prefix/', 'http://username@vps1:8000/prefix/group/repo1'),
-        ('{scheme}://{user}@{netloc}/_{repoid}', 'group/repo1', {}, '', 'http://vps1:8000/_23'),
-        ('{scheme}://{user}@{netloc}/_{repoid}', 'group/repo1', {'user': 'username'}, '', 'http://username@vps1:8000/_23'),
-        ('http://{user}@{netloc}/_{repoid}', 'group/repo1', {'user': 'username'}, '', 'http://username@vps1:8000/_23'),
-        ('http://{netloc}/_{repoid}', 'group/repo1', {'user': 'username'}, '', 'http://vps1:8000/_23'),
-        ('https://{user}@proxy1.example.com/{repo}', 'group/repo1', {'user': 'username'}, '', 'https://username@proxy1.example.com/group/repo1'),
-        ('https://{user}@proxy1.example.com/{repo}', 'group/repo1', {}, '', 'https://proxy1.example.com/group/repo1'),
-        ('https://proxy1.example.com/{user}/{repo}', 'group/repo1', {'user': 'username'}, '', 'https://proxy1.example.com/username/group/repo1'),
+    @parametrize('clone_uri_tmpl,repo_name,username,prefix,expected', [
+        (Repository.DEFAULT_CLONE_URI, 'group/repo1', None, '', 'http://vps1:8000/group/repo1'),
+        (Repository.DEFAULT_CLONE_URI, 'group/repo1', 'username', '', 'http://username@vps1:8000/group/repo1'),
+        (Repository.DEFAULT_CLONE_URI, 'group/repo1', None, '/prefix', 'http://vps1:8000/prefix/group/repo1'),
+        (Repository.DEFAULT_CLONE_URI, 'group/repo1', 'user', '/prefix', 'http://user@vps1:8000/prefix/group/repo1'),
+        (Repository.DEFAULT_CLONE_URI, 'group/repo1', 'username', '/prefix', 'http://username@vps1:8000/prefix/group/repo1'),
+        (Repository.DEFAULT_CLONE_URI, 'group/repo1', 'user', '/prefix/', 'http://user@vps1:8000/prefix/group/repo1'),
+        (Repository.DEFAULT_CLONE_URI, 'group/repo1', 'username', '/prefix/', 'http://username@vps1:8000/prefix/group/repo1'),
+        ('{scheme}://{user}@{netloc}/_{repoid}', 'group/repo1', None, '', 'http://vps1:8000/_23'),
+        ('{scheme}://{user}@{netloc}/_{repoid}', 'group/repo1', 'username', '', 'http://username@vps1:8000/_23'),
+        ('http://{user}@{netloc}/_{repoid}', 'group/repo1', 'username', '', 'http://username@vps1:8000/_23'),
+        ('http://{netloc}/_{repoid}', 'group/repo1', 'username', '', 'http://vps1:8000/_23'),
+        ('https://{user}@proxy1.example.com/{repo}', 'group/repo1', 'username', '', 'https://username@proxy1.example.com/group/repo1'),
+        ('https://{user}@proxy1.example.com/{repo}', 'group/repo1', None, '', 'https://proxy1.example.com/group/repo1'),
+        ('https://proxy1.example.com/{user}/{repo}', 'group/repo1', 'username', '', 'https://proxy1.example.com/username/group/repo1'),
     ])
-    def test_clone_url_generator(self, tmpl, repo_name, overrides, prefix, expected):
+    def test_clone_url_generator(self, clone_uri_tmpl, repo_name, username, prefix, expected):
         from kallithea.lib.utils2 import get_clone_url
-        clone_url = get_clone_url(uri_tmpl=tmpl, qualified_home_url='http://vps1:8000'+prefix,
-                                  repo_name=repo_name, repo_id=23, **overrides)
+        clone_url = get_clone_url(clone_uri_tmpl=clone_uri_tmpl, prefix_url='http://vps1:8000' + prefix,
+                                  repo_name=repo_name, repo_id=23, username=username)
         assert clone_url == expected
 
     def _quick_url(self, text, tmpl="""<a class="changeset_hash" href="%s">%s</a>""", url_=None):
@@ -532,26 +535,32 @@
 
     @parametrize('test,expected', [
       ("", None),
-      ("/_2", '2'),
-      ("_2", '2'),
-      ("/_2/", '2'),
-      ("_2/", '2'),
-
-      ("/_21", '21'),
-      ("_21", '21'),
-      ("/_21/", '21'),
-      ("_21/", '21'),
+      ("/_2", None),
+      ("_2", 2),
+      ("_2/", None),
+    ])
+    def test_get_permanent_id(self, test, expected):
+        from kallithea.lib.utils import _get_permanent_id
+        extracted = _get_permanent_id(test)
+        assert extracted == expected, 'url:%s, got:`%s` expected: `%s`' % (test, _test, expected)
 
-      ("/_21/foobar", '21'),
-      ("_21/121", '21'),
-      ("/_21/_12", '21'),
-      ("_21/prefix/foo", '21'),
+    @parametrize('test,expected', [
+      ("", ""),
+      ("/", "/"),
+      ("/_ID", '/_ID'),
+      ("ID", "ID"),
+      ("_ID", 'NAME'),
+      ("_ID/", 'NAME/'),
+      ("_ID/1/2", 'NAME/1/2'),
+      ("_IDa", '_IDa'),
     ])
-    def test_get_repo_by_id(self, test, expected):
-        from kallithea.lib.utils import _extract_id_from_repo_name
-        _test = _extract_id_from_repo_name(test)
-        assert _test == expected, 'url:%s, got:`%s` expected: `%s`' % (test, _test, expected)
-
+    def test_fix_repo_id_name(self, test, expected):
+        repo = Repository.get_by_repo_name(HG_REPO)
+        test = test.replace('ID', str(repo.repo_id))
+        expected = expected.replace('NAME', repo.repo_name).replace('ID', str(repo.repo_id))
+        from kallithea.lib.utils import fix_repo_id_name
+        replaced = fix_repo_id_name(test)
+        assert replaced == expected, 'url:%s, got:`%s` expected: `%s`' % (test, replaced, expected)
 
     @parametrize('canonical,test,expected', [
         ('http://www.example.org/', '/abc/xyz', 'http://www.example.org/abc/xyz'),
--- a/kallithea/tests/other/test_mail.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/other/test_mail.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,8 +1,8 @@
 import mock
 
 import kallithea
+from kallithea.model.db import User
 from kallithea.tests.base import *
-from kallithea.model.db import User
 
 
 class smtplib_mock(object):
--- a/kallithea/tests/other/test_validators.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/other/test_validators.py	Sun Jan 05 04:07:51 2020 +0100
@@ -2,15 +2,14 @@
 import formencode
 import pytest
 
-from kallithea.tests.base import *
-
 from kallithea.model import validators as v
-from kallithea.model.user_group import UserGroupModel
-
 from kallithea.model.meta import Session
 from kallithea.model.repo_group import RepoGroupModel
+from kallithea.model.user_group import UserGroupModel
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 
+
 fixture = Fixture()
 
 
@@ -139,13 +138,6 @@
         with pytest.raises(formencode.Invalid):
             validator.to_python(invalid_creds)
 
-    def test_ValidAuthToken(self):
-        validator = v.ValidAuthToken()
-        # this is untestable without a threadlocal
-#        self.assertRaises(formencode.Invalid,
-#                          validator.to_python, 'BadToken')
-        validator
-
     def test_ValidRepoName(self):
         validator = v.ValidRepoName()
 
--- a/kallithea/tests/other/test_vcs_operations.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/other/test_vcs_operations.py	Sun Jan 05 04:07:51 2020 +0100
@@ -25,23 +25,27 @@
 
 """
 
+from __future__ import print_function
+
+import json
 import os
 import re
 import tempfile
 import time
 import urllib2
-import json
+from subprocess import PIPE, Popen
 from tempfile import _RandomNameSequence
-from subprocess import Popen, PIPE
 
 import pytest
 
+from kallithea import CONFIG
+from kallithea.model.db import CacheInvalidation, Repository, Ui, User, UserIpMap, UserLog
+from kallithea.model.meta import Session
+from kallithea.model.ssh_key import SshKeyModel
+from kallithea.model.user import UserModel
 from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
-from kallithea.model.db import User, Repository, UserIpMap, CacheInvalidation, Ui, UserLog
-from kallithea.model.meta import Session
-from kallithea.model.repo import RepoModel
-from kallithea.model.user import UserModel
+
 
 DEBUG = True
 HOST = '127.0.0.1:4999'  # test host
@@ -49,20 +53,100 @@
 fixture = Fixture()
 
 
+# Parameterize different kinds of VCS testing - both the kind of VCS and the
+# access method (HTTP/SSH)
+
+# Mixin for using HTTP and SSH URLs
+class HttpVcsTest(object):
+    @staticmethod
+    def repo_url_param(webserver, repo_name, **kwargs):
+        return webserver.repo_url(repo_name, **kwargs)
+
+class SshVcsTest(object):
+    public_keys = {
+        TEST_USER_REGULAR_LOGIN: u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== kallithea@localhost',
+        TEST_USER_ADMIN_LOGIN: u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUq== kallithea@localhost',
+    }
+
+    @classmethod
+    def repo_url_param(cls, webserver, repo_name, username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS, client_ip=IP_ADDR):
+        user = User.get_by_username(username)
+        if user.ssh_keys:
+            ssh_key = user.ssh_keys[0]
+        else:
+            sshkeymodel = SshKeyModel()
+            ssh_key = sshkeymodel.create(user, u'test key', cls.public_keys[user.username])
+            Session().commit()
+
+        return cls._ssh_param(repo_name, user, ssh_key, client_ip)
+
+# Mixins for using Mercurial and Git
+class HgVcsTest(object):
+    repo_type = 'hg'
+    repo_name = HG_REPO
+
+class GitVcsTest(object):
+    repo_type = 'git'
+    repo_name = GIT_REPO
+
+# Combine mixins to give the combinations we want to parameterize tests with
+class HgHttpVcsTest(HgVcsTest, HttpVcsTest):
+    pass
+
+class GitHttpVcsTest(GitVcsTest, HttpVcsTest):
+    pass
+
+class HgSshVcsTest(HgVcsTest, SshVcsTest):
+    @staticmethod
+    def _ssh_param(repo_name, user, ssh_key, client_ip):
+        # Specify a custom ssh command on the command line
+        return r"""--config ui.ssh="bash -c 'SSH_ORIGINAL_COMMAND=\"\$2\" SSH_CONNECTION=\"%s 1024 127.0.0.1 22\" kallithea-cli ssh-serve -c %s %s %s' --" ssh://someuser@somehost/%s""" % (
+            client_ip,
+            CONFIG['__file__'],
+            user.user_id,
+            ssh_key.user_ssh_key_id,
+            repo_name)
+
+class GitSshVcsTest(GitVcsTest, SshVcsTest):
+    @staticmethod
+    def _ssh_param(repo_name, user, ssh_key, client_ip):
+        # Set a custom ssh command in the global environment
+        os.environ['GIT_SSH_COMMAND'] = r"""bash -c 'SSH_ORIGINAL_COMMAND="$2" SSH_CONNECTION="%s 1024 127.0.0.1 22" kallithea-cli ssh-serve -c %s %s %s' --""" % (
+            client_ip,
+            CONFIG['__file__'],
+            user.user_id,
+            ssh_key.user_ssh_key_id)
+        return "ssh://someuser@somehost/%s""" % repo_name
+
+parametrize_vcs_test = parametrize('vt', [
+    HgHttpVcsTest,
+    GitHttpVcsTest,
+    HgSshVcsTest,
+    GitSshVcsTest,
+])
+parametrize_vcs_test_hg = parametrize('vt', [
+    HgHttpVcsTest,
+    HgSshVcsTest,
+])
+parametrize_vcs_test_http = parametrize('vt', [
+    HgHttpVcsTest,
+    GitHttpVcsTest,
+])
+
 class Command(object):
 
     def __init__(self, cwd):
         self.cwd = cwd
 
-    def execute(self, cmd, *args, **environ):
+    def execute(self, *args, **environ):
         """
-        Runs command on the system with given ``args``.
+        Runs command on the system with given ``args`` using simple space
+        join without safe quoting.
         """
-
-        command = cmd + ' ' + ' '.join(args)
+        command = ' '.join(args)
         ignoreReturnCode = environ.pop('ignoreReturnCode', False)
         if DEBUG:
-            print '*** CMD %s ***' % command
+            print('*** CMD %s ***' % command)
         testenv = dict(os.environ)
         testenv['LANG'] = 'en_US.UTF-8'
         testenv['LANGUAGE'] = 'en_US:en'
@@ -73,9 +157,9 @@
         stdout, stderr = p.communicate()
         if DEBUG:
             if stdout:
-                print 'stdout:', repr(stdout)
+                print('stdout:', stdout)
             if stderr:
-                print 'stderr:', repr(stderr)
+                print('stderr:', stderr)
         if not ignoreReturnCode:
             assert p.returncode == 0
         return stdout, stderr
@@ -95,7 +179,7 @@
     """
     added_file = '%ssetup.py' % _RandomNameSequence().next()
     open(os.path.join(dest_dir, added_file), 'a').close()
-    Command(dest_dir).execute('%s add %s' % (vcs, added_file))
+    Command(dest_dir).execute(vcs, 'add', added_file)
 
     email = 'me@example.com'
     if os.name == 'nt':
@@ -116,29 +200,19 @@
         # git commit needs EMAIL on some machines
         Command(dest_dir).execute(cmd, EMAIL=email)
 
-def _add_files_and_push(webserver, vcs, dest_dir, ignoreReturnCode=False, files_no=3,
-                            clone_url=None, username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS):
-    _add_files(vcs, dest_dir, files_no=files_no)
+def _add_files_and_push(webserver, vt, dest_dir, clone_url, ignoreReturnCode=False, files_no=3):
+    _add_files(vt.repo_type, dest_dir, files_no=files_no)
     # PUSH it back
-    _REPO = None
-    if vcs == 'hg':
-        _REPO = HG_REPO
-    elif vcs == 'git':
-        _REPO = GIT_REPO
-
-    if clone_url is None:
-        clone_url = webserver.repo_url(_REPO, username=username, password=password)
-
     stdout = stderr = None
-    if vcs == 'hg':
-        stdout, stderr = Command(dest_dir).execute('hg push --verbose', clone_url, ignoreReturnCode=ignoreReturnCode)
-    elif vcs == 'git':
-        stdout, stderr = Command(dest_dir).execute('git push --verbose', clone_url, "master", ignoreReturnCode=ignoreReturnCode)
+    if vt.repo_type == 'hg':
+        stdout, stderr = Command(dest_dir).execute('hg push -f --verbose', clone_url, ignoreReturnCode=ignoreReturnCode)
+    elif vt.repo_type == 'git':
+        stdout, stderr = Command(dest_dir).execute('git push -f --verbose', clone_url, "master", ignoreReturnCode=ignoreReturnCode)
 
     return stdout, stderr
 
 
-def _check_outgoing(vcs, cwd, clone_url=''):
+def _check_outgoing(vcs, cwd, clone_url):
     if vcs == 'hg':
         # hg removes the password from default URLs, so we have to provide it here via the clone_url
         return Command(cwd).execute('hg -q outgoing', clone_url, ignoreReturnCode=True)
@@ -161,7 +235,6 @@
 
 
 def _check_proper_git_push(stdout, stderr):
-    # WTF Git stderr is output ?!
     assert 'fatal' not in stderr
     assert 'rejected' not in stderr
     assert 'Pushing to' in stderr
@@ -176,17 +249,6 @@
         # DISABLE ANONYMOUS ACCESS
         set_anonymous_access(False)
 
-    def setup_method(self, method):
-        r = Repository.get_by_repo_name(GIT_REPO)
-        Repository.unlock(r)
-        r.enable_locking = False
-        Session().commit()
-
-        r = Repository.get_by_repo_name(HG_REPO)
-        Repository.unlock(r)
-        r.enable_locking = False
-        Session().commit()
-
     @pytest.fixture()
     def testhook_cleanup(self):
         yield
@@ -206,61 +268,57 @@
         fixture.create_fork(HG_REPO, hg_fork_name)
         return {'git': git_fork_name, 'hg': hg_fork_name}
 
-    def test_clone_hg_repo_by_admin(self, webserver):
-        clone_url = webserver.repo_url(HG_REPO)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir())
-
-        assert 'requesting all changes' in stdout
-        assert 'adding changesets' in stdout
-        assert 'adding manifests' in stdout
-        assert 'adding file changes' in stdout
-
-        assert stderr == ''
+    @parametrize_vcs_test
+    def test_clone_repo_by_admin(self, webserver, vt):
+        clone_url = vt.repo_url_param(webserver, vt.repo_name)
+        stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir())
 
-    def test_clone_git_repo_by_admin(self, webserver):
-        clone_url = webserver.repo_url(GIT_REPO)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir())
-
-        assert 'Cloning into' in stdout + stderr
-        assert stderr == '' or stdout == ''
+        if vt.repo_type == 'git':
+            assert 'Cloning into' in stdout + stderr
+            assert stderr == '' or stdout == ''
+        elif vt.repo_type == 'hg':
+            assert 'requesting all changes' in stdout
+            assert 'adding changesets' in stdout
+            assert 'adding manifests' in stdout
+            assert 'adding file changes' in stdout
+            assert stderr == ''
 
-    def test_clone_wrong_credentials_hg(self, webserver):
-        clone_url = webserver.repo_url(HG_REPO, password='bad!')
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
-        assert 'abort: authorization failed' in stderr
-
-    def test_clone_wrong_credentials_git(self, webserver):
-        clone_url = webserver.repo_url(GIT_REPO, password='bad!')
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
-        assert 'fatal: Authentication failed' in stderr
+    @parametrize_vcs_test_http
+    def test_clone_wrong_credentials(self, webserver, vt):
+        clone_url = vt.repo_url_param(webserver, vt.repo_name, password='bad!')
+        stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
+        if vt.repo_type == 'git':
+            assert 'fatal: Authentication failed' in stderr
+        elif vt.repo_type == 'hg':
+            assert 'abort: authorization failed' in stderr
 
     def test_clone_git_dir_as_hg(self, webserver):
-        clone_url = webserver.repo_url(GIT_REPO)
+        clone_url = HgHttpVcsTest.repo_url_param(webserver, GIT_REPO)
         stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
-        assert 'HTTP Error 404: Not Found' in stderr
+        assert 'HTTP Error 404: Not Found' in stderr or "not a valid repository" in stdout and 'abort:' in stderr
 
     def test_clone_hg_repo_as_git(self, webserver):
-        clone_url = webserver.repo_url(HG_REPO)
+        clone_url = GitHttpVcsTest.repo_url_param(webserver, HG_REPO)
         stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
         assert 'not found' in stderr
 
-    def test_clone_non_existing_path_hg(self, webserver):
-        clone_url = webserver.repo_url('trololo')
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
-        assert 'HTTP Error 404: Not Found' in stderr
+    @parametrize_vcs_test
+    def test_clone_non_existing_path(self, webserver, vt):
+        clone_url = vt.repo_url_param(webserver, 'trololo')
+        stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
+        if vt.repo_type == 'git':
+            assert 'not found' in stderr or 'abort: Access to %r denied' % 'trololo' in stderr
+        elif vt.repo_type == 'hg':
+            assert 'HTTP Error 404: Not Found' in stderr or 'abort: no suitable response from remote hg' in stderr and 'remote: abort: Access to %r denied' % 'trololo' in stdout
 
-    def test_clone_non_existing_path_git(self, webserver):
-        clone_url = webserver.repo_url('trololo')
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
-        assert 'not found' in stderr
-
-    def test_push_new_repo_git(self, webserver):
+    @parametrize_vcs_test
+    def test_push_new_repo(self, webserver, vt):
         # Clear the log so we know what is added
         UserLog.query().delete()
         Session().commit()
 
         # Create an empty server repo using the API
-        repo_name = u'new_git_%s' % _RandomNameSequence().next()
+        repo_name = u'new_%s_%s' % (vt.repo_type, _RandomNameSequence().next())
         usr = User.get_by_username(TEST_USER_ADMIN_LOGIN)
         params = {
             "id": 7,
@@ -268,7 +326,7 @@
             "method": 'create_repo',
             "args": dict(repo_name=repo_name,
                          owner=TEST_USER_ADMIN_LOGIN,
-                         repo_type='git'),
+                         repo_type=vt.repo_type),
         }
         req = urllib2.Request(
             'http://%s:%s/_admin/api' % webserver.server_address,
@@ -277,324 +335,180 @@
         response = urllib2.urlopen(req)
         result = json.loads(response.read())
         # Expect something like:
-        # {u'result': {u'msg': u'Created new repository `new_git_XXX`', u'task': None, u'success': True}, u'id': 7, u'error': None}
+        # {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']
 
         # Create local clone of the empty server repo
         local_clone_dir = _get_tmp_dir()
-        clone_url = webserver.repo_url(repo_name)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, local_clone_dir, ignoreReturnCode=True)
+        clone_url = vt.repo_url_param(webserver, repo_name)
+        stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, local_clone_dir)
 
         # Make 3 commits and push to the empty server repo.
         # The server repo doesn't have any other heads than the
         # refs/heads/master we are pushing, but the `git log` in the push hook
         # should still list the 3 commits.
-        stdout, stderr = _add_files_and_push(webserver, 'git', local_clone_dir, clone_url=clone_url)
-        _check_proper_git_push(stdout, stderr)
+        stdout, stderr = _add_files_and_push(webserver, vt, local_clone_dir, clone_url=clone_url)
+        if vt.repo_type == 'git':
+            _check_proper_git_push(stdout, stderr)
+        elif vt.repo_type == 'hg':
+            assert 'pushing to ' in stdout
+            assert 'remote: added ' in stdout
 
         # Verify that we got the right events in UserLog. Expect something like:
         # <UserLog('id:new_git_XXX:started_following_repo')>
         # <UserLog('id:new_git_XXX:user_created_repo')>
         # <UserLog('id:new_git_XXX:pull')>
         # <UserLog('id:new_git_XXX:push:aed9d4c1732a1927da3be42c47eb9afdc200d427,d38b083a07af10a9f44193486959a96a23db78da,4841ff9a2b385bec995f4679ef649adb3f437622')>
-        uls = list(UserLog.query().order_by(UserLog.user_log_id))
-        assert len(uls) == 4
-        assert uls[0].action == 'started_following_repo'
-        assert uls[1].action == 'user_created_repo'
-        assert uls[2].action == 'pull'
-        assert uls[3].action.startswith(u'push:')
-        assert uls[3].action.count(',') == 2 # expect 3 commits
-
-    def test_push_new_file_hg(self, webserver, testfork):
-        dest_dir = _get_tmp_dir()
-        clone_url = webserver.repo_url(HG_REPO)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, dest_dir)
-
-        clone_url = webserver.repo_url(testfork['hg'])
-        stdout, stderr = _add_files_and_push(webserver, 'hg', dest_dir, clone_url=clone_url)
-
-        assert 'pushing to' in stdout
-        assert 'Repository size' in stdout
-        assert 'Last revision is now' in stdout
+        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)]
+            if vt.repo_type == 'git' else [
+            (u'started_following_repo', 0),
+            (u'user_created_repo', 0),
+            # (u'pull', 0), # Mercurial outgoing hook is not called for empty clones
+            (u'push', 3)])
 
-    def test_push_new_file_git(self, webserver, testfork):
-        dest_dir = _get_tmp_dir()
-        clone_url = webserver.repo_url(GIT_REPO)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, dest_dir)
-
-        # commit some stuff into this repo
-        clone_url = webserver.repo_url(testfork['git'])
-        stdout, stderr = _add_files_and_push(webserver, 'git', dest_dir, clone_url=clone_url)
-        print [(x.repo_full_path,x.repo_path) for x in Repository.query()] # TODO: what is this for
-        _check_proper_git_push(stdout, stderr)
-
-    def test_push_invalidates_cache_hg(self, webserver, testfork):
-        key = CacheInvalidation.query().filter(CacheInvalidation.cache_key
-                                               == HG_REPO).scalar()
-        if not key:
-            key = CacheInvalidation(HG_REPO, HG_REPO)
-            Session().add(key)
-
-        key.cache_active = True
+    @parametrize_vcs_test
+    def test_push_new_file(self, webserver, testfork, vt):
+        UserLog.query().delete()
         Session().commit()
 
         dest_dir = _get_tmp_dir()
-        clone_url = webserver.repo_url(testfork['hg'])
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, dest_dir)
+        clone_url = vt.repo_url_param(webserver, vt.repo_name)
+        stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir)
+
+        clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type])
+        stdout, stderr = _add_files_and_push(webserver, vt, dest_dir, clone_url=clone_url)
+
+        if vt.repo_type == 'git':
+            _check_proper_git_push(stdout, stderr)
+        elif vt.repo_type == 'hg':
+            assert 'pushing to' in stdout
+            assert 'Repository size' in stdout
+            assert 'Last revision is now' in stdout
+
+        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)]
 
-        stdout, stderr = _add_files_and_push(webserver, 'hg', dest_dir, files_no=1, clone_url=clone_url)
+    @parametrize_vcs_test
+    def test_pull(self, webserver, testfork, vt):
+        UserLog.query().delete()
+        Session().commit()
+
+        dest_dir = _get_tmp_dir()
+        stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'init', dest_dir)
+
+        clone_url = vt.repo_url_param(webserver, vt.repo_name)
+        stdout, stderr = Command(dest_dir).execute(vt.repo_type, 'pull', clone_url)
+
+        if vt.repo_type == 'git':
+            assert 'FETCH_HEAD' in stderr
+        elif vt.repo_type == 'hg':
+            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']
+
+    @parametrize_vcs_test
+    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['hg']).all()
-        assert key == []
-
-    def test_push_invalidates_cache_git(self, webserver, testfork):
-        key = CacheInvalidation.query().filter(CacheInvalidation.cache_key
-                                               == GIT_REPO).scalar()
+                                               == testfork[vt.repo_type]).scalar()
         if not key:
-            key = CacheInvalidation(GIT_REPO, GIT_REPO)
+            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 = webserver.repo_url(testfork['git'])
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, dest_dir)
+        clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type])
+        stdout, stderr = Command(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)
 
-        # commit some stuff into this repo
-        stdout, stderr = _add_files_and_push(webserver, 'git', dest_dir, files_no=1, clone_url=clone_url)
-        _check_proper_git_push(stdout, stderr)
+        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['git']).all()
+                                               == testfork[vt.repo_type]).all()
         assert key == []
 
-    def test_push_wrong_credentials_hg(self, webserver):
-        dest_dir = _get_tmp_dir()
-        clone_url = webserver.repo_url(HG_REPO)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, dest_dir)
-
-        stdout, stderr = _add_files_and_push(webserver, 'hg', dest_dir, username='bad',
-                                             password='name', ignoreReturnCode=True)
-
-        assert 'abort: authorization failed' in stderr
-
-    def test_push_wrong_credentials_git(self, webserver):
-        dest_dir = _get_tmp_dir()
-        clone_url = webserver.repo_url(GIT_REPO)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, dest_dir)
-
-        stdout, stderr = _add_files_and_push(webserver, 'git', dest_dir, username='bad',
-                                             password='name', ignoreReturnCode=True)
-
-        assert 'fatal: Authentication failed' in stderr
-
-    def test_push_with_readonly_credentials_hg(self, webserver):
+    @parametrize_vcs_test_http
+    def test_push_wrong_credentials(self, webserver, vt):
         dest_dir = _get_tmp_dir()
-        clone_url = webserver.repo_url(HG_REPO, username=TEST_USER_REGULAR_LOGIN, password=TEST_USER_REGULAR_PASS)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, dest_dir)
+        clone_url = vt.repo_url_param(webserver, vt.repo_name)
+        stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir)
+
+        clone_url = webserver.repo_url(vt.repo_name, username='bad', password='name')
+        stdout, stderr = _add_files_and_push(webserver, vt, dest_dir,
+                                             clone_url=clone_url, ignoreReturnCode=True)
 
-        stdout, stderr = _add_files_and_push(webserver, 'hg', dest_dir, username=TEST_USER_REGULAR_LOGIN,
-                                             password=TEST_USER_REGULAR_PASS, ignoreReturnCode=True)
+        if vt.repo_type == 'git':
+            assert 'fatal: Authentication failed' in stderr
+        elif vt.repo_type == 'hg':
+            assert 'abort: authorization failed' in stderr
 
-        assert 'abort: HTTP Error 403: Forbidden' in stderr
+    @parametrize_vcs_test
+    def test_push_with_readonly_credentials(self, webserver, vt):
+        UserLog.query().delete()
+        Session().commit()
 
-    def test_push_with_readonly_credentials_git(self, webserver):
         dest_dir = _get_tmp_dir()
-        clone_url = webserver.repo_url(GIT_REPO, username=TEST_USER_REGULAR_LOGIN, password=TEST_USER_REGULAR_PASS)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, dest_dir)
+        clone_url = vt.repo_url_param(webserver, vt.repo_name, username=TEST_USER_REGULAR_LOGIN, password=TEST_USER_REGULAR_PASS)
+        stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir)
+
+        stdout, stderr = _add_files_and_push(webserver, vt, dest_dir, ignoreReturnCode=True, clone_url=clone_url)
 
-        stdout, stderr = _add_files_and_push(webserver, 'git', dest_dir, username=TEST_USER_REGULAR_LOGIN,
-                                             password=TEST_USER_REGULAR_PASS, ignoreReturnCode=True)
+        if vt.repo_type == 'git':
+            assert 'The requested URL returned error: 403' in stderr or 'abort: Push access to %r denied' % str(vt.repo_name) in stderr
+        elif vt.repo_type == 'hg':
+            assert 'abort: HTTP Error 403: Forbidden' in stderr or 'abort: push failed on remote' in stderr and 'remote: Push access to %r denied' % str(vt.repo_name) in stdout
 
-        assert 'The requested URL returned error: 403' in stderr
+        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)]
 
-    def test_push_back_to_wrong_url_hg(self, webserver):
+    @parametrize_vcs_test
+    def test_push_back_to_wrong_url(self, webserver, vt):
         dest_dir = _get_tmp_dir()
-        clone_url = webserver.repo_url(HG_REPO)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, dest_dir)
+        clone_url = vt.repo_url_param(webserver, vt.repo_name)
+        stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir)
 
         stdout, stderr = _add_files_and_push(
-            webserver, 'hg', dest_dir, clone_url='http://%s:%s/tmp' % (
-                webserver.server_address[0], webserver.server_address[1]),
-            ignoreReturnCode=True)
-
-        assert 'HTTP Error 404: Not Found' in stderr
-
-    def test_push_back_to_wrong_url_git(self, webserver):
-        dest_dir = _get_tmp_dir()
-        clone_url = webserver.repo_url(GIT_REPO)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, dest_dir)
-
-        stdout, stderr = _add_files_and_push(
-            webserver, 'git', dest_dir, clone_url='http://%s:%s/tmp' % (
+            webserver, vt, dest_dir, clone_url='http://%s:%s/tmp' % (
                 webserver.server_address[0], webserver.server_address[1]),
             ignoreReturnCode=True)
 
-        assert 'not found' in stderr
-
-    def test_clone_and_create_lock_hg(self, webserver):
-        # enable locking
-        r = Repository.get_by_repo_name(HG_REPO)
-        r.enable_locking = True
-        Session().commit()
-        # clone
-        clone_url = webserver.repo_url(HG_REPO)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir())
-
-        # check if lock was made
-        r = Repository.get_by_repo_name(HG_REPO)
-        assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id
-
-    def test_clone_and_create_lock_git(self, webserver):
-        # enable locking
-        r = Repository.get_by_repo_name(GIT_REPO)
-        r.enable_locking = True
-        Session().commit()
-        # clone
-        clone_url = webserver.repo_url(GIT_REPO)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir())
-
-        # check if lock was made
-        r = Repository.get_by_repo_name(GIT_REPO)
-        assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id
-
-    def test_clone_after_repo_was_locked_hg(self, webserver):
-        # lock repo
-        r = Repository.get_by_repo_name(HG_REPO)
-        Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id)
-        # pull fails since repo is locked
-        clone_url = webserver.repo_url(HG_REPO)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
-        msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`"""
-                % (HG_REPO, TEST_USER_ADMIN_LOGIN))
-        assert msg in stderr
-
-    def test_clone_after_repo_was_locked_git(self, webserver):
-        # lock repo
-        r = Repository.get_by_repo_name(GIT_REPO)
-        Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id)
-        # pull fails since repo is locked
-        clone_url = webserver.repo_url(GIT_REPO)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
-        msg = ("""The requested URL returned error: 423""")
-        assert msg in stderr
-
-    def test_push_on_locked_repo_by_other_user_hg(self, webserver):
-        # clone some temp
-        dest_dir = _get_tmp_dir()
-        clone_url = webserver.repo_url(HG_REPO)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, dest_dir)
-
-        # lock repo
-        r = Repository.get_by_repo_name(HG_REPO)
-        # let this user actually push !
-        RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN,
-                                          perm='repository.write')
-        Session().commit()
-        Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id)
-
-        # push fails repo is locked by other user !
-        stdout, stderr = _add_files_and_push(webserver, 'hg', dest_dir,
-                                             username=TEST_USER_REGULAR_LOGIN,
-                                             password=TEST_USER_REGULAR_PASS,
-                                             ignoreReturnCode=True)
-        msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`"""
-                % (HG_REPO, TEST_USER_ADMIN_LOGIN))
-        assert msg in stderr
-
-    def test_push_on_locked_repo_by_other_user_git(self, webserver):
-        # Note: Git hooks must be executable on unix. This test will thus fail
-        # for example on Linux if /tmp is mounted noexec.
+        if vt.repo_type == 'git':
+            assert 'not found' in stderr
+        elif vt.repo_type == 'hg':
+            assert 'HTTP Error 404: Not Found' in stderr
 
-        # clone some temp
-        dest_dir = _get_tmp_dir()
-        clone_url = webserver.repo_url(GIT_REPO)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, dest_dir)
-
-        # lock repo
-        r = Repository.get_by_repo_name(GIT_REPO)
-        # let this user actually push !
-        RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN,
-                                          perm='repository.write')
-        Session().commit()
-        Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id)
-
-        # push fails repo is locked by other user !
-        stdout, stderr = _add_files_and_push(webserver, 'git', dest_dir,
-                                             username=TEST_USER_REGULAR_LOGIN,
-                                             password=TEST_USER_REGULAR_PASS,
-                                             ignoreReturnCode=True)
-        err = 'Repository `%s` locked by user `%s`' % (GIT_REPO, TEST_USER_ADMIN_LOGIN)
-        assert err in stderr
-
-        # TODO: fix this somehow later on Git, Git is stupid and even if we throw
-        # back 423 to it, it makes ANOTHER request and we fail there with 405 :/
-
-        msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`"""
-                % (GIT_REPO, TEST_USER_ADMIN_LOGIN))
-        #msg = "405 Method Not Allowed"
-        #assert msg in stderr
-
-    def test_push_unlocks_repository_hg(self, webserver, testfork):
-        # enable locking
-        r = Repository.get_by_repo_name(testfork['hg'])
-        r.enable_locking = True
-        Session().commit()
-        # clone some temp
-        dest_dir = _get_tmp_dir()
-        clone_url = webserver.repo_url(testfork['hg'])
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, dest_dir)
-
-        # check for lock repo after clone
-        r = Repository.get_by_repo_name(testfork['hg'])
-        uid = User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id
-        assert r.locked[0] == uid
-
-        # push is ok and repo is now unlocked
-        stdout, stderr = _add_files_and_push(webserver, 'hg', dest_dir, clone_url=clone_url)
-        assert str('remote: Released lock on repo `%s`' % testfork['hg']) in stdout
-        # we need to cleanup the Session Here !
-        Session.remove()
-        r = Repository.get_by_repo_name(testfork['hg'])
-        assert r.locked == [None, None]
-
-    # TODO: fix me ! somehow during tests hooks don't get called on Git
-    def test_push_unlocks_repository_git(self, webserver, testfork):
-        # enable locking
-        r = Repository.get_by_repo_name(testfork['git'])
-        r.enable_locking = True
-        Session().commit()
-        # clone some temp
-        dest_dir = _get_tmp_dir()
-        clone_url = webserver.repo_url(testfork['git'])
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, dest_dir)
-
-        # check for lock repo after clone
-        r = Repository.get_by_repo_name(testfork['git'])
-        assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id
-
-        # push is ok and repo is now unlocked
-        stdout, stderr = _add_files_and_push(webserver, 'git', dest_dir, clone_url=clone_url)
-        _check_proper_git_push(stdout, stderr)
-
-        assert ('remote: Released lock on repo `%s`' % testfork['git']) in stderr
-        # we need to cleanup the Session Here !
-        Session.remove()
-        r = Repository.get_by_repo_name(testfork['git'])
-        assert r.locked == [None, None]
-
-    def test_ip_restriction_hg(self, webserver):
+    @parametrize_vcs_test
+    def test_ip_restriction(self, webserver, vt):
         user_model = UserModel()
         try:
+            # Add IP constraint that excludes the test context:
             user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32')
             Session().commit()
             # IP permissions are cached, need to wait for the cache in the server process to expire
             time.sleep(1.5)
-            clone_url = webserver.repo_url(HG_REPO)
-            stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
-            assert 'abort: HTTP Error 403: Forbidden' in stderr
+            clone_url = vt.repo_url_param(webserver, vt.repo_name)
+            stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
+            if vt.repo_type == 'git':
+                # The message apparently changed in Git 1.8.3, so match it loosely.
+                assert re.search(r'\b403\b', stderr) or 'abort: User test_admin from 127.0.0.127 cannot be authorized' in stderr
+            elif vt.repo_type == 'hg':
+                assert 'abort: HTTP Error 403: Forbidden' in stderr or 'remote: abort: User test_admin from 127.0.0.127 cannot be authorized' in stdout
         finally:
             # release IP restrictions
             for ip in UserIpMap.query():
@@ -603,116 +517,87 @@
             # IP permissions are cached, need to wait for the cache in the server process to expire
             time.sleep(1.5)
 
-        clone_url = webserver.repo_url(HG_REPO)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir())
-
-        assert 'requesting all changes' in stdout
-        assert 'adding changesets' in stdout
-        assert 'adding manifests' in stdout
-        assert 'adding file changes' in stdout
-
-        assert stderr == ''
+        clone_url = vt.repo_url_param(webserver, vt.repo_name)
+        stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, _get_tmp_dir())
 
-    def test_ip_restriction_git(self, webserver):
-        user_model = UserModel()
-        try:
-            user_model.add_extra_ip(TEST_USER_ADMIN_LOGIN, '10.10.10.10/32')
-            Session().commit()
-            # IP permissions are cached, need to wait for the cache in the server process to expire
-            time.sleep(1.5)
-            clone_url = webserver.repo_url(GIT_REPO)
-            stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True)
-            # The message apparently changed in Git 1.8.3, so match it loosely.
-            assert re.search(r'\b403\b', stderr)
-        finally:
-            # release IP restrictions
-            for ip in UserIpMap.query():
-                UserIpMap.delete(ip.ip_id)
-            Session().commit()
-            # IP permissions are cached, need to wait for the cache in the server process to expire
-            time.sleep(1.5)
+        if vt.repo_type == 'git':
+            assert 'Cloning into' in stdout + stderr
+            assert stderr == '' or stdout == ''
+        elif vt.repo_type == 'hg':
+            assert 'requesting all changes' in stdout
+            assert 'adding changesets' in stdout
+            assert 'adding manifests' in stdout
+            assert 'adding file changes' in stdout
 
-        clone_url = webserver.repo_url(GIT_REPO)
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir())
-
-        assert 'Cloning into' in stdout + stderr
-        assert stderr == '' or stdout == ''
+            assert stderr == ''
 
-    @parametrize('repo_type, repo_name', [
-                #('git',      GIT_REPO), # git hooks doesn't work like hg hooks
-                ('hg',       HG_REPO),
-    ])
-    def test_custom_hooks_preoutgoing(self, testhook_cleanup, webserver, testfork, repo_type, repo_name):
+    @parametrize_vcs_test_hg # git hooks doesn't work like hg hooks
+    def test_custom_hooks_preoutgoing(self, testhook_cleanup, webserver, testfork, vt):
         # set prechangegroup to failing hook (returns True)
         Ui.create_or_update_hook('preoutgoing.testhook', 'python:kallithea.tests.fixture.failing_test_hook')
         Session().commit()
         # clone repo
-        clone_url = webserver.repo_url(testfork[repo_type], username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS)
+        clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type], username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS)
         dest_dir = _get_tmp_dir()
         stdout, stderr = Command(TESTS_TMP_PATH) \
-            .execute('%s clone' % repo_type, clone_url, dest_dir, ignoreReturnCode=True)
-        if repo_type == 'hg':
+            .execute(vt.repo_type, 'clone', clone_url, dest_dir, ignoreReturnCode=True)
+        if vt.repo_type == 'hg':
             assert 'preoutgoing.testhook hook failed' in stdout
-        elif repo_type == 'git':
+        elif vt.repo_type == 'git':
             assert 'error: 406' in stderr
 
-    @parametrize('repo_type, repo_name', [
-                #('git',      GIT_REPO), # git hooks doesn't work like hg hooks
-                ('hg',       HG_REPO),
-    ])
-    def test_custom_hooks_prechangegroup(self, testhook_cleanup, webserver, testfork, repo_type, repo_name):
-
-        # set prechangegroup to failing hook (returns True)
+    @parametrize_vcs_test_hg # git hooks doesn't work like hg hooks
+    def test_custom_hooks_prechangegroup(self, testhook_cleanup, webserver, testfork, vt):
+        # set prechangegroup to failing hook (returns exit code 1)
         Ui.create_or_update_hook('prechangegroup.testhook', 'python:kallithea.tests.fixture.failing_test_hook')
         Session().commit()
         # clone repo
-        clone_url = webserver.repo_url(testfork[repo_type], username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS)
+        clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type], username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS)
         dest_dir = _get_tmp_dir()
-        stdout, stderr = Command(TESTS_TMP_PATH).execute('%s clone' % repo_type, clone_url, dest_dir)
+        stdout, stderr = Command(TESTS_TMP_PATH).execute(vt.repo_type, 'clone', clone_url, dest_dir)
 
-        stdout, stderr = _add_files_and_push(webserver, repo_type, dest_dir,
-                                             username=TEST_USER_ADMIN_LOGIN,
-                                             password=TEST_USER_ADMIN_PASS,
+        stdout, stderr = _add_files_and_push(webserver, vt, dest_dir, clone_url,
                                              ignoreReturnCode=True)
         assert 'failing_test_hook failed' in stdout + stderr
         assert 'Traceback' not in stdout + stderr
         assert 'prechangegroup.testhook hook failed' in stdout + stderr
         # there are still outgoing changesets
-        stdout, stderr = _check_outgoing(repo_type, dest_dir, clone_url)
+        stdout, stderr = _check_outgoing(vt.repo_type, dest_dir, clone_url)
         assert stdout != ''
 
         # set prechangegroup hook to exception throwing method
         Ui.create_or_update_hook('prechangegroup.testhook', 'python:kallithea.tests.fixture.exception_test_hook')
         Session().commit()
         # re-try to push
-        stdout, stderr = Command(dest_dir).execute('%s push' % repo_type, clone_url, ignoreReturnCode=True)
-        if repo_type == 'hg':
+        stdout, stderr = Command(dest_dir).execute('%s push' % vt.repo_type, clone_url, ignoreReturnCode=True)
+        if vt is HgHttpVcsTest:
             # like with 'hg serve...' 'HTTP Error 500: INTERNAL SERVER ERROR' should be returned
             assert 'HTTP Error 500: INTERNAL SERVER ERROR' in stderr
-        elif repo_type == 'git':
-            assert 'exception_test_hook threw an exception' in stderr
+        elif vt is HgSshVcsTest:
+            assert 'remote: Exception: exception_test_hook threw an exception' in stdout
+        else: assert False
         # there are still outgoing changesets
-        stdout, stderr = _check_outgoing(repo_type, dest_dir, clone_url)
+        stdout, stderr = _check_outgoing(vt.repo_type, dest_dir, clone_url)
         assert stdout != ''
 
         # set prechangegroup hook to method that returns False
         Ui.create_or_update_hook('prechangegroup.testhook', 'python:kallithea.tests.fixture.passing_test_hook')
         Session().commit()
         # re-try to push
-        stdout, stderr = Command(dest_dir).execute('%s push' % repo_type, clone_url, ignoreReturnCode=True)
+        stdout, stderr = Command(dest_dir).execute('%s push' % vt.repo_type, clone_url, ignoreReturnCode=True)
         assert 'passing_test_hook succeeded' in stdout + stderr
         assert 'Traceback' not in stdout + stderr
         assert 'prechangegroup.testhook hook failed' not in stdout + stderr
         # no more outgoing changesets
-        stdout, stderr = _check_outgoing(repo_type, dest_dir, clone_url)
+        stdout, stderr = _check_outgoing(vt.repo_type, dest_dir, clone_url)
         assert stdout == ''
         assert stderr == ''
 
-    def test_add_submodule(self, webserver, testfork):
+    def test_add_submodule_git(self, webserver, testfork):
         dest_dir = _get_tmp_dir()
-        clone_url = webserver.repo_url(GIT_REPO)
+        clone_url = GitHttpVcsTest.repo_url_param(webserver, GIT_REPO)
 
-        fork_url = webserver.repo_url(testfork['git'])
+        fork_url = GitHttpVcsTest.repo_url_param(webserver, testfork['git'])
 
         # add submodule
         stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', fork_url, dest_dir)
@@ -726,6 +611,9 @@
                                     repo_name=testfork['git'],
                                     revision='tip',
                                     f_path='/'))
+        # check _repo_files_url that will be used to reload as AJAX
+        response.mustcontain('var _repo_files_url = ("/%s/files/");' % testfork['git'])
+
         response.mustcontain('<a class="submodule-dir" href="%s" target="_blank"><i class="icon-file-submodule"></i><span>testsubmodule @ ' % clone_url)
 
         # check that following a submodule link actually works - and redirects
--- a/kallithea/tests/performance/test_vcs.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/performance/test_vcs.py	Sun Jan 05 04:07:51 2020 +0100
@@ -17,6 +17,7 @@
 from kallithea.model.db import Repository
 from kallithea.tests.base import *
 
+
 @pytest.mark.skipif("not os.environ.has_key('TEST_PERFORMANCE')", reason="skipping performance tests, set TEST_PERFORMANCE in environment if desired")
 class TestVCSPerformance(TestController):
 
--- a/kallithea/tests/scripts/manual_test_concurrency.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/scripts/manual_test_concurrency.py	Sun Jan 05 04:07:51 2020 +0100
@@ -26,25 +26,27 @@
 
 """
 
+from __future__ import print_function
+
+import logging
 import os
+import shutil
 import sys
-import shutil
-import logging
 import tempfile
 from os.path import dirname
-from subprocess import Popen, PIPE
+from subprocess import PIPE, Popen
 
 from paste.deploy import appconfig
 from sqlalchemy import engine_from_config
 
+from kallithea.config.environment import load_environment
+from kallithea.lib.auth import get_crypt_password
 from kallithea.lib.utils import setup_cache_regions
-from kallithea.model.base import init_model
 from kallithea.model import meta
-from kallithea.model.db import User, Repository, Ui
-from kallithea.lib.auth import get_crypt_password
+from kallithea.model.base import init_model
+from kallithea.model.db import Repository, Ui, User
+from kallithea.tests.base import HG_REPO, TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS
 
-from kallithea.tests.base import HG_REPO
-from kallithea.config.environment import load_environment
 
 rel_path = dirname(dirname(dirname(dirname(os.path.abspath(__file__)))))
 conf = appconfig('config:development.ini', relative_to=rel_path)
@@ -72,11 +74,11 @@
         command = cmd + ' ' + ' '.join(args)
         log.debug('Executing %s', command)
         if DEBUG:
-            print command
+            print(command)
         p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE, cwd=self.cwd)
         stdout, stderr = p.communicate()
         if DEBUG:
-            print stdout, stderr
+            print(stdout, stderr)
         return stdout, stderr
 
 
@@ -88,20 +90,20 @@
 
 
 def create_test_user(force=True):
-    print 'creating test user'
+    print('creating test user')
     sa = get_session()
 
     user = sa.query(User).filter(User.username == USER).scalar()
 
     if force and user is not None:
-        print 'removing current user'
+        print('removing current user')
         for repo in sa.query(Repository).filter(Repository.user == user).all():
             sa.delete(repo)
         sa.delete(user)
         sa.commit()
 
     if user is None or force:
-        print 'creating new one'
+        print('creating new one')
         new_usr = User()
         new_usr.username = USER
         new_usr.password = get_crypt_password(PASS)
@@ -113,11 +115,11 @@
         sa.add(new_usr)
         sa.commit()
 
-    print 'done'
+    print('done')
 
 
 def create_test_repo(force=True):
-    print 'creating test repo'
+    print('creating test repo')
     from kallithea.model.repo import RepoModel
     sa = get_session()
 
@@ -128,7 +130,7 @@
     repo = sa.query(Repository).filter(Repository.repo_name == HG_REPO).scalar()
 
     if repo is None:
-        print 'repo not found creating'
+        print('repo not found creating')
 
         form_data = {'repo_name': HG_REPO,
                      'repo_type': 'hg',
@@ -138,7 +140,7 @@
         rm.base_path = '/home/hg'
         rm.create(form_data, user)
 
-    print 'done'
+    print('done')
 
 
 def set_anonymous_access(enable=True):
@@ -208,9 +210,9 @@
                                         backend=backend)
         s = time.time()
         for i in range(1, int(sys.argv[2]) + 1):
-            print 'take', i
+            print('take', i)
             test_clone_with_credentials(repo=sys.argv[1], method=METHOD,
                                         backend=backend)
-        print 'time taken %.3f' % (time.time() - s)
+        print('time taken %.3f' % (time.time() - s))
     except Exception as e:
         sys.exit('stop on %s' % e)
--- a/kallithea/tests/scripts/manual_test_crawler.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/scripts/manual_test_crawler.py	Sun Jan 05 04:07:51 2020 +0100
@@ -30,23 +30,26 @@
 :license: GPLv3, see LICENSE.md for more details.
 """
 
+from __future__ import print_function
 
 import cookielib
-import urllib
-import urllib2
-import time
 import os
 import sys
 import tempfile
+import time
+import urllib
+import urllib2
 from os.path import dirname
 
+from kallithea.lib import vcs
+from kallithea.lib.compat import OrderedSet
+from kallithea.lib.vcs.exceptions import RepositoryError
+
+
 __here__ = os.path.abspath(__file__)
 __root__ = dirname(dirname(dirname(__here__)))
 sys.path.append(__root__)
 
-from kallithea.lib import vcs
-from kallithea.lib.compat import OrderedSet
-from kallithea.lib.vcs.exceptions import RepositoryError
 
 PASES = 3
 HOST = 'http://127.0.0.1'
@@ -59,7 +62,7 @@
 if not BASE_URI.endswith('/'):
     BASE_URI += '/'
 
-print 'Crawling @ %s' % BASE_URI
+print('Crawling @ %s' % BASE_URI)
 BASE_URI += '%s'
 PROJECT_PATH = os.path.join('/', 'home', 'username', 'repos')
 PROJECTS = [
@@ -107,16 +110,16 @@
         size = len(f.read())
         e = time.time() - s
         total_time += e
-        print 'visited %s size:%s req:%s ms' % (full_uri, size, e)
+        print('visited %s size:%s req:%s ms' % (full_uri, size, e))
 
-    print 'total_time', total_time
-    print 'average on req', total_time / float(pages)
+    print('total_time', total_time)
+    print('average on req', total_time / float(pages))
 
 
 def test_changeset_walk(proj, limit=None):
     repo, proj = _get_repo(proj)
 
-    print 'processing', os.path.join(PROJECT_PATH, proj)
+    print('processing', os.path.join(PROJECT_PATH, proj))
     total_time = 0
 
     cnt = 0
@@ -127,22 +130,22 @@
             break
 
         full_uri = (BASE_URI % raw_cs)
-        print '%s visiting %s\%s' % (cnt, full_uri, i)
+        print('%s visiting %s\%s' % (cnt, full_uri, i))
         s = time.time()
         f = o.open(full_uri)
         size = len(f.read())
         e = time.time() - s
         total_time += e
-        print '%s visited %s\%s size:%s req:%s ms' % (cnt, full_uri, i, size, e)
+        print('%s visited %s\%s size:%s req:%s ms' % (cnt, full_uri, i, size, e))
 
-    print 'total_time', total_time
-    print 'average on req', total_time / float(cnt)
+    print('total_time', total_time)
+    print('average on req', total_time / float(cnt))
 
 
 def test_files_walk(proj, limit=100):
     repo, proj = _get_repo(proj)
 
-    print 'processing', os.path.join(PROJECT_PATH, proj)
+    print('processing', os.path.join(PROJECT_PATH, proj))
     total_time = 0
 
     paths_ = OrderedSet([''])
@@ -169,22 +172,22 @@
 
         file_path = '/'.join((proj, 'files', 'tip', f))
         full_uri = (BASE_URI % file_path)
-        print '%s visiting %s' % (cnt, full_uri)
+        print('%s visiting %s' % (cnt, full_uri))
         s = time.time()
         f = o.open(full_uri)
         size = len(f.read())
         e = time.time() - s
         total_time += e
-        print '%s visited OK size:%s req:%s ms' % (cnt, size, e)
+        print('%s visited OK size:%s req:%s ms' % (cnt, size, e))
 
-    print 'total_time', total_time
-    print 'average on req', total_time / float(cnt)
+    print('total_time', total_time)
+    print('average on req', total_time / float(cnt))
 
 if __name__ == '__main__':
     for path in PROJECTS:
         repo = vcs.get_repo(os.path.join(PROJECT_PATH, path))
         for i in range(PASES):
-            print 'PASS %s/%s' % (i, PASES)
+            print('PASS %s/%s' % (i, PASES))
             test_changelog_walk(repo, pages=80)
             test_changeset_walk(repo, limit=100)
             test_files_walk(repo, limit=100)
--- a/kallithea/tests/vcs/__init__.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/__init__.py	Sun Jan 05 04:07:51 2020 +0100
@@ -22,7 +22,7 @@
 import os
 import shutil
 
-from kallithea.tests.base import TEST_HG_REPO, HG_REMOTE_REPO, TEST_GIT_REPO, GIT_REMOTE_REPO, TESTS_TMP_PATH
+from kallithea.tests.base import GIT_REMOTE_REPO, HG_REMOTE_REPO, TEST_GIT_REPO, TEST_HG_REPO, TESTS_TMP_PATH
 from kallithea.tests.vcs.utils import SCMFetcher
 
 
--- a/kallithea/tests/vcs/base.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/base.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,14 +1,13 @@
 """
 Module providing backend independent mixin class.
 """
-import os
+import datetime
 import time
-import datetime
+
 import pytest
 
 from kallithea.lib import vcs
 from kallithea.lib.vcs.nodes import FileNode
-
 from kallithea.tests.vcs.conf import get_new_dir
 
 
--- a/kallithea/tests/vcs/conf.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/conf.py	Sun Jan 05 04:07:51 2020 +0100
@@ -8,12 +8,8 @@
 # module. Some of these configuration options are subsequently
 # consumed by the VCS test module.
 from kallithea.tests.base import (
-    TESTS_TMP_PATH,
-    TEST_HG_REPO, HG_REMOTE_REPO,
-    TEST_HG_REPO_CLONE, TEST_HG_REPO_PULL,
-    TEST_GIT_REPO, GIT_REMOTE_REPO,
-    TEST_GIT_REPO_CLONE,
-)
+    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__ = (
     'TEST_HG_REPO', 'TEST_GIT_REPO', 'HG_REMOTE_REPO', 'GIT_REMOTE_REPO',
--- a/kallithea/tests/vcs/test_archives.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/test_archives.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,15 +1,14 @@
+import datetime
 import os
+import StringIO
 import tarfile
+import tempfile
 import zipfile
-import datetime
-import tempfile
-import StringIO
 
 import pytest
 
 from kallithea.lib.vcs.exceptions import VCSError
 from kallithea.lib.vcs.nodes import FileNode
-
 from kallithea.tests.vcs.base import _BackendTestMixin
 from kallithea.tests.vcs.conf import TESTS_TMP_PATH
 
--- a/kallithea/tests/vcs/test_branches.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/test_branches.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,7 +1,7 @@
 import datetime
+
 from kallithea.lib import vcs
 from kallithea.lib.vcs.nodes import FileNode
-
 from kallithea.tests.vcs.base import _BackendTestMixin
 
 
--- a/kallithea/tests/vcs/test_changesets.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/test_changesets.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,24 +1,14 @@
 # encoding: utf-8
 
-import time
 import datetime
 
 import pytest
 
 from kallithea.lib import vcs
-
 from kallithea.lib.vcs.backends.base import BaseChangeset
-from kallithea.lib.vcs.nodes import (
-    FileNode, AddedFileNodesGenerator,
-    ChangedFileNodesGenerator, RemovedFileNodesGenerator
-)
-from kallithea.lib.vcs.exceptions import (
-    BranchDoesNotExistError, ChangesetDoesNotExistError,
-    RepositoryError, EmptyRepositoryError
-)
-
+from kallithea.lib.vcs.exceptions import BranchDoesNotExistError, ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError
+from kallithea.lib.vcs.nodes import AddedFileNodesGenerator, ChangedFileNodesGenerator, FileNode, RemovedFileNodesGenerator
 from kallithea.tests.vcs.base import _BackendTestMixin
-from kallithea.tests.vcs.conf import get_new_dir
 
 
 class TestBaseChangeset(object):
--- a/kallithea/tests/vcs/test_getitem.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/test_getitem.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,7 +1,7 @@
 import datetime
 
+from kallithea.lib.vcs.nodes import FileNode
 from kallithea.tests.vcs.base import _BackendTestMixin
-from kallithea.lib.vcs.nodes import FileNode
 
 
 class GetitemTestCaseMixin(_BackendTestMixin):
--- a/kallithea/tests/vcs/test_getslice.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/test_getslice.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,7 +1,6 @@
 import datetime
 
 from kallithea.lib.vcs.nodes import FileNode
-
 from kallithea.tests.vcs.base import _BackendTestMixin
 
 
--- a/kallithea/tests/vcs/test_git.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/test_git.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,16 +1,15 @@
+import datetime
 import os
 import sys
-import mock
-import datetime
 import urllib2
 
+import mock
 import pytest
 
-from kallithea.lib.vcs.backends.git import GitRepository, GitChangeset
-from kallithea.lib.vcs.exceptions import RepositoryError, VCSError, NodeDoesNotExistError
-from kallithea.lib.vcs.nodes import NodeKind, FileNode, DirNode, NodeState
+from kallithea.lib.vcs.backends.git import GitChangeset, GitRepository
+from kallithea.lib.vcs.exceptions import NodeDoesNotExistError, RepositoryError, VCSError
+from kallithea.lib.vcs.nodes import DirNode, FileNode, NodeKind, NodeState
 from kallithea.model.scm import ScmModel
-
 from kallithea.tests.vcs.base import _BackendTestMixin
 from kallithea.tests.vcs.conf import TEST_GIT_REPO, TEST_GIT_REPO_CLONE, TESTS_TMP_PATH, get_new_dir
 
--- a/kallithea/tests/vcs/test_hg.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/test_hg.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,15 +1,13 @@
 import os
 
+import mock
 import pytest
-import mock
 
 from kallithea.lib.utils2 import safe_str
-from kallithea.lib.vcs.backends.hg import MercurialRepository, MercurialChangeset
-from kallithea.lib.vcs.exceptions import RepositoryError, VCSError, NodeDoesNotExistError
+from kallithea.lib.vcs.backends.hg import MercurialChangeset, MercurialRepository
+from kallithea.lib.vcs.exceptions import NodeDoesNotExistError, RepositoryError, VCSError
 from kallithea.lib.vcs.nodes import NodeKind, NodeState
-
-from kallithea.tests.vcs.conf import TEST_HG_REPO, TEST_HG_REPO_CLONE, \
-    TEST_HG_REPO_PULL, TESTS_TMP_PATH
+from kallithea.tests.vcs.conf import TEST_HG_REPO, TEST_HG_REPO_CLONE, TEST_HG_REPO_PULL, TESTS_TMP_PATH
 
 
 class TestMercurialRepository(object):
--- a/kallithea/tests/vcs/test_inmemchangesets.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/test_inmemchangesets.py	Sun Jan 05 04:07:51 2020 +0100
@@ -3,23 +3,15 @@
 Tests so called "in memory changesets" commit API of vcs.
 """
 
-import time
 import datetime
 
 import pytest
 
 from kallithea.lib import vcs
-from kallithea.lib.vcs.exceptions import EmptyRepositoryError
-from kallithea.lib.vcs.exceptions import NodeAlreadyAddedError
-from kallithea.lib.vcs.exceptions import NodeAlreadyExistsError
-from kallithea.lib.vcs.exceptions import NodeAlreadyRemovedError
-from kallithea.lib.vcs.exceptions import NodeAlreadyChangedError
-from kallithea.lib.vcs.exceptions import NodeDoesNotExistError
-from kallithea.lib.vcs.exceptions import NodeNotChangedError
-from kallithea.lib.vcs.nodes import DirNode
-from kallithea.lib.vcs.nodes import FileNode
+from kallithea.lib.vcs.exceptions import (
+    EmptyRepositoryError, NodeAlreadyAddedError, NodeAlreadyChangedError, NodeAlreadyExistsError, NodeAlreadyRemovedError, NodeDoesNotExistError, NodeNotChangedError)
+from kallithea.lib.vcs.nodes import DirNode, FileNode
 from kallithea.lib.vcs.utils import safe_unicode
-
 from kallithea.tests.vcs.base import _BackendTestMixin
 
 
--- a/kallithea/tests/vcs/test_nodes.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/test_nodes.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,13 +1,9 @@
+import mimetypes
 import stat
-import mimetypes
 
 import pytest
 
-from kallithea.lib.vcs.nodes import DirNode
-from kallithea.lib.vcs.nodes import FileNode
-from kallithea.lib.vcs.nodes import Node
-from kallithea.lib.vcs.nodes import NodeError
-from kallithea.lib.vcs.nodes import NodeKind
+from kallithea.lib.vcs.nodes import DirNode, FileNode, Node, NodeError, NodeKind
 
 
 class TestNodeBasic(object):
--- a/kallithea/tests/vcs/test_repository.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/test_repository.py	Sun Jan 05 04:07:51 2020 +0100
@@ -2,11 +2,10 @@
 
 import pytest
 
+from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError
 from kallithea.lib.vcs.nodes import FileNode
-from kallithea.lib.vcs.exceptions import ChangesetDoesNotExistError
-
+from kallithea.tests.vcs import TEST_USER_CONFIG_FILE
 from kallithea.tests.vcs.base import _BackendTestMixin
-from kallithea.tests.vcs import TEST_USER_CONFIG_FILE
 
 
 class RepositoryBaseTest(_BackendTestMixin):
--- a/kallithea/tests/vcs/test_tags.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/test_tags.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,8 +1,6 @@
 import pytest
 
-from kallithea.lib.vcs.exceptions import TagAlreadyExistError
-from kallithea.lib.vcs.exceptions import TagDoesNotExistError
-
+from kallithea.lib.vcs.exceptions import TagAlreadyExistError, TagDoesNotExistError
 from kallithea.tests.vcs.base import _BackendTestMixin
 
 
--- a/kallithea/tests/vcs/test_utils.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/test_utils.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,25 +1,18 @@
 # -*- coding: utf-8 -*-
 
+import datetime
 import os
-import mock
+import shutil
 import time
-import shutil
-import datetime
 
+import mock
 import pytest
 
-from kallithea.lib.vcs.utils.paths import get_dirs_for_path
-from kallithea.lib.vcs.utils.helpers import get_dict_for_attrs
-from kallithea.lib.vcs.utils.helpers import get_scm
-from kallithea.lib.vcs.utils.helpers import get_scms_for_path
-from kallithea.lib.vcs.utils.helpers import get_total_seconds
-from kallithea.lib.vcs.utils.helpers import parse_changesets
-from kallithea.lib.vcs.utils.helpers import parse_datetime
+from kallithea.lib.vcs.exceptions import VCSError
 from kallithea.lib.vcs.utils import author_email, author_name
-from kallithea.lib.vcs.utils.paths import get_user_home
-from kallithea.lib.vcs.exceptions import VCSError
-
-from kallithea.tests.vcs.conf import TEST_HG_REPO, TEST_GIT_REPO, TESTS_TMP_PATH
+from kallithea.lib.vcs.utils.helpers import get_dict_for_attrs, get_scm, get_scms_for_path, parse_changesets, parse_datetime
+from kallithea.lib.vcs.utils.paths import get_dirs_for_path, get_user_home
+from kallithea.tests.vcs.conf import TEST_GIT_REPO, TEST_HG_REPO, TESTS_TMP_PATH
 
 
 class TestPaths(object):
@@ -231,21 +224,6 @@
         }
 
 
-class TestGetTotalSeconds(object):
-
-    def assertTotalSecondsEqual(self, timedelta, expected_seconds):
-        result = get_total_seconds(timedelta)
-        assert result == expected_seconds, \
-            "We computed %s seconds for %s but expected %s" \
-            % (result, timedelta, expected_seconds)
-
-    def test_get_total_seconds_returns_proper_value(self):
-        self.assertTotalSecondsEqual(datetime.timedelta(seconds=1001), 1001)
-
-    def test_get_total_seconds_returns_proper_value_for_partial_seconds(self):
-        self.assertTotalSecondsEqual(datetime.timedelta(seconds=50.65), 50.65)
-
-
 class TestGetUserHome(object):
 
     @mock.patch.object(os, 'environ', {})
--- a/kallithea/tests/vcs/test_vcs.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/test_vcs.py	Sun Jan 05 04:07:51 2020 +0100
@@ -4,10 +4,9 @@
 import pytest
 
 from kallithea.lib.utils2 import safe_str
-from kallithea.lib.vcs import VCSError, get_repo, get_backend
+from kallithea.lib.vcs import VCSError, get_backend, get_repo
 from kallithea.lib.vcs.backends.hg import MercurialRepository
-
-from kallithea.tests.vcs.conf import TEST_HG_REPO, TEST_GIT_REPO, TESTS_TMP_PATH
+from kallithea.tests.vcs.conf import TEST_GIT_REPO, TEST_HG_REPO, TESTS_TMP_PATH
 
 
 class TestVCS(object):
--- a/kallithea/tests/vcs/test_workdirs.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/test_workdirs.py	Sun Jan 05 04:07:51 2020 +0100
@@ -3,7 +3,6 @@
 import pytest
 
 from kallithea.lib.vcs.nodes import FileNode
-
 from kallithea.tests.vcs.base import _BackendTestMixin
 
 
--- a/kallithea/tests/vcs/utils.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/kallithea/tests/vcs/utils.py	Sun Jan 05 04:07:51 2020 +0100
@@ -4,7 +4,6 @@
 """
 import os
 import sys
-
 from subprocess import Popen
 
 
--- a/pytest.ini	Sat Aug 24 21:48:43 2019 +0200
+++ b/pytest.ini	Sun Jan 05 04:07:51 2020 +0100
@@ -7,3 +7,6 @@
     -rfEsxXw
     # Shorter scrollbacks; less stuff to scroll through
     --tb=short
+    #
+    --doctest-modules
+    --doctest-ignore-import-errors
--- a/scripts/contributor_data.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/scripts/contributor_data.py	Sun Jan 05 04:07:51 2020 +0100
@@ -30,6 +30,7 @@
 name_fixes['mao <mao@lins.fju.edu.tw>'] = "Ching-Chen Mao <mao@lins.fju.edu.tw>"
 name_fixes['marcink'] = "Marcin Kuźmiński <marcin@python-works.com>"
 name_fixes['Marcin Kuzminski'] = "Marcin Kuźmiński <marcin@python-works.com>"
+name_fixes['mikespook'] = "mikespook <mikespook@gmail.com>"
 name_fixes['nansenat16@null.tw'] = "nansenat16 <nansenat16@null.tw>"
 name_fixes['Peter Vitt'] = "Peter Vitt <petervitt@web.de>"
 name_fixes['philip.j@hostdime.com'] = "Philip Jameson <philip.j@hostdime.com>"
@@ -62,6 +63,36 @@
 # Was reworked and contributed later and shadowed by other contributions:
 no_about.add(('Sean Farley <sean.michael.farley@gmail.com>', '2013'))
 
+# Contributors in about.html and CONTRIBUTORS not appearing in repository
+# history:
+other = [
+    # Work folded into commits attributed to others:
+    ('2013', 'Ilya Beda <ir4y.ix@gmail.com>'),
+    ('2015', 'Bradley M. Kuhn <bkuhn@sfconservancy.org>'),
+    # Translators previously listed in
+    # kallithea/i18n/*/LC_MESSAGES/kallithea.po and originating from before the
+    # use of Weblate.
+    ('2012', 'Augusto Herrmann <augusto.herrmann@gmail.com>'),
+    ('2012', 'Nemcio <areczek01@gmail.com>'),
+    ('2012', 'Nemcio <bogdan114@g.pl>'),
+    ('2013', 'Andrey Mivrenik <myvrenik@gmail.com>'),
+    ('2013', 'ArcheR <aleclitvinov1980@gmail.com>'),
+    ('2013', 'gnustavo <gustavo@gnustavo.com>'),
+    ('2013', 'ivlevdenis <ivlevdenis.ru@gmail.com>'),
+    ('2013', 'Mikhail Zholobov <legal90@gmail.com>'),
+    ('2013', 'mokeev1995 <mokeev_andre@mail.ru>'),
+    ('2013', 'Nemcio <areczek01@gmail.com>'),
+    ('2013', 'Ruslan Bekenev <furyinbox@gmail.com>'),
+    ('2013', 'shirou - しろう'),
+    ('2013', 'softforwinxp <softforwinxp@gmail.com>'),
+    ('2013', 'stephanj <info@stephan-jauernick.de>'),
+    ('2013', 'zhmylove <zhmylove@narod.ru>'),
+    ('2013', 'こいんとす <tkondou@gmail.com>'),
+    ('2014', 'invision70 <invision70@gmail.com>'),
+    ('2014', 'SkryabinD <skryabind@gmail.com>'),
+    ('2014', 'whosaysni <whosaysni@gmail.com>'),
+]
+
 # Preserve contributors listed in about.html but not appearing in repository
 # history:
 other_about = [
--- a/scripts/docs-headings.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/scripts/docs-headings.py	Sun Jan 05 04:07:51 2020 +0100
@@ -4,9 +4,12 @@
 Consistent formatting of rst section titles
 """
 
+from __future__ import print_function
+
 import re
 import subprocess
 
+
 spaces = [
     (0, 1), # we assume this is a over-and-underlined header
     (2, 1),
@@ -32,7 +35,7 @@
 def main():
     filenames = subprocess.check_output(['hg', 'loc', 'set:**.rst+kallithea/i18n/how_to']).splitlines()
     for fn in filenames:
-        print 'processing %s' % fn
+        print('processing %s' % fn)
         s = open(fn).read()
 
         # find levels and their styles
@@ -43,11 +46,11 @@
             if style in styles:
                 stylepos = styles.index(style)
                 if stylepos > lastpos + 1:
-                    print 'bad style %r with level %s - was at %s' % (style, stylepos, lastpos)
+                    print('bad style %r with level %s - was at %s' % (style, stylepos, lastpos))
             else:
                 stylepos = len(styles)
                 if stylepos > lastpos + 1:
-                    print 'bad new style %r - expected %r' % (style, styles[lastpos + 1])
+                    print('bad new style %r - expected %r' % (style, styles[lastpos + 1]))
                 else:
                     styles.append(style)
             lastpos = stylepos
@@ -74,7 +77,7 @@
 
         open(fn, 'w').write(s)
 
-    print subprocess.check_output(['hg', 'diff'] + filenames)
+    print(subprocess.check_output(['hg', 'diff'] + filenames))
 
 if __name__ == '__main__':
     main()
--- a/scripts/generate-ini.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/scripts/generate-ini.py	Sun Jan 05 04:07:51 2020 +0100
@@ -3,10 +3,13 @@
 Based on kallithea/lib/paster_commands/template.ini.mako, generate development.ini
 """
 
+from __future__ import print_function
+
 import re
 
 from kallithea.lib import inifile
 
+
 # files to be generated from the mako template
 ini_files = [
     ('development.ini',
@@ -17,13 +20,10 @@
             '[app:main]': {
                 'debug': 'true',
                 'app_instance_uuid': 'development-not-secret',
-                'beaker.session.secret': 'development-not-secret',
+                'session.secret': 'development-not-secret',
             },
-            '[handler_console]': {
-                'formatter': 'color_formatter',
-            },
-            '[handler_console_sql]': {
-                'formatter': 'color_formatter_sql',
+            '[logger_root]': {
+                'handlers': 'console_color',
             },
             '[logger_routes]': {
                 'level': 'DEBUG',
@@ -54,17 +54,17 @@
 def main():
     # make sure all mako lines starting with '#' (the '##' comments) are marked up as <text>
     makofile = inifile.template_file
-    print 'reading:', makofile
+    print('reading:', makofile)
     mako_org = open(makofile).read()
     mako_no_text_markup = re.sub(r'</?%text>', '', mako_org)
     mako_marked_up = re.sub(r'\n(##.*)', r'\n<%text>\1</%text>', mako_no_text_markup, flags=re.MULTILINE)
     if mako_marked_up != mako_org:
-        print 'writing:', makofile
+        print('writing:', makofile)
         open(makofile, 'w').write(mako_marked_up)
 
     # create ini files
     for fn, settings in ini_files:
-        print 'updating:', fn
+        print('updating:', fn)
         inifile.create(fn, None, settings)
 
 
--- a/scripts/logformat.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/scripts/logformat.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,14 +1,10 @@
 #!/usr/bin/env python2
 
+from __future__ import print_function
+
 import re
 import sys
 
-if len(sys.argv) < 2:
-    print 'Cleanup of superfluous % formatting of log statements.'
-    print 'Usage:'
-    print '''  hg revert `hg loc '*.py'|grep -v logformat.py` && scripts/logformat.py `hg loc '*.py'` && hg diff'''
-    raise SystemExit(1)
-
 
 logre = r'''
 (log\.(?:error|info|warning|debug)
@@ -19,21 +15,35 @@
 [ \n]*[)]
 )
 '''
+
+
 res = [
     # handle % () - keeping spaces around the old %
-    (re.compile(logre % r'''("[^"]*"|'[^']*')   ([\n ]*) %  ([\n ]*) \( ( (?:[^()]|\n)* (?: \( (?:[^()]|\n)* \) (?:[^()]|\n)* )* ) \) ''', flags=re.MULTILINE|re.VERBOSE), r'\1\2,\3\4\5\6'),
+    (re.compile(logre % r'''("[^"]*"|'[^']*')   ([\n ]*) %  ([\n ]*) \( ( (?:[^()]|\n)* (?: \( (?:[^()]|\n)* \) (?:[^()]|\n)* )* ) \) ''', flags=re.MULTILINE | re.VERBOSE), r'\1\2,\3\4\5\6'),
     # handle % without () - keeping spaces around the old %
-    (re.compile(logre % r'''("[^"]*"|'[^']*')   ([\n ]*) %  ([\n ]*)    ( (?:[^()]|\n)* (?: \( (?:[^()]|\n)* \) (?:[^()]|\n)* )* )    ''', flags=re.MULTILINE|re.VERBOSE), r'\1\2,\3\4\5\6'),
+    (re.compile(logre % r'''("[^"]*"|'[^']*')   ([\n ]*) %  ([\n ]*)    ( (?:[^()]|\n)* (?: \( (?:[^()]|\n)* \) (?:[^()]|\n)* )* )    ''', flags=re.MULTILINE | re.VERBOSE), r'\1\2,\3\4\5\6'),
     # remove extra space if it is on next line
-    (re.compile(logre % r'''("[^"]*"|'[^']*') , (\n [ ]) ([ ][\n ]*)    ( (?:[^()]|\n)* (?: \( (?:[^()]|\n)* \) (?:[^()]|\n)* )* )    ''', flags=re.MULTILINE|re.VERBOSE), r'\1\2,\3\4\5\6'),
+    (re.compile(logre % r'''("[^"]*"|'[^']*') , (\n [ ]) ([ ][\n ]*)    ( (?:[^()]|\n)* (?: \( (?:[^()]|\n)* \) (?:[^()]|\n)* )* )    ''', flags=re.MULTILINE | re.VERBOSE), r'\1\2,\3\4\5\6'),
     # remove extra space if it is on same line
-    (re.compile(logre % r'''("[^"]*"|'[^']*') , [ ]+  () (   [\n ]+)    ( (?:[^()]|\n)* (?: \( (?:[^()]|\n)* \) (?:[^()]|\n)* )* )    ''', flags=re.MULTILINE|re.VERBOSE), r'\1\2,\3\4\5\6'),
+    (re.compile(logre % r'''("[^"]*"|'[^']*') , [ ]+  () (   [\n ]+)    ( (?:[^()]|\n)* (?: \( (?:[^()]|\n)* \) (?:[^()]|\n)* )* )    ''', flags=re.MULTILINE | re.VERBOSE), r'\1\2,\3\4\5\6'),
     # remove trailing , and space
-    (re.compile(logre % r'''("[^"]*"|'[^']*') ,       () (   [\n ]*)    ( (?:[^()]|\n)* (?: \( (?:[^()]|\n)* \) (?:[^()]|\n)* )* [^(), \n] ) [ ,]*''', flags=re.MULTILINE|re.VERBOSE), r'\1\2,\3\4\5\6'),
+    (re.compile(logre % r'''("[^"]*"|'[^']*') ,       () (   [\n ]*)    ( (?:[^()]|\n)* (?: \( (?:[^()]|\n)* \) (?:[^()]|\n)* )* [^(), \n] ) [ ,]*''', flags=re.MULTILINE | re.VERBOSE), r'\1\2,\3\4\5\6'),
     ]
 
-for f in sys.argv[1:]:
+
+def rewrite(f):
     s = open(f).read()
     for r, t in res:
         s = r.sub(t, s)
     open(f, 'w').write(s)
+
+
+if __name__ == '__main__':
+    if len(sys.argv) < 2:
+        print('Cleanup of superfluous % formatting of log statements.')
+        print('Usage:')
+        print('''  hg revert `hg loc '*.py'|grep -v logformat.py` && scripts/logformat.py `hg loc '*.py'` && hg diff''')
+        raise SystemExit(1)
+
+    for f in sys.argv[1:]:
+        rewrite(f)
--- a/scripts/make-release	Sat Aug 24 21:48:43 2019 +0200
+++ b/scripts/make-release	Sun Jan 05 04:07:51 2020 +0100
@@ -19,8 +19,7 @@
 . "$venv/bin/activate"
 
 echo "Install/verify tools needed for building and uploading stuff"
-pip install --upgrade -e .
-pip install --upgrade -r dev_requirements.txt twine
+pip install --upgrade -e . -r dev_requirements.txt twine
 
 echo "Cleanup and update copyrights ... and clean checkout"
 scripts/run-all-cleanup
--- a/scripts/shortlog.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/scripts/shortlog.py	Sun Jan 05 04:07:51 2020 +0100
@@ -8,8 +8,10 @@
 import argparse
 import os
 from collections import Counter
+
 import contributor_data
 
+
 def main():
 
     parser = argparse.ArgumentParser(description='Generate a list of committers and commit counts.')
--- a/scripts/update-copyrights.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/scripts/update-copyrights.py	Sun Jan 05 04:07:51 2020 +0100
@@ -41,6 +41,7 @@
 import os
 import re
 from collections import defaultdict
+
 import contributor_data
 
 
@@ -127,7 +128,7 @@
 
     insert_entries(
         filename='kallithea/templates/about.html',
-        all_entries=repo_entries + contributor_data.other_about,
+        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)*',
@@ -137,7 +138,7 @@
 
     insert_entries(
         filename='CONTRIBUTORS',
-        all_entries=repo_entries + contributor_data.other_contributors,
+        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)*',
@@ -155,6 +156,17 @@
         format_f=lambda years, name: ' ' + nice_years(years, '&ndash;', ', ') + ' ',
         )
 
+    #docs/conf.py:copyright = u'2010-2016 by various authors, licensed as GPLv3.'
+    insert_entries(
+        filename='docs/conf.py',
+        all_entries=repo_entries,
+        no_entries=contributor_data.total_ignore,
+        domain_extra={},
+        split_re=r"(?<=copyright = u').*(?= by various authors)",
+        normalize_name=lambda name: '',
+        format_f=lambda years, name: nice_years(years, '-', ', '),
+        )
+
 
 if __name__ == '__main__':
     main()
--- a/scripts/validate-commits	Sat Aug 24 21:48:43 2019 +0200
+++ b/scripts/validate-commits	Sun Jan 05 04:07:51 2020 +0100
@@ -1,4 +1,4 @@
-#!/usr/bin/env bash
+#!/bin/bash
 # Validate the specified commits against test suite and other checks.
 
 if [ -n "$VIRTUAL_ENV" ]; then
@@ -37,9 +37,7 @@
     virtualenv -p "$(command -v python2)" "$venv"
     source "$venv/bin/activate"
     pip install --upgrade pip setuptools
-    pip install -e .
-    pip install -r dev_requirements.txt
-    pip install python-ldap python-pam
+    pip install -e . -r dev_requirements.txt python-ldap python-pam
 
     # run-all-cleanup
     scripts/run-all-cleanup
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/validate-minimum-dependency-versions	Sun Jan 05 04:07:51 2020 +0100
@@ -0,0 +1,55 @@
+#!/bin/bash
+# Test that installation of all dependencies works fine if versions are set to
+# the minimum ones.
+
+set -e
+
+if [ -n "$VIRTUAL_ENV" ]; then
+    echo "This script will create its own virtualenv - please don't run it inside an existing one." >&2
+    exit 1
+fi
+
+cd "$(hg root)"
+
+venv=build/minimum-dependency-versions-venv
+log=build/minimum-dependency-versions.log
+min_requirements=build/minimum-dependency-versions-requirements.txt
+echo "virtualenv: $venv"
+echo "log: $log"
+echo "minimum requirements file: $min_requirements"
+
+# clean up previous runs
+rm -rf "$venv" "$log"
+mkdir -p "$venv"
+
+# Make a light weight parsing of setup.py and dev_requirements.txt,
+# finding all >= requirements and dumping into a custom requirements.txt
+# while fixating the requirement at the lower bound.
+sed -n 's/.*"\(.*\)>=\(.*\)".*/\1==\2/p' setup.py > "$min_requirements"
+sed 's/>=/==/p' dev_requirements.txt >> "$min_requirements"
+
+virtualenv -p "$(command -v python2)" "$venv"
+source "$venv/bin/activate"
+pip install --upgrade pip setuptools
+pip install -e . -r "$min_requirements" python-ldap python-pam 2> >(tee "$log" >&2)
+
+# Strip out the known Python 2.7 deprecation message.
+sed -i '/DEPRECATION: Python 2\.7 will reach the end of its life/d' "$log"
+
+# Treat any message on stderr as a problem, for the caller to interpret.
+if [ -s "$log" ]; then
+    echo
+    echo "Error: pip detected following problems:"
+    cat "$log"
+    echo
+    exit 1
+fi
+
+freeze_txt=build/minimum-dependency-versions.txt
+pip freeze > $freeze_txt
+echo "Installation of minimum packages was successful, providing a set of packages as in $freeze_txt . Now running test suite..."
+
+pytest
+
+echo "Test suite execution was successful."
+echo "You can now do additional validation using virtual env '$venv'."
--- a/scripts/whitespacecleanup.sh	Sat Aug 24 21:48:43 2019 +0200
+++ b/scripts/whitespacecleanup.sh	Sun Jan 05 04:07:51 2020 +0100
@@ -2,7 +2,7 @@
 
 # Enforce some consistency in whitespace - just to avoid spurious whitespaces changes
 
-files=`hg mani | egrep -v '/fontello/|/email_templates/|(/lockfiles.py|^LICENSE-MERGELY.html|^docs/Makefile|^scripts/whitespacecleanup.sh|/(graph|mergely|native.history)\.js|/test_dump_html_mails.ref.html|\.png|\.gif|\.ico|\.pot|\.po|\.mo|\.tar\.gz|\.diff)$'`
+files=`hg mani | egrep -v '/fontello/|/email_templates/|(^LICENSE-MERGELY.html|^docs/Makefile|^scripts/whitespacecleanup.sh|/(graph|mergely|native.history)\.js|/test_dump_html_mails.ref.html|\.png|\.gif|\.ico|\.pot|\.po|\.mo|\.tar\.gz|\.diff)$'`
 
 sed -i "s/`printf '\r'`//g" $files
 sed -i -e "s,`printf '\t'`,    ,g" $files
@@ -17,4 +17,7 @@
 hg mani | xargs chmod -x
 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 diff
--- a/setup.cfg	Sat Aug 24 21:48:43 2019 +0200
+++ b/setup.cfg	Sun Jan 05 04:07:51 2020 +0100
@@ -16,7 +16,6 @@
 output_file = kallithea/i18n/kallithea.pot
 msgid-bugs-address = translations@kallithea-scm.org
 copyright-holder = Various authors, licensing as GPLv3
-no-wrap = true
 
 [init_catalog]
 domain = kallithea
--- a/setup.py	Sat Aug 24 21:48:43 2019 +0200
+++ b/setup.py	Sun Jan 05 04:07:51 2020 +0100
@@ -1,11 +1,16 @@
 #!/usr/bin/env python2
 # -*- coding: utf-8 -*-
 import os
+import platform
 import sys
-import platform
+
+import setuptools
+# monkey patch setuptools to use distutils owner/group functionality
+from setuptools.command import sdist
+
 
 if sys.version_info < (2, 6) or sys.version_info >= (3,):
-    raise Exception('Kallithea requires python 2.6 or 2.7')
+    raise Exception('Kallithea requires python 2.7')
 
 
 here = os.path.abspath(os.path.dirname(__file__))
@@ -36,38 +41,36 @@
 
 requirements = [
     "alembic >= 0.8.0, < 1.1",
-    "gearbox < 1",
-    "waitress >= 0.8.8, < 1.2",
-    "WebOb >= 1.7, < 1.8", # turbogears2 2.3.12 requires WebOb<1.8.0
+    "gearbox >= 0.1.0, < 1",
+    "waitress >= 0.8.8, < 1.4",
+    "WebOb >= 1.7, < 1.9",
     "backlash >= 0.1.2, < 1",
-    "TurboGears2 >= 2.3.10, < 2.4",
+    "TurboGears2 >= 2.3.10, < 2.5",
     "tgext.routes >= 0.2.0, < 1",
     "Beaker >= 1.7.0, < 2",
     "WebHelpers >= 1.3, < 1.4",
-    "FormEncode >= 1.2.4, < 1.4",
-    "SQLAlchemy >= 1.1, < 1.3",
+    "WebHelpers2 >= 2.0, < 2.1",
+    "FormEncode >= 1.3.0, < 1.4",
+    "SQLAlchemy >= 1.1, < 1.4",
     "Mako >= 0.9.0, < 1.1",
-    "Pygments >= 2.0, < 2.3",
+    "Pygments >= 2.2.0, < 2.5",
     "Whoosh >= 2.5.0, < 2.8",
-    "celery >= 3.1, < 4.0", # celery 4 doesn't work
-    "Babel >= 1.3, < 2.7",
-    "python-dateutil >= 1.5.0, < 2.8",
-    "Markdown >= 2.2.1, < 2.7",
+    "celery >= 3.1, < 4.0", # TODO: celery 4 doesn't work
+    "Babel >= 1.3, < 2.8",
+    "python-dateutil >= 1.5.0, < 2.9",
+    "Markdown >= 2.2.1, < 3.2",
     "docutils >= 0.11, < 0.15",
     "URLObject >= 2.3.4, < 2.5",
-    "Routes >= 1.13, < 2",
+    "Routes >= 1.13, < 2", # TODO: bumping to 2.0 will make test_file_annotation fail
     "dulwich >= 0.14.1, < 0.20",
-    "mercurial >= 4.1.1, < 4.10",
-    "decorator >= 3.3.2, < 4.4",
+    "mercurial >= 4.5, < 5.3",
+    "decorator >= 3.3.2, < 4.5",
     "Paste >= 2.0.3, < 3.1",
-    "bleach >= 3.0, < 3.1",
+    "bleach >= 3.0, < 3.2",
     "Click >= 7.0, < 8",
+    "ipaddr >= 2.1.10, < 2.3",
 ]
 
-if sys.version_info < (2, 7):
-    requirements.append("importlib == 1.0.1")
-    requirements.append("argparse")
-
 if not is_windows:
     requirements.append("bcrypt >= 3.1.0, < 3.2")
 
@@ -82,7 +85,6 @@
     'License :: OSI Approved :: GNU General Public License (GPL)',
     'Operating System :: OS Independent',
     'Programming Language :: Python',
-    'Programming Language :: Python :: 2.6',
     'Programming Language :: Python :: 2.7',
     'Topic :: Software Development :: Version Control',
 ]
@@ -113,10 +115,7 @@
     )
     long_description = description
 
-import setuptools
 
-# monkey patch setuptools to use distutils owner/group functionality
-from setuptools.command import sdist
 sdist_org = sdist.sdist
 class sdist_new(sdist_org):
     def initialize_options(self):
--- a/tox.ini	Sat Aug 24 21:48:43 2019 +0200
+++ b/tox.ini	Sun Jan 05 04:07:51 2020 +0100
@@ -1,13 +1,12 @@
 [tox]
 minversion = 1.8
-envlist = py{26,27}-pytest
+envlist = py27-pytest
 
 [testenv]
 setenv =
     PYTHONHASHSEED = 0
 deps =
     -r{toxinidir}/dev_requirements.txt
-    py26-pytest: unittest2
     python-ldap
     python-pam
 commands =