Skip to content

fix(add-ons): use fetch_validated_url to trigger webhooks#18815

Merged
nijel merged 2 commits into
WeblateOrg:mainfrom
nijel:fetch
Apr 7, 2026
Merged

fix(add-ons): use fetch_validated_url to trigger webhooks#18815
nijel merged 2 commits into
WeblateOrg:mainfrom
nijel:fetch

Conversation

@nijel

@nijel nijel commented Apr 7, 2026

Copy link
Copy Markdown
Member

This pulls existing external endpoint validation in.

@nijel nijel added this to the 5.17 milestone Apr 7, 2026
@nijel nijel self-assigned this Apr 7, 2026
@nijel nijel requested a review from AliceVisek as a code owner April 7, 2026 09:10
@nijel nijel requested a review from Copilot April 7, 2026 09:10

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 66919b9ee2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread weblate/addons/webhooks.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens add-on webhook delivery by routing outbound webhook requests through the existing URL validation pipeline, preventing delivery to private-network targets (SSRF mitigation) and documenting the security improvement.

Changes:

  • Switch webhook delivery from fetch_url() to fetch_validated_url() with allow_private_targets=False.
  • Add a regression test ensuring private webhook targets are blocked and logged as errors.
  • Note the security improvement in the 5.17 changelog.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
weblate/addons/webhooks.py Uses validated outbound HTTP helper to block private webhook targets; extends exception handling to include validation failures.
weblate/addons/tests.py Adds test covering private-target blocking behavior and expected activity log state.
docs/changes.rst Records the security improvement in release notes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread weblate/addons/webhooks.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 678146cbc8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/changes.rst Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread weblate/addons/tests.py Outdated
Comment thread weblate/addons/webhooks.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread weblate/addons/tests.py Outdated
Comment thread docs/changes.rst

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 87d0655896

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +85 to +86
allow_private_targets=not settings.WEBHOOK_RESTRICT_PRIVATE,
allowed_domains=settings.WEBHOOK_PRIVATE_ALLOWLIST,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Honor webhook allowlist during direct delivery checks

Passing allowed_domains=settings.WEBHOOK_PRIVATE_ALLOWLIST here does not actually allow private webhook targets for normal (non-proxy) delivery: fetch_validated_url only uses allowed_domains in the proxy branch, while direct requests still run runtime IP/peer checks that reject private addresses unconditionally. In practice, with WEBHOOK_RESTRICT_PRIVATE=True and WEBHOOK_PRIVATE_ALLOWLIST configured, saving the add-on can succeed but delivery still fails for allowlisted internal hosts unless an HTTP(S) proxy is used.

Useful? React with 👍 / 👎.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread weblate/settings_example.py Outdated
Comment thread docs/admin/config.rst
@codecov

codecov Bot commented Apr 7, 2026

Copy link
Copy Markdown

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
6181 1 6180 705
View the top 1 failed test(s) by shortest run time
weblate.addons.tests.WebhooksAddonTest::test_form
Stack Traces | 0.98s run time
self = <weblate.addons.tests.WebhooksAddonTest testMethod=test_form>

    def test_form(self) -> None:
        """Test WebhooksAddonForm."""
        self.user.is_superuser = True
        self.user.save()
        # Missing url param
        response = self.client.post(
            reverse("addons", kwargs=self.kw_component),
            {
                "name": "weblate.webhook.webhook",
                "form": "1",
            },
            follow=True,
        )
        self.assertNotContains(response, "Installed 1 add-on")
    
        # empty secret
        response = self.client.post(
            reverse("addons", kwargs=self.kw_component),
            {
                "name": "weblate.webhook.webhook",
                "form": "1",
                "webhook_url": "https://example.com/webhooks",
                "secret": "",
            },
            follow=True,
        )
        self.assertContains(response, "Installed 1 add-on")
    
        # private target blocked by default
        response = self.client.post(
            reverse("addons", kwargs=self.kw_component),
            {
                "name": "weblate.webhook.webhook",
                "form": "1",
                "webhook_url": "http:.../localhost/hook",
                "events": [ActionEvents.NEW],
            },
            follow=True,
        )
        self.assertContains(response, "internal or non-public address")
    
        with override_settings(WEBHOOK_RESTRICT_PRIVATE=False):
            response = self.client.post(
                reverse("addons", kwargs=self.kw_component),
                {
                    "name": "weblate.webhook.webhook",
                    "form": "1",
                    "webhook_url": "http:.../localhost/hook",
                    "events": [ActionEvents.NEW],
                },
                follow=True,
            )
>           self.assertContains(response, "Installed 1 add-on")
E           AssertionError: False is not true : Couldn't find 'Installed 1 add-on' in the following response
E           b'\n\n<!DOCTYPE html>\n\n<html lang="en"\n      dir="ltr"\n      >\n  <head>\n    <meta http-equiv="X-UA-Compatible" content="IE=edge" />\n    <meta name="referrer" content="origin" />\n    <meta name="author" content="Michal \xc4\x8ciha\xc5\x99" />\n    <meta name="copyright" content="Copyright \xc2\xa9 Michal \xc4\x8ciha\xc5\x99" />\n    <meta name="robots" content="noindex,nofollow" />\n\n    <title>\n  Test/Test @ Weblate\n\n</title>\n    <meta name="description" content="This site runs Weblate for localizing various software projects." />\n    <meta name="twitter:card" content="summary_large_image" />\n\n    \n    \n\n    \n      <link rel="alternate"\n            type="application/rss+xml"\n            title="RSS feed"\n            href=".../rss/test/test/" />\n      <meta property="og:image"\n            content="http://example..../test/test/open-graph.png" />\n    \n\n    \n\n    \n\n\n  \n    <link rel="stylesheet"\n          href=".../styles/vendor/bootstrap5.css?v=19fd79b" />\n  \n  <link rel="stylesheet"\n        href="....../static/weblate_fonts/source-code-pro.css?v=19fd79b" />\n  <link rel="stylesheet"\n        href="....../static/weblate_fonts/source-sans-3.css?v=19fd79b" />\n  <link rel="stylesheet" href=".../styles/vendor/multi.css?v=19fd79b" />\n  <link rel="stylesheet" href=".../static/styles/new-language.css?v=19fd79b" />\n  <link rel="stylesheet" href=".../static/styles/variables.css?v=19fd79b" />\n  <link rel="stylesheet" href=".../static/styles/main.css?v=19fd79b" />\n  <link rel="stylesheet" href="/static/daterangepicker.css?v=19fd79b" />\n  \n    <link rel="stylesheet"\n          href="/static/style-dark.css?v=19fd79b"\n          media="(prefers-color-scheme: dark)" />\n  \n\n\n\n\n    <script src="/js/i18n/" defer></script>\n    \n      <script defer\n              data-cfasync="false"\n              src=".../js/vendor/main.js?v=19fd79b"></script>\n      <script defer\n              data-cfasync="false"\n              src=".../js/vendor/autosize.js?v=19fd79b"></script>\n      <script defer\n              data-cfasync="false"\n              src=".../js/vendor/altcha.js?v=19fd79b"></script>\n      <script defer\n              data-cfasync="false"\n              src=".../js/vendor/multi.js?v=19fd79b"></script>\n      <script defer\n              data-cfasync="false"\n              src=".../js/vendor/mousetrap.js?v=19fd79b"></script>\n      <script defer\n              data-cfasync="false"\n              src=".../js/vendor/bootstrap5.js?v=19fd79b"></script>\n      <script defer\n              data-cfasync="false"\n              src=".../js/vendor/tribute.js?v=19fd79b"></script>\n      <script defer\n              data-cfasync="false"\n              src=".../js/vendor/autoComplete.js?v=19fd79b"></script>\n      <script defer\n              data-cfasync="false"\n              src=".../js/vendor/prismjs.js?v=19fd79b"></script>\n      <script defer\n              data-cfasync="false"\n              src="/static/prism-weblatesearch.js?v=19fd79b"></script>\n      <script defer\n              data-cfasync="false"\n              src="/static/loader-bootstrap.js?v=19fd79b"></script>\n      <script defer\n              data-cfasync="false"\n              src=".../static/js/keyboard-shortcuts.js?v=19fd79b"></script>\n      <script defer\n              data-cfasync="false"\n              src=".../editor/tools/search.js?v=19fd79b"></script>\n    \n\n    \n\n    <link rel="image_src" type="image/png" href="/static/weblate-128.png" />\n    <link rel="icon" type="image/png" sizes="32x32" href="/static/logo-32.png">\n    <link rel="icon" type="image/png" sizes="16x16" href="/static/logo-16.png">\n    <link rel="apple-touch-icon" sizes="180x180" href="/static/weblate-180.png" />\n    <link rel="mask-icon" href="/static/weblate-black.svg" color="#144d3f">\n    <meta name="msapplication-TileColor" content="#144d3f">\n    <meta name="msapplication-config" content="/browserconfig.xml">\n    <link rel="manifest" href="/site.webmanifest">\n    \n    \n    <meta name="theme-color" content="#144d3f">\n\n    <meta name="viewport" content="width=device-width, initial-scale=1" />\n    <meta property="og:site_name" content="Weblate" />\n    <meta property="og:title"\n          content="Test/Test" />\n    <meta property="og:description" content="This site runs Weblate for localizing various software projects." />\n\n    \n\n    \n\n  </head>\n\n  <body data-theme="auto"\n        >\n    <div id="popup-alerts"></div>\n    <header>\n      <nav class="navbar navbar-expand-lg bg-dark" role="navigation">\n        <div class="container-fluid">\n          <!-- Brand and toggle get grouped for better mobile display -->\n          <div class="navbar-brand">\n\n<a class="navbar-brand" href="/"><svg width="27" height="20" version="1.1" viewBox="0 0 27 20" xmlns="http://www.w3.org/2000/svg"><path d="m13.505 4.028c-0.0017-4e-5 -0.0034-7.5e-5 -5e-3 -1.05e-4 -0.0017 3e-5 -0.0034 6.5e-5 -5e-3 1.05e-4 -0.11025-0.0015-0.22073 0.01793-0.32591 0.06238-0.59671 0.25261-0.9728 0.90036-1.2087 1.5476-0.20481 0.56175-0.29546 1.1651-0.29679 1.7605l-0.0016 0.07791c-0.0019 0.03033-0.0043 0.06055-0.0075 0.09067 0.02191 1.5184 0.30756 3.048 0.90819 4.445 0.67267 1.5645 1.7419 3.0037 3.2516 3.6616 1.1389 0.49637 2.4014 0.37928 3.4336-0.20534 1.2816-0.72588 2.2062-2.0094 2.8114-3.3878 1.2572-2.8648 1.2874-6.3574 0.03289-9.2972 1.2227-0.63339 1.22-1.8963 1.22-1.8963s1.1453 0.82078 2.4332 0.30544c1.715 4.0186 1.6736 8.75-0.13474 12.708-1.0572 2.3139-2.7738 4.3411-5.0202 5.384-1.9998 0.9286-4.3513 0.9518-6.3527 0.07963-1.7985-0.78402-3.2613-2.1966-4.3137-3.839-1.5242-2.3788-2.246-5.2748-2.2492-8.1286h0.01183c-9.01e-4 -0.03006-0.0013-0.06012-9.54e-4 -0.09024 0.02318-2.5663 1.0748-5.18 3.1841-6.5213 0.77462-0.49257 1.6798-0.77459 2.5936-0.78467 0.01046-8.1e-5 0.02122-1.32e-4 0.03183-1.51e-4 0.01379-1e-5 0.02811 4.4e-5 0.04191 1.51e-4 0.91371 0.01007 1.8189 0.2921 2.5936 0.78467 2.1093 1.3413 3.1609 3.9551 3.1841 6.5213 3.18e-4 0.03012-5.3e-5 0.06018-9.55e-4 0.09024h0.01183c-0.0031 2.7121-0.65515 5.4624-2.0282 7.7706-0.39383-2e-3 -0.78628-0.08215-1.1562-0.24339-0.83333-0.36312-1.5671-1.0489-2.1641-1.9768 0.17024-0.30266 0.32367-0.61606 0.46065-0.93466 0.60064-1.3969 0.88629-2.9266 0.90819-4.445-0.0032-0.03012-0.0057-0.06034-0.0075-0.09067l-0.0016-0.07792c-0.0013-0.59534-0.09198-1.1987-0.29679-1.7605-0.23595-0.64722-0.61204-1.295-1.2087-1.5476-0.10522-0.04446-0.21573-0.06389-0.32591-0.06255v1.8e-4zm-0.88468 15.396c-1.97 0.81042-4.258 0.76693-6.2107-0.13979-2.2465-1.043-3.963-3.0701-5.0202-5.384-1.8083-3.9579-1.8497-8.6893-0.13474-12.708 1.2879 0.51534 2.4332-0.30544 2.4332-0.30544s-0.0027 1.2629 1.22 1.8963c-1.2545 2.9398-1.2243 6.4325 0.03289 9.2972 0.60525 1.3784 1.5298 2.662 2.8114 3.3878 0.45742 0.25906 0.96005 0.42632 1.4771 0.48907 0.0019 3e-3 0.0038 6e-3 0.0057 9e-3 0.91308 1.425 2.0633 2.6126 3.3853 3.4577z"/></svg>Weblate</a>\n</div>\n          <button type="button"\n                  class="navbar-toggler"\n                  data-bs-toggle="collapse"\n                  data-bs-target="#wl-navbar-main"\n                  data-bs-theme="dark"\n                  id="navbar-toggle">\n            <span class="visually-hidden">Toggle navigation</span>\n            <span class="navbar-toggler-icon"></span>\n          </button>\n\n          <!-- Collect the nav links, forms, and other content for toggling -->\n          <div class="collapse navbar-collapse" id="wl-navbar-main">\n            <form class="navbar-form">\n              <div class="form-group">\n                <input type="text"\n                       class="form-control"\n                       id="sitewide-search"\n                       placeholder="Search">\n              </div>\n            </form>\n            <ul class="navbar-nav">\n              <li class="nav-item">\n                <a class="nav-link" href="/">Dashboard</a>\n              </li>\n              <li class="nav-item dropdown">\n                <a class="nav-link dropdown-toggle"\n                   href="#"\n                   role="button"\n                   data-bs-toggle="dropdown"\n                   id="projects-menu">Projects</a>\n                <ul class="dropdown-menu shadow">\n                  \n                  \n                    <li>\n                      <a class="dropdown-item" href="/accounts/profile/#notifications">Manage watched projects</a>\n                    </li>\n                    <li>\n                      <hr class="dropdown-divider">\n                    </li>\n                  \n                  <li>\n                    <a class="dropdown-item" href="/projects/">Browse all projects</a>\n                  </li>\n                </ul>\n              </li>\n              \n                <li class="nav-item dropdown">\n                  <a href="#"\n                     class="nav-link dropdown-toggle"\n                     role="button"\n                     data-bs-toggle="dropdown"\n                     id="languages-menu">Languages</a>\n                  <ul class="dropdown-menu shadow">\n                    \n                    \n                      <li>\n                        <a class="dropdown-item" href="/accounts/profile/#languages">Manage translated languages</a>\n                      </li>\n                      <li>\n                        <hr class="dropdown-divider">\n                      </li>\n                    \n                    <li>\n                      <a class="dropdown-item" href="/languages/">Browse all languages</a>\n                    </li>\n                  </ul>\n                </li>\n                <li class="nav-item dropdown">\n                  <a href="#"\n                     class="nav-link dropdown-toggle"\n                     role="button"\n                     data-bs-toggle="dropdown"\n                     id="checks-menu">Checks</a>\n                  <ul class="dropdown-menu shadow">\n                    \n                    \n                    <li>\n                      <a class="dropdown-item" href="/checks/">Checks overview</a>\n                    </li>\n                  </ul>\n                </li>\n              \n            </ul>\n            <ul class="navbar-nav ms-auto">\n\n              \n              \n                \n                \n                  <li class="nav-item">\n                    <a class="nav-link button"\n                       id="admin-button"\n                       href="/manage/"\n                       title="Administration">\n                      <span class="d-none d-sm-inline"><svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m22.7 19-9.1-9.1c0.9-2.3 0.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3l4.3 4.3-3 3-4.4-4.3c-1.2 2.4-0.7 5.4 1.3 7.4 1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c0.4 0.4 1 0.4 1.4 0l2.3-2.3c0.5-0.4 0.5-1.1 0.1-1.4z"/></svg></span>\n                      <span class="d-inline d-sm-none">Administration</span>\n                    </a>\n                  </li>\n                  \n                \n              \n\n              \n              \n\n              \n              \n                \n                \n                \n                  <li class="nav-item dropdown">\n                    <a href="#" class="nav-link dropdown-toggle" data-bs-toggle="dropdown">\n                      <span class="d-none d-sm-inline"><svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m19 13h-6v6h-2v-6h-6v-2h6v-6h2v6h6v2z"/></svg></span>\n                      <span class="d-inline d-sm-none">Add</span>\n                    </a>\n                    <ul class="dropdown-menu dropdown-menu-end shadow">\n                      \n                        <li>\n                          <a class="dropdown-item" href="/create/project/">Add new translation project</a>\n                        </li>\n                      \n                      \n                        <li>\n                          <a class="dropdown-item"\n                             href="/create/component/">Add new translation component</a>\n                        </li>\n                      \n                      \n                      \n                    </ul>\n                  </li>\n                \n              \n\n              \n              \n                <li class="nav-item dropdown">\n                  <a href="#"\n                     id="user-dropdown"\n                     class="nav-link dropdown-toggle"\n                     data-bs-toggle="dropdown"\n                     title="Your profile">\n                    \n                      <span class="d-none d-sm-inline">\n                        <img class="avatar"\n                             alt="User avatar"\n                             src=".../avatar/24/testuser.png" />\n                      </span>\n                      <span class="d-inline d-sm-none">Your profile</span>\n                    \n                  </a>\n                  <ul class="dropdown-menu dropdown-menu-end shadow">\n                    <li id="profile-name">\n                      <a class="dropdown-item button"\n                         id="profile-button"\n                         href="/user/testuser/"><b>Weblate Test</b>\n                        <br />\n                      @testuser</a>\n                    </li>\n                    <li>\n                      <hr class="dropdown-divider">\n                    </li>\n                    \n                      <li>\n                        <a class="dropdown-item button" id="billing-button" href="/billing/">Billing overview</a>\n                      </li>\n                    \n                    <li>\n                      <a class="dropdown-item" id="memory-button" href="/memory/">Translation memory</a>\n                    </li>\n                    <li>\n                      <a class="dropdown-item button" id="settings-button" href="/accounts/profile/">Settings</a>\n                    </li>\n                    <li>\n                      <hr class="dropdown-divider">\n                    </li>\n                    <li>\n                      <a id="logout-button"\n                         href=""\n                         class="dropdown-item button link-post"\n                         data-href="/accounts/logout/">Sign out</a>\n                    </li>\n                  </ul>\n                </li>\n              \n\n              \n              <li class="nav-item dropdown">\n                <a href="#"\n                   class="nav-link dropdown-toggle support"\n                   data-bs-toggle="dropdown"\n                   title="Help">\n                  <span class="d-none d-sm-inline"><svg width="16" height="4" version="1.1" viewBox="0 0 16 4" xmlns="http://www.w3.org/2000/svg"><path d="m12 2c0-1.1046 0.89543-2 2-2s2 0.89543 2 2-0.89543 2-2 2-2-0.89543-2-2zm-6 0c0-1.1046 0.89543-2 2-2s2 0.89543 2 2-0.89543 2-2 2-2-0.89543-2-2zm-6 0c0-1.1046 0.89543-2 2-2s2 0.89543 2 2-0.89543 2-2 2-2-0.89543-2-2z"/></svg></span>\n                  <span class="d-inline d-sm-none">Help</span>\n                </a>\n                <ul class="dropdown-menu dropdown-menu-end shadow">\n                  <li class="dropdown-header">Get help</li>\n                  \n                    <li>\n                      <a class="dropdown-item" href="/contact/">Contact server admins</a>\n                    </li>\n                  \n                  <li>\n                    <a class="dropdown-item" href="https://github..../orgs/WeblateOrg/discussions">Community discussions</a>\n                  </li>\n                  \n                    <li>\n                      <a class="dropdown-item" href="https://weblate.org/support/">Get professional support</a>\n                    </li>\n                    \n                  \n\n                  <li class="dropdown-header">Documentation</li>\n                  <li>\n                    <a class="dropdown-item" href="https://docs.weblate..../en/latest/index.html">Documentation</a>\n                  </li>\n                  <li>\n                    <a class="dropdown-item" id="shortcuts-btn" href="#">Keyboard shortcuts</a>\n                  </li>\n                  <li>\n                    <li class="dropdown-header">Weblate project</li>\n                  </li>\n                  <li>\n                    <a class="dropdown-item" href="https://weblate.org/contribute/">Contribute</a>\n                  </li>\n                  \n                    <li>\n                      <a class="dropdown-item" href="/donate/">Become a supporter</a>\n                    </li>\n                  \n                  <li>\n                    <a class="dropdown-item" href="/about/">About</a>\n                  </li>\n                  <li>\n                    <a class="dropdown-item" href="https://weblate.org/">Website</a>\n                  </li>\n                </ul>\n              </li>\n            </ul>\n          </div>\n        </div>\n      </nav>\n      \n        <h1>\n          <ol class="breadcrumb">\n            <li class="bread-icon"><svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m2 10.96c-0.5-0.28-0.65-0.89-0.37-1.37l1.5-2.59c0.11-0.2 0.28-0.34 0.47-0.42l7.83-4.4c0.16-0.12 0.36-0.18 0.57-0.18s0.41 0.06 0.57 0.18l7.9 4.44c0.19 0.1 0.35 0.26 0.44 0.46l1.45 2.52c0.28 0.48 0.11 1.09-0.36 1.36l-1 0.58v4.96c0 0.38-0.21 0.71-0.53 0.88l-7.9 4.44c-0.16 0.12-0.36 0.18-0.57 0.18s-0.41-0.06-0.57-0.18l-7.9-4.44c-0.32-0.17-0.53-0.5-0.53-0.88v-5.54c-0.3 0.17-0.68 0.18-1 0m10-6.81v6.7l5.96-3.35-5.96-3.35m-7 11.76 6 3.38v-6.71l-6-3.37v6.7m14 0v-3.22l-5 2.9c-0.33 0.18-0.7 0.17-1 0.01v3.69l6-3.38m-5.15-2.55 6.28-3.63-0.58-1.01-6.28 3.63 0.58 1.01z"/></svg></li>\n            \n  \n    <li class="breadcrumb-item"><a href="/projects/test/">Test</a></li>\n<li class="breadcrumb-item"><a href=".............../projects/test/test/">Test</a></li>\n    <li class="breadcrumb-item">\n      <a href=".../addons/test/test/">Add-ons</a>\n    </li>\n  \n\n\n          </ol>\n          <div class="clearfix"></div>\n        </h1>\n      \n\n    </header>\n\n    <div class="main-content \n       ">\n\n      \n\n      \n\n      \n\n      \n\n      \n  <ul class="nav nav-pills">\n    <li class="nav-item">\n      <a class="nav-link active" data-bs-target="#addons" data-bs-toggle="tab" href="#">Add-ons</a>\n    </li>\n    <li class="nav-item">\n      <a class="nav-link" data-bs-target="#history" data-bs-toggle="tab" href="#">History</a>\n    </li>\n  </ul>\n\n\n      \n\n  <div class="tab-content">\n\n    <div class="tab-pane active" id="addons">\n      <div class="card">\n        <div class="card-header">\n          <h4 class="card-title">\n            <a class="float-end doc-link" href="https://docs.weblate..../latest/admin/addons.html" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n            \n              Installed 2 add-ons\n            \n          </h4>\n        </div>\n        <table class="table table-striped">\n          <tbody>\n            \n              <tr>\n                <td>\n                  \n                    \n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10.46,19C9,21.07 6.15,21.59 4.09,20.15C2.04,18.71 1.56,15.84 3,13.75C3.87,12.5 5.21,11.83 6.58,11.77L6.63,13.2C5.72,13.27 4.84,13.74 4.27,14.56C3.27,16 3.58,17.94 4.95,18.91C6.33,19.87 8.26,19.5 9.26,18.07C9.57,17.62 9.75,17.13 9.82,16.63V15.62L15.4,15.58L15.47,15.47C16,14.55 17.15,14.23 18.05,14.75C18.95,15.27 19.26,16.43 18.73,17.35C18.2,18.26 17.04,18.58 16.14,18.06C15.73,17.83 15.44,17.46 15.31,17.04L11.24,17.06C11.13,17.73 10.87,18.38 10.46,19M17.74,11.86C20.27,12.17 22.07,14.44 21.76,16.93C21.45,19.43 19.15,21.2 16.62,20.89C15.13,20.71 13.9,19.86 13.19,18.68L14.43,17.96C14.92,18.73 15.75,19.28 16.75,19.41C18.5,19.62 20.05,18.43 20.26,16.76C20.47,15.09 19.23,13.56 17.5,13.35C16.96,13.29 16.44,13.36 15.97,13.53L15.12,13.97L12.54,9.2H12.32C11.26,9.16 10.44,8.29 10.47,7.25C10.5,6.21 11.4,5.4 12.45,5.44C13.5,5.5 14.33,6.35 14.3,7.39C14.28,7.83 14.11,8.23 13.84,8.54L15.74,12.05C16.36,11.85 17.04,11.78 17.74,11.86M8.25,9.14C7.25,6.79 8.31,4.1 10.62,3.12C12.94,2.14 15.62,3.25 16.62,5.6C17.21,6.97 17.09,8.47 16.42,9.67L15.18,8.95C15.6,8.14 15.67,7.15 15.27,6.22C14.59,4.62 12.78,3.85 11.23,4.5C9.67,5.16 8.97,7 9.65,8.6C9.93,9.26 10.4,9.77 10.97,10.11L11.36,10.32L8.29,15.31C8.32,15.36 8.36,15.42 8.39,15.5C8.88,16.41 8.54,17.56 7.62,18.05C6.71,18.54 5.56,18.18 5.06,17.24C4.57,16.31 4.91,15.16 5.83,14.67C6.22,14.46 6.65,14.41 7.06,14.5L9.37,10.73C8.9,10.3 8.5,9.76 8.25,9.14Z" /></svg>\n  Webhook\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-webhook-webhook" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Sends notifications to external services based on selected events, following the Standard Webhooks specification.</p>\n\n  \n    \n      <div>\n        <span class="format-item">Webhook URL <span>https://example.com/webhooks</span></span>\n      </div>\n    \n  \n\n\n                  \n                </td>\n                <td class="bottom-button">\n                  <form method="post" action="/addon/195/" class="inlineform">\n                    <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                    <input type="hidden" name="delete" value="weblate.webhook.webhook" />\n                    <button type="submit" class="btn btn-danger">Uninstall</button>\n                  </form>\n                  <a class="btn btn-primary" href=".../addon/195/logs/">View Logs</a>\n                  \n                    <a class="btn btn-primary" href="/addon/195/">Configure</a>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n                  \n                    \n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10.46,19C9,21.07 6.15,21.59 4.09,20.15C2.04,18.71 1.56,15.84 3,13.75C3.87,12.5 5.21,11.83 6.58,11.77L6.63,13.2C5.72,13.27 4.84,13.74 4.27,14.56C3.27,16 3.58,17.94 4.95,18.91C6.33,19.87 8.26,19.5 9.26,18.07C9.57,17.62 9.75,17.13 9.82,16.63V15.62L15.4,15.58L15.47,15.47C16,14.55 17.15,14.23 18.05,14.75C18.95,15.27 19.26,16.43 18.73,17.35C18.2,18.26 17.04,18.58 16.14,18.06C15.73,17.83 15.44,17.46 15.31,17.04L11.24,17.06C11.13,17.73 10.87,18.38 10.46,19M17.74,11.86C20.27,12.17 22.07,14.44 21.76,16.93C21.45,19.43 19.15,21.2 16.62,20.89C15.13,20.71 13.9,19.86 13.19,18.68L14.43,17.96C14.92,18.73 15.75,19.28 16.75,19.41C18.5,19.62 20.05,18.43 20.26,16.76C20.47,15.09 19.23,13.56 17.5,13.35C16.96,13.29 16.44,13.36 15.97,13.53L15.12,13.97L12.54,9.2H12.32C11.26,9.16 10.44,8.29 10.47,7.25C10.5,6.21 11.4,5.4 12.45,5.44C13.5,5.5 14.33,6.35 14.3,7.39C14.28,7.83 14.11,8.23 13.84,8.54L15.74,12.05C16.36,11.85 17.04,11.78 17.74,11.86M8.25,9.14C7.25,6.79 8.31,4.1 10.62,3.12C12.94,2.14 15.62,3.25 16.62,5.6C17.21,6.97 17.09,8.47 16.42,9.67L15.18,8.95C15.6,8.14 15.67,7.15 15.27,6.22C14.59,4.62 12.78,3.85 11.23,4.5C9.67,5.16 8.97,7 9.65,8.6C9.93,9.26 10.4,9.77 10.97,10.11L11.36,10.32L8.29,15.31C8.32,15.36 8.36,15.42 8.39,15.5C8.88,16.41 8.54,17.56 7.62,18.05C6.71,18.54 5.56,18.18 5.06,17.24C4.57,16.31 4.91,15.16 5.83,14.67C6.22,14.46 6.65,14.41 7.06,14.5L9.37,10.73C8.9,10.3 8.5,9.76 8.25,9.14Z" /></svg>\n  Webhook\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-webhook-webhook" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Sends notifications to external services based on selected events, following the Standard Webhooks specification.</p>\n\n  \n    \n      <div>\n        <span class="format-item">Webhook URL <span>http:.../localhost/hook</span></span><span class="format-item">Change events <span>Translation added</span></span>\n      </div>\n    \n  \n\n\n                  \n                </td>\n                <td class="bottom-button">\n                  <form method="post" action="/addon/196/" class="inlineform">\n                    <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                    <input type="hidden" name="delete" value="weblate.webhook.webhook" />\n                    <button type="submit" class="btn btn-danger">Uninstall</button>\n                  </form>\n                  <a class="btn btn-primary" href=".../addon/196/logs/">View Logs</a>\n                  \n                    <a class="btn btn-primary" href="/addon/196/">Configure</a>\n                  \n                </td>\n              </tr>\n            \n          </tbody>\n        </table>\n        <div class="card-footer">\n          \n          \n            <a href="/addons/test/"\n               class="btn btn-primary">\n              Manage project-wide add-ons (0 installed)\n            </a>\n          \n          \n          \n            \n            <a href="/manage/addons/"\n               class="btn btn-primary"\n               >\n              Manage site-wide add-ons (0 installed)\n            </a>\n          \n        </div>\n      </div>\n\n      <div class="card">\n        <div class="card-header">\n          <h4 class="card-title">\n            <a class="float-end doc-link" href="https://docs.weblate..../latest/admin/addons.html" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n            Available add-ons\n          </h4>\n        </div>\n        <table class="table table-striped">\n          <tbody>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m12.87 15.07-2.54-2.51 0.03-0.03c1.74-1.94 2.98-4.17 3.71-6.53h2.93v-2h-7v-2h-2v2h-7v2h11.17c-0.67 1.92-1.73 3.75-3.17 5.35-0.93-1.03-1.7-2.16-2.31-3.35h-2c0.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02 1.42 1.42 5-5 3.11 3.11 0.76-2.04m5.63-5.07h-2l-4.5 12h2l1.12-3h4.75l1.13 3h2l-4.5-12m-2.62 7 1.62-4.33 1.62 4.33h-3.24z"/></svg>\n  Automatic translation\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-autotranslate-autotranslate" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Automatically translates strings using machine translation or other components.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.autotranslate.autotranslate" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.autotranslate.autotranslate">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n    <span class="badge float-end text-bg-secondary"\n          title="This add-on is used for all components sharing this repository.">repository wide</span>\n  \n  <svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m9.5 3a6.5 6.5 0 0 1 6.5 6.5c0 1.61-0.59 3.09-1.56 4.23l0.27 0.27h0.79l5 5-1.5 1.5-5-5v-0.79l-0.27-0.27c-1.14 0.97-2.62 1.56-4.23 1.56a6.5 6.5 0 0 1-6.5-6.5 6.5 6.5 0 0 1 6.5-6.5m0 2c-2.5 0-4.5 2-4.5 4.5s2 4.5 4.5 4.5 4.5-2 4.5-4.5-2-4.5-4.5-4.5z"/></svg>\n  Component discovery\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-discovery-discovery" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Automatically adds or removes project components based on file changes in the version control system.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.discovery.discovery" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.discovery.discovery">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m12 15.5a3.5 3.5 0 0 1-3.5-3.5 3.5 3.5 0 0 1 3.5-3.5 3.5 3.5 0 0 1 3.5 3.5 3.5 3.5 0 0 1-3.5 3.5m7.43-2.53c0.04-0.32 0.07-0.64 0.07-0.97s-0.03-0.66-0.07-1l2.11-1.63c0.19-0.15 0.24-0.42 0.12-0.64l-2-3.46c-0.12-0.22-0.39-0.31-0.61-0.22l-2.49 1c-0.52-0.39-1.06-0.73-1.69-0.98l-0.37-2.65c-0.04-0.24-0.25-0.42-0.5-0.42h-4c-0.25 0-0.46 0.18-0.5 0.42l-0.37 2.65c-0.63 0.25-1.17 0.59-1.69 0.98l-2.49-1c-0.22-0.09-0.49 0-0.61 0.22l-2 3.46c-0.13 0.22-0.07 0.49 0.12 0.64l2.11 1.63c-0.04 0.34-0.07 0.67-0.07 1s0.03 0.65 0.07 0.97l-2.11 1.66c-0.19 0.15-0.25 0.42-0.12 0.64l2 3.46c0.12 0.22 0.39 0.3 0.61 0.22l2.49-1.01c0.52 0.4 1.06 0.74 1.69 0.99l0.37 2.65c0.04 0.24 0.25 0.42 0.5 0.42h4c0.25 0 0.46-0.18 0.5-0.42l0.37-2.65c0.63-0.26 1.17-0.59 1.69-0.99l2.49 1.01c0.22 0.08 0.49 0 0.61-0.22l2-3.46c0.12-0.22 0.07-0.49-0.12-0.64l-2.11-1.66z"/></svg>\n  Bulk edit\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-flags-bulk" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Bulk edit flags, labels, or states of strings.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.flags.bulk" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.flags.bulk">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M14.4,6L14,4H5V21H7V14H12.6L13,16H20V6H14.4Z"/></svg>\n  Flag updated translations from repository as &quot;Needs rewriting&quot;\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-flags-target-repo-update" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Whenever a string translation is changed from the VCS, it is flagged as needing rewriting in Weblate. Especially useful if translation files are often updated manually or by an external service.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.flags.target_repo_update" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.flags.target_repo_update">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m12.87 15.07-2.54-2.51 0.03-0.03c1.74-1.94 2.98-4.17 3.71-6.53h2.93v-2h-7v-2h-2v2h-7v2h11.17c-0.67 1.92-1.73 3.75-3.17 5.35-0.93-1.03-1.7-2.16-2.31-3.35h-2c0.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02 1.42 1.42 5-5 3.11 3.11 0.76-2.04m5.63-5.07h-2l-4.5 12h2l1.12-3h4.75l1.13 3h2l-4.5-12m-2.62 7 1.62-4.33 1.62 4.33h-3.24z"/></svg>\n  Fill read-only strings with source\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-generate-fill-read-only" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Fills in translation of read-only strings with source string.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.generate.fill_read_only" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.generate.fill_read_only">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m3 22v-14h4v14h-4m7 0v-20h4v20h-4m7 0v-8h4v8h-4z"/></svg>\n  Statistics generator\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-generate-generate" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Generates a file containing detailed info about the translation status.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.generate.generate" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.generate.generate">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m12.87 15.07-2.54-2.51 0.03-0.03c1.74-1.94 2.98-4.17 3.71-6.53h2.93v-2h-7v-2h-2v2h-7v2h11.17c-0.67 1.92-1.73 3.75-3.17 5.35-0.93-1.03-1.7-2.16-2.31-3.35h-2c0.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02 1.42 1.42 5-5 3.11 3.11 0.76-2.04m5.63-5.07h-2l-4.5 12h2l1.12-3h4.75l1.13 3h2l-4.5-12m-2.62 7 1.62-4.33 1.62 4.33h-3.24z"/></svg>\n  Prefill translation with source\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-generate-prefill" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Fills in translation strings with source string.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.generate.prefill" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.generate.prefill">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m12.87 15.07-2.54-2.51 0.03-0.03c1.74-1.94 2.98-4.17 3.71-6.53h2.93v-2h-7v-2h-2v2h-7v2h11.17c-0.67 1.92-1.73 3.75-3.17 5.35-0.93-1.03-1.7-2.16-2.31-3.35h-2c0.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02 1.42 1.42 5-5 3.11 3.11 0.76-2.04m5.63-5.07h-2l-4.5 12h2l1.12-3h4.75l1.13 3h2l-4.5-12m-2.62 7 1.62-4.33 1.62 4.33h-3.24z"/></svg>\n  Pseudolocale generation\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-generate-pseudolocale" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Generates a translation by adding prefix and suffix to source strings automatically.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.generate.pseudolocale" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.generate.pseudolocale">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m12 15.5a3.5 3.5 0 0 1-3.5-3.5 3.5 3.5 0 0 1 3.5-3.5 3.5 3.5 0 0 1 3.5 3.5 3.5 3.5 0 0 1-3.5 3.5m7.43-2.53c0.04-0.32 0.07-0.64 0.07-0.97s-0.03-0.66-0.07-1l2.11-1.63c0.19-0.15 0.24-0.42 0.12-0.64l-2-3.46c-0.12-0.22-0.39-0.31-0.61-0.22l-2.49 1c-0.52-0.39-1.06-0.73-1.69-0.98l-0.37-2.65c-0.04-0.24-0.25-0.42-0.5-0.42h-4c-0.25 0-0.46 0.18-0.5 0.42l-0.37 2.65c-0.63 0.25-1.17 0.59-1.69 0.98l-2.49-1c-0.22-0.09-0.49 0-0.61 0.22l-2 3.46c-0.13 0.22-0.07 0.49 0.12 0.64l2.11 1.63c-0.04 0.34-0.07 0.67-0.07 1s0.03 0.65 0.07 0.97l-2.11 1.66c-0.19 0.15-0.25 0.42-0.12 0.64l2 3.46c0.12 0.22 0.39 0.3 0.61 0.22l2.49-1.01c0.52 0.4 1.06 0.74 1.69 0.99l0.37 2.65c0.04 0.24 0.25 0.42 0.5 0.42h4c0.25 0 0.46-0.18 0.5-0.42l0.37-2.65c0.63-0.26 1.17-0.59 1.69-0.99l2.49 1.01c0.22 0.08 0.49 0 0.61-0.22l2-3.46c0.12-0.22 0.07-0.49-0.12-0.64l-2.11-1.66z"/></svg>\n  Contributors in comment\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-gettext-authors" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Updates the comment part of the PO file header to include contributor names and years of contributions.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.gettext.authors" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.gettext.authors">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m12 15.5a3.5 3.5 0 0 1-3.5-3.5 3.5 3.5 0 0 1 3.5-3.5 3.5 3.5 0 0 1 3.5 3.5 3.5 3.5 0 0 1-3.5 3.5m7.43-2.53c0.04-0.32 0.07-0.64 0.07-0.97s-0.03-0.66-0.07-1l2.11-1.63c0.19-0.15 0.24-0.42 0.12-0.64l-2-3.46c-0.12-0.22-0.39-0.31-0.61-0.22l-2.49 1c-0.52-0.39-1.06-0.73-1.69-0.98l-0.37-2.65c-0.04-0.24-0.25-0.42-0.5-0.42h-4c-0.25 0-0.46 0.18-0.5 0.42l-0.37 2.65c-0.63 0.25-1.17 0.59-1.69 0.98l-2.49-1c-0.22-0.09-0.49 0-0.61 0.22l-2 3.46c-0.13 0.22-0.07 0.49 0.12 0.64l2.11 1.63c-0.04 0.34-0.07 0.67-0.07 1s0.03 0.65 0.07 0.97l-2.11 1.66c-0.19 0.15-0.25 0.42-0.12 0.64l2 3.46c0.12 0.22 0.39 0.3 0.61 0.22l2.49-1.01c0.52 0.4 1.06 0.74 1.69 0.99l0.37 2.65c0.04 0.24 0.25 0.42 0.5 0.42h4c0.25 0 0.46-0.18 0.5-0.42l0.37-2.65c0.63-0.26 1.17-0.59 1.69-0.99l2.49 1.01c0.22 0.08 0.49 0 0.61-0.22l2-3.46c0.12-0.22 0.07-0.49-0.12-0.64l-2.11-1.66z"/></svg>\n  Update ALL_LINGUAS variable in the &quot;configure&quot; file\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-gettext-configure" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Updates the ALL_LINGUAS variable in &quot;configure&quot;, &quot;configure.in&quot; or &quot;configure.ac&quot; files, when a new translation is added.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.gettext.configure" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.gettext.configure">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m12 15.5a3.5 3.5 0 0 1-3.5-3.5 3.5 3.5 0 0 1 3.5-3.5 3.5 3.5 0 0 1 3.5 3.5 3.5 3.5 0 0 1-3.5 3.5m7.43-2.53c0.04-0.32 0.07-0.64 0.07-0.97s-0.03-0.66-0.07-1l2.11-1.63c0.19-0.15 0.24-0.42 0.12-0.64l-2-3.46c-0.12-0.22-0.39-0.31-0.61-0.22l-2.49 1c-0.52-0.39-1.06-0.73-1.69-0.98l-0.37-2.65c-0.04-0.24-0.25-0.42-0.5-0.42h-4c-0.25 0-0.46 0.18-0.5 0.42l-0.37 2.65c-0.63 0.25-1.17 0.59-1.69 0.98l-2.49-1c-0.22-0.09-0.49 0-0.61 0.22l-2 3.46c-0.13 0.22-0.07 0.49 0.12 0.64l2.11 1.63c-0.04 0.34-0.07 0.67-0.07 1s0.03 0.65 0.07 0.97l-2.11 1.66c-0.19 0.15-0.25 0.42-0.12 0.64l2 3.46c0.12 0.22 0.39 0.3 0.61 0.22l2.49-1.01c0.52 0.4 1.06 0.74 1.69 0.99l0.37 2.65c0.04 0.24 0.25 0.42 0.5 0.42h4c0.25 0 0.46-0.18 0.5-0.42l0.37-2.65c0.63-0.26 1.17-0.59 1.69-0.99l2.49 1.01c0.22 0.08 0.49 0 0.61-0.22l2-3.46c0.12-0.22 0.07-0.49-0.12-0.64l-2.11-1.66z"/></svg>\n  Update LINGUAS file\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-gettext-linguas" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Updates the LINGUAS file when a new translation is added.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.gettext.linguas" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.gettext.linguas">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m12 15.5a3.5 3.5 0 0 1-3.5-3.5 3.5 3.5 0 0 1 3.5-3.5 3.5 3.5 0 0 1 3.5 3.5 3.5 3.5 0 0 1-3.5 3.5m7.43-2.53c0.04-0.32 0.07-0.64 0.07-0.97s-0.03-0.66-0.07-1l2.11-1.63c0.19-0.15 0.24-0.42 0.12-0.64l-2-3.46c-0.12-0.22-0.39-0.31-0.61-0.22l-2.49 1c-0.52-0.39-1.06-0.73-1.69-0.98l-0.37-2.65c-0.04-0.24-0.25-0.42-0.5-0.42h-4c-0.25 0-0.46 0.18-0.5 0.42l-0.37 2.65c-0.63 0.25-1.17 0.59-1.69 0.98l-2.49-1c-0.22-0.09-0.49 0-0.61 0.22l-2 3.46c-0.13 0.22-0.07 0.49 0.12 0.64l2.11 1.63c-0.04 0.34-0.07 0.67-0.07 1s0.03 0.65 0.07 0.97l-2.11 1.66c-0.19 0.15-0.25 0.42-0.12 0.64l2 3.46c0.12 0.22 0.39 0.3 0.61 0.22l2.49-1.01c0.52 0.4 1.06 0.74 1.69 0.99l0.37 2.65c0.04 0.24 0.25 0.42 0.5 0.42h4c0.25 0 0.46-0.18 0.5-0.42l0.37-2.65c0.63-0.26 1.17-0.59 1.69-0.99l2.49 1.01c0.22 0.08 0.49 0 0.61-0.22l2-3.46c0.12-0.22 0.07-0.49-0.12-0.64l-2.11-1.66z"/></svg>\n  Generate MO files\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-gettext-mo" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Automatically generates a MO file for every changed PO file.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.gettext.mo" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.gettext.mo">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m12 15.5a3.5 3.5 0 0 1-3.5-3.5 3.5 3.5 0 0 1 3.5-3.5 3.5 3.5 0 0 1 3.5 3.5 3.5 3.5 0 0 1-3.5 3.5m7.43-2.53c0.04-0.32 0.07-0.64 0.07-0.97s-0.03-0.66-0.07-1l2.11-1.63c0.19-0.15 0.24-0.42 0.12-0.64l-2-3.46c-0.12-0.22-0.39-0.31-0.61-0.22l-2.49 1c-0.52-0.39-1.06-0.73-1.69-0.98l-0.37-2.65c-0.04-0.24-0.25-0.42-0.5-0.42h-4c-0.25 0-0.46 0.18-0.5 0.42l-0.37 2.65c-0.63 0.25-1.17 0.59-1.69 0.98l-2.49-1c-0.22-0.09-0.49 0-0.61 0.22l-2 3.46c-0.13 0.22-0.07 0.49 0.12 0.64l2.11 1.63c-0.04 0.34-0.07 0.67-0.07 1s0.03 0.65 0.07 0.97l-2.11 1.66c-0.19 0.15-0.25 0.42-0.12 0.64l2 3.46c0.12 0.22 0.39 0.3 0.61 0.22l2.49-1.01c0.52 0.4 1.06 0.74 1.69 0.99l0.37 2.65c0.04 0.24 0.25 0.42 0.5 0.42h4c0.25 0 0.46-0.18 0.5-0.42l0.37-2.65c0.63-0.26 1.17-0.59 1.69-0.99l2.49 1.01c0.22 0.08 0.49 0 0.61-0.22l2-3.46c0.12-0.22 0.07-0.49-0.12-0.64l-2.11-1.66z"/></svg>\n  Update PO files to match POT (msgmerge)\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-gettext-msgmerge" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Updates all PO files (as configured by &quot;File mask&quot;) to match the POT file (as configured by &quot;Template for new translations&quot;) using msgmerge.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.gettext.msgmerge" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.gettext.msgmerge">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n    <span class="badge float-end text-bg-secondary"\n          title="This add-on is used for all components sharing this repository.">repository wide</span>\n  \n  <svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M16.59,5.41L15.17,4L12,7.17L8.83,4L7.41,5.41L12,10M7.41,18.59L8.83,20L12,16.83L15.17,20L16.58,18.59L12,14L7.41,18.59Z"/></svg>\n  Squash Git commits\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-git-squash" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Squash Git commits prior to pushing changes.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.git.squash" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.git.squash">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z"/></svg>\n  Stale comment removal\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-removal-comments" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Set a timeframe for removal of comments.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.removal.comments" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.removal.comments">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z"/></svg>\n  Stale suggestion removal\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-removal-suggestions" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Set a timeframe for removal of suggestions.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.removal.suggestions" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.removal.suggestions">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n  <svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6,15A2,2 0 0,1 4,17A2,2 0 0,1 2,15A2,2 0 0,1 4,13H6V15M7,15A2,2 0 0,1 9,13A2,2 0 0,1 11,15V20A2,2 0 0,1 9,22A2,2 0 0,1 7,20V15M9,7A2,2 0 0,1 7,5A2,2 0 0,1 9,3A2,2 0 0,1 11,5V7H9M9,8A2,2 0 0,1 11,10A2,2 0 0,1 9,12H4A2,2 0 0,1 2,10A2,2 0 0,1 4,8H9M17,10A2,2 0 0,1 19,8A2,2 0 0,1 21,10A2,2 0 0,1 19,12H17V10M16,10A2,2 0 0,1 14,12A2,2 0 0,1 12,10V5A2,2 0 0,1 14,3A2,2 0 0,1 16,5V10M14,18A2,2 0 0,1 16,20A2,2 0 0,1 14,22A2,2 0 0,1 12,20V18H14M14,17A2,2 0 0,1 12,15A2,2 0 0,1 14,13H19A2,2 0 0,1 21,15A2,2 0 0,1 19,17H14Z" /></svg>\n  Slack Webhooks\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-webhook-slack" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Sends notification to a Slack channel based on selected events.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.webhook.slack" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.webhook.slack">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n              <tr>\n                <td>\n\n<h4>\n  \n  <svg width="24" height="24" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10.46,19C9,21.07 6.15,21.59 4.09,20.15C2.04,18.71 1.56,15.84 3,13.75C3.87,12.5 5.21,11.83 6.58,11.77L6.63,13.2C5.72,13.27 4.84,13.74 4.27,14.56C3.27,16 3.58,17.94 4.95,18.91C6.33,19.87 8.26,19.5 9.26,18.07C9.57,17.62 9.75,17.13 9.82,16.63V15.62L15.4,15.58L15.47,15.47C16,14.55 17.15,14.23 18.05,14.75C18.95,15.27 19.26,16.43 18.73,17.35C18.2,18.26 17.04,18.58 16.14,18.06C15.73,17.83 15.44,17.46 15.31,17.04L11.24,17.06C11.13,17.73 10.87,18.38 10.46,19M17.74,11.86C20.27,12.17 22.07,14.44 21.76,16.93C21.45,19.43 19.15,21.2 16.62,20.89C15.13,20.71 13.9,19.86 13.19,18.68L14.43,17.96C14.92,18.73 15.75,19.28 16.75,19.41C18.5,19.62 20.05,18.43 20.26,16.76C20.47,15.09 19.23,13.56 17.5,13.35C16.96,13.29 16.44,13.36 15.97,13.53L15.12,13.97L12.54,9.2H12.32C11.26,9.16 10.44,8.29 10.47,7.25C10.5,6.21 11.4,5.4 12.45,5.44C13.5,5.5 14.33,6.35 14.3,7.39C14.28,7.83 14.11,8.23 13.84,8.54L15.74,12.05C16.36,11.85 17.04,11.78 17.74,11.86M8.25,9.14C7.25,6.79 8.31,4.1 10.62,3.12C12.94,2.14 15.62,3.25 16.62,5.6C17.21,6.97 17.09,8.47 16.42,9.67L15.18,8.95C15.6,8.14 15.67,7.15 15.27,6.22C14.59,4.62 12.78,3.85 11.23,4.5C9.67,5.16 8.97,7 9.65,8.6C9.93,9.26 10.4,9.77 10.97,10.11L11.36,10.32L8.29,15.31C8.32,15.36 8.36,15.42 8.39,15.5C8.88,16.41 8.54,17.56 7.62,18.05C6.71,18.54 5.56,18.18 5.06,17.24C4.57,16.31 4.91,15.16 5.83,14.67C6.22,14.46 6.65,14.41 7.06,14.5L9.37,10.73C8.9,10.3 8.5,9.76 8.25,9.14Z" /></svg>\n  Webhook\n  <a class=" doc-link" href="https://docs.weblate..../latest/admin/addons.html#addon-weblate-webhook-webhook" title="Documentation" target="_blank" rel="noopener" tabindex="-1"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" version="1.1" viewBox="0 0 14 14"><path fill="#bfc3c7" d="m7 14c-3.92 0-7-3.08-7-7s3.08-7 7-7 7 3.08 7 7-3.08 7-7 7zm0-2c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm1-7h-2v-2h2zm0 6h-2v-5h2z"/></svg></a>\n</h4>\n<p>Sends notifications to external services based on selected events, following the Standard Webhooks specification.</p>\n\n</td>\n                <td class="bottom-button">\n                  \n                    <form method="post" class="inlineform">\n                      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n                      <input type="hidden" name="name" value="weblate.webhook.webhook" />\n                      <button type="submit" class="btn btn-primary" data-addon="weblate.webhook.webhook">Install</button>\n                    </form>\n                  \n                </td>\n              </tr>\n            \n          </tbody>\n        </table>\n        <div class="card-footer">\n          \n            Some add-ons will ask for additional configuration during installation.\n          \n        </div>\n      </div>\n    </div>\n\n    <div class="tab-pane" id="history">\n      \n\n<table id="changes-table" class="table table-autowidth container-fluid">\n  <tbody id="changes-list">\n    \n      <tr id="changes-item"\n          class="history-row row"\n          >\n        <td class="history-event col-md-3">\n          <strong class="ms-2"><a href="/user/testuser/" title="Weblate Test" class="user-link"><span><img src="....../avatar/32/testuser.png" class="avatar w32" loading="lazy" alt="User avatar" /> testuser</span></a></strong>\n          <p class="text-muted">Add-on installed</p>\n          <ul class="breadcrumb">\n            \n              <li class="breadcrumb-item"><a href="/projects/test/">Test</a></li>\n<li class="breadcrumb-item"><a href=".............../projects/test/test/">Test</a></li>\n            \n            \n          </ul>\n        </td>\n        <td class="history-data col-md-9">\n          \n            <div class="btn-float">\n              \n              \n              \n              <a class="btn btn-link"\n                 href=".............../projects/test/test/"\n                 title="View details"><svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m15.5 14 5 5-1.5 1.5-5-5v-0.79l-0.27-0.28c-1.14 0.98-2.62 1.57-4.23 1.57a6.5 6.5 0 0 1-6.5-6.5 6.5 6.5 0 0 1 6.5-6.5 6.5 6.5 0 0 1 6.5 6.5c0 1.61-0.59 3.09-1.57 4.23l0.28 0.27h0.79m-6 0c2.5 0 4.5-2 4.5-4.5s-2-4.5-4.5-4.5-4.5 2-4.5 4.5 2 4.5 4.5 4.5m2.5-4h-2v2h-1v-2h-2v-1h2v-2h1v2h2v1z"/></svg></a>\n            </div>\n          \n          <div class="comment-content">\n            weblate.webhook.webhook\n            \n            <span class="float-end text-muted"><span title="04/07/2026 10:23 a.m." data-datetime="2026-04-07T10:23:31+00:00" class="naturaltime">04/07/2026</span></span>\n            <div class="clearfix" ></div>\n          </div>\n          \n        </td>\n      </tr>\n    \n      <tr id="changes-item"\n          class="history-row row"\n          >\n        <td class="history-event col-md-3">\n          <strong class="ms-2"><a href="/user/testuser/" title="Weblate Test" class="user-link"><span><img src="....../avatar/32/testuser.png" class="avatar w32" loading="lazy" alt="User avatar" /> testuser</span></a></strong>\n          <p class="text-muted">Add-on installed</p>\n          <ul class="breadcrumb">\n            \n              <li class="breadcrumb-item"><a href="/projects/test/">Test</a></li>\n<li class="breadcrumb-item"><a href=".............../projects/test/test/">Test</a></li>\n            \n            \n          </ul>\n        </td>\n        <td class="history-data col-md-9">\n          \n            <div class="btn-float">\n              \n              \n              \n              <a class="btn btn-link"\n                 href=".............../projects/test/test/"\n                 title="View details"><svg width="24" height="24" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m15.5 14 5 5-1.5 1.5-5-5v-0.79l-0.27-0.28c-1.14 0.98-2.62 1.57-4.23 1.57a6.5 6.5 0 0 1-6.5-6.5 6.5 6.5 0 0 1 6.5-6.5 6.5 6.5 0 0 1 6.5 6.5c0 1.61-0.59 3.09-1.57 4.23l0.28 0.27h0.79m-6 0c2.5 0 4.5-2 4.5-4.5s-2-4.5-4.5-4.5-4.5 2-4.5 4.5 2 4.5 4.5 4.5m2.5-4h-2v2h-1v-2h-2v-1h2v-2h1v2h2v1z"/></svg></a>\n            </div>\n          \n          <div class="comment-content">\n            weblate.webhook.webhook\n            \n            <span class="float-end text-muted"><span title="04/07/2026 10:23 a.m." data-datetime="2026-04-07T10:23:31+00:00" class="naturaltime">04/07/2026</span></span>\n            <div class="clearfix" ></div>\n          </div>\n          \n        </td>\n      </tr>\n    \n  </tbody>\n</table>\n\n      <a class="btn btn-primary"\n         href=".../browse/test/test/?action=60&amp;action=61&amp;action=62">Browse all add-on changes</a>\n    </div>\n\n  </div>\n\n\n    </div>\n    <form id="link-post" method="post">\n      <input type="hidden" name="csrfmiddlewaretoken" value="BFqJYGqe8QYR7fcjhZ2Iucv7MEp7PTcaMtB7ZDNQrLri9rOkjm7sIn6S3T1nVn5j">\n    </form>\n    <!-- Creates the bootstrap modal where the image will appear -->\n    <div class="modal fade fullmodal"\n         id="imagemodal"\n         tabindex="-1"\n         role="dialog"\n         aria-labelledby="screenshotModal"\n         aria-hidden="true">\n      <div class="modal-dialog">\n        <div class="modal-content">\n          <div class="modal-header">\n            <h4 class="modal-title" id="screenshotModal"></h4>\n            <button type="button"\n                    class="btn-close"\n                    data-bs-dismiss="modal"\n                    aria-label="Close"></button>\n          </div>\n          <div class="modal-body">\n            <img src="" id="imagepreview" class="img-fluid">\n          </div>\n          <div class="modal-footer">\n            <a class="btn btn-warning"\n               id="modalDetailsLink"\n               data-edit-text="Edit screenshot">Screenshot details</a>\n            <button type="button" class="btn btn-primary" data-bs-dismiss="modal">Close</button>\n          </div>\n        </div>\n      </div>\n    </div>\n    \n\n<!-- Modal that shows available keyboard shortcuts  -->\n<div class="modal fade"\n     id="shortcuts-modal"\n     tabindex="-1"\n     role="dialog"\n     aria-labelledby="shortcutsModal">\n  <div class="modal-dialog" role="document">\n    <div class="modal-content">\n      <div class="modal-header">\n        <h5 id="shortcutsModal" class="modal-title">Keyboard shortcuts</h5>\n        <button type="button"\n                class="btn-close float-end"\n                data-bs-dismiss="modal"\n                aria-label="Close"></button>\n      </div>\n      <div class="modal-body" id="shortcuts-table5-container">\n        <table class="table table-striped">\n          <thead class="thead-dark">\n            <tr>\n              <th scope="col" id="t-head">Shortcut</th>\n              <th scope="col" id="t-head">Action</th>\n            </tr>\n          </thead>\n          <tbody>\n            <tr id="shortcut">\n              <td>\n                <kbd>?</kbd>\n              </td>\n              <td>Open available keyboard shortcuts.</td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>Alt</kbd> + <kbd>Home</kbd>\n              </td>\n              <td>Navigate to the first translation in the current search.</td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>Alt</kbd> + <kbd>End</kbd>\n              </td>\n              <td>Navigate to the last translation in the current search.</td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>Alt</kbd> + <kbd>PageUp</kbd> or\n                <br>\n                <kbd>Ctrl</kbd> + <kbd>\xe2\x86\x91</kbd> or\n                <br>\n                <kbd>Alt</kbd> + <kbd>\xe2\x86\x91</kbd> or\n                <br>\n                <kbd>Cmd</kbd> + <kbd>\xe2\x86\x91</kbd> or\n                <br>\n              </td>\n              <td>Navigate to the previous translation in the current search.</td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>Alt</kbd> + <kbd>PageDown</kbd> or\n                <br>\n                <kbd>Ctrl</kbd> + <kbd>\xe2\x86\x93</kbd> or\n                <br>\n                <kbd>Alt</kbd> + <kbd>\xe2\x86\x93</kbd> or\n                <br>\n                <kbd>Cmd</kbd> + <kbd>\xe2\x86\x93</kbd> or\n                <br>\n              </td>\n              <td>Navigate to the next translation in the current search.</td>\n            </tr>\n\n            <tr>\n              <td>\n                <kbd>Ctrl</kbd> + <kbd>Enter</kbd> or\n                <br>\n                <kbd>Cmd</kbd> + <kbd>Enter</kbd>\n              </td>\n              <td>\n                Submit current form; this works the same as pressing Save and continue while editing translation.\n              </td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>Enter</kbd> or\n                <br>\n                <kbd>Cmd</kbd> + <kbd>Shift</kbd> +<kbd>Enter</kbd>\n              </td>\n              <td>Unmark translation as Needing edit and submit it.</td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>Alt</kbd> + <kbd>Enter</kbd> or\n                <br>\n                <kbd>Option</kbd> + <kbd>Enter</kbd>\n              </td>\n              <td>\n                Submit the string as a suggestion; this works the same as pressing Suggest while editing translation.\n              </td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>Ctrl</kbd> + <kbd>E</kbd> or\n                <br>\n                <kbd>Cmd</kbd> + <kbd>E</kbd>\n              </td>\n              <td>Focus on translation editor.</td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>Ctrl</kbd> + <kbd>U</kbd> or\n                <br>\n                <kbd>Cmd</kbd> + <kbd>U</kbd>\n              </td>\n              <td>Focus on comment editor.</td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>Ctrl</kbd> + <kbd>M</kbd> or\n                <br>\n                <kbd>Cmd</kbd> + <kbd>M</kbd>\n              </td>\n              <td>Shows Automatic suggestions tab.</td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>Ctrl</kbd> + <kbd>1</kbd> to\n                <kbd>Ctrl</kbd> + <kbd>9</kbd> or\n                <br>\n                <kbd>Cmd</kbd> + <kbd>1</kbd> to\n                <kbd>Cmd</kbd> + <kbd>9</kbd>\n              </td>\n              <td>Copies placeable of a given number from source string.</td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>Ctrl</kbd> + <kbd>M</kbd> followed by\n                <kbd>1</kbd> to <kbd>9</kbd> or\n                <br>\n                <kbd>Cmd</kbd> + <kbd>M</kbd> followed by\n                <kbd>1</kbd> to\n                <kbd>9</kbd>\n              </td>\n              <td>Copy the machine translation of a given number to current translation.</td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>Ctrl</kbd> + <kbd>I</kbd> followed by\n                <kbd>1</kbd> to\n                <kbd>9</kbd> or\n                <br>\n                <kbd>Cmd</kbd> + <kbd>I</kbd> followed by\n                <kbd>1</kbd> to\n                <kbd>9</kbd>\n              </td>\n              <td>Ignore one item in the list of failing checks.</td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>Ctrl</kbd> + <kbd>J</kbd> or\n                <br>\n                <kbd>Cmd</kbd> + <kbd>J</kbd>\n              </td>\n              <td>Shows the Nearby strings tab.</td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>Ctrl</kbd> + <kbd>S</kbd> or\n                <br>\n                <kbd>Cmd</kbd> + <kbd>S</kbd>\n              </td>\n              <td>Focus on search field.</td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>Ctrl</kbd> + <kbd>O</kbd> or\n                <br>\n                <kbd>Cmd</kbd> + <kbd>O</kbd>\n              </td>\n              <td>Copy the source string.</td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>Ctrl</kbd> + <kbd>Y</kbd> or\n                <br>\n                <kbd>Cmd</kbd> + <kbd>Y</kbd>\n              </td>\n              <td>Toggle the Needs editing checkbox.</td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>\xe2\x86\x92</kbd>\n              </td>\n              <td>Browse the next translation string.</td>\n            </tr>\n            <tr>\n              <td>\n                <kbd>\xe2\x86\x90</kbd>\n              </td>\n              <td>Browse the previous translation string.</td>\n            </tr>\n          </tbody>\n        </table>\n      </div>\n      <div class="modal-footer">\n        <button type="button" class="btn btn-primary" data-bs-dismiss="modal">Close</button>\n      </div>\n    </div>\n  </div>\n</div>\n\n    \n\n<footer>\n  <ul>\n    <li>\n      Powered by <a href="https://weblate.org/">Weblate 5.17-dev</a>\n    </li>\n    <li>\n      <a href="/about/" id="footer-about-link">About</a>\n    </li>\n    \n      <li>\n        <a href="/legal/terms/">Terms</a>\n      </li>\n      <li>\n        <a href="/legal/privacy/">Privacy</a>\n      </li>\n    \n    \n    \n      <li>\n        <a href="/contact/">Contact</a>\n      </li>\n    \n    <li>\n      <a href="https://docs.weblate..../en/latest/index.html">Documentation</a>\n    </li>\n    \n      <li>\n        <a href="/donate/">Become a Weblate supporter</a>\n      </li>\n    \n  </ul>\n</footer>\n\n\n\n\n\n  </body>\n</html>\n'

weblate/addons/tests.py:4800: AssertionError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@nijel nijel force-pushed the fetch branch 2 times, most recently from 0deb80e to e2f4e88 Compare April 7, 2026 10:57
@nijel nijel requested a review from Copilot April 7, 2026 10:59

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e2f4e88ef4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

raise MessageNotDeliveredError("; ".join(error.messages)) from error
except requests.exceptions.ConnectionError as error:
raise MessageNotDeliveredError from error
msg = "Unable to deliver webhook: could not connect to the remote server."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Make webhook connection error text translatable

send_message introduces a hard-coded English message ("Unable to deliver webhook: could not connect to the remote server.") that is surfaced to users through add-on activity logs when delivery fails, so non-English instances will always see this error in English. The repository guidance in /workspace/weblate/AGENTS.md explicitly requires user-facing strings to use Django i18n helpers, so this should be wrapped in a translatable string before raising MessageNotDeliveredError.

Useful? React with 👍 / 👎.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread weblate/utils/requests.py Outdated
Comment thread weblate/utils/requests.py Outdated
Comment thread weblate/utils/requests.py Outdated
Comment thread weblate/utils/models.py
Comment thread weblate/utils/requests.py Outdated
This pulls existing external endpoint validation in.
@nijel nijel requested a review from Copilot April 7, 2026 11:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread weblate/addons/webhooks.py
Comment thread weblate/addons/forms.py Outdated
@argos-ci

argos-ci Bot commented Apr 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ⚠️ Changes detected (Review) 20 changed Apr 7, 2026, 6:42 PM

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@nijel nijel enabled auto-merge (squash) April 7, 2026 16:58
@nijel nijel merged commit 9b1908a into WeblateOrg:main Apr 7, 2026
48 of 49 checks passed
@nijel nijel deleted the fetch branch April 7, 2026 19:22
Samuel-k276 pushed a commit to dinis-sales/weblate that referenced this pull request Jun 4, 2026
…#18815)

This pulls existing external endpoint validation in.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants