Repository: WeblateOrg/weblate

Issue:
Unable to add suggestion while the component is locked
### Describe the issue

Unable to add suggestion while the component is locked.

### 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

1. Go to translate page
2. Change the translation
3. Click the <kbd>Suggest</kbd> button
4. No suggestion added

### Expected behavior

A suggestion added after the <kbd>Suggest</kbd> button is clicked.

### Screenshots

_No response_

### Exception traceback

_No response_

### How do you run Weblate?

weblate.org service

### Weblate versions

_No response_

### Weblate deploy checks

_No response_

### Additional context

_No response_


Discussion:

Resolving patch:
diff --git a/weblate/trans/views/edit.py b/weblate/trans/views/edit.py
--- a/weblate/trans/views/edit.py
+++ b/weblate/trans/views/edit.py
@@ -568,9 +568,6 @@ def translate(request, project, component, lang):  # noqa: C901
             messages.error(request, _("Invalid search string!"))
             return redirect(obj)
 
-    # Check locks
-    locked = unit.translation.component.locked
-
     # Some URLs we will most likely use
     base_unit_url = "{}?{}&offset=".format(
         obj.get_translate_url(), search_result["url"]
@@ -585,26 +582,25 @@ def translate(request, project, component, lang):  # noqa: C901
         return redirect(next_unit_url)
     if request.method == "POST" and "merge" not in request.POST:
         if (
-            not locked
-            and "accept" not in request.POST
-            and "accept_edit" not in request.POST
-            and "delete" not in request.POST
-            and "spam" not in request.POST
-            and "upvote" not in request.POST
-            and "downvote" not in request.POST
+            "accept" in request.POST
+            or "accept_edit" in request.POST
+            or "delete" in request.POST
+            or "spam" in request.POST
+            or "upvote" in request.POST
+            or "downvote" in request.POST
         ):
-            # Handle translation
-            response = handle_translate(request, unit, this_unit_url, next_unit_url)
-        elif not locked or "delete" in request.POST or "spam" in request.POST:
             # Handle accepting/deleting suggestions
             response = handle_suggestions(request, unit, this_unit_url, next_unit_url)
+        else:
+            # Handle translation
+            response = handle_translate(request, unit, this_unit_url, next_unit_url)
 
     # Handle translation merging
-    elif "merge" in request.POST and not locked:
+    elif "merge" in request.POST:
         response = handle_merge(unit, request, next_unit_url)
 
     # Handle reverting
-    elif "revert" in request.GET and not locked:
+    elif "revert" in request.GET:
         response = handle_revert(unit, request, this_unit_url)
 
     # Pass possible redirect further
@@ -659,7 +655,7 @@ def translate(request, project, component, lang):  # noqa: C901
             "context_form": ContextForm(instance=unit.source_unit, user=user),
             "search_form": search_result["form"].reset_offset(),
             "secondary": secondary,
-            "locked": locked,
+            "locked": unit.translation.component.locked,
             "glossary": get_glossary_terms(unit),
             "addterm_form": TermForm(unit, user),
             "last_changes": unit.change_set.prefetch().order()[:10].preload("unit"),


Test patch:
diff --git a/weblate/trans/tests/test_edit.py b/weblate/trans/tests/test_edit.py
--- a/weblate/trans/tests/test_edit.py
+++ b/weblate/trans/tests/test_edit.py
@@ -892,7 +892,7 @@ def test_commit_push(self):
     def test_edit_locked(self):
         self.component.locked = True
         self.component.save()
-        response = self.edit_unit("Hello, world!\n", "Nazdar svete!\n")
+        response = self.edit_unit("Hello, world!\n", "Nazdar svete!\n", follow=True)
         # We should get to second message
         self.assertContains(
             response,
diff --git a/weblate/trans/tests/test_views.py b/weblate/trans/tests/test_views.py
--- a/weblate/trans/tests/test_views.py
+++ b/weblate/trans/tests/test_views.py
@@ -144,7 +144,7 @@ def get_request(self, user=None):
     def get_translation(self, language="cs"):
         return self.component.translation_set.get(language__code=language)
 
-    def get_unit(self, source="Hello, world!\n", language="cs"):
+    def get_unit(self, source: str = "Hello, world!\n", language: str = "cs"):
         translation = self.get_translation(language)
         return translation.unit_set.get(source__startswith=source)
 
@@ -153,7 +153,14 @@ def change_unit(self, target, source="Hello, world!\n", language="cs", user=None
         unit.target = target
         unit.save_backend(user or self.user)
 
-    def edit_unit(self, source, target, language="cs", **kwargs):
+    def edit_unit(
+        self,
+        source: str,
+        target: str,
+        language: str = "cs",
+        follow: bool = False,
+        **kwargs,
+    ):
         """Do edit single unit using web interface."""
         unit = self.get_unit(source, language)
         params = {
@@ -165,7 +172,7 @@ def edit_unit(self, source, target, language="cs", **kwargs):
         }
         params.update(kwargs)
         return self.client.post(
-            self.get_translation(language).get_translate_url(), params
+            self.get_translation(language).get_translate_url(), params, follow=follow
         )
 
     def assert_redirects_offset(self, response, exp_path, exp_offset):