Repository: WeblateOrg/weblate

Issue:
Exception: FOR NO KEY UPDATE cannot be applied to the nullable side of an outer join
### Describe the issue

Internal server error is triggered when trying to bulk-edit some translations.

### I already tried

- [X] I've read and searched [the documentation](https://docs.weblate.org/).
- [X] I've searched for similar issues in this repository.

### Steps to reproduce the behavior

(from https://codeberg.org/Codeberg/Community/issues/954#issuecomment-828074)

Here is what I tried:
After an automatic translation I tried bulk-editing the auto-translated strings (setting status to "translated" and removing the label).
For this I tried several values in the search box, eg (afair),

    has:label
    has:automatically-translated
    has:Automatically-translated
    has:"Automatically translated"
    has:label "Automatically translated"

(Reason for this: the help does not give an example in how to select by a specific label. Anyhow even "has:label" failed")

### Expected behavior

No internal server error.

### Screenshots

_No response_

### Exception traceback

```pytb
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)

The above exception (FOR NO KEY UPDATE cannot be applied to the nullable side of an outer join
) was the direct cause of the following exception:
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 56, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.11/site-packages/django/contrib/auth/decorators.py", line 23, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/usr/local/lib/python3.11/site-packages/django/views/decorators/http.py", line 43, in inner
    return func(request, *args, **kwargs)
  File "/usr/local/lib/python3.11/site-packages/django/views/decorators/cache.py", line 62, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "/usr/local/lib/python3.11/site-packages/weblate/trans/views/search.py", line 245, in bulk_edit
    updated = bulk_perform(
  File "/usr/local/lib/python3.11/site-packages/weblate/trans/bulk.py", line 56, in bulk_perform
    for unit in component_units.select_for_update():
  File "/usr/local/lib/python3.11/site-packages/django/db/models/query.py", line 394, in __iter__
    self._fetch_all()
  File "/usr/local/lib/python3.11/site-packages/django/db/models/query.py", line 1867, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/usr/local/lib/python3.11/site-packages/django/db/models/query.py", line 87, in __iter__
    results = compiler.execute_sql(
  File "/usr/local/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1398, in execute_sql
    cursor.execute(sql, params)
  File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(
  File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 84, in _execute
    with self.db.wrap_database_errors:
  File "/usr/local/lib/python3.11/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)

Exception Type: NotSupportedError at /bulk-edit/pdftools/pdfjoin/fr/
Exception Value: FOR NO KEY UPDATE cannot be applied to the nullable side of an outer join

Raised during: weblate.trans.views.search.bulk_edit
```


### How do you run Weblate?

Docker container

### Weblate versions

```
WEBLATE_VERSION:Cython = '0.29.33'
WEBLATE_VERSION:Django = '4.1.7'
WEBLATE_VERSION:Git = '2.30.8'
WEBLATE_VERSION:GitPython = '3.1.31'
WEBLATE_VERSION:Mercurial = '6.3.3'
WEBLATE_VERSION:Pillow = '9.4.0'
WEBLATE_VERSION:PostgreSQL server = '15.2'
WEBLATE_VERSION:Python = '3.11.2'
WEBLATE_VERSION:Redis server = '7.0.9'
WEBLATE_VERSION:Weblate = '4.16.2'
WEBLATE_VERSION:aeidon = '1.12'
WEBLATE_VERSION:borgbackup = '1.2.3'
WEBLATE_VERSION:boto3 = '1.26.86'
WEBLATE_VERSION:celery = '5.2.7'
WEBLATE_VERSION:charset-normalizer = '3.1.0'
WEBLATE_VERSION:diff-match-patch = '20200713'
WEBLATE_VERSION:django-appconf = '1.0.5'
WEBLATE_VERSION:django-celery-beat = '2.4.0'
WEBLATE_VERSION:django-compressor = '4.3.1'
WEBLATE_VERSION:django-crispy-forms = '2.0'
WEBLATE_VERSION:django-filter = '22.1'
WEBLATE_VERSION:django-redis = '5.2.0'
WEBLATE_VERSION:djangorestframework = '3.14.0'
WEBLATE_VERSION:filelock = '3.9.0'
WEBLATE_VERSION:git-review = '2.3.1'
WEBLATE_VERSION:git-svn = '2.30.8'
WEBLATE_VERSION:hiredis = '2.2.2'
WEBLATE_VERSION:html2text = '2020.1.16'
WEBLATE_VERSION:iniparse = '0.5'
WEBLATE_VERSION:kombu = '5.2.4'
WEBLATE_VERSION:lxml = '4.9.2'
WEBLATE_VERSION:misaka = '2.1.1'
WEBLATE_VERSION:mysqlclient = '2.1.1'
WEBLATE_VERSION:nh3 = '0.2.8'
WEBLATE_VERSION:oauthlib = '3.2.2'
WEBLATE_VERSION:openpyxl = '3.1.1'
WEBLATE_VERSION:phply = '1.2.6'
WEBLATE_VERSION:psycopg2 = '2.9.5'
WEBLATE_VERSION:psycopg2-binary = '2.9.5'
WEBLATE_VERSION:pyahocorasick = '2.0.0'
WEBLATE_VERSION:pycairo = '1.23.0'
WEBLATE_VERSION:pygobject = '3.42.2'
WEBLATE_VERSION:pyparsing = '3.0.9'
WEBLATE_VERSION:python-dateutil = '2.8.2'
WEBLATE_VERSION:python-redis-lock = '4.0.0'
WEBLATE_VERSION:rapidfuzz = '********************'
WEBLATE_VERSION:requests = '2.28.2'
WEBLATE_VERSION:ruamel.yaml = '0.17.21'
WEBLATE_VERSION:sentry_sdk = '1.16.0'
WEBLATE_VERSION:siphashc = '2.1'
WEBLATE_VERSION:social-auth-app-django = '5.0.0'
WEBLATE_VERSION:social-auth-core = '4.3.0'
WEBLATE_VERSION:tesserocr = '2.5.2'
WEBLATE_VERSION:translate-toolkit = '3.8.6'
WEBLATE_VERSION:translation-finder = '2.15'
WEBLATE_VERSION:user-agents = '2.2.0'
WEBLATE_VERSION:weblate-language-data = '2023.3'
WEBLATE_VERSION:zeep = '4.2.1'
```

### Weblate deploy checks

```shell
SystemCheckError: System check identified some issues:

CRITICALS:
?: (weblate.E018) Failed to download avatar: 404 Client Error: Not Found for url: https://codeberg.org/user/avatar/noreply@weblate.org/32
	HINT: https://docs.weblate.org/en/weblate-4.16.2/admin/optionals.html#avatars

INFOS:
?: (weblate.I021) Error collection is not set up, it is highly recommended for production use
	HINT: https://docs.weblate.org/en/weblate-4.16.2/admin/install.html#collecting-errors
?: (weblate.I028) Backups are not configured, it is highly recommended for production use
	HINT: https://docs.weblate.org/en/weblate-4.16.2/admin/backup.html

System check identified 3 issues (1 silenced).
```


### Additional context

<details> 
  <summary>Full Error e-mail</summary>
<pre>Internal Server Error: /bulk-edit/pdftools/pdfjoin/fr/

NotSupportedError at /bulk-edit/pdftools/pdfjoin/fr/
FOR NO KEY UPDATE cannot be applied to the nullable side of an outer join


Request Method: POST
Request URL: https://translate.codeberg.org/bulk-edit/pdftools/pdfjoin/fr/
Django Version: 4.1.7
Python Executable: /usr/local/bin/python
Python Version: 3.11.2
Python Path: ['/', '/usr/local/lib/python3.11/site-packages/git/ext/gitdb', '/', '/usr/local/bin', '/usr/local/lib/python311.zip', '/usr/local/lib/python3.11', '/usr/local/lib/python3.11/lib-dynload', '/usr/local/lib/python3.11/site-packages', '/app/data/python']
Server time: Wed, 08 Mar 2023 14:04:23 +0000
Installed Applications:
['customize',
 'weblate.addons',
 'weblate.auth',
 'weblate.checks',
 'weblate.formats',
 'weblate.glossary',
 'weblate.machinery',
 'weblate.trans',
 'weblate.lang',
 'weblate_language_data',
 'weblate.memory',
 'weblate.screenshots',
 'weblate.fonts',
 'weblate.accounts',
 'weblate.configuration',
 'weblate.utils',
 'weblate.vcs',
 'weblate.wladmin',
 'weblate.metrics',
 'weblate',
 'weblate.gitexport',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.admin.apps.SimpleAdminConfig',
 'django.contrib.admindocs',
 'django.contrib.sitemaps',
 'django.contrib.humanize',
 'social_django',
 'crispy_forms',
 'crispy_bootstrap3',
 'compressor',
 'rest_framework',
 'rest_framework.authtoken',
 'django_filters',
 'django_celery_beat',
 'corsheaders']
Installed Middleware:
['weblate.middleware.RedirectMiddleware',
 'weblate.middleware.ProxyMiddleware',
 'corsheaders.middleware.CorsMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'weblate.accounts.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'social_django.middleware.SocialAuthExceptionMiddleware',
 'weblate.accounts.middleware.RequireLoginMiddleware',
 'weblate.api.middleware.ThrottlingMiddleware',
 'weblate.middleware.SecurityMiddleware']


Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)

The above exception (FOR NO KEY UPDATE cannot be applied to the nullable side of an outer join
) was the direct cause of the following exception:
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 56, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.11/site-packages/django/contrib/auth/decorators.py", line 23, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/usr/local/lib/python3.11/site-packages/django/views/decorators/http.py", line 43, in inner
    return func(request, *args, **kwargs)
  File "/usr/local/lib/python3.11/site-packages/django/views/decorators/cache.py", line 62, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "/usr/local/lib/python3.11/site-packages/weblate/trans/views/search.py", line 245, in bulk_edit
    updated = bulk_perform(
  File "/usr/local/lib/python3.11/site-packages/weblate/trans/bulk.py", line 56, in bulk_perform
    for unit in component_units.select_for_update():
  File "/usr/local/lib/python3.11/site-packages/django/db/models/query.py", line 394, in __iter__
    self._fetch_all()
  File "/usr/local/lib/python3.11/site-packages/django/db/models/query.py", line 1867, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/usr/local/lib/python3.11/site-packages/django/db/models/query.py", line 87, in __iter__
    results = compiler.execute_sql(
  File "/usr/local/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1398, in execute_sql
    cursor.execute(sql, params)
  File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(
  File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 84, in _execute
    with self.db.wrap_database_errors:
  File "/usr/local/lib/python3.11/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)

Exception Type: NotSupportedError at /bulk-edit/pdftools/pdfjoin/fr/
Exception Value: FOR NO KEY UPDATE cannot be applied to the nullable side of an outer join

Raised during: weblate.trans.views.search.bulk_edit
Request information:
USER: Weblate Admin

GET: No GET data

POST:
csrfmiddlewaretoken = 'XXXXXX'
q = 'has:label'
state = '20'
add_flags = ''
remove_flags = ''
remove_labels = '7'

FILES: No FILES data

COOKIES:
sessionid = 'XXXXX'
django_language = 'en'

META:
CONTENT_LENGTH = '827'
CONTENT_TYPE = 'multipart/form-data; boundary=---------------------------83925850915342725642201754421'
CSRF_COOKIE = 'XXXXXXX'
CSRF_COOKIE_NEEDS_UPDATE = True
HTTP_ACCEPT = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8'
HTTP_ACCEPT_ENCODING = 'gzip, deflate, br'
HTTP_ACCEPT_LANGUAGE = 'en-US,en;q=0.5'
HTTP_CONNECTION = 'close'
HTTP_COOKIE = 'sessionid=XXXXXX; django_language=en'
HTTP_DNT = '1'
HTTP_HOST = 'translate.codeberg.org'
HTTP_ORIGIN = 'https://translate.codeberg.org/'
HTTP_REFERER = 'https://translate.codeberg.org/'
HTTP_SEC_FETCH_DEST = 'document'
HTTP_SEC_FETCH_MODE = 'navigate'
HTTP_SEC_FETCH_SITE = 'same-origin'
HTTP_SEC_FETCH_USER = '?1'
HTTP_UPGRADE_INSECURE_REQUESTS = '1'
HTTP_USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0'
HTTP_X_FORWARDED_FOR = 'XXXXXX'
HTTP_X_FORWARDED_PROTO = 'https'
PATH_INFO = '/bulk-edit/pdftools/pdfjoin/fr/'
QUERY_STRING = ''
RAW_URI = '/bulk-edit/pdftools/pdfjoin/fr/'
REMOTE_ADDR = ''
REQUEST_METHOD = 'POST'
SCRIPT_NAME = ''
SERVER_NAME = 'translate.codeberg.org'
SERVER_PORT = '443'
SERVER_PROTOCOL = 'HTTP/1.0'
SERVER_SOFTWARE = 'gunicorn/20.1.0'
WEBLATE_LANGUAGE = ''
WEBLATE_USER = "'admin'"
WEBLATE_VERSION:Cython = '0.29.33'
WEBLATE_VERSION:Django = '4.1.7'
WEBLATE_VERSION:Git = '2.30.8'
WEBLATE_VERSION:GitPython = '3.1.31'
WEBLATE_VERSION:Mercurial = '6.3.3'
WEBLATE_VERSION:Pillow = '9.4.0'
WEBLATE_VERSION:PostgreSQL server = '15.2'
WEBLATE_VERSION:Python = '3.11.2'
WEBLATE_VERSION:Redis server = '7.0.9'
WEBLATE_VERSION:Weblate = '4.16.2'
WEBLATE_VERSION:aeidon = '1.12'
WEBLATE_VERSION:borgbackup = '1.2.3'
WEBLATE_VERSION:boto3 = '1.26.86'
WEBLATE_VERSION:celery = '5.2.7'
WEBLATE_VERSION:charset-normalizer = '3.1.0'
WEBLATE_VERSION:diff-match-patch = '20200713'
WEBLATE_VERSION:django-appconf = '1.0.5'
WEBLATE_VERSION:django-celery-beat = '2.4.0'
WEBLATE_VERSION:django-compressor = '4.3.1'
WEBLATE_VERSION:django-crispy-forms = '2.0'
WEBLATE_VERSION:django-filter = '22.1'
WEBLATE_VERSION:django-redis = '5.2.0'
WEBLATE_VERSION:djangorestframework = '3.14.0'
WEBLATE_VERSION:filelock = '3.9.0'
WEBLATE_VERSION:git-review = '2.3.1'
WEBLATE_VERSION:git-svn = '2.30.8'
WEBLATE_VERSION:hiredis = '2.2.2'
WEBLATE_VERSION:html2text = '2020.1.16'
WEBLATE_VERSION:iniparse = '0.5'
WEBLATE_VERSION:kombu = '5.2.4'
WEBLATE_VERSION:lxml = '4.9.2'
WEBLATE_VERSION:misaka = '2.1.1'
WEBLATE_VERSION:mysqlclient = '2.1.1'
WEBLATE_VERSION:nh3 = '0.2.8'
WEBLATE_VERSION:oauthlib = '3.2.2'
WEBLATE_VERSION:openpyxl = '3.1.1'
WEBLATE_VERSION:phply = '1.2.6'
WEBLATE_VERSION:psycopg2 = '2.9.5'
WEBLATE_VERSION:psycopg2-binary = '2.9.5'
WEBLATE_VERSION:pyahocorasick = '2.0.0'
WEBLATE_VERSION:pycairo = '1.23.0'
WEBLATE_VERSION:pygobject = '3.42.2'
WEBLATE_VERSION:pyparsing = '3.0.9'
WEBLATE_VERSION:python-dateutil = '2.8.2'
WEBLATE_VERSION:python-redis-lock = '4.0.0'
WEBLATE_VERSION:rapidfuzz = '********************'
WEBLATE_VERSION:requests = '2.28.2'
WEBLATE_VERSION:ruamel.yaml = '0.17.21'
WEBLATE_VERSION:sentry_sdk = '1.16.0'
WEBLATE_VERSION:siphashc = '2.1'
WEBLATE_VERSION:social-auth-app-django = '5.0.0'
WEBLATE_VERSION:social-auth-core = '4.3.0'
WEBLATE_VERSION:tesserocr = '2.5.2'
WEBLATE_VERSION:translate-toolkit = '3.8.6'
WEBLATE_VERSION:translation-finder = '2.15'
WEBLATE_VERSION:user-agents = '2.2.0'
WEBLATE_VERSION:weblate-language-data = '2023.3'
WEBLATE_VERSION:zeep = '4.2.1'
gunicorn.socket = <socket.socket fd=9, family=1, type=1, proto=0, laddr=/run/gunicorn/app/weblate/socket>
wsgi.errors = <gunicorn.http.wsgi.WSGIErrorsWrapper object at 0x7f4bb5875fc0>
wsgi.file_wrapper = <class 'gunicorn.http.wsgi.FileWrapper'>
wsgi.input = <gunicorn.http.body.Body object at 0x7f4bb5714290>
wsgi.input_terminated = True
wsgi.multiprocess = True
wsgi.multithread = False
wsgi.run_once = False
wsgi.url_scheme = 'https'
wsgi.version = '(1, 0)'

Settings:
Using settings module weblate.settings_docker
ABSOLUTE_URL_OVERRIDES = {}
ADDITIONAL_CONFIG = '/app/data/settings-override.py'
ADMINS = "(('Weblate Admin', 'XXXXX'),)"
ADMINS_BILLING = []
ADMINS_CONTACT = []
ADMINS_HOSTING = []
AKISMET_API_KEY = '********************'
ALLOWED_HOSTS = ['*']
ANONYMOUS_USER_NAME = 'anonymous'
APPEND_SLASH = True
AUDITLOG_EXPIRY = 180
AUTHENTICATION_BACKENDS = "('social_core.backends.gitea.GiteaOAuth2', 'weblate.accounts.auth.WeblateUserBackend')"
AUTH_LOCK_ATTEMPTS = 10
AUTH_PASSWORD_DAYS = '********************'
AUTH_PASSWORD_VALIDATORS = '********************'
AUTH_RESTRICT_ADMINS = {}
AUTH_TOKEN_VALID = '********************'
AUTH_USER_MODEL = 'weblate_auth.User'
AUTOFIX_LIST = ['weblate.trans.autofixes.whitespace.SameBookendingWhitespace', 'weblate.trans.autofixes.chars.ReplaceTrailingDotsWithEllipsis', 'weblate.trans.autofixes.chars.RemoveZeroSpace', 'weblate.trans.autofixes.chars.RemoveControlChars']
AUTO_UPDATE = False
AVATAR_DEFAULT_IMAGE = 'identicon'
AVATAR_URL_PREFIX = 'https://codeberg.org/user/'
BACKGROUND_ADMIN_CHECKS = True
BACKGROUND_TASKS = 'monthly'
BASIC_LANGUAGES = None
BITBUCKETSERVER_CREDENTIALS = {None: {'username': None, 'token': '********************'}}
BORG_EXTRA_ARGS = []
CACHES = {'default': {'BACKEND': 'django_redis.cache.RedisCache', 'LOCATION': 'redis://cache:6379/1', 'OPTIONS': {'CLIENT_CLASS': 'django_redis.client.DefaultClient', 'PARSER_CLASS': 'redis.connection.HiredisParser', 'PASSWORD': '********************', 'CONNECTION_POOL_KWARGS': {}}, 'KEY_PREFIX': '********************', 'TIMEOUT': 3600}, 'avatar': {'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': '/app/cache/avatar', 'TIMEOUT': 86400, 'OPTIONS': {'MAX_ENTRIES': 1000}}}
CACHE_DIR = '/app/cache'
CACHE_MIDDLEWARE_ALIAS = 'default'
CACHE_MIDDLEWARE_KEY_PREFIX = '********************'
CACHE_MIDDLEWARE_SECONDS = 600
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'
CELERY_BROKER_URL = 'redis://cache:6379/1'
CELERY_RESULT_BACKEND = 'redis://cache:6379/1'
CELERY_TASK_ALWAYS_EAGER = False
CELERY_TASK_ROUTES = {'weblate.trans.tasks.auto_translate*': {'queue': 'translate'}, 'weblate.accounts.tasks.notify_*': {'queue': 'notify'}, 'weblate.accounts.tasks.send_mails': {'queue': 'notify'}, 'weblate.utils.tasks.settings_backup': {'queue': 'backup'}, 'weblate.utils.tasks.database_backup': {'queue': 'backup'}, 'weblate.wladmin.tasks.backup': {'queue': 'backup'}, 'weblate.wladmin.tasks.backup_service': {'queue': 'backup'}, 'weblate.memory.tasks.*': {'queue': 'memory'}}
CELERY_WORKER_MAX_MEMORY_PER_CHILD = 200000
CHECK_LIST = ['weblate.checks.same.SameCheck', 'weblate.checks.chars.BeginNewlineCheck', 'weblate.checks.chars.EndNewlineCheck', 'weblate.checks.chars.BeginSpaceCheck', 'weblate.checks.chars.EndSpaceCheck', 'weblate.checks.chars.DoubleSpaceCheck', 'weblate.checks.chars.EndStopCheck', 'weblate.checks.chars.EndColonCheck', 'weblate.checks.chars.EndQuestionCheck', 'weblate.checks.chars.EndExclamationCheck', 'weblate.checks.chars.EndEllipsisCheck', 'weblate.checks.chars.EndSemicolonCheck', 'weblate.checks.chars.MaxLengthCheck', 'weblate.checks.chars.KashidaCheck', 'weblate.checks.chars.PunctuationSpacingCheck', 'weblate.checks.format.PythonFormatCheck', 'weblate.checks.format.PythonBraceFormatCheck', 'weblate.checks.format.PHPFormatCheck', 'weblate.checks.format.CFormatCheck', 'weblate.checks.format.PerlFormatCheck', 'weblate.checks.format.JavaScriptFormatCheck', 'weblate.checks.format.LuaFormatCheck', 'weblate.checks.format.ObjectPascalFormatCheck', 'weblate.checks.format.SchemeFormatCheck', 'weblate.checks.format.CSharpFormatCheck', 'weblate.checks.format.JavaFormatCheck', 'weblate.checks.format.JavaMessageFormatCheck', 'weblate.checks.format.PercentPlaceholdersCheck', 'weblate.checks.format.VueFormattingCheck', 'weblate.checks.format.I18NextInterpolationCheck', 'weblate.checks.format.ESTemplateLiteralsCheck', 'weblate.checks.angularjs.AngularJSInterpolationCheck', 'weblate.checks.icu.ICUMessageFormatCheck', 'weblate.checks.icu.ICUSourceCheck', 'weblate.checks.qt.QtFormatCheck', 'weblate.checks.qt.QtPluralCheck', 'weblate.checks.ruby.RubyFormatCheck', 'weblate.checks.consistency.PluralsCheck', 'weblate.checks.consistency.SamePluralsCheck', 'weblate.checks.consistency.ConsistencyCheck', 'weblate.checks.consistency.TranslatedCheck', 'weblate.checks.chars.EscapedNewlineCountingCheck', 'weblate.checks.chars.NewLineCountCheck', 'weblate.checks.markup.BBCodeCheck', 'weblate.checks.chars.ZeroWidthSpaceCheck', 'weblate.checks.render.MaxSizeCheck', 'weblate.checks.markup.XMLValidityCheck', 'weblate.checks.markup.XMLTagsCheck', 'weblate.checks.markup.MarkdownRefLinkCheck', 'weblate.checks.markup.MarkdownLinkCheck', 'weblate.checks.markup.MarkdownSyntaxCheck', 'weblate.checks.markup.URLCheck', 'weblate.checks.markup.SafeHTMLCheck', 'weblate.checks.placeholders.PlaceholderCheck', 'weblate.checks.placeholders.RegexCheck', 'weblate.checks.duplicate.DuplicateCheck', 'weblate.checks.source.OptionalPluralCheck', 'weblate.checks.source.EllipsisCheck', 'weblate.checks.source.MultipleFailingCheck', 'weblate.checks.source.LongUntranslatedCheck', 'weblate.checks.format.MultipleUnnamedFormatsCheck', 'weblate.checks.glossary.GlossaryCheck']
COMMENT_CLEANUP_DAYS = None
COMMIT_PENDING_HOURS = 24
COMPRESSORS = {'css': 'compressor.css.CssCompressor', 'js': 'compressor.js.JsCompressor'}
COMPRESS_CACHEABLE_PRECOMPILERS = '()'
COMPRESS_CACHE_BACKEND = 'default'
COMPRESS_CACHE_KEY_FUNCTION = '********************'
COMPRESS_CLEAN_CSS_ARGUMENTS = ''
COMPRESS_CLEAN_CSS_BINARY = 'cleancss'
COMPRESS_CLOSURE_COMPILER_ARGUMENTS = ''
COMPRESS_CLOSURE_COMPILER_BINARY = 'java -jar compiler.jar'
COMPRESS_CSS_HASHING_METHOD = 'mtime'
COMPRESS_DATA_URI_MAX_SIZE = 1024
COMPRESS_DEBUG_TOGGLE = None
COMPRESS_ENABLED = True
COMPRESS_FILTERS = {'css': ['compressor.filters.css_default.CssAbsoluteFilter', 'compressor.filters.cssmin.rCSSMinFilter'], 'js': ['compressor.filters.jsmin.rJSMinFilter']}
COMPRESS_JINJA2_GET_ENVIRONMENT = <function CompressorConf.JINJA2_GET_ENVIRONMENT at 0x7f4bb7f9d440>
COMPRESS_MINT_DELAY = 30
COMPRESS_MTIME_DELAY = 10
COMPRESS_OFFLINE = True
COMPRESS_OFFLINE_CONTEXT = [{'fonts_cdn_url': None, 'STATIC_URL': '/static/', 'LANGUAGE_BIDI': True}, {'fonts_cdn_url': None, 'STATIC_URL': '/static/', 'LANGUAGE_BIDI': False}]
COMPRESS_OFFLINE_MANIFEST = 'manifest.json'
COMPRESS_OFFLINE_MANIFEST_STORAGE = 'compressor.storage.OfflineManifestFileStorage'
COMPRESS_OFFLINE_TIMEOUT = 31536000
COMPRESS_OUTPUT_DIR = 'CACHE'
COMPRESS_PARSER = 'compressor.parser.AutoSelectParser'
COMPRESS_PRECOMPILERS = '()'
COMPRESS_REBUILD_TIMEOUT = 2592000
COMPRESS_ROOT = '/app/cache/static'
COMPRESS_STORAGE = 'compressor.storage.CompressorFileStorage'
COMPRESS_TEMPLATE_FILTER_CONTEXT = {'STATIC_URL': '/static/'}
COMPRESS_URL = '/static/'
COMPRESS_URL_PLACEHOLDER = '/__compressor_url_placeholder__/'
COMPRESS_VERBOSE = False
COMPRESS_YUGLIFY_BINARY = 'yuglify'
COMPRESS_YUGLIFY_CSS_ARGUMENTS = '--terminal'
COMPRESS_YUGLIFY_JS_ARGUMENTS = '--terminal'
COMPRESS_YUI_BINARY = 'java -jar yuicompressor.jar'
COMPRESS_YUI_CSS_ARGUMENTS = ''
COMPRESS_YUI_JS_ARGUMENTS = ''
CONTACT_FORM = 'reply-to'
CORS_ALLOWED_ORIGINS = []
CORS_URLS_REGEX = '^/api/.*$'
CRISPY_ALLOWED_TEMPLATE_PACKS = 'bootstrap3'
CRISPY_TEMPLATE_PACK = 'bootstrap3'
CSP_CONNECT_SRC = []
CSP_FONT_SRC = []
CSP_IMG_SRC = []
CSP_SCRIPT_SRC = []
CSP_STYLE_SRC = []
CSRF_COOKIE_AGE = 31449600
CSRF_COOKIE_DOMAIN = None
CSRF_COOKIE_HTTPONLY = True
CSRF_COOKIE_MASKED = False
CSRF_COOKIE_NAME = 'csrftoken'
CSRF_COOKIE_PATH = '/'
CSRF_COOKIE_SAMESITE = 'Lax'
CSRF_COOKIE_SECURE = True
CSRF_FAILURE_VIEW = 'weblate.trans.views.error.csrf_failure'
CSRF_HEADER_NAME = 'HTTP_X_CSRFTOKEN'
CSRF_TRUSTED_ORIGINS = []
CSRF_USE_SESSIONS = True
DATABASES = {'default': {'ENGINE': 'django.db.backends.postgresql', 'NAME': 'weblate', 'USER': 'weblate', 'ALTER_ROLE': 'weblate', 'PASSWORD': '********************', 'HOST': 'database', 'PORT': '', 'OPTIONS': {'sslmode': 'prefer'}, 'CONN_MAX_AGE': 0, 'DISABLE_SERVER_SIDE_CURSORS': False, 'ATOMIC_REQUESTS': False, 'AUTOCOMMIT': True, 'CONN_HEALTH_CHECKS': False, 'TIME_ZONE': None, 'TEST': {'CHARSET': None, 'COLLATION': None, 'MIGRATE': True, 'MIRROR': None, 'NAME': None}}}
DATABASE_BACKUP = 'plain'
DATABASE_ROUTERS = []
DATA_DIR = '/app/data'
DATA_UPLOAD_MAX_MEMORY_SIZE = 50000000
DATA_UPLOAD_MAX_NUMBER_FIELDS = 1000
DATA_UPLOAD_MAX_NUMBER_FILES = 100
DATETIME_FORMAT = 'N j, Y, P'
DATETIME_INPUT_FORMATS = ['%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M:%S.%f', '%Y-%m-%d %H:%M', '%m/%d/%Y %H:%M:%S', '%m/%d/%Y %H:%M:%S.%f', '%m/%d/%Y %H:%M', '%m/%d/%y %H:%M:%S', '%m/%d/%y %H:%M:%S.%f', '%m/%d/%y %H:%M']
DATE_FORMAT = 'N j, Y'
DATE_INPUT_FORMATS = ['%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', '%b %d %Y', '%b %d, %Y', '%d %b %Y', '%d %b, %Y', '%B %d %Y', '%B %d, %Y', '%d %B %Y', '%d %B, %Y']
DEBUG = False
DEBUG_PROPAGATE_EXCEPTIONS = False
DECIMAL_SEPARATOR = '.'
DEFAULT_ACCESS_CONTROL = 0
DEFAULT_ADDONS = {}
DEFAULT_ADDON_MESSAGE = 'Update translation files\n\nUpdated by "{{ addon_name }}" hook in Weblate.\n\nTranslation: {{ project_name }}/{{ component_name }}\nTranslate-URL: {{ url }}'
DEFAULT_ADD_MESSAGE = 'Added translation using Weblate ({{ language_name }})\n\n'
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
DEFAULT_AUTO_LOCK_ERROR = True
DEFAULT_AUTO_WATCH = True
DEFAULT_CHARSET = 'utf-8'
DEFAULT_COMMITER_EMAIL = '[translate@codeberg.org](mailto:translate@codeberg.org)'
DEFAULT_COMMITER_NAME = 'Codeberg Translate'
DEFAULT_COMMIT_MESSAGE = 'Translated using Weblate ({{ language_name }})\n\nCurrently translated at {{ stats.translated_percent }}% ({{ stats.translated }} of {{ stats.all }} strings)\n\nTranslation: {{ project_name }}/{{ component_name }}\nTranslate-URL: {{ url }}'
DEFAULT_DELETE_MESSAGE = 'Deleted translation using Weblate ({{ language_name }})\n\n'
DEFAULT_EXCEPTION_REPORTER = 'django.views.debug.ExceptionReporter'
DEFAULT_EXCEPTION_REPORTER_FILTER = 'weblate.trans.debug.WeblateExceptionReporterFilter'
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
DEFAULT_FROM_EMAIL = '[weblate@codeberg.org](mailto:weblate@codeberg.org)'
DEFAULT_INDEX_TABLESPACE = ''
DEFAULT_LANGUAGE = 'en'
DEFAULT_LOG = 'console'
DEFAULT_LOGLEVEL = 'INFO'
DEFAULT_MERGE_MESSAGE = "Merge branch '{{ component_remote_branch }}' into Weblate.\n\n"
DEFAULT_MERGE_STYLE = 'rebase'
DEFAULT_PAGE_LIMIT = 100
DEFAULT_PULL_MESSAGE = 'Translations update from {{ site_title }}\n\nTranslations update from [{{ site_title }}]({{ site_url }}) for [{{ project_name }}/{{ component_name }}]({{url}}).\n\n{% if component_linked_childs %}\nIt also includes following components:\n{% for linked in component_linked_childs %}\n* [{{ linked.project_name }}/{{ linked.name }}]({{ linked.url }})\n{% endfor %}\n{% endif %}\n\nCurrent translation status:\n\n![Weblate translation status]({{widget_url}})\n'
DEFAULT_PUSH_ON_COMMIT = True
DEFAULT_RESTRICTED_COMPONENT = False
DEFAULT_SHARED_TM = True
DEFAULT_TABLESPACE = ''
DEFAULT_TRANSLATION_PROPAGATION = True
DEFAULT_VCS = 'git'
DISALLOWED_USER_AGENTS = []
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.codeberg.org'
EMAIL_HOST_PASSWORD = '********************'
EMAIL_HOST_USER = 'translate'
EMAIL_PORT = 25
EMAIL_SEND_HTML = True
EMAIL_SSL_CERTFILE = None
EMAIL_SSL_KEYFILE = '********************'
EMAIL_SUBJECT_PREFIX = '[Weblate] '
EMAIL_TIMEOUT = None
EMAIL_USE_LOCALTIME = False
EMAIL_USE_SSL = False
EMAIL_USE_TLS = True
ENABLE_AVATARS = True
ENABLE_HOOKS = True
ENABLE_HTTPS = True
ENABLE_SHARING = True
EXTRA_HTML_HEAD = ''
FILE_UPLOAD_DIRECTORY_PERMISSIONS = None
FILE_UPLOAD_HANDLERS = ['django.core.files.uploadhandler.MemoryFileUploadHandler', 'django.core.files.uploadhandler.TemporaryFileUploadHandler']
FILE_UPLOAD_MAX_MEMORY_SIZE = 2621440
FILE_UPLOAD_PERMISSIONS = 420
FILE_UPLOAD_TEMP_DIR = None
FIRST_DAY_OF_WEEK = 0
FIXTURE_DIRS = []
FONTS_CDN_URL = None
FORCE_SCRIPT_NAME = None
FORMAT_MODULE_PATH = None
FORM_RENDERER = 'django.forms.renderers.DjangoTemplates'
GET_HELP_URL = 'https://docs.codeberg.org/'
GITEA_CREDENTIALS = {'codeberg.org': {'username': 'translate', 'token': '********************'}}
GITHUB_CREDENTIALS = {None: {'username': None, 'token': '********************'}}
GITLAB_CREDENTIALS = {None: {'username': None, 'token': '********************'}}
GOOGLE_ANALYTICS_ID = None
HAVE_SYSLOG = False
HIDE_REPO_CREDENTIALS = True
HIDE_VERSION = False
IGNORABLE_404_URLS = []
INSTALLED_APPS = ['customize', 'weblate.addons', 'weblate.auth', 'weblate.checks', 'weblate.formats', 'weblate.glossary', 'weblate.machinery', 'weblate.trans', 'weblate.lang', 'weblate_language_data', 'weblate.memory', 'weblate.screenshots', 'weblate.fonts', 'weblate.accounts', 'weblate.configuration', 'weblate.utils', 'weblate.vcs', 'weblate.wladmin', 'weblate.metrics', 'weblate', 'weblate.gitexport', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.admin.apps.SimpleAdminConfig', 'django.contrib.admindocs', 'django.contrib.sitemaps', 'django.contrib.humanize', 'social_django', 'crispy_forms', 'crispy_bootstrap3', 'compressor', 'rest_framework', 'rest_framework.authtoken', 'django_filters', 'django_celery_beat', 'corsheaders']
INTERLEDGER_PAYMENT_POINTERS = ['$ilp.uphold.com/ENU7fREdeZi9']
INTERNAL_IPS = []
INVOICE_PATH = ''
IP_BEHIND_REVERSE_PROXY = False
IP_PROXY_HEADER = ''
IP_PROXY_OFFSET = 0
LANGUAGES = "(('ar', 'العربية'), ('az', 'Azərbaycan'), ('be', 'Беларуская'), ('be@latin', 'Biełaruskaja'), ('bg', 'Български'), ('br', 'Brezhoneg'), ('ca', 'Català'), ('cs', 'Čeština'), ('da', 'Dansk'), ('de', 'Deutsch'), ('en', 'English'), ('el', 'Ελληνικά'), ('en-gb', 'English (United Kingdom)'), ('es', 'Español'), ('fi', 'Suomi'), ('fr', 'Français'), ('gl', 'Galego'), ('he', 'עברית'), ('hu', 'Magyar'), ('hr', 'Hrvatski'), ('id', 'Indonesia'), ('is', 'Íslenska'), ('it', 'Italiano'), ('ja', '日本語'), ('kab', 'Taqbaylit'), ('kk', 'Қазақ тілі'), ('ko', '한국어'), ('nb', 'Norsk bokmål'), ('nl', 'Nederlands'), ('pl', 'Polski'), ('pt', 'Português'), ('pt-br', 'Português brasileiro'), ('ro', 'Română'), ('ru', 'Русский'), ('sk', 'Slovenčina'), ('sl', 'Slovenščina'), ('sq', 'Shqip'), ('sr', 'Српски'), ('sr-latn', 'Srpski'), ('sv', 'Svenska'), ('th', 'ไทย'), ('tr', 'Türkçe'), ('uk', 'Українська'), ('zh-hans', '简体中文'), ('zh-hant', '正體中文'))"
LANGUAGES_BIDI = ['he', 'ar', 'ar-dz', 'fa', 'ur']
LANGUAGE_CODE = 'en-us'
LANGUAGE_COOKIE_AGE = 12096000
LANGUAGE_COOKIE_DOMAIN = None
LANGUAGE_COOKIE_HTTPONLY = True
LANGUAGE_COOKIE_NAME = 'django_language'
LANGUAGE_COOKIE_PATH = '/'
LANGUAGE_COOKIE_SAMESITE = 'Lax'
LANGUAGE_COOKIE_SECURE = True
LEGAL_URL = 'https://codeberg.org/Codeberg/org/src/branch/main/Imprint.md'
LICENSE_EXTRA = []
LICENSE_FILTER = None
LICENSE_REQUIRED = False
LIMIT_TRANSLATION_LENGTH_BY_SOURCE_LENGTH = True
LOCALE_PATHS = []
LOCALIZE_CDN_PATH = None
LOCALIZE_CDN_URL = None
LOGGING = {'version': 1, 'disable_existing_loggers': True, 'filters': {'require_debug_false': {'()': 'django.utils.log.RequireDebugFalse'}}, 'formatters': {'syslog': {'format': 'weblate[%(process)d]: %(levelname)s %(message)s'}, 'simple': {'format': '[%(asctime)s: %(levelname)s/%(process)s] %(message)s'}, 'logfile': {'format': '%(asctime)s %(levelname)s %(message)s'}, 'django.server': {'()': 'django.utils.log.ServerFormatter', 'format': '[%(server_time)s] %(message)s'}}, 'handlers': {'mail_admins': {'level': 'ERROR', 'filters': ['require_debug_false'], 'class': 'django.utils.log.AdminEmailHandler', 'include_html': True}, 'console': {'level': 'DEBUG', 'class': 'logging.StreamHandler', 'formatter': 'simple'}, 'django.server': {'level': 'INFO', 'class': 'logging.StreamHandler', 'formatter': 'django.server'}}, 'loggers': {'django.request': {'handlers': ['mail_admins', 'console'], 'level': 'ERROR', 'propagate': True}, 'django.server': {'handlers': ['django.server'], 'level': 'INFO', 'propagate': False}, 'django.db.backends': {'handlers': ['console'], 'level': 'CRITICAL'}, 'weblate': {'handlers': ['console'], 'level': 'INFO'}, 'weblate.vcs': {'handlers': ['console'], 'level': 'INFO'}, 'social': {'handlers': ['console'], 'level': 'INFO'}, 'django_auth_ldap': {'handlers': ['console'], 'level': 'INFO'}, 'djangosaml2idp': {'handlers': ['console'], 'level': 'INFO'}}}
LOGGING_CONFIG = 'logging.config.dictConfig'
LOGIN_REDIRECT_URL = '/'
LOGIN_REQUIRED_URLS = []
LOGIN_REQUIRED_URLS_EXCEPTIONS = ['/accounts/(.*)$', '/admin/login/(.*)$', '/static/(.*)$', '/widgets/(.*)$', '/data/(.*)$', '/hooks/(.*)$', '/healthz/$', '/api/(.*)$', '/js/i18n/$', '/contact/$', '/legal/(.*)$', '/avatar/(.*)$']
LOGIN_URL = '/accounts/login/'
LOGOUT_REDIRECT_URL = None
LOGOUT_URL = '/accounts/logout/'
MANAGERS = "(('Weblate Admin', 'XXXXXX'),)"
MATOMO_SITE_ID = None
MATOMO_URL = None
MEDIA_ROOT = '/app/data/media'
MEDIA_URL = '/media/'
MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
MIDDLEWARE = ['weblate.middleware.RedirectMiddleware', 'weblate.middleware.ProxyMiddleware', 'corsheaders.middleware.CorsMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'weblate.accounts.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'social_django.middleware.SocialAuthExceptionMiddleware', 'weblate.accounts.middleware.RequireLoginMiddleware', 'weblate.api.middleware.ThrottlingMiddleware', 'weblate.middleware.SecurityMiddleware']
MIGRATION_MODULES = {}
MONTH_DAY_FORMAT = 'F j'
MT_APERTIUM_APY = None
MT_AWS_ACCESS_KEY_ID = '********************'
MT_AWS_REGION = None
MT_AWS_SECRET_ACCESS_KEY = '********************'
MT_DEEPL_API_URL = '********************'
MT_DEEPL_KEY = '********************'
MT_GOOGLE_CREDENTIALS = None
MT_GOOGLE_KEY = '********************'
MT_GOOGLE_LOCATION = 'global'
MT_GOOGLE_PROJECT = None
MT_LIBRETRANSLATE_API_URL = '********************'
MT_LIBRETRANSLATE_KEY = '********************'
MT_MICROSOFT_BASE_URL = 'api.cognitive.microsofttranslator.com'
MT_MICROSOFT_COGNITIVE_KEY = '********************'
MT_MICROSOFT_ENDPOINT_URL = 'api.cognitive.microsoft.com'
MT_MICROSOFT_REGION = None
MT_MODERNMT_KEY = '********************'
MT_MODERNMT_URL = 'https://api.modernmt.com/'
MT_MYMEMORY_EMAIL = 'XXXX'
MT_MYMEMORY_KEY = '********************'
MT_MYMEMORY_USER = None
MT_NETEASE_KEY = '********************'
MT_NETEASE_SECRET = '********************'
MT_SAP_BASE_URL = None
MT_SAP_PASSWORD = '********************'
MT_SAP_SANDBOX_APIKEY = '********************'
MT_SAP_USERNAME = None
MT_SAP_USE_MT = True
MT_SERVICES = "('weblate.machinery.weblatetm.WeblateTranslation', 'weblate.memory.machine.WeblateMemory')"
MT_TMSERVER = None
MT_YANDEX_KEY = '********************'
MT_YOUDAO_ID = None
MT_YOUDAO_SECRET = '********************'
NEARBY_MESSAGES = 15
NUMBER_GROUPING = 0
OFFER_HOSTING = False
PAGURE_CREDENTIALS = {None: {'username': None, 'token': '********************'}}
PASSWORD_HASHERS = '********************'
PASSWORD_RESET_TIMEOUT = '********************'
PREPEND_WWW = False
PRIVACY_URL = 'https://codeberg.org/codeberg/org/src/PrivacyPolicy.md'
PRIVATE_COMMIT_EMAIL_OPT_IN = True
PRIVATE_COMMIT_EMAIL_TEMPLATE = '{[username}@users.noreply](mailto:username}@users.noreply).{site_domain}'
PROJECT_BACKUP_KEEP_COUNT = 3
PROJECT_BACKUP_KEEP_DAYS = 30
PROJECT_NAME_RESTRICT_RE = None
PROJECT_WEB_RESTRICT_HOST = {'localhost'}
PROJECT_WEB_RESTRICT_NUMERIC = True
PROJECT_WEB_RESTRICT_RE = None
RATELIMIT_ATTEMPTS = 5
RATELIMIT_COMMENT_ATTEMPTS = 30
RATELIMIT_COMMENT_WINDOW = 60
RATELIMIT_GLOSSARY_ATTEMPTS = 30
RATELIMIT_GLOSSARY_WINDOW = 60
RATELIMIT_LANGUAGE_ATTEMPTS = 2
RATELIMIT_LANGUAGE_LOCKOUT = 600
RATELIMIT_LANGUAGE_WINDOW = 300
RATELIMIT_LOCKOUT = 600
RATELIMIT_MESSAGE_ATTEMPTS = 2
RATELIMIT_PROJECT_ATTEMPTS = 5
RATELIMIT_PROJECT_LOCKOUT = 600
RATELIMIT_PROJECT_WINDOW = 600
RATELIMIT_SEARCH_ATTEMPTS = 30
RATELIMIT_SEARCH_LOCKOUT = 60
RATELIMIT_SEARCH_WINDOW = 60
RATELIMIT_TRANSLATE_ATTEMPTS = 30
RATELIMIT_TRANSLATE_WINDOW = 60
RATELIMIT_TRIAL_ATTEMPTS = 1
RATELIMIT_TRIAL_LOCKOUT = 600
RATELIMIT_TRIAL_WINDOW = 60
RATELIMIT_WINDOW = 300
REDIS_PASSWORD = '********************'
REDIS_PROTO = 'redis'
REGISTRATION_ALLOW_BACKENDS = []
REGISTRATION_CAPTCHA = True
REGISTRATION_EMAIL_MATCH = '.*'
REGISTRATION_HINTS = {}
REGISTRATION_OPEN = True
REGISTRATION_REBIND = False
REPOSITORY_ALERT_THRESHOLD = 25
REQUIRE_LOGIN = False
REST_FRAMEWORK = {'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.IsAuthenticatedOrReadOnly'], 'DEFAULT_AUTHENTICATION_CLASSES': ('rest_framework.authentication.TokenAuthentication', 'weblate.api.authentication.BearerAuthentication', 'rest_framework.authentication.SessionAuthentication'), 'DEFAULT_THROTTLE_CLASSES': ('weblate.api.throttling.UserRateThrottle', 'weblate.api.throttling.AnonRateThrottle'), 'DEFAULT_THROTTLE_RATES': {'anon': '100/day', 'user': '5000/hour'}, 'DEFAULT_PAGINATION_CLASS': 'weblate.api.pagination.StandardPagination', 'PAGE_SIZE': 50, 'VIEW_DESCRIPTION_FUNCTION': 'weblate.api.views.get_view_description', 'UNAUTHENTICATED_USER': 'weblate.auth.models.get_anonymous'}
ROOT_URLCONF = 'weblate.urls'
SECRET_KEY = '********************'
SECRET_KEY_FALLBACKS = '********************'
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_CROSS_ORIGIN_OPENER_POLICY = 'same-origin'
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SECURE_HSTS_SECONDS = 31536000
SECURE_PROXY_SSL_HEADER = None
SECURE_REDIRECT_EXEMPT = "('healthz/$',)"
SECURE_REFERRER_POLICY = 'same-origin'
SECURE_SSL_HOST = 'translate.codeberg.org'
SECURE_SSL_REDIRECT = True
SENTRY_DSN = None
SENTRY_ENVIRONMENT = None
SENTRY_EXTRA_ARGS = {}
SENTRY_PROJECTS = ['weblate']
SENTRY_SECURITY = None
SENTRY_TOKEN = '********************'
SENTRY_TRACES_SAMPLE_RATE = 0.0
SERVER_EMAIL = '[translate@codeberg.org](mailto:translate@codeberg.org)'
SESSION_CACHE_ALIAS = 'default'
SESSION_COOKIE_AGE = 1000
SESSION_COOKIE_AGE_AUTHENTICATED = 1209600
SESSION_COOKIE_DOMAIN = None
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_NAME = 'sessionid'
SESSION_COOKIE_PATH = '/'
SESSION_COOKIE_SAMESITE = 'Lax'
SESSION_COOKIE_SECURE = True
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_EXPIRE_AT_BROWSER_CLOSE = False
SESSION_FILE_PATH = None
SESSION_SAVE_EVERY_REQUEST = False
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.JSONSerializer'
SETTINGS_MODULE = 'weblate.settings_docker'
SHORT_DATETIME_FORMAT = 'm/d/Y P'
SHORT_DATE_FORMAT = 'm/d/Y'
SIGNING_BACKEND = 'django.core.signing.TimestampSigner'
SILENCED_SYSTEM_CHECKS = ['admin.E408']
SIMILAR_MESSAGES = 5
SIMPLIFY_LANGUAGES = True
SINGLE_PROJECT = False
SITE_DOMAIN = 'translate.codeberg.org'
SITE_ID = 1
SITE_TITLE = 'Weblate'
SITE_URL = 'https://translate.codeberg.org/'
SOCIAL_AUTH_AUTH0_IMAGE = 'auth0.svg'
SOCIAL_AUTH_AUTH0_TITLE = 'Auth0'
SOCIAL_AUTH_AZUREAD_OAUTH2_KEY = '********************'
SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET = '********************'
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_KEY = '********************'
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_SECRET = '********************'
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_TENANT_ID = ''
SOCIAL_AUTH_BITBUCKET_KEY = '********************'
SOCIAL_AUTH_BITBUCKET_OAUTH2_KEY = '********************'
SOCIAL_AUTH_BITBUCKET_OAUTH2_SECRET = '********************'
SOCIAL_AUTH_BITBUCKET_OAUTH2_VERIFIED_EMAILS_ONLY = True
SOCIAL_AUTH_BITBUCKET_SECRET = '********************'
SOCIAL_AUTH_BITBUCKET_VERIFIED_EMAILS_ONLY = True
SOCIAL_AUTH_DISCONNECT_PIPELINE = "('social_core.pipeline.disconnect.allowed_to_disconnect', 'social_core.pipeline.disconnect.get_entries', 'social_core.pipeline.disconnect.revoke_tokens', 'weblate.accounts.pipeline.cycle_session', 'weblate.accounts.pipeline.adjust_primary_mail', 'weblate.accounts.pipeline.notify_disconnect', 'social_core.pipeline.disconnect.disconnect', 'weblate.accounts.pipeline.cleanup_next')"
SOCIAL_AUTH_EMAIL_FORM_URL = '/accounts/email/'
SOCIAL_AUTH_EMAIL_VALIDATION_FUNCTION = 'weblate.accounts.pipeline.send_validation'
SOCIAL_AUTH_EMAIL_VALIDATION_URL = '/accounts/email-sent/'
SOCIAL_AUTH_FACEBOOK_KEY = '********************'
SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {'fields': 'id,name,email'}
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email', 'public_profile']
SOCIAL_AUTH_FACEBOOK_SECRET = '********************'
SOCIAL_AUTH_GITEA_API_URL = '********************'
SOCIAL_AUTH_GITEA_IMAGE = 'codeberg.png'
SOCIAL_AUTH_GITEA_KEY = '********************'
SOCIAL_AUTH_GITEA_SECRET = '********************'
SOCIAL_AUTH_GITEA_TITLE = 'Codeberg'
SOCIAL_AUTH_GITHUB_KEY = '********************'
SOCIAL_AUTH_GITHUB_ORG_KEY = '********************'
SOCIAL_AUTH_GITHUB_ORG_NAME = ''
SOCIAL_AUTH_GITHUB_ORG_SCOPE = ['user:email', 'read:org']
SOCIAL_AUTH_GITHUB_ORG_SECRET = '********************'
SOCIAL_AUTH_GITHUB_SCOPE = ['user:email']
SOCIAL_AUTH_GITHUB_SECRET = '********************'
SOCIAL_AUTH_GITHUB_TEAM_ID = ''
SOCIAL_AUTH_GITHUB_TEAM_KEY = '********************'
SOCIAL_AUTH_GITHUB_TEAM_SCOPE = ['user:email', 'read:org']
SOCIAL_AUTH_GITHUB_TEAM_SECRET = '********************'
SOCIAL_AUTH_GITLAB_KEY = '********************'
SOCIAL_AUTH_GITLAB_SCOPE = ['read_user']
SOCIAL_AUTH_GITLAB_SECRET = '********************'
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '********************'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = '********************'
SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS = []
SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_EMAILS = []
SOCIAL_AUTH_LOGIN_ERROR_URL = '/accounts/login/'
SOCIAL_AUTH_NEW_ASSOCIATION_REDIRECT_URL = '/accounts/profile/#account'
SOCIAL_AUTH_PIPELINE = "('social_core.pipeline.social_auth.social_details', 'social_core.pipeline.social_auth.social_uid', 'social_core.pipeline.social_auth.auth_allowed', 'social_core.pipeline.social_auth.social_user', 'weblate.accounts.pipeline.store_params', 'weblate.accounts.pipeline.verify_open', 'social_core.pipeline.user.get_username', 'weblate.accounts.pipeline.require_email', 'social_core.pipeline.mail.mail_validation', 'weblate.accounts.pipeline.revoke_mail_code', 'weblate.accounts.pipeline.ensure_valid', 'weblate.accounts.pipeline.remove_account', 'social_core.pipeline.social_auth.associate_by_email', 'weblate.accounts.pipeline.reauthenticate', 'weblate.accounts.pipeline.verify_username', 'social_core.pipeline.user.create_user', 'social_core.pipeline.social_auth.associate_user', 'social_core.pipeline.social_auth.load_extra_data', 'weblate.accounts.pipeline.cleanup_next', 'weblate.accounts.pipeline.user_full_name', 'weblate.accounts.pipeline.store_email', 'weblate.accounts.pipeline.notify_connect', 'weblate.accounts.pipeline.password_reset')"
SOCIAL_AUTH_PROTECTED_USER_FIELDS = "('email',)"
SOCIAL_AUTH_RAISE_EXCEPTIONS = True
SOCIAL_AUTH_REDIRECT_IS_HTTPS = True
SOCIAL_AUTH_SAML_IMAGE = 'saml.svg'
SOCIAL_AUTH_SAML_TITLE = 'SAML'
SOCIAL_AUTH_SLUGIFY_FUNCTION = 'weblate.accounts.pipeline.slugify_username'
SOCIAL_AUTH_SLUGIFY_USERNAMES = True
SOCIAL_AUTH_STRATEGY = 'weblate.accounts.strategy.WeblateStrategy'
SPECIAL_CHARS = "('\\t', '\\n', '\\xa0', '…')"
SSH_EXTRA_ARGS = ''
STATICFILES_DIRS = '()'
STATICFILES_FINDERS = "('django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'compressor.finders.CompressorFinder')"
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'
STATIC_ROOT = '/app/cache/static'
STATIC_URL = '/static/'
STATUS_URL = None
SUGGESTION_CLEANUP_DAYS = None
SUPPORT_API_URL = '********************'
TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates', 'OPTIONS': {'context_processors': ['django.contrib.auth.context_processors.auth', 'django.template.context_processors.debug', 'django.template.context_processors.i18n', 'django.template.context_processors.request', 'django.template.context_processors.csrf', 'django.contrib.messages.context_processors.messages', 'weblate.trans.context_processors.weblate_context']}, 'APP_DIRS': True}]
TEST_NON_SERIALIZED_APPS = []
TEST_RUNNER = 'django.test.runner.DiscoverRunner'
THOUSAND_SEPARATOR = ','
TIME_FORMAT = 'P'
TIME_INPUT_FORMATS = ['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
TIME_ZONE = 'UTC'
UPDATE_LANGUAGES = True
URL_PREFIX = ''
USE_DEPRECATED_PYTZ = False
USE_I18N = True
USE_L10N = True
USE_THOUSAND_SEPARATOR = False
USE_TZ = True
USE_X_FORWARDED_HOST = False
USE_X_FORWARDED_PORT = False
VAT_RATE = 1.21
VCS_API_DELAY = '********************'
VCS_BACKENDS = "('weblate.vcs.git.GitRepository', 'weblate.vcs.git.GitWithGerritRepository', 'weblate.vcs.git.SubversionRepository', 'weblate.vcs.git.GithubRepository', 'weblate.vcs.git.GiteaRepository', 'weblate.vcs.git.GitLabRepository', 'weblate.vcs.git.PagureRepository', 'weblate.vcs.git.LocalRepository', 'weblate.vcs.git.GitForcePushRepository', 'weblate.vcs.git.BitbucketServerRepository', 'weblate.vcs.mercurial.HgRepository')"
VCS_CLONE_DEPTH = 1
WEBLATE_ADDONS = ['weblate.addons.gettext.GenerateMoAddon', 'weblate.addons.gettext.UpdateLinguasAddon', 'weblate.addons.gettext.UpdateConfigureAddon', 'weblate.addons.gettext.MsgmergeAddon', 'weblate.addons.gettext.GettextCustomizeAddon', 'weblate.addons.gettext.GettextAuthorComments', 'weblate.addons.cleanup.CleanupAddon', 'weblate.addons.cleanup.RemoveBlankAddon', 'weblate.addons.consistency.LangaugeConsistencyAddon', 'weblate.addons.discovery.DiscoveryAddon', 'weblate.addons.autotranslate.AutoTranslateAddon', 'weblate.addons.flags.SourceEditAddon', 'weblate.addons.flags.TargetEditAddon', 'weblate.addons.flags.SameEditAddon', 'weblate.addons.flags.BulkEditAddon', 'weblate.addons.generate.GenerateFileAddon', 'weblate.addons.generate.PseudolocaleAddon', 'weblate.addons.generate.PrefillAddon', 'weblate.addons.json.JSONCustomizeAddon', 'weblate.addons.xml.XMLCustomizeAddon', 'weblate.addons.properties.PropertiesSortAddon', 'weblate.addons.git.GitSquashAddon', 'weblate.addons.removal.RemoveComments', 'weblate.addons.removal.RemoveSuggestions', 'weblate.addons.resx.ResxUpdateAddon', 'weblate.addons.yaml.YAMLCustomizeAddon', 'weblate.addons.cdn.CDNJSAddon']
WEBLATE_EXPORTERS = "('weblate.formats.exporters.PoExporter', 'weblate.formats.exporters.PoXliffExporter', 'weblate.formats.exporters.XliffExporter', 'weblate.formats.exporters.TBXExporter', 'weblate.formats.exporters.TMXExporter', 'weblate.formats.exporters.MoExporter', 'weblate.formats.exporters.CSVExporter', 'weblate.formats.exporters.XlsxExporter', 'weblate.formats.exporters.JSONExporter', 'weblate.formats.exporters.AndroidResourceExporter', 'weblate.formats.exporters.StringsExporter')"
WEBLATE_FORMATS = "('weblate.formats.ttkit.PoFormat', 'weblate.formats.ttkit.PoMonoFormat', 'weblate.formats.ttkit.TSFormat', 'weblate.formats.ttkit.XliffFormat', 'weblate.formats.ttkit.RichXliffFormat', 'weblate.formats.ttkit.PoXliffFormat', 'weblate.formats.ttkit.StringsFormat', 'weblate.formats.ttkit.StringsUtf8Format', 'weblate.formats.ttkit.PropertiesUtf8Format', 'weblate.formats.ttkit.PropertiesUtf16Format', 'weblate.formats.ttkit.PropertiesFormat', 'weblate.formats.ttkit.JoomlaFormat', 'weblate.formats.ttkit.GWTFormat', 'weblate.formats.ttkit.GWTISOFormat', 'weblate.formats.ttkit.PhpFormat', 'weblate.formats.ttkit.LaravelPhpFormat', 'weblate.formats.ttkit.RESXFormat', 'weblate.formats.ttkit.AndroidFormat', 'weblate.formats.ttkit.JSONFormat', 'weblate.formats.ttkit.JSONNestedFormat', 'weblate.formats.ttkit.WebExtensionJSONFormat', 'weblate.formats.ttkit.I18NextFormat', 'weblate.formats.ttkit.I18NextV4Format', 'weblate.formats.ttkit.GoI18JSONFormat', 'weblate.formats.ttkit.GoI18V2JSONFormat', 'weblate.formats.ttkit.GoTextFormat', 'weblate.formats.ttkit.ARBFormat', 'weblate.formats.ttkit.CSVFormat', 'weblate.formats.ttkit.CSVUtf8Format', 'weblate.formats.ttkit.CSVSimpleFormat', 'weblate.formats.ttkit.CSVUtf8SimpleFormat', 'weblate.formats.ttkit.CSVSimpleFormatISO', 'weblate.formats.ttkit.YAMLFormat', 'weblate.formats.ttkit.RubyYAMLFormat', 'weblate.formats.ttkit.SubRipFormat', 'weblate.formats.ttkit.MicroDVDFormat', 'weblate.formats.ttkit.AdvSubStationAlphaFormat', 'weblate.formats.ttkit.SubStationAlphaFormat', 'weblate.formats.ttkit.DTDFormat', 'weblate.formats.ttkit.FlatXMLFormat', 'weblate.formats.ttkit.ResourceDictionaryFormat', 'weblate.formats.ttkit.INIFormat', 'weblate.formats.ttkit.InnoSetupINIFormat', 'weblate.formats.ttkit.PropertiesMi18nFormat', 'weblate.formats.external.XlsxFormat', 'weblate.formats.txt.AppStoreFormat', 'weblate.formats.convert.HTMLFormat', 'weblate.formats.convert.IDMLFormat', 'weblate.formats.convert.OpenDocumentFormat', 'weblate.formats.convert.PlainTextFormat', 'weblate.formats.convert.DokuWikiFormat', 'weblate.formats.convert.MediaWikiFormat', 'weblate.formats.convert.WindowsRCFormat', 'weblate.formats.ttkit.XWikiPropertiesFormat', 'weblate.formats.ttkit.XWikiPagePropertiesFormat', 'weblate.formats.ttkit.XWikiFullPageFormat', 'weblate.formats.ttkit.TBXFormat', 'weblate.formats.ttkit.StringsdictFormat', 'weblate.formats.ttkit.FluentFormat', 'weblate.formats.multi.MultiCSVUtf8Format')"
WEBLATE_GPG_ALGO = 'default'
WEBLATE_GPG_IDENTITY = 'Codeberg Translate [<translate@codeberg.org>](mailto:translate@codeberg.org)'
WEBLATE_MACHINERY = "('weblate.machinery.apertium.ApertiumAPYTranslation', 'weblate.machinery.aws.AWSTranslation', 'weblate.machinery.baidu.BaiduTranslation', 'weblate.machinery.deepl.DeepLTranslation', 'weblate.machinery.glosbe.GlosbeTranslation', 'weblate.machinery.google.GoogleTranslation', 'weblate.machinery.googlev3.GoogleV3Translation', 'weblate.machinery.libretranslate.LibreTranslateTranslation', 'weblate.machinery.microsoft.MicrosoftCognitiveTranslation', 'weblate.machinery.microsoftterminology.MicrosoftTerminologyService', 'weblate.machinery.modernmt.ModernMTTranslation', 'weblate.machinery.mymemory.MyMemoryTranslation', 'weblate.machinery.netease.NeteaseSightTranslation', 'weblate.machinery.tmserver.AmagamaTranslation', 'weblate.machinery.tmserver.TMServerTranslation', 'weblate.machinery.yandex.YandexTranslation', 'weblate.machinery.saptranslationhub.SAPTranslationHub', 'weblate.machinery.youdao.YoudaoTranslation', 'weblate.machinery.ibm.IBMTranslation', 'weblate.machinery.weblatetm.WeblateTranslation', 'weblate.memory.machine.WeblateMemory')"
WEBLATE_SECURE_PROXY_SSL_HEADER = []
WEBSITE_REQUIRED = True
WSGI_APPLICATION = None
X_FRAME_OPTIONS = 'DENY'
YEAR_MONTH_FORMAT = 'F Y'
</pre>
</details>


Discussion:

Resolving patch:
diff --git a/weblate/trans/bulk.py b/weblate/trans/bulk.py
--- a/weblate/trans/bulk.py
+++ b/weblate/trans/bulk.py
@@ -23,7 +23,7 @@ def bulk_perform(
     project,
     components=None,
 ):
-    matching = unit_set.search(query, distinct=False, project=project).prefetch()
+    matching = unit_set.search(query, project=project)
     if components is None:
         components = Component.objects.filter(
             id__in=matching.values_list("translation__component_id", flat=True)
@@ -52,8 +52,11 @@ def bulk_perform(
             else:
                 update_unit_ids = []
                 source_units = []
+                unit_ids = list(component_units.values_list("id", flat=True))
                 # Generate changes for state change
-                for unit in component_units.select_for_update():
+                for unit in (
+                    Unit.objects.filter(id__in=unit_ids).prefetch().select_for_update()
+                ):
                     source_unit_ids.add(unit.source_unit_id)
 
                     if (
diff --git a/weblate/trans/models/unit.py b/weblate/trans/models/unit.py
--- a/weblate/trans/models/unit.py
+++ b/weblate/trans/models/unit.py
@@ -128,12 +128,10 @@ def prefetch_recent_content_changes(self):
             )
         )
 
-    def search(self, query, distinct: bool = True, **context):
+    def search(self, query, **context):
         """High level wrapper for searching."""
         result = self.filter(parse_query(query, **context))
-        if distinct:
-            result = result.distinct()
-        return result
+        return result.distinct()
 
     def same(self, unit, exclude=True):
         """Unit with same source within same project."""
diff --git a/weblate/trans/views/search.py b/weblate/trans/views/search.py
--- a/weblate/trans/views/search.py
+++ b/weblate/trans/views/search.py
@@ -90,17 +90,22 @@ def search_replace(request, project, component=None, lang=None):
 
     matching = unit_set.filter(target__contains=search_text)
     if query:
-        matching = matching.search(query, distinct=False)
+        matching = matching.search(query)
 
     updated = 0
-    if matching.exists():
-        confirm = ReplaceConfirmForm(matching, request.POST)
-        limited = False
 
-        if matching.count() > 300:
-            matching = matching.order_by("id")[:250]
+    matching_ids = list(matching.order_by("id").values_list("id", flat=True)[:251])
+
+    if matching_ids:
+        if len(matching_ids) == 251:
+            matching_ids = matching_ids[:250]
             limited = True
 
+        matching = Unit.objects.filter(id__in=matching_ids).prefetch()
+
+        confirm = ReplaceConfirmForm(matching, request.POST)
+        limited = False
+
         if not confirm.is_valid():
             for unit in matching:
                 unit.replacement = unit.target.replace(search_text, replacement)


Test patch: