We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Input turns language to Chinese
<!-- PLEASE FILL THESE FIELDS, IT REALLY HELPS THE MAINTAINERS OF SEARX -->

**Version of Searx, commit number if you are using on master branch and stipulate if you forked Searx**
0.17.0-17b48ff6e858b0c74116068cf6444bd578bbb747
<!-- If you are running on master branch using git execute this command
in order to fetch the latest commit ID:
```
git log -1
``` 
If you are using searx-docker then look at the bottom of the Searx page
and check for the version after "Powered by searx"

Please also stipulate if you are using a forked version of Searx and
include a link to the fork source code.
-->
**How did you install Searx?**
Manual install
<!-- Did you install Searx using the official wiki or using searx-docker
or manually by executing the searx/webapp.py file? -->
**What happened?**
If I search the phrase `parser error : invalid character in attribute value`, the search language changes to `zh`.
<!-- A clear and concise description of what the bug is. -->

**How To Reproduce**
This works on every searx instance I can find. Just search the phrase `parser error : invalid character in attribute value`.
<!-- How can we reproduce this issue? (as minimally and as precisely as possible) -->

**Expected behavior**
Results in the language chosen.
<!-- A clear and concise description of what you expected to happen. -->


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `searx/query.py`
Content:
```
1 #!/usr/bin/env python
2 
3 '''
4 searx is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Affero General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8 
9 searx is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU Affero General Public License for more details.
13 
14 You should have received a copy of the GNU Affero General Public License
15 along with searx. If not, see < http://www.gnu.org/licenses/ >.
16 
17 (C) 2014 by Thomas Pointhuber, <thomas.pointhuber@gmx.at>
18 '''
19 
20 import re
21 
22 from searx.languages import language_codes
23 from searx.engines import categories, engines, engine_shortcuts
24 from searx.search import EngineRef
25 from searx.webutils import VALID_LANGUAGE_CODE
26 
27 
28 class RawTextQuery:
29     """parse raw text query (the value from the html input)"""
30 
31     def __init__(self, query, disabled_engines):
32         assert isinstance(query, str)
33         self.query = query
34         self.disabled_engines = []
35 
36         if disabled_engines:
37             self.disabled_engines = disabled_engines
38 
39         self.query_parts = []
40         self.user_query_parts = []
41         self.enginerefs = []
42         self.languages = []
43         self.timeout_limit = None
44         self.external_bang = None
45         self.specific = False
46         self._parse_query()
47 
48     # parse query, if tags are set, which
49     # change the search engine or search-language
50     def _parse_query(self):
51         self.query_parts = []
52 
53         # split query, including whitespaces
54         raw_query_parts = re.split(r'(\s+)', self.query)
55 
56         for query_part in raw_query_parts:
57             searx_query_part = False
58 
59             # part does only contain spaces, skip
60             if query_part.isspace()\
61                or query_part == '':
62                 continue
63 
64             # this force the timeout
65             if query_part[0] == '<':
66                 try:
67                     raw_timeout_limit = int(query_part[1:])
68                     if raw_timeout_limit < 100:
69                         # below 100, the unit is the second ( <3 = 3 seconds timeout )
70                         self.timeout_limit = float(raw_timeout_limit)
71                     else:
72                         # 100 or above, the unit is the millisecond ( <850 = 850 milliseconds timeout )
73                         self.timeout_limit = raw_timeout_limit / 1000.0
74                     searx_query_part = True
75                 except ValueError:
76                     # error not reported to the user
77                     pass
78 
79             # this force a language
80             if query_part[0] == ':':
81                 lang = query_part[1:].lower().replace('_', '-')
82 
83                 # check if any language-code is equal with
84                 # declared language-codes
85                 for lc in language_codes:
86                     lang_id, lang_name, country, english_name = map(str.lower, lc)
87 
88                     # if correct language-code is found
89                     # set it as new search-language
90                     if (lang == lang_id
91                         or lang == lang_name
92                         or lang == english_name
93                         or lang.replace('-', ' ') == country)\
94                        and lang not in self.languages:
95                         searx_query_part = True
96                         lang_parts = lang_id.split('-')
97                         if len(lang_parts) == 2:
98                             self.languages.append(lang_parts[0] + '-' + lang_parts[1].upper())
99                         else:
100                             self.languages.append(lang_id)
101                         # to ensure best match (first match is not necessarily the best one)
102                         if lang == lang_id:
103                             break
104 
105                 # user may set a valid, yet not selectable language
106                 if VALID_LANGUAGE_CODE.match(lang):
107                     lang_parts = lang.split('-')
108                     if len(lang_parts) > 1:
109                         lang = lang_parts[0].lower() + '-' + lang_parts[1].upper()
110                     if lang not in self.languages:
111                         self.languages.append(lang)
112                         searx_query_part = True
113 
114             # external bang
115             if query_part[0:2] == "!!":
116                 self.external_bang = query_part[2:]
117                 searx_query_part = True
118                 continue
119             # this force a engine or category
120             if query_part[0] == '!' or query_part[0] == '?':
121                 prefix = query_part[1:].replace('-', ' ').replace('_', ' ')
122 
123                 # check if prefix is equal with engine shortcut
124                 if prefix in engine_shortcuts:
125                     searx_query_part = True
126                     engine_name = engine_shortcuts[prefix]
127                     if engine_name in engines:
128                         self.enginerefs.append(EngineRef(engine_name, 'none'))
129 
130                 # check if prefix is equal with engine name
131                 elif prefix in engines:
132                     searx_query_part = True
133                     self.enginerefs.append(EngineRef(prefix, 'none'))
134 
135                 # check if prefix is equal with categorie name
136                 elif prefix in categories:
137                     # using all engines for that search, which
138                     # are declared under that categorie name
139                     searx_query_part = True
140                     self.enginerefs.extend(EngineRef(engine.name, prefix)
141                                            for engine in categories[prefix]
142                                            if (engine.name, prefix) not in self.disabled_engines)
143 
144             if query_part[0] == '!':
145                 self.specific = True
146 
147             # append query part to query_part list
148             if searx_query_part:
149                 self.query_parts.append(query_part)
150             else:
151                 self.user_query_parts.append(query_part)
152 
153     def changeQuery(self, query):
154         self.user_query_parts = query.strip().split()
155         return self
156 
157     def getQuery(self):
158         return ' '.join(self.user_query_parts)
159 
160     def getFullQuery(self):
161         # get full querry including whitespaces
162         return '{0} {1}'.format(''.join(self.query_parts), self.getQuery()).strip()
163
```
--- 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()

```

diff --git a/searx/query.py b/searx/query.py
--- a/searx/query.py
+++ b/searx/query.py
@@ -77,7 +77,7 @@
                     pass
 
             # this force a language
-            if query_part[0] == ':':
+            if query_part[0] == ':' and len(query_part) > 1:
                 lang = query_part[1:].lower().replace('_', '-')
 
                 # check if any language-code is equal with

{"golden_diff": "diff --git a/searx/query.py b/searx/query.py\n--- a/searx/query.py\n+++ b/searx/query.py\n@@ -77,7 +77,7 @@\n                     pass\n \n             # this force a language\n-            if query_part[0] == ':':\n+            if query_part[0] == ':' and len(query_part) > 1:\n                 lang = query_part[1:].lower().replace('_', '-')\n \n                 # check if any language-code is equal with\n", "issue": "Input turns language to Chinese\n<!-- PLEASE FILL THESE FIELDS, IT REALLY HELPS THE MAINTAINERS OF SEARX -->\r\n\r\n**Version of Searx, commit number if you are using on master branch and stipulate if you forked Searx**\r\n0.17.0-17b48ff6e858b0c74116068cf6444bd578bbb747\r\n<!-- If you are running on master branch using git execute this command\r\nin order to fetch the latest commit ID:\r\n```\r\ngit log -1\r\n``` \r\nIf you are using searx-docker then look at the bottom of the Searx page\r\nand check for the version after \"Powered by searx\"\r\n\r\nPlease also stipulate if you are using a forked version of Searx and\r\ninclude a link to the fork source code.\r\n-->\r\n**How did you install Searx?**\r\nManual install\r\n<!-- Did you install Searx using the official wiki or using searx-docker\r\nor manually by executing the searx/webapp.py file? -->\r\n**What happened?**\r\nIf I search the phrase `parser error : invalid character in attribute value`, the search language changes to `zh`.\r\n<!-- A clear and concise description of what the bug is. -->\r\n\r\n**How To Reproduce**\r\nThis works on every searx instance I can find. Just search the phrase `parser error : invalid character in attribute value`.\r\n<!-- How can we reproduce this issue? (as minimally and as precisely as possible) -->\r\n\r\n**Expected behavior**\r\nResults in the language chosen.\r\n<!-- A clear and concise description of what you expected to happen. -->\r\n\n", "before_files": [{"content": "#!/usr/bin/env python\n\n'''\nsearx is free software: you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nsearx is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with searx. If not, see < http://www.gnu.org/licenses/ >.\n\n(C) 2014 by Thomas Pointhuber, <thomas.pointhuber@gmx.at>\n'''\n\nimport re\n\nfrom searx.languages import language_codes\nfrom searx.engines import categories, engines, engine_shortcuts\nfrom searx.search import EngineRef\nfrom searx.webutils import VALID_LANGUAGE_CODE\n\n\nclass RawTextQuery:\n    \"\"\"parse raw text query (the value from the html input)\"\"\"\n\n    def __init__(self, query, disabled_engines):\n        assert isinstance(query, str)\n        self.query = query\n        self.disabled_engines = []\n\n        if disabled_engines:\n            self.disabled_engines = disabled_engines\n\n        self.query_parts = []\n        self.user_query_parts = []\n        self.enginerefs = []\n        self.languages = []\n        self.timeout_limit = None\n        self.external_bang = None\n        self.specific = False\n        self._parse_query()\n\n    # parse query, if tags are set, which\n    # change the search engine or search-language\n    def _parse_query(self):\n        self.query_parts = []\n\n        # split query, including whitespaces\n        raw_query_parts = re.split(r'(\\s+)', self.query)\n\n        for query_part in raw_query_parts:\n            searx_query_part = False\n\n            # part does only contain spaces, skip\n            if query_part.isspace()\\\n               or query_part == '':\n                continue\n\n            # this force the timeout\n            if query_part[0] == '<':\n                try:\n                    raw_timeout_limit = int(query_part[1:])\n                    if raw_timeout_limit < 100:\n                        # below 100, the unit is the second ( <3 = 3 seconds timeout )\n                        self.timeout_limit = float(raw_timeout_limit)\n                    else:\n                        # 100 or above, the unit is the millisecond ( <850 = 850 milliseconds timeout )\n                        self.timeout_limit = raw_timeout_limit / 1000.0\n                    searx_query_part = True\n                except ValueError:\n                    # error not reported to the user\n                    pass\n\n            # this force a language\n            if query_part[0] == ':':\n                lang = query_part[1:].lower().replace('_', '-')\n\n                # check if any language-code is equal with\n                # declared language-codes\n                for lc in language_codes:\n                    lang_id, lang_name, country, english_name = map(str.lower, lc)\n\n                    # if correct language-code is found\n                    # set it as new search-language\n                    if (lang == lang_id\n                        or lang == lang_name\n                        or lang == english_name\n                        or lang.replace('-', ' ') == country)\\\n                       and lang not in self.languages:\n                        searx_query_part = True\n                        lang_parts = lang_id.split('-')\n                        if len(lang_parts) == 2:\n                            self.languages.append(lang_parts[0] + '-' + lang_parts[1].upper())\n                        else:\n                            self.languages.append(lang_id)\n                        # to ensure best match (first match is not necessarily the best one)\n                        if lang == lang_id:\n                            break\n\n                # user may set a valid, yet not selectable language\n                if VALID_LANGUAGE_CODE.match(lang):\n                    lang_parts = lang.split('-')\n                    if len(lang_parts) > 1:\n                        lang = lang_parts[0].lower() + '-' + lang_parts[1].upper()\n                    if lang not in self.languages:\n                        self.languages.append(lang)\n                        searx_query_part = True\n\n            # external bang\n            if query_part[0:2] == \"!!\":\n                self.external_bang = query_part[2:]\n                searx_query_part = True\n                continue\n            # this force a engine or category\n            if query_part[0] == '!' or query_part[0] == '?':\n                prefix = query_part[1:].replace('-', ' ').replace('_', ' ')\n\n                # check if prefix is equal with engine shortcut\n                if prefix in engine_shortcuts:\n                    searx_query_part = True\n                    engine_name = engine_shortcuts[prefix]\n                    if engine_name in engines:\n                        self.enginerefs.append(EngineRef(engine_name, 'none'))\n\n                # check if prefix is equal with engine name\n                elif prefix in engines:\n                    searx_query_part = True\n                    self.enginerefs.append(EngineRef(prefix, 'none'))\n\n                # check if prefix is equal with categorie name\n                elif prefix in categories:\n                    # using all engines for that search, which\n                    # are declared under that categorie name\n                    searx_query_part = True\n                    self.enginerefs.extend(EngineRef(engine.name, prefix)\n                                           for engine in categories[prefix]\n                                           if (engine.name, prefix) not in self.disabled_engines)\n\n            if query_part[0] == '!':\n                self.specific = True\n\n            # append query part to query_part list\n            if searx_query_part:\n                self.query_parts.append(query_part)\n            else:\n                self.user_query_parts.append(query_part)\n\n    def changeQuery(self, query):\n        self.user_query_parts = query.strip().split()\n        return self\n\n    def getQuery(self):\n        return ' '.join(self.user_query_parts)\n\n    def getFullQuery(self):\n        # get full querry including whitespaces\n        return '{0} {1}'.format(''.join(self.query_parts), self.getQuery()).strip()\n", "path": "searx/query.py"}], "after_files": [{"content": "#!/usr/bin/env python\n\n'''\nsearx is free software: you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nsearx is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with searx. If not, see < http://www.gnu.org/licenses/ >.\n\n(C) 2014 by Thomas Pointhuber, <thomas.pointhuber@gmx.at>\n'''\n\nimport re\n\nfrom searx.languages import language_codes\nfrom searx.engines import categories, engines, engine_shortcuts\nfrom searx.search import EngineRef\nfrom searx.webutils import VALID_LANGUAGE_CODE\n\n\nclass RawTextQuery:\n    \"\"\"parse raw text query (the value from the html input)\"\"\"\n\n    def __init__(self, query, disabled_engines):\n        assert isinstance(query, str)\n        self.query = query\n        self.disabled_engines = []\n\n        if disabled_engines:\n            self.disabled_engines = disabled_engines\n\n        self.query_parts = []\n        self.user_query_parts = []\n        self.enginerefs = []\n        self.languages = []\n        self.timeout_limit = None\n        self.external_bang = None\n        self.specific = False\n        self._parse_query()\n\n    # parse query, if tags are set, which\n    # change the search engine or search-language\n    def _parse_query(self):\n        self.query_parts = []\n\n        # split query, including whitespaces\n        raw_query_parts = re.split(r'(\\s+)', self.query)\n\n        for query_part in raw_query_parts:\n            searx_query_part = False\n\n            # part does only contain spaces, skip\n            if query_part.isspace()\\\n               or query_part == '':\n                continue\n\n            # this force the timeout\n            if query_part[0] == '<':\n                try:\n                    raw_timeout_limit = int(query_part[1:])\n                    if raw_timeout_limit < 100:\n                        # below 100, the unit is the second ( <3 = 3 seconds timeout )\n                        self.timeout_limit = float(raw_timeout_limit)\n                    else:\n                        # 100 or above, the unit is the millisecond ( <850 = 850 milliseconds timeout )\n                        self.timeout_limit = raw_timeout_limit / 1000.0\n                    searx_query_part = True\n                except ValueError:\n                    # error not reported to the user\n                    pass\n\n            # this force a language\n            if query_part[0] == ':' and len(query_part) > 1:\n                lang = query_part[1:].lower().replace('_', '-')\n\n                # check if any language-code is equal with\n                # declared language-codes\n                for lc in language_codes:\n                    lang_id, lang_name, country, english_name = map(str.lower, lc)\n\n                    # if correct language-code is found\n                    # set it as new search-language\n                    if (lang == lang_id\n                        or lang == lang_name\n                        or lang == english_name\n                        or lang.replace('-', ' ') == country)\\\n                       and lang not in self.languages:\n                        searx_query_part = True\n                        lang_parts = lang_id.split('-')\n                        if len(lang_parts) == 2:\n                            self.languages.append(lang_parts[0] + '-' + lang_parts[1].upper())\n                        else:\n                            self.languages.append(lang_id)\n                        # to ensure best match (first match is not necessarily the best one)\n                        if lang == lang_id:\n                            break\n\n                # user may set a valid, yet not selectable language\n                if VALID_LANGUAGE_CODE.match(lang):\n                    lang_parts = lang.split('-')\n                    if len(lang_parts) > 1:\n                        lang = lang_parts[0].lower() + '-' + lang_parts[1].upper()\n                    if lang not in self.languages:\n                        self.languages.append(lang)\n                        searx_query_part = True\n\n            # external bang\n            if query_part[0:2] == \"!!\":\n                self.external_bang = query_part[2:]\n                searx_query_part = True\n                continue\n            # this force a engine or category\n            if query_part[0] == '!' or query_part[0] == '?':\n                prefix = query_part[1:].replace('-', ' ').replace('_', ' ')\n\n                # check if prefix is equal with engine shortcut\n                if prefix in engine_shortcuts:\n                    searx_query_part = True\n                    engine_name = engine_shortcuts[prefix]\n                    if engine_name in engines:\n                        self.enginerefs.append(EngineRef(engine_name, 'none'))\n\n                # check if prefix is equal with engine name\n                elif prefix in engines:\n                    searx_query_part = True\n                    self.enginerefs.append(EngineRef(prefix, 'none'))\n\n                # check if prefix is equal with categorie name\n                elif prefix in categories:\n                    # using all engines for that search, which\n                    # are declared under that categorie name\n                    searx_query_part = True\n                    self.enginerefs.extend(EngineRef(engine.name, prefix)\n                                           for engine in categories[prefix]\n                                           if (engine.name, prefix) not in self.disabled_engines)\n\n            if query_part[0] == '!':\n                self.specific = True\n\n            # append query part to query_part list\n            if searx_query_part:\n                self.query_parts.append(query_part)\n            else:\n                self.user_query_parts.append(query_part)\n\n    def changeQuery(self, query):\n        self.user_query_parts = query.strip().split()\n        return self\n\n    def getQuery(self):\n        return ' '.join(self.user_query_parts)\n\n    def getFullQuery(self):\n        # get full querry including whitespaces\n        return '{0} {1}'.format(''.join(self.query_parts), self.getQuery()).strip()\n", "path": "searx/query.py"}]}