prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Search results presents the locale in the wrong case
  **Summary**
  E.g. https://developer.mozilla.org/en-US/search?q=mdn+contribute+
  See screenshot:
  <img width="932" alt="Screen Shot 2021-02-04 at 10 59 44 AM" src="https://user-images.githubusercontent.com/26739/106919753-6cd80e80-66d8-11eb-97a1-d409dfc2e36b.png">
  
  
  **Additional context**
  
  The Yari site-search is coming. But this might be easy to fix. 
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `kuma/search/views.py`
  Content:
  ```
  1 from urllib.parse import parse_qs, urlencode
  2 
  3 from django.conf import settings
  4 from django.shortcuts import render
  5 from django.urls import reverse_lazy
  6 from django.views.decorators.cache import never_cache
  7 from django.views.decorators.http import require_GET
  8 from django.views.generic import RedirectView
  9 from ratelimit.decorators import ratelimit
  10 
  11 from kuma.api.v1.search import search as search_api
  12 from kuma.core.decorators import shared_cache_control
  13 
  14 
  15 # Since the search endpoint accepts user input (via query parameters) and its
  16 # response is compressed, use rate limiting to mitigate the BREACH attack
  17 # (see http://breachattack.com/). It still needs to allow a user to click
  18 # the filter switches (bug 1426968).
  19 # Alternate: forbid gzip by setting Content-Encoding: identity
  20 @never_cache
  21 @require_GET
  22 @ratelimit(key="user_or_ip", rate="25/m", block=True)
  23 def search(request, *args, **kwargs):
  24     """
  25     The search view.
  26 
  27     --2021-- THIS VIEW IS A HACK! --2021--
  28     This Django view exists to server-side render the search results page.
  29     But we're moving the search result page to Yari and that one will use a XHR
  30     request (to /api/v1/search) from a skeleton page (aka. SPA).
  31     But as a way to get to that, we need to transition from the old to the new.
  32     So, this page uses the Django view in kuma.api.v1.search.search, which
  33     returns a special `JsonResponse` instance whose data we can pluck out
  34     to our needs for this old view.
  35     Once we've fully moved to the Yari (static + XHR to v1 API) site-search,
  36     we can comfortably delete this view.
  37     """
  38     # The underlying v1 API supports searching without a 'q' but the web
  39     # UI doesn't. For example, the search input field requires a value.
  40     # So we match that here too.
  41     if not request.GET.get("q", "").strip():
  42         status = 400
  43         context = {"results": {}}
  44     else:
  45         # TODO consider, if the current locale is *not* en-US, that we force
  46         # it to do a search in both locales.
  47         # This might come in handy for people searching in a locale where
  48         # there's very little results but they'd be happy to get the en-US ones.
  49         response = search_api(request, locale=request.LANGUAGE_CODE, *args, **kwargs)
  50         results = response.data
  51 
  52         error = None
  53         status = response.status_code
  54 
  55         # Determine if there were validation errors
  56         if status == 400:
  57             error = ""
  58             for key, messages in results["errors"].items():
  59                 for message in messages:
  60                     error += f"{key}: {message['message']}\n"
  61         else:
  62             # Have to rearrange the 'results' in a way the old search expects it.
  63             # ...which is as follows:
  64             #  - `count`: integer number of matched documents
  65             #  - `previous`: a URL or empty string
  66             #  - `next`: a URL or empty string
  67             #  - `query`: string
  68             #  - `start`: pagination number
  69             #  - `end`: pagination number
  70             #  - `documents`:
  71             #      - `title`
  72             #      - `locale`
  73             #      - `slug`
  74             #      - `excerpt`: string of safe HTML
  75             next_url = ""
  76             previous_url = ""
  77             page = results["metadata"]["page"]
  78             size = results["metadata"]["size"]
  79             count = results["metadata"]["total"]["value"]
  80             query_string = request.META.get("QUERY_STRING")
  81             query_string_parsed = parse_qs(query_string)
  82             if (page + 1) * size < count:
  83                 query_string_parsed["page"] = f"{page + 1}"
  84                 next_url = f"?{urlencode(query_string_parsed, True)}"
  85             if page > 1:
  86                 if page == 2:
  87                     del query_string_parsed["page"]
  88                 else:
  89                     query_string_parsed["page"] = f"{page - 1}"
  90                 previous_url = f"?{urlencode(query_string_parsed, True)}"
  91 
  92             results = {
  93                 "count": count,
  94                 "next": next_url,
  95                 "previous": previous_url,
  96                 "query": request.GET.get("q"),
  97                 "start": (page - 1) * size + 1,
  98                 "end": page * size,
  99                 "documents": [
  100                     {
  101                         "title": x["title"],
  102                         "slug": x["slug"],
  103                         "locale": x["locale"],
  104                         "summary": x["summary"],
  105                         "excerpt": "<br>".join(x["highlight"].get("body", [])),
  106                     }
  107                     for x in results["documents"]
  108                 ],
  109             }
  110 
  111         context = {"results": {"results": None if error else results, "error": error}}
  112     return render(request, "search/react.html", context, status=status)
  113 
  114 
  115 class SearchRedirectView(RedirectView):
  116     permanent = True
  117 
  118     def get_redirect_url(self, *args, **kwargs):
  119         query_string = self.request.META.get("QUERY_STRING")
  120         url = reverse_lazy("api.v1.search")
  121         qs = parse_qs(query_string)
  122         # If you used `/en-Us/search.json` you can skip the `?locale=`
  123         # because the default locale in `/api/v1/search` is `en-US`.
  124         if self.request.LANGUAGE_CODE.lower() != settings.LANGUAGE_CODE.lower():
  125             qs["locale"] = self.request.LANGUAGE_CODE
  126         if qs:
  127             url += "?" + urlencode(qs, True)
  128         return url
  129 
  130 
  131 @shared_cache_control(s_maxage=60 * 60 * 24 * 7)
  132 def plugin(request):
  133     """Render an OpenSearch Plugin."""
  134     return render(
  135         request,
  136         "search/plugin.html",
  137         {"locale": request.LANGUAGE_CODE},
  138         content_type="application/opensearchdescription+xml",
  139     )
  140
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/kuma/search/views.py b/kuma/search/views.py
  --- a/kuma/search/views.py
  +++ b/kuma/search/views.py
  @@ -89,6 +89,21 @@
                       query_string_parsed["page"] = f"{page - 1}"
                   previous_url = f"?{urlencode(query_string_parsed, True)}"
   
  +            def package_document(document):
  +                # The `results['documents']` will have the `locale` in lowercase.
  +                # That's good for searching but now what we want to display.
  +                # Here in Kuma we can't use the `mdn_url` so to get that right
  +                # we have to manually correct that.
  +                locale, slug = document["mdn_url"][1:].split("/docs/")
  +                data = {
  +                    "title": document["title"],
  +                    "slug": slug,
  +                    "locale": locale,
  +                    "summary": document["summary"],
  +                    "excerpt": "<br>".join(document["highlight"].get("body", [])),
  +                }
  +                return data
  +
               results = {
                   "count": count,
                   "next": next_url,
  @@ -96,16 +111,7 @@
                   "query": request.GET.get("q"),
                   "start": (page - 1) * size + 1,
                   "end": page * size,
  -                "documents": [
  -                    {
  -                        "title": x["title"],
  -                        "slug": x["slug"],
  -                        "locale": x["locale"],
  -                        "summary": x["summary"],
  -                        "excerpt": "<br>".join(x["highlight"].get("body", [])),
  -                    }
  -                    for x in results["documents"]
  -                ],
  +                "documents": [package_document(x) for x in results["documents"]],
               }
   
           context = {"results": {"results": None if error else results, "error": error}}
  
verification_info: {"golden_diff": "diff --git a/kuma/search/views.py b/kuma/search/views.py\n--- a/kuma/search/views.py\n+++ b/kuma/search/views.py\n@@ -89,6 +89,21 @@\n                     query_string_parsed[\"page\"] = f\"{page - 1}\"\n                 previous_url = f\"?{urlencode(query_string_parsed, True)}\"\n \n+            def package_document(document):\n+                # The `results['documents']` will have the `locale` in lowercase.\n+                # That's good for searching but now what we want to display.\n+                # Here in Kuma we can't use the `mdn_url` so to get that right\n+                # we have to manually correct that.\n+                locale, slug = document[\"mdn_url\"][1:].split(\"/docs/\")\n+                data = {\n+                    \"title\": document[\"title\"],\n+                    \"slug\": slug,\n+                    \"locale\": locale,\n+                    \"summary\": document[\"summary\"],\n+                    \"excerpt\": \"<br>\".join(document[\"highlight\"].get(\"body\", [])),\n+                }\n+                return data\n+\n             results = {\n                 \"count\": count,\n                 \"next\": next_url,\n@@ -96,16 +111,7 @@\n                 \"query\": request.GET.get(\"q\"),\n                 \"start\": (page - 1) * size + 1,\n                 \"end\": page * size,\n-                \"documents\": [\n-                    {\n-                        \"title\": x[\"title\"],\n-                        \"slug\": x[\"slug\"],\n-                        \"locale\": x[\"locale\"],\n-                        \"summary\": x[\"summary\"],\n-                        \"excerpt\": \"<br>\".join(x[\"highlight\"].get(\"body\", [])),\n-                    }\n-                    for x in results[\"documents\"]\n-                ],\n+                \"documents\": [package_document(x) for x in results[\"documents\"]],\n             }\n \n         context = {\"results\": {\"results\": None if error else results, \"error\": error}}\n", "issue": "Search results presents the locale in the wrong case\n**Summary**\r\nE.g. https://developer.mozilla.org/en-US/search?q=mdn+contribute+\r\nSee screenshot:\r\n<img width=\"932\" alt=\"Screen Shot 2021-02-04 at 10 59 44 AM\" src=\"https://user-images.githubusercontent.com/26739/106919753-6cd80e80-66d8-11eb-97a1-d409dfc2e36b.png\">\r\n\r\n\r\n**Additional context**\r\n\r\nThe Yari site-search is coming. But this might be easy to fix. \r\n\n", "before_files": [{"content": "from urllib.parse import parse_qs, urlencode\n\nfrom django.conf import settings\nfrom django.shortcuts import render\nfrom django.urls import reverse_lazy\nfrom django.views.decorators.cache import never_cache\nfrom django.views.decorators.http import require_GET\nfrom django.views.generic import RedirectView\nfrom ratelimit.decorators import ratelimit\n\nfrom kuma.api.v1.search import search as search_api\nfrom kuma.core.decorators import shared_cache_control\n\n\n# Since the search endpoint accepts user input (via query parameters) and its\n# response is compressed, use rate limiting to mitigate the BREACH attack\n# (see http://breachattack.com/). It still needs to allow a user to click\n# the filter switches (bug 1426968).\n# Alternate: forbid gzip by setting Content-Encoding: identity\n@never_cache\n@require_GET\n@ratelimit(key=\"user_or_ip\", rate=\"25/m\", block=True)\ndef search(request, *args, **kwargs):\n    \"\"\"\n    The search view.\n\n    --2021-- THIS VIEW IS A HACK! --2021--\n    This Django view exists to server-side render the search results page.\n    But we're moving the search result page to Yari and that one will use a XHR\n    request (to /api/v1/search) from a skeleton page (aka. SPA).\n    But as a way to get to that, we need to transition from the old to the new.\n    So, this page uses the Django view in kuma.api.v1.search.search, which\n    returns a special `JsonResponse` instance whose data we can pluck out\n    to our needs for this old view.\n    Once we've fully moved to the Yari (static + XHR to v1 API) site-search,\n    we can comfortably delete this view.\n    \"\"\"\n    # The underlying v1 API supports searching without a 'q' but the web\n    # UI doesn't. For example, the search input field requires a value.\n    # So we match that here too.\n    if not request.GET.get(\"q\", \"\").strip():\n        status = 400\n        context = {\"results\": {}}\n    else:\n        # TODO consider, if the current locale is *not* en-US, that we force\n        # it to do a search in both locales.\n        # This might come in handy for people searching in a locale where\n        # there's very little results but they'd be happy to get the en-US ones.\n        response = search_api(request, locale=request.LANGUAGE_CODE, *args, **kwargs)\n        results = response.data\n\n        error = None\n        status = response.status_code\n\n        # Determine if there were validation errors\n        if status == 400:\n            error = \"\"\n            for key, messages in results[\"errors\"].items():\n                for message in messages:\n                    error += f\"{key}: {message['message']}\\n\"\n        else:\n            # Have to rearrange the 'results' in a way the old search expects it.\n            # ...which is as follows:\n            #  - `count`: integer number of matched documents\n            #  - `previous`: a URL or empty string\n            #  - `next`: a URL or empty string\n            #  - `query`: string\n            #  - `start`: pagination number\n            #  - `end`: pagination number\n            #  - `documents`:\n            #      - `title`\n            #      - `locale`\n            #      - `slug`\n            #      - `excerpt`: string of safe HTML\n            next_url = \"\"\n            previous_url = \"\"\n            page = results[\"metadata\"][\"page\"]\n            size = results[\"metadata\"][\"size\"]\n            count = results[\"metadata\"][\"total\"][\"value\"]\n            query_string = request.META.get(\"QUERY_STRING\")\n            query_string_parsed = parse_qs(query_string)\n            if (page + 1) * size < count:\n                query_string_parsed[\"page\"] = f\"{page + 1}\"\n                next_url = f\"?{urlencode(query_string_parsed, True)}\"\n            if page > 1:\n                if page == 2:\n                    del query_string_parsed[\"page\"]\n                else:\n                    query_string_parsed[\"page\"] = f\"{page - 1}\"\n                previous_url = f\"?{urlencode(query_string_parsed, True)}\"\n\n            results = {\n                \"count\": count,\n                \"next\": next_url,\n                \"previous\": previous_url,\n                \"query\": request.GET.get(\"q\"),\n                \"start\": (page - 1) * size + 1,\n                \"end\": page * size,\n                \"documents\": [\n                    {\n                        \"title\": x[\"title\"],\n                        \"slug\": x[\"slug\"],\n                        \"locale\": x[\"locale\"],\n                        \"summary\": x[\"summary\"],\n                        \"excerpt\": \"<br>\".join(x[\"highlight\"].get(\"body\", [])),\n                    }\n                    for x in results[\"documents\"]\n                ],\n            }\n\n        context = {\"results\": {\"results\": None if error else results, \"error\": error}}\n    return render(request, \"search/react.html\", context, status=status)\n\n\nclass SearchRedirectView(RedirectView):\n    permanent = True\n\n    def get_redirect_url(self, *args, **kwargs):\n        query_string = self.request.META.get(\"QUERY_STRING\")\n        url = reverse_lazy(\"api.v1.search\")\n        qs = parse_qs(query_string)\n        # If you used `/en-Us/search.json` you can skip the `?locale=`\n        # because the default locale in `/api/v1/search` is `en-US`.\n        if self.request.LANGUAGE_CODE.lower() != settings.LANGUAGE_CODE.lower():\n            qs[\"locale\"] = self.request.LANGUAGE_CODE\n        if qs:\n            url += \"?\" + urlencode(qs, True)\n        return url\n\n\n@shared_cache_control(s_maxage=60 * 60 * 24 * 7)\ndef plugin(request):\n    \"\"\"Render an OpenSearch Plugin.\"\"\"\n    return render(\n        request,\n        \"search/plugin.html\",\n        {\"locale\": request.LANGUAGE_CODE},\n        content_type=\"application/opensearchdescription+xml\",\n    )\n", "path": "kuma/search/views.py"}], "after_files": [{"content": "from urllib.parse import parse_qs, urlencode\n\nfrom django.conf import settings\nfrom django.shortcuts import render\nfrom django.urls import reverse_lazy\nfrom django.views.decorators.cache import never_cache\nfrom django.views.decorators.http import require_GET\nfrom django.views.generic import RedirectView\nfrom ratelimit.decorators import ratelimit\n\nfrom kuma.api.v1.search import search as search_api\nfrom kuma.core.decorators import shared_cache_control\n\n\n# Since the search endpoint accepts user input (via query parameters) and its\n# response is compressed, use rate limiting to mitigate the BREACH attack\n# (see http://breachattack.com/). It still needs to allow a user to click\n# the filter switches (bug 1426968).\n# Alternate: forbid gzip by setting Content-Encoding: identity\n@never_cache\n@require_GET\n@ratelimit(key=\"user_or_ip\", rate=\"25/m\", block=True)\ndef search(request, *args, **kwargs):\n    \"\"\"\n    The search view.\n\n    --2021-- THIS VIEW IS A HACK! --2021--\n    This Django view exists to server-side render the search results page.\n    But we're moving the search result page to Yari and that one will use a XHR\n    request (to /api/v1/search) from a skeleton page (aka. SPA).\n    But as a way to get to that, we need to transition from the old to the new.\n    So, this page uses the Django view in kuma.api.v1.search.search, which\n    returns a special `JsonResponse` instance whose data we can pluck out\n    to our needs for this old view.\n    Once we've fully moved to the Yari (static + XHR to v1 API) site-search,\n    we can comfortably delete this view.\n    \"\"\"\n    # The underlying v1 API supports searching without a 'q' but the web\n    # UI doesn't. For example, the search input field requires a value.\n    # So we match that here too.\n    if not request.GET.get(\"q\", \"\").strip():\n        status = 400\n        context = {\"results\": {}}\n    else:\n        # TODO consider, if the current locale is *not* en-US, that we force\n        # it to do a search in both locales.\n        # This might come in handy for people searching in a locale where\n        # there's very little results but they'd be happy to get the en-US ones.\n        response = search_api(request, locale=request.LANGUAGE_CODE, *args, **kwargs)\n        results = response.data\n\n        error = None\n        status = response.status_code\n\n        # Determine if there were validation errors\n        if status == 400:\n            error = \"\"\n            for key, messages in results[\"errors\"].items():\n                for message in messages:\n                    error += f\"{key}: {message['message']}\\n\"\n        else:\n            # Have to rearrange the 'results' in a way the old search expects it.\n            # ...which is as follows:\n            #  - `count`: integer number of matched documents\n            #  - `previous`: a URL or empty string\n            #  - `next`: a URL or empty string\n            #  - `query`: string\n            #  - `start`: pagination number\n            #  - `end`: pagination number\n            #  - `documents`:\n            #      - `title`\n            #      - `locale`\n            #      - `slug`\n            #      - `excerpt`: string of safe HTML\n            next_url = \"\"\n            previous_url = \"\"\n            page = results[\"metadata\"][\"page\"]\n            size = results[\"metadata\"][\"size\"]\n            count = results[\"metadata\"][\"total\"][\"value\"]\n            query_string = request.META.get(\"QUERY_STRING\")\n            query_string_parsed = parse_qs(query_string)\n            if (page + 1) * size < count:\n                query_string_parsed[\"page\"] = f\"{page + 1}\"\n                next_url = f\"?{urlencode(query_string_parsed, True)}\"\n            if page > 1:\n                if page == 2:\n                    del query_string_parsed[\"page\"]\n                else:\n                    query_string_parsed[\"page\"] = f\"{page - 1}\"\n                previous_url = f\"?{urlencode(query_string_parsed, True)}\"\n\n            def package_document(document):\n                # The `results['documents']` will have the `locale` in lowercase.\n                # That's good for searching but now what we want to display.\n                # Here in Kuma we can't use the `mdn_url` so to get that right\n                # we have to manually correct that.\n                locale, slug = document[\"mdn_url\"][1:].split(\"/docs/\")\n                data = {\n                    \"title\": document[\"title\"],\n                    \"slug\": slug,\n                    \"locale\": locale,\n                    \"summary\": document[\"summary\"],\n                    \"excerpt\": \"<br>\".join(document[\"highlight\"].get(\"body\", [])),\n                }\n                return data\n\n            results = {\n                \"count\": count,\n                \"next\": next_url,\n                \"previous\": previous_url,\n                \"query\": request.GET.get(\"q\"),\n                \"start\": (page - 1) * size + 1,\n                \"end\": page * size,\n                \"documents\": [package_document(x) for x in results[\"documents\"]],\n            }\n\n        context = {\"results\": {\"results\": None if error else results, \"error\": error}}\n    return render(request, \"search/react.html\", context, status=status)\n\n\nclass SearchRedirectView(RedirectView):\n    permanent = True\n\n    def get_redirect_url(self, *args, **kwargs):\n        query_string = self.request.META.get(\"QUERY_STRING\")\n        url = reverse_lazy(\"api.v1.search\")\n        qs = parse_qs(query_string)\n        # If you used `/en-Us/search.json` you can skip the `?locale=`\n        # because the default locale in `/api/v1/search` is `en-US`.\n        if self.request.LANGUAGE_CODE.lower() != settings.LANGUAGE_CODE.lower():\n            qs[\"locale\"] = self.request.LANGUAGE_CODE\n        if qs:\n            url += \"?\" + urlencode(qs, True)\n        return url\n\n\n@shared_cache_control(s_maxage=60 * 60 * 24 * 7)\ndef plugin(request):\n    \"\"\"Render an OpenSearch Plugin.\"\"\"\n    return render(\n        request,\n        \"search/plugin.html\",\n        {\"locale\": request.LANGUAGE_CODE},\n        content_type=\"application/opensearchdescription+xml\",\n    )\n", "path": "kuma/search/views.py"}]}