Repository: WeblateOrg/weblate

Issue:
Make 404 more useful when possible
### Describe the problem

For example, if you try go to a non-existent language of a component, the page will only suggest to go home or to all projects, while it would be better if it linked to the component, or suggested adding a language that you tried to visit. Example: https://hosted.weblate.org/projects/keepassxc/keepassxc-browser-dev/fil/

![image](https://user-images.githubusercontent.com/39462442/170858920-68e686b2-649b-40ce-8d04-c9f5de9b24fb.png)


### Describe the solution you'd like

Add useful suggestions depending on the context.

### Describe alternatives you've considered

_No response_

### Screenshots

_No response_

### Additional context

https://github.com/WeblateOrg/weblate/blob/1804a951c8ae9199d23099a8ec322134ee5b45bc/weblate/urls.py#L136-L140

https://github.com/WeblateOrg/weblate/blob/329dabf59991ed2ee1b44f331929da41d8031c98/weblate/templates/404.html


Discussion:
There is already a middleware dealing with this:

https://github.com/WeblateOrg/weblate/blob/12e59a7f1e6a381b46f186680fe192f49ad791d7/weblate/middleware.py#L75-L191
This issue seems to be a good fit for newbie contributors. You are welcome to contribute to Weblate! Don't hesitate to ask any questions you would have while implementing this.

You can learn about how to get started in our [contributors documentation](https://docs.weblate.org/en/latest/contributing/index.html).
@nijel Can you please add more context what is expected here?
When you enter a URL to an existing component, but not an existing language, it should redirect to the component and telling user to add that language.

For example, https://hosted.weblate.org/projects/weblate/application/ace/ should redirect to https://hosted.weblate.org/projects/weblate/application/ and tell user that Acehnese translation is currently not existing, but can be added.

Resolving patch:
diff --git a/weblate/middleware.py b/weblate/middleware.py
--- a/weblate/middleware.py
+++ b/weblate/middleware.py
@@ -20,11 +20,14 @@
 from urllib.parse import urlparse
 
 from django.conf import settings
+from django.contrib import messages
 from django.core.exceptions import ValidationError
 from django.core.validators import validate_ipv46_address
 from django.http import Http404, HttpResponsePermanentRedirect
+from django.shortcuts import redirect
 from django.urls import is_valid_path, reverse
 from django.utils.http import escape_leading_slashes
+from django.utils.translation import gettext_lazy as _
 
 from weblate.lang.models import Language
 from weblate.trans.models import Change, Component, Project
@@ -151,6 +154,13 @@ def fixup_component(self, slug, request, project):
         request.user.check_access_component(component)
         return component
 
+    def check_existing_translations(self, slug, project):
+        """Check in existing translations for specific language.
+
+        Return False if language translation not present, else True.
+        """
+        return any(lang.name == slug for lang in project.languages)
+
     def process_exception(self, request, exception):
         if not isinstance(exception, Http404):
             return None
@@ -161,12 +171,13 @@ def process_exception(self, request, exception):
             return None
 
         kwargs = dict(resolver_match.kwargs)
-
+        new_lang = None
         if "lang" in kwargs:
             language = self.fixup_language(kwargs["lang"])
             if language is None:
                 return None
             kwargs["lang"] = language.code
+            new_lang = language.name
 
         if "project" in kwargs:
             project = self.fixup_project(kwargs["project"], request)
@@ -180,6 +191,24 @@ def process_exception(self, request, exception):
                     return None
                 kwargs["component"] = component.slug
 
+                if new_lang:
+                    existing_trans = self.check_existing_translations(new_lang, project)
+                    if not existing_trans:
+                        messages.add_message(
+                            request,
+                            messages.INFO,
+                            _(
+                                f"{new_lang} translation is currently not available,\
+                                but can be added."
+                            ),
+                        )
+                        return redirect(
+                            reverse(
+                                "component",
+                                args=[kwargs["project"], kwargs["component"]],
+                            )
+                        )
+
         if kwargs != resolver_match.kwargs:
             query = request.META["QUERY_STRING"]
             if query:


Test patch:
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
@@ -428,6 +428,16 @@ def test_view_redirect(self):
             status_code=301,
         )
 
+        # Non existing translated language should redirect with an info message
+        self.kw_component["lang"] = "Hindi"
+        response = self.client.get(reverse("translation", kwargs=self.kw_component))
+        self.kw_component.pop("lang")
+        self.assertRedirects(
+            response, reverse("component", kwargs=self.kw_component), status_code=302
+        )
+        messages = [m.message for m in get_messages(response.wsgi_request)]
+        self.assertIn("Hindi translation is currently not available", messages[0])
+
     def test_view_unit(self):
         unit = self.get_unit()
         response = self.client.get(unit.get_absolute_url())