on master help sign in
[fix] get correct locale with country from browser

Some of our interface locales include uppercase country codes, which are separated by `_` instead of the more common `-`. Also, a browser's `Accept-Language` header could be in lowercase. This commit attempts to normalize those cases so a browser's language+country codes can better match with our locales. This solution assumes that our UI locales have nothing more than language and optionally country. If we ever add a script specific locale like `zh-Hant-TW` this would have to change to accomodate that, but the idea would be pretty much the same as this fix.

commitc937a9e85f510820f7d9b98666dcf83f72f80ceb authorMarc Abonce Seguin <marc-abonce@mailbox.org> dateWed 3 Feb 2021, 01:02 (6 years ago) parent321788f
2 files changed+20−5
searx/webapp.py+6−5 tests/unit/test_webapp.py+14
searx/webapp.py+6−5
@@ -142,6 +142,7 @@ babel = Babel(app)
142142
143143rtl_locales = ['ar', 'arc', 'bcc', 'bqi', 'ckb', 'dv', 'fa', 'fa_IR', 'glk', 'he',
144144 'ku', 'mzn', 'pnb', 'ps', 'sd', 'ug', 'ur', 'yi']
145+ui_locale_codes = [l.replace('_', '-') for l in settings['locales'].keys()]
145146
146147# used when translating category names
147148_category_names = (gettext('files'),
@@ -175,6 +176,9 @@ def _get_browser_or_settings_language(request, lang_list):
175176 for lang in request.headers.get("Accept-Language", "en").split(","):
176177 if ';' in lang:
177178 lang = lang.split(';')[0]
179+ if '-' in lang:
180+ lang_parts = lang.split('-')
181+ lang = "{}-{}".format(lang_parts[0], lang_parts[-1].upper())
178182 locale = match_language(lang, lang_list, fallback=None)
179183 if locale is not None:
180184 return locale
@@ -194,13 +198,10 @@ def get_locale():
194198 locale_source = 'preferences'
195199 else:
196200 # use local from the browser
197− locale = _get_browser_or_settings_language(request, settings['locales'].keys())
201+ locale = _get_browser_or_settings_language(request, ui_locale_codes)
202+ locale = locale.replace('-', '_')
198203 locale_source = 'browser'
199204
200− #
201− if locale == 'zh_TW':
202− locale = 'zh_Hant_TW'
203−
204205 # see _get_translations function
205206 # and https://github.com/searx/searx/pull/1863
206207 if locale == 'oc':
tests/unit/test_webapp.py+14
@@ -198,6 +198,20 @@ class ViewsTestCase(SearxTestCase):
198198 result.data
199199 )
200200
201+ def test_browser_locale(self):
202+ result = self.app.get('/preferences', headers={'Accept-Language': 'zh-tw;q=0.8'})
203+ self.assertEqual(result.status_code, 200)
204+ self.assertIn(
205+ b'<option value="zh_TW" selected="selected">',
206+ result.data,
207+ 'Interface locale ignored browser preference.'
208+ )
209+ self.assertIn(
210+ b'<option value="zh-TW" selected="selected">',
211+ result.data,
212+ 'Search language ignored browser preference.'
213+ )
214+
201215 def test_stats(self):
202216 result = self.app.get('/stats')
203217 self.assertEqual(result.status_code, 200)