prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  [regression] Multi-locale search is not searching in all locales
  **Summary**
  http://localhost.org:8000/api/v1/search?q=video&locale=fr&locale=de
  actually searches on `locale == ['de']` and 
  http://localhost.org:8000/api/v1/search?q=video&locale=de&locale=fr actually searches on `locale== ['fr']`.
  
  Originally from here:
  https://github.com/mdn/yari/pull/1473#pullrequestreview-584750752
  
  
  
  --- 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/api/v1/search/forms.py`
  Content:
  ```
  1 from django import forms
  2 from django.conf import settings
  3 from django.utils.datastructures import MultiValueDict
  4 
  5 
  6 class SearchForm(forms.Form):
  7     q = forms.CharField(max_length=settings.ES_Q_MAXLENGTH)
  8     locale = forms.MultipleChoiceField(
  9         required=False,
  10         # The `settings.LANGUAGES` looks like this:
  11         #   [('en-US', 'English (US)'), ...]
  12         # But all locales are stored in lowercase in Elasticsearch, so
  13         # force everything to lowercase.
  14         choices=[(code.lower(), name) for code, name in settings.LANGUAGES],
  15     )
  16 
  17     SORT_CHOICES = ("best", "relevance", "popularity")
  18     sort = forms.ChoiceField(required=False, choices=[(x, x) for x in SORT_CHOICES])
  19 
  20     ARCHIVE_CHOICES = ("exclude", "include", "only")
  21     archive = forms.ChoiceField(
  22         required=False, choices=[(x, x) for x in ARCHIVE_CHOICES]
  23     )
  24 
  25     size = forms.IntegerField(required=True, min_value=1, max_value=100)
  26     page = forms.IntegerField(required=True, min_value=1, max_value=10)
  27 
  28     def __init__(self, data, **kwargs):
  29         initial = kwargs.get("initial", {})
  30         # This makes it possible to supply `initial={some dict}` to the form
  31         # and have its values become part of the default. Normally, in Django,
  32         # the `SomeForm(data, initial={...})` is just used to prepopulate the
  33         # HTML generated form widgets.
  34         # See https://www.peterbe.com/plog/initial-values-bound-django-form-rendered
  35         data = MultiValueDict({**{k: [v] for k, v in initial.items()}, **data})
  36 
  37         # Because the `?locale=en-US&locale=Fr` might come in from the `request.GET`
  38         # we can't edit it there. So instead, we mutate it here in the `data`
  39         if "locale" in data:
  40             # Always force it to lowercase, because that's what the ChoiceField
  41             # is configured to. And the searches should always be in lower case.
  42             # Remember, Django forms will allow this to be a single string
  43             # (e.g. `?locale=Fr`) or a multi-value (`?locale=fr&locale=En-US`).
  44             if isinstance(data["locale"], str):
  45                 data["locale"] = data["locale"].lower()
  46             else:
  47                 data["locale"] = [x.lower() for x in data["locale"]]
  48 
  49         # If, for keys we have an initial value for, it was passed an empty string,
  50         # then swap it for the initial value.
  51         # For example `?q=searching&page=` you probably meant to omit it
  52         # but "allowing" it to be an empty string makes it convenient for the client.
  53         for key, values in data.items():
  54             if key in initial and values == "":
  55                 data[key] = initial[key]
  56 
  57         super().__init__(data, **kwargs)
  58
  ```
  --- 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/api/v1/search/forms.py b/kuma/api/v1/search/forms.py
  --- a/kuma/api/v1/search/forms.py
  +++ b/kuma/api/v1/search/forms.py
  @@ -3,15 +3,26 @@
   from django.utils.datastructures import MultiValueDict
   
   
  +class MultipleChoiceFieldICase(forms.MultipleChoiceField):
  +    """Just like forms.MultipleChoiceField but everything's case insentive.
  +
  +    For simplicity, this field assumes that each choice is a tuple where
  +    the first element is always a string.
  +    """
  +
  +    def valid_value(self, value):
  +        return str(value).lower() in [x[0].lower() for x in self.choices]
  +
  +
   class SearchForm(forms.Form):
       q = forms.CharField(max_length=settings.ES_Q_MAXLENGTH)
  -    locale = forms.MultipleChoiceField(
  +    locale = MultipleChoiceFieldICase(
           required=False,
           # The `settings.LANGUAGES` looks like this:
           #   [('en-US', 'English (US)'), ...]
           # But all locales are stored in lowercase in Elasticsearch, so
           # force everything to lowercase.
  -        choices=[(code.lower(), name) for code, name in settings.LANGUAGES],
  +        choices=[(code, name) for code, name in settings.LANGUAGES],
       )
   
       SORT_CHOICES = ("best", "relevance", "popularity")
  @@ -34,18 +45,6 @@
           # See https://www.peterbe.com/plog/initial-values-bound-django-form-rendered
           data = MultiValueDict({**{k: [v] for k, v in initial.items()}, **data})
   
  -        # Because the `?locale=en-US&locale=Fr` might come in from the `request.GET`
  -        # we can't edit it there. So instead, we mutate it here in the `data`
  -        if "locale" in data:
  -            # Always force it to lowercase, because that's what the ChoiceField
  -            # is configured to. And the searches should always be in lower case.
  -            # Remember, Django forms will allow this to be a single string
  -            # (e.g. `?locale=Fr`) or a multi-value (`?locale=fr&locale=En-US`).
  -            if isinstance(data["locale"], str):
  -                data["locale"] = data["locale"].lower()
  -            else:
  -                data["locale"] = [x.lower() for x in data["locale"]]
  -
           # If, for keys we have an initial value for, it was passed an empty string,
           # then swap it for the initial value.
           # For example `?q=searching&page=` you probably meant to omit it
  
verification_info: {"golden_diff": "diff --git a/kuma/api/v1/search/forms.py b/kuma/api/v1/search/forms.py\n--- a/kuma/api/v1/search/forms.py\n+++ b/kuma/api/v1/search/forms.py\n@@ -3,15 +3,26 @@\n from django.utils.datastructures import MultiValueDict\n \n \n+class MultipleChoiceFieldICase(forms.MultipleChoiceField):\n+    \"\"\"Just like forms.MultipleChoiceField but everything's case insentive.\n+\n+    For simplicity, this field assumes that each choice is a tuple where\n+    the first element is always a string.\n+    \"\"\"\n+\n+    def valid_value(self, value):\n+        return str(value).lower() in [x[0].lower() for x in self.choices]\n+\n+\n class SearchForm(forms.Form):\n     q = forms.CharField(max_length=settings.ES_Q_MAXLENGTH)\n-    locale = forms.MultipleChoiceField(\n+    locale = MultipleChoiceFieldICase(\n         required=False,\n         # The `settings.LANGUAGES` looks like this:\n         #   [('en-US', 'English (US)'), ...]\n         # But all locales are stored in lowercase in Elasticsearch, so\n         # force everything to lowercase.\n-        choices=[(code.lower(), name) for code, name in settings.LANGUAGES],\n+        choices=[(code, name) for code, name in settings.LANGUAGES],\n     )\n \n     SORT_CHOICES = (\"best\", \"relevance\", \"popularity\")\n@@ -34,18 +45,6 @@\n         # See https://www.peterbe.com/plog/initial-values-bound-django-form-rendered\n         data = MultiValueDict({**{k: [v] for k, v in initial.items()}, **data})\n \n-        # Because the `?locale=en-US&locale=Fr` might come in from the `request.GET`\n-        # we can't edit it there. So instead, we mutate it here in the `data`\n-        if \"locale\" in data:\n-            # Always force it to lowercase, because that's what the ChoiceField\n-            # is configured to. And the searches should always be in lower case.\n-            # Remember, Django forms will allow this to be a single string\n-            # (e.g. `?locale=Fr`) or a multi-value (`?locale=fr&locale=En-US`).\n-            if isinstance(data[\"locale\"], str):\n-                data[\"locale\"] = data[\"locale\"].lower()\n-            else:\n-                data[\"locale\"] = [x.lower() for x in data[\"locale\"]]\n-\n         # If, for keys we have an initial value for, it was passed an empty string,\n         # then swap it for the initial value.\n         # For example `?q=searching&page=` you probably meant to omit it\n", "issue": "[regression] Multi-locale search is not searching in all locales\n**Summary**\r\nhttp://localhost.org:8000/api/v1/search?q=video&locale=fr&locale=de\r\nactually searches on `locale == ['de']` and \r\nhttp://localhost.org:8000/api/v1/search?q=video&locale=de&locale=fr actually searches on `locale== ['fr']`.\r\n\r\nOriginally from here:\r\nhttps://github.com/mdn/yari/pull/1473#pullrequestreview-584750752\r\n\r\n\n", "before_files": [{"content": "from django import forms\nfrom django.conf import settings\nfrom django.utils.datastructures import MultiValueDict\n\n\nclass SearchForm(forms.Form):\n    q = forms.CharField(max_length=settings.ES_Q_MAXLENGTH)\n    locale = forms.MultipleChoiceField(\n        required=False,\n        # The `settings.LANGUAGES` looks like this:\n        #   [('en-US', 'English (US)'), ...]\n        # But all locales are stored in lowercase in Elasticsearch, so\n        # force everything to lowercase.\n        choices=[(code.lower(), name) for code, name in settings.LANGUAGES],\n    )\n\n    SORT_CHOICES = (\"best\", \"relevance\", \"popularity\")\n    sort = forms.ChoiceField(required=False, choices=[(x, x) for x in SORT_CHOICES])\n\n    ARCHIVE_CHOICES = (\"exclude\", \"include\", \"only\")\n    archive = forms.ChoiceField(\n        required=False, choices=[(x, x) for x in ARCHIVE_CHOICES]\n    )\n\n    size = forms.IntegerField(required=True, min_value=1, max_value=100)\n    page = forms.IntegerField(required=True, min_value=1, max_value=10)\n\n    def __init__(self, data, **kwargs):\n        initial = kwargs.get(\"initial\", {})\n        # This makes it possible to supply `initial={some dict}` to the form\n        # and have its values become part of the default. Normally, in Django,\n        # the `SomeForm(data, initial={...})` is just used to prepopulate the\n        # HTML generated form widgets.\n        # See https://www.peterbe.com/plog/initial-values-bound-django-form-rendered\n        data = MultiValueDict({**{k: [v] for k, v in initial.items()}, **data})\n\n        # Because the `?locale=en-US&locale=Fr` might come in from the `request.GET`\n        # we can't edit it there. So instead, we mutate it here in the `data`\n        if \"locale\" in data:\n            # Always force it to lowercase, because that's what the ChoiceField\n            # is configured to. And the searches should always be in lower case.\n            # Remember, Django forms will allow this to be a single string\n            # (e.g. `?locale=Fr`) or a multi-value (`?locale=fr&locale=En-US`).\n            if isinstance(data[\"locale\"], str):\n                data[\"locale\"] = data[\"locale\"].lower()\n            else:\n                data[\"locale\"] = [x.lower() for x in data[\"locale\"]]\n\n        # If, for keys we have an initial value for, it was passed an empty string,\n        # then swap it for the initial value.\n        # For example `?q=searching&page=` you probably meant to omit it\n        # but \"allowing\" it to be an empty string makes it convenient for the client.\n        for key, values in data.items():\n            if key in initial and values == \"\":\n                data[key] = initial[key]\n\n        super().__init__(data, **kwargs)\n", "path": "kuma/api/v1/search/forms.py"}], "after_files": [{"content": "from django import forms\nfrom django.conf import settings\nfrom django.utils.datastructures import MultiValueDict\n\n\nclass MultipleChoiceFieldICase(forms.MultipleChoiceField):\n    \"\"\"Just like forms.MultipleChoiceField but everything's case insentive.\n\n    For simplicity, this field assumes that each choice is a tuple where\n    the first element is always a string.\n    \"\"\"\n\n    def valid_value(self, value):\n        return str(value).lower() in [x[0].lower() for x in self.choices]\n\n\nclass SearchForm(forms.Form):\n    q = forms.CharField(max_length=settings.ES_Q_MAXLENGTH)\n    locale = MultipleChoiceFieldICase(\n        required=False,\n        # The `settings.LANGUAGES` looks like this:\n        #   [('en-US', 'English (US)'), ...]\n        # But all locales are stored in lowercase in Elasticsearch, so\n        # force everything to lowercase.\n        choices=[(code, name) for code, name in settings.LANGUAGES],\n    )\n\n    SORT_CHOICES = (\"best\", \"relevance\", \"popularity\")\n    sort = forms.ChoiceField(required=False, choices=[(x, x) for x in SORT_CHOICES])\n\n    ARCHIVE_CHOICES = (\"exclude\", \"include\", \"only\")\n    archive = forms.ChoiceField(\n        required=False, choices=[(x, x) for x in ARCHIVE_CHOICES]\n    )\n\n    size = forms.IntegerField(required=True, min_value=1, max_value=100)\n    page = forms.IntegerField(required=True, min_value=1, max_value=10)\n\n    def __init__(self, data, **kwargs):\n        initial = kwargs.get(\"initial\", {})\n        # This makes it possible to supply `initial={some dict}` to the form\n        # and have its values become part of the default. Normally, in Django,\n        # the `SomeForm(data, initial={...})` is just used to prepopulate the\n        # HTML generated form widgets.\n        # See https://www.peterbe.com/plog/initial-values-bound-django-form-rendered\n        data = MultiValueDict({**{k: [v] for k, v in initial.items()}, **data})\n\n        # If, for keys we have an initial value for, it was passed an empty string,\n        # then swap it for the initial value.\n        # For example `?q=searching&page=` you probably meant to omit it\n        # but \"allowing\" it to be an empty string makes it convenient for the client.\n        for key, values in data.items():\n            if key in initial and values == \"\":\n                data[key] = initial[key]\n\n        super().__init__(data, **kwargs)\n", "path": "kuma/api/v1/search/forms.py"}]}