Browse Source

[mod] replace engines_languages.json by engines_traits.json

Implementations of the *traits* of the engines.

Engine's traits are fetched from the origin engine and stored in a JSON file in
the *data folder*.  Most often traits are languages and region codes and their
mapping from SearXNG's representation to the representation in the origin search
engine.

To load traits from the persistence::

    searx.enginelib.traits.EngineTraitsMap.from_data()

For new traits new properties can be added to the class::

    searx.enginelib.traits.EngineTraits

.. hint::

   Implementation is downward compatible to the deprecated *supported_languages
   method* from the vintage implementation.

   The vintage code is tagged as *deprecated* an can be removed when all engines
   has been ported to the *traits method*.

Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>
Markus Heiser 2 years ago
parent
commit
6e5f22e558

+ 1 - 1
.github/workflows/data-update.yml

@@ -17,7 +17,7 @@ jobs:
           - update_currencies.py
           - update_currencies.py
           - update_external_bangs.py
           - update_external_bangs.py
           - update_firefox_version.py
           - update_firefox_version.py
-          - update_languages.py
+          - update_engine_traits.py
           - update_wikidata_units.py
           - update_wikidata_units.py
           - update_engine_descriptions.py
           - update_engine_descriptions.py
     steps:
     steps:

+ 1 - 1
docs/admin/engines/configured_engines.rst

@@ -42,7 +42,7 @@ Explanation of the :ref:`general engine configuration` shown in the table
         - Timeout
         - Timeout
         - Weight
         - Weight
         - Paging
         - Paging
-        - Language
+        - Language, Region
         - Safe search
         - Safe search
         - Time range
         - Time range
 
 

+ 5 - 2
docs/admin/engines/settings.rst

@@ -569,10 +569,13 @@ engine is shown.  Most of the options have a default value or even are optional.
   To disable by default the engine, but not deleting it.  It will allow the user
   To disable by default the engine, but not deleting it.  It will allow the user
   to manually activate it in the settings.
   to manually activate it in the settings.
 
 
+``inactive``: optional
+  Remove the engine from the settings (*disabled & removed*).
+
 ``language`` : optional
 ``language`` : optional
   If you want to use another language for a specific engine, you can define it
   If you want to use another language for a specific engine, you can define it
-  by using the full ISO code of language and country, like ``fr_FR``, ``en_US``,
-  ``de_DE``.
+  by using the ISO code of language (and region), like ``fr``, ``en-US``,
+  ``de-DE``.
 
 
 ``tokens`` : optional
 ``tokens`` : optional
   A list of secret tokens to make this engine *private*, more details see
   A list of secret tokens to make this engine *private*, more details see

+ 5 - 0
docs/conf.py

@@ -127,6 +127,10 @@ extensions = [
     'notfound.extension',  # https://github.com/readthedocs/sphinx-notfound-page
     'notfound.extension',  # https://github.com/readthedocs/sphinx-notfound-page
 ]
 ]
 
 
+autodoc_default_options = {
+    'member-order': 'groupwise',
+}
+
 myst_enable_extensions = [
 myst_enable_extensions = [
   "replacements", "smartquotes"
   "replacements", "smartquotes"
 ]
 ]
@@ -135,6 +139,7 @@ suppress_warnings = ['myst.domains']
 
 
 intersphinx_mapping = {
 intersphinx_mapping = {
     "python": ("https://docs.python.org/3/", None),
     "python": ("https://docs.python.org/3/", None),
+    "babel" : ("https://babel.readthedocs.io/en/latest/", None),
     "flask": ("https://flask.palletsprojects.com/", None),
     "flask": ("https://flask.palletsprojects.com/", None),
     "flask_babel": ("https://python-babel.github.io/flask-babel/", None),
     "flask_babel": ("https://python-babel.github.io/flask-babel/", None),
     # "werkzeug": ("https://werkzeug.palletsprojects.com/", None),
     # "werkzeug": ("https://werkzeug.palletsprojects.com/", None),

+ 36 - 6
docs/dev/engine_overview.rst

@@ -54,6 +54,7 @@ Engine File
                                        - ``offline`` :ref:`[ref] <offline engines>`
                                        - ``offline`` :ref:`[ref] <offline engines>`
                                        - ``online_dictionary``
                                        - ``online_dictionary``
                                        - ``online_currency``
                                        - ``online_currency``
+                                       - ``online_url_search``
    ======================= =========== ========================================================
    ======================= =========== ========================================================
 
 
 .. _engine settings:
 .. _engine settings:
@@ -131,8 +132,10 @@ Passed Arguments (request)
 These arguments can be used to construct the search query.  Furthermore,
 These arguments can be used to construct the search query.  Furthermore,
 parameters with default value can be redefined for special purposes.
 parameters with default value can be redefined for special purposes.
 
 
+.. _engine request online:
 
 
-.. table:: If the ``engine_type`` is ``online``
+.. table:: If the ``engine_type`` is :py:obj:`online
+           <searx.search.processors.online.OnlineProcessor.get_params>`
    :width: 100%
    :width: 100%
 
 
    ====================== ============== ========================================================================
    ====================== ============== ========================================================================
@@ -149,12 +152,16 @@ parameters with default value can be redefined for special purposes.
    safesearch             int            ``0``, between ``0`` and ``2`` (normal, moderate, strict)
    safesearch             int            ``0``, between ``0`` and ``2`` (normal, moderate, strict)
    time_range             Optional[str]  ``None``, can be ``day``, ``week``, ``month``, ``year``
    time_range             Optional[str]  ``None``, can be ``day``, ``week``, ``month``, ``year``
    pageno                 int            current pagenumber
    pageno                 int            current pagenumber
-   language               str            specific language code like ``'en_US'``, or ``'all'`` if unspecified
+   searxng_locale         str            SearXNG's locale selected by user.  Specific language code like
+                                         ``'en'``, ``'en-US'``, or ``'all'`` if unspecified.
    ====================== ============== ========================================================================
    ====================== ============== ========================================================================
 
 
 
 
-.. table:: If the ``engine_type`` is ``online_dictionary``, in addition to the
-           ``online`` arguments:
+.. _engine request online_dictionary:
+
+.. table:: If the ``engine_type`` is :py:obj:`online_dictionary
+           <searx.search.processors.online_dictionary.OnlineDictionaryProcessor.get_params>`,
+           in addition to the :ref:`online <engine request online>` arguments:
    :width: 100%
    :width: 100%
 
 
    ====================== ============== ========================================================================
    ====================== ============== ========================================================================
@@ -165,8 +172,11 @@ parameters with default value can be redefined for special purposes.
    query                  str            the text query without the languages
    query                  str            the text query without the languages
    ====================== ============== ========================================================================
    ====================== ============== ========================================================================
 
 
-.. table:: If the ``engine_type`` is ``online_currency```, in addition to the
-           ``online`` arguments:
+.. _engine request online_currency:
+
+.. table:: If the ``engine_type`` is :py:obj:`online_currency
+           <searx.search.processors.online_currency.OnlineCurrencyProcessor.get_params>`,
+           in addition to the :ref:`online <engine request online>` arguments:
    :width: 100%
    :width: 100%
 
 
    ====================== ============== ========================================================================
    ====================== ============== ========================================================================
@@ -179,6 +189,26 @@ parameters with default value can be redefined for special purposes.
    to_name                str            currency name
    to_name                str            currency name
    ====================== ============== ========================================================================
    ====================== ============== ========================================================================
 
 
+.. _engine request online_url_search:
+
+.. table:: If the ``engine_type`` is :py:obj:`online_url_search
+           <searx.search.processors.online_url_search.OnlineUrlSearchProcessor.get_params>`,
+           in addition to the :ref:`online <engine request online>` arguments:
+   :width: 100%
+
+   ====================== ============== ========================================================================
+   argument               type           default-value, information
+   ====================== ============== ========================================================================
+   search_url             dict           URLs from the search query:
+
+                                         .. code:: python
+
+                                            {
+                                              'http': str,
+                                              'ftp': str,
+                                              'data:image': str
+                                            }
+   ====================== ============== ========================================================================
 
 
 Specify Request
 Specify Request
 ---------------
 ---------------

+ 4 - 4
docs/dev/searxng_extra/update.rst

@@ -52,12 +52,12 @@ Scripts to update static data in :origin:`searx/data/`
   :members:
   :members:
 
 
 
 
-``update_languages.py``
-=======================
+``update_engine_traits.py``
+===========================
 
 
-:origin:`[source] <searxng_extra/update/update_languages.py>`
+:origin:`[source] <searxng_extra/update/update_engine_traits.py>`
 
 
-.. automodule:: searxng_extra.update.update_languages
+.. automodule:: searxng_extra.update.update_engine_traits
   :members:
   :members:
 
 
 
 

+ 17 - 0
docs/src/searx.enginelib.rst

@@ -0,0 +1,17 @@
+.. _searx.enginelib:
+
+============
+Engine model
+============
+
+.. automodule:: searx.enginelib
+  :members:
+
+.. _searx.enginelib.traits:
+
+=============
+Engine traits
+=============
+
+.. automodule:: searx.enginelib.traits
+  :members:

+ 4 - 4
docs/src/searx.engines.rst

@@ -1,8 +1,8 @@
-.. _load_engines:
+.. _searx.engines:
 
 
-============
-Load Engines
-============
+=================
+SearXNG's engines
+=================
 
 
 .. automodule:: searx.engines
 .. automodule:: searx.engines
   :members:
   :members:

+ 47 - 0
docs/src/searx.search.processors.rst

@@ -0,0 +1,47 @@
+.. _searx.search.processors:
+
+=================
+Search processors
+=================
+
+.. contents:: Contents
+   :depth: 2
+   :local:
+   :backlinks: entry
+
+
+Abstract processor class
+========================
+
+.. automodule:: searx.search.processors.abstract
+  :members:
+
+Offline processor
+=================
+
+.. automodule:: searx.search.processors.offline
+  :members:
+
+Online processor
+================
+
+.. automodule:: searx.search.processors.online
+  :members:
+
+Online currency processor
+=========================
+
+.. automodule:: searx.search.processors.online_currency
+  :members:
+
+Online Dictionary processor
+===========================
+
+.. automodule:: searx.search.processors.online_dictionary
+  :members:
+
+Online URL search processor
+===========================
+
+.. automodule:: searx.search.processors.online_url_search
+  :members:

+ 1 - 1
manage

@@ -63,7 +63,7 @@ PYLINT_SEARXNG_DISABLE_OPTION="\
 I,C,R,\
 I,C,R,\
 W0105,W0212,W0511,W0603,W0613,W0621,W0702,W0703,W1401,\
 W0105,W0212,W0511,W0603,W0613,W0621,W0702,W0703,W1401,\
 E1136"
 E1136"
-PYLINT_ADDITIONAL_BUILTINS_FOR_ENGINES="supported_languages,language_aliases,logger,categories"
+PYLINT_ADDITIONAL_BUILTINS_FOR_ENGINES="traits,supported_languages,language_aliases,logger,categories"
 PYLINT_OPTIONS="-m pylint -j 0 --rcfile .pylintrc"
 PYLINT_OPTIONS="-m pylint -j 0 --rcfile .pylintrc"
 
 
 help() {
 help() {

+ 11 - 4
searx/autocomplete.py

@@ -12,7 +12,7 @@ from lxml import etree
 from httpx import HTTPError
 from httpx import HTTPError
 
 
 from searx import settings
 from searx import settings
-from searx.data import ENGINES_LANGUAGES
+from searx.engines import engines
 from searx.network import get as http_get
 from searx.network import get as http_get
 from searx.exceptions import SearxEngineResponseException
 from searx.exceptions import SearxEngineResponseException
 
 
@@ -111,7 +111,7 @@ def seznam(query, _lang):
 
 
 def startpage(query, lang):
 def startpage(query, lang):
     # startpage autocompleter
     # startpage autocompleter
-    lui = ENGINES_LANGUAGES['startpage'].get(lang, 'english')
+    lui = engines['startpage'].supported_languages.get(lang, 'english')  # vintage / deprecated
     url = 'https://startpage.com/suggestions?{query}'
     url = 'https://startpage.com/suggestions?{query}'
     resp = get(url.format(query=urlencode({'q': query, 'segment': 'startpage.udog', 'lui': lui})))
     resp = get(url.format(query=urlencode({'q': query, 'segment': 'startpage.udog', 'lui': lui})))
     data = resp.json()
     data = resp.json()
@@ -177,12 +177,19 @@ backends = {
 }
 }
 
 
 
 
-def search_autocomplete(backend_name, query, lang):
+def search_autocomplete(backend_name, query, sxng_locale):
     backend = backends.get(backend_name)
     backend = backends.get(backend_name)
     if backend is None:
     if backend is None:
         return []
         return []
 
 
+    if engines[backend_name].traits.data_type != "traits_v1":
+        # vintage / deprecated
+        if not sxng_locale or sxng_locale == 'all':
+            sxng_locale = 'en'
+        else:
+            sxng_locale = sxng_locale.split('-')[0]
+
     try:
     try:
-        return backend(query, lang)
+        return backend(query, sxng_locale)
     except (HTTPError, SearxEngineResponseException):
     except (HTTPError, SearxEngineResponseException):
         return []
         return []

+ 2 - 2
searx/data/__init__.py

@@ -7,7 +7,7 @@
 """
 """
 
 
 __all__ = [
 __all__ = [
-    'ENGINES_LANGUAGES',
+    'ENGINE_TRAITS',
     'CURRENCIES',
     'CURRENCIES',
     'USER_AGENTS',
     'USER_AGENTS',
     'EXTERNAL_URLS',
     'EXTERNAL_URLS',
@@ -42,7 +42,6 @@ def ahmia_blacklist_loader():
         return f.read().split()
         return f.read().split()
 
 
 
 
-ENGINES_LANGUAGES = _load('engines_languages.json')
 CURRENCIES = _load('currencies.json')
 CURRENCIES = _load('currencies.json')
 USER_AGENTS = _load('useragents.json')
 USER_AGENTS = _load('useragents.json')
 EXTERNAL_URLS = _load('external_urls.json')
 EXTERNAL_URLS = _load('external_urls.json')
@@ -50,3 +49,4 @@ WIKIDATA_UNITS = _load('wikidata_units.json')
 EXTERNAL_BANGS = _load('external_bangs.json')
 EXTERNAL_BANGS = _load('external_bangs.json')
 OSM_KEYS_TAGS = _load('osm_keys_tags.json')
 OSM_KEYS_TAGS = _load('osm_keys_tags.json')
 ENGINE_DESCRIPTIONS = _load('engine_descriptions.json')
 ENGINE_DESCRIPTIONS = _load('engine_descriptions.json')
+ENGINE_TRAITS = _load('engine_traits.json')

+ 4534 - 0
searx/data/engine_traits.json

@@ -0,0 +1,4534 @@
+{
+  "bing": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": [
+      "af",
+      "am",
+      "ar",
+      "as",
+      "az-latn",
+      "be",
+      "bg",
+      "bn",
+      "bs-latn",
+      "ca",
+      "ca-es-valencia",
+      "chr-cher",
+      "cs",
+      "cy",
+      "da",
+      "de",
+      "el",
+      "en",
+      "es",
+      "et",
+      "eu",
+      "fa",
+      "fi",
+      "fil",
+      "fr",
+      "ga",
+      "gd",
+      "gl",
+      "gu",
+      "ha-latn",
+      "he",
+      "hi",
+      "hr",
+      "hu",
+      "hy",
+      "id",
+      "ig",
+      "is",
+      "it",
+      "ja",
+      "ka",
+      "kk",
+      "km",
+      "kn",
+      "ko",
+      "kok",
+      "ku-arab",
+      "ky",
+      "lb",
+      "lo",
+      "lt",
+      "lv",
+      "mi",
+      "mk",
+      "ml",
+      "mn-Cyrl-MN",
+      "mr",
+      "ms",
+      "mt",
+      "nb",
+      "ne",
+      "nl",
+      "nn",
+      "nso",
+      "or",
+      "pa-arab",
+      "pa-guru",
+      "pl",
+      "prs",
+      "pt-BR",
+      "pt-PT",
+      "quc",
+      "quz",
+      "ro",
+      "ru",
+      "rw",
+      "sd-arab",
+      "si",
+      "sk",
+      "sl",
+      "sq",
+      "sr-cyrl",
+      "sr-latn",
+      "sv",
+      "sw",
+      "ta",
+      "te",
+      "tg-cyrl",
+      "th",
+      "ti",
+      "tk",
+      "tn",
+      "tr",
+      "tt",
+      "ug",
+      "uk",
+      "ur",
+      "uz-latn",
+      "vi",
+      "wo",
+      "xh",
+      "yo",
+      "zh-Hans",
+      "zh-Hant",
+      "zu"
+    ]
+  },
+  "bing images": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": [
+      "af",
+      "am",
+      "ar",
+      "as",
+      "az-latn",
+      "be",
+      "bg",
+      "bn",
+      "bs-latn",
+      "ca",
+      "ca-es-valencia",
+      "chr-cher",
+      "cs",
+      "cy",
+      "da",
+      "de",
+      "el",
+      "en",
+      "es",
+      "et",
+      "eu",
+      "fa",
+      "fi",
+      "fil",
+      "fr",
+      "ga",
+      "gd",
+      "gl",
+      "gu",
+      "ha-latn",
+      "he",
+      "hi",
+      "hr",
+      "hu",
+      "hy",
+      "id",
+      "ig",
+      "is",
+      "it",
+      "ja",
+      "ka",
+      "kk",
+      "km",
+      "kn",
+      "ko",
+      "kok",
+      "ku-arab",
+      "ky",
+      "lb",
+      "lo",
+      "lt",
+      "lv",
+      "mi",
+      "mk",
+      "ml",
+      "mn-Cyrl-MN",
+      "mr",
+      "ms",
+      "mt",
+      "nb",
+      "ne",
+      "nl",
+      "nn",
+      "nso",
+      "or",
+      "pa-arab",
+      "pa-guru",
+      "pl",
+      "prs",
+      "pt-BR",
+      "pt-PT",
+      "quc",
+      "quz",
+      "ro",
+      "ru",
+      "rw",
+      "sd-arab",
+      "si",
+      "sk",
+      "sl",
+      "sq",
+      "sr-cyrl",
+      "sr-latn",
+      "sv",
+      "sw",
+      "ta",
+      "te",
+      "tg-cyrl",
+      "th",
+      "ti",
+      "tk",
+      "tn",
+      "tr",
+      "tt",
+      "ug",
+      "uk",
+      "ur",
+      "uz-latn",
+      "vi",
+      "wo",
+      "xh",
+      "yo",
+      "zh-Hans",
+      "zh-Hant",
+      "zu"
+    ]
+  },
+  "bing news": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": [
+      "af",
+      "am",
+      "ar",
+      "as",
+      "az-latn",
+      "be",
+      "bg",
+      "bn",
+      "bs-latn",
+      "ca",
+      "ca-es-valencia",
+      "chr-cher",
+      "cs",
+      "cy",
+      "da",
+      "de",
+      "el",
+      "en",
+      "es",
+      "et",
+      "eu",
+      "fa",
+      "fi",
+      "fil",
+      "fr",
+      "ga",
+      "gd",
+      "gl",
+      "gu",
+      "ha-latn",
+      "he",
+      "hi",
+      "hr",
+      "hu",
+      "hy",
+      "id",
+      "ig",
+      "is",
+      "it",
+      "ja",
+      "ka",
+      "kk",
+      "km",
+      "kn",
+      "ko",
+      "kok",
+      "ku-arab",
+      "ky",
+      "lb",
+      "lo",
+      "lt",
+      "lv",
+      "mi",
+      "mk",
+      "ml",
+      "mn-Cyrl-MN",
+      "mr",
+      "ms",
+      "mt",
+      "nb",
+      "ne",
+      "nl",
+      "nn",
+      "nso",
+      "or",
+      "pa-arab",
+      "pa-guru",
+      "pl",
+      "prs",
+      "pt-BR",
+      "pt-PT",
+      "quc",
+      "quz",
+      "ro",
+      "ru",
+      "rw",
+      "sd-arab",
+      "si",
+      "sk",
+      "sl",
+      "sq",
+      "sr-cyrl",
+      "sr-latn",
+      "sv",
+      "sw",
+      "ta",
+      "te",
+      "tg-cyrl",
+      "th",
+      "ti",
+      "tk",
+      "tn",
+      "tr",
+      "tt",
+      "ug",
+      "uk",
+      "ur",
+      "uz-latn",
+      "vi",
+      "wo",
+      "xh",
+      "yo",
+      "zh-Hans",
+      "zh-Hant",
+      "zu"
+    ]
+  },
+  "bing videos": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": [
+      "af",
+      "am",
+      "ar",
+      "as",
+      "az-latn",
+      "be",
+      "bg",
+      "bn",
+      "bs-latn",
+      "ca",
+      "ca-es-valencia",
+      "chr-cher",
+      "cs",
+      "cy",
+      "da",
+      "de",
+      "el",
+      "en",
+      "es",
+      "et",
+      "eu",
+      "fa",
+      "fi",
+      "fil",
+      "fr",
+      "ga",
+      "gd",
+      "gl",
+      "gu",
+      "ha-latn",
+      "he",
+      "hi",
+      "hr",
+      "hu",
+      "hy",
+      "id",
+      "ig",
+      "is",
+      "it",
+      "ja",
+      "ka",
+      "kk",
+      "km",
+      "kn",
+      "ko",
+      "kok",
+      "ku-arab",
+      "ky",
+      "lb",
+      "lo",
+      "lt",
+      "lv",
+      "mi",
+      "mk",
+      "ml",
+      "mn-Cyrl-MN",
+      "mr",
+      "ms",
+      "mt",
+      "nb",
+      "ne",
+      "nl",
+      "nn",
+      "nso",
+      "or",
+      "pa-arab",
+      "pa-guru",
+      "pl",
+      "prs",
+      "pt-BR",
+      "pt-PT",
+      "quc",
+      "quz",
+      "ro",
+      "ru",
+      "rw",
+      "sd-arab",
+      "si",
+      "sk",
+      "sl",
+      "sq",
+      "sr-cyrl",
+      "sr-latn",
+      "sv",
+      "sw",
+      "ta",
+      "te",
+      "tg-cyrl",
+      "th",
+      "ti",
+      "tk",
+      "tn",
+      "tr",
+      "tt",
+      "ug",
+      "uk",
+      "ur",
+      "uz-latn",
+      "vi",
+      "wo",
+      "xh",
+      "yo",
+      "zh-Hans",
+      "zh-Hant",
+      "zu"
+    ]
+  },
+  "dailymotion": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": [
+      "ar_AA",
+      "ar_AE",
+      "ar_EG",
+      "ar_SA",
+      "de_AT",
+      "de_CH",
+      "de_DE",
+      "el_GR",
+      "en_AU",
+      "en_CA",
+      "en_EN",
+      "en_GB",
+      "en_HK",
+      "en_IE",
+      "en_IN",
+      "en_NG",
+      "en_PH",
+      "en_PK",
+      "en_SG",
+      "en_US",
+      "en_ZA",
+      "es_AR",
+      "es_ES",
+      "es_MX",
+      "fr_BE",
+      "fr_CA",
+      "fr_CH",
+      "fr_CI",
+      "fr_FR",
+      "fr_MA",
+      "fr_SN",
+      "fr_TN",
+      "id_ID",
+      "it_CH",
+      "it_IT",
+      "ja_JP",
+      "ko_KR",
+      "ms_MY",
+      "nl_BE",
+      "nl_NL",
+      "pl_PL",
+      "pt_BR",
+      "pt_PT",
+      "ro_RO",
+      "ru_RU",
+      "th_TH",
+      "tr_TR",
+      "vi_VN",
+      "zh_CN",
+      "zh_TW"
+    ]
+  },
+  "ddg definitions": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": [
+      "ar-XA",
+      "bg-BG",
+      "ca-CT",
+      "ca-ES",
+      "cs-CZ",
+      "da-DK",
+      "de-AT",
+      "de-CH",
+      "de-DE",
+      "el-GR",
+      "en-AU",
+      "en-CA",
+      "en-ID",
+      "en-IE",
+      "en-IL",
+      "en-IN",
+      "en-MY",
+      "en-NZ",
+      "en-PH",
+      "en-PK",
+      "en-SG",
+      "en-TH",
+      "en-UK",
+      "en-US",
+      "en-VN",
+      "en-ZA",
+      "es-AR",
+      "es-CL",
+      "es-CO",
+      "es-ES",
+      "es-MX",
+      "es-PE",
+      "es-US",
+      "et-EE",
+      "fi-FI",
+      "fr-BE",
+      "fr-CA",
+      "fr-CH",
+      "fr-FR",
+      "hr-HR",
+      "hu-HU",
+      "it-IT",
+      "jp-JP",
+      "kr-KR",
+      "lt-LT",
+      "lv-LV",
+      "nl-BE",
+      "nl-NL",
+      "no-NO",
+      "pl-PL",
+      "pt-BR",
+      "pt-PT",
+      "ro-RO",
+      "ru-RU",
+      "sk-SK",
+      "sl-SL",
+      "sv-SE",
+      "tr-TR",
+      "tzh-HK",
+      "tzh-TW",
+      "uk-UA",
+      "wt-WT",
+      "zh-CN"
+    ]
+  },
+  "duckduckgo": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": [
+      "ar-XA",
+      "bg-BG",
+      "ca-CT",
+      "ca-ES",
+      "cs-CZ",
+      "da-DK",
+      "de-AT",
+      "de-CH",
+      "de-DE",
+      "el-GR",
+      "en-AU",
+      "en-CA",
+      "en-ID",
+      "en-IE",
+      "en-IL",
+      "en-IN",
+      "en-MY",
+      "en-NZ",
+      "en-PH",
+      "en-PK",
+      "en-SG",
+      "en-TH",
+      "en-UK",
+      "en-US",
+      "en-VN",
+      "en-ZA",
+      "es-AR",
+      "es-CL",
+      "es-CO",
+      "es-ES",
+      "es-MX",
+      "es-PE",
+      "es-US",
+      "et-EE",
+      "fi-FI",
+      "fr-BE",
+      "fr-CA",
+      "fr-CH",
+      "fr-FR",
+      "hr-HR",
+      "hu-HU",
+      "it-IT",
+      "jp-JP",
+      "kr-KR",
+      "lt-LT",
+      "lv-LV",
+      "nl-BE",
+      "nl-NL",
+      "no-NO",
+      "pl-PL",
+      "pt-BR",
+      "pt-PT",
+      "ro-RO",
+      "ru-RU",
+      "sk-SK",
+      "sl-SL",
+      "sv-SE",
+      "tr-TR",
+      "tzh-HK",
+      "tzh-TW",
+      "uk-UA",
+      "wt-WT",
+      "zh-CN"
+    ]
+  },
+  "duckduckgo images": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": [
+      "ar-XA",
+      "bg-BG",
+      "ca-CT",
+      "ca-ES",
+      "cs-CZ",
+      "da-DK",
+      "de-AT",
+      "de-CH",
+      "de-DE",
+      "el-GR",
+      "en-AU",
+      "en-CA",
+      "en-ID",
+      "en-IE",
+      "en-IL",
+      "en-IN",
+      "en-MY",
+      "en-NZ",
+      "en-PH",
+      "en-PK",
+      "en-SG",
+      "en-TH",
+      "en-UK",
+      "en-US",
+      "en-VN",
+      "en-ZA",
+      "es-AR",
+      "es-CL",
+      "es-CO",
+      "es-ES",
+      "es-MX",
+      "es-PE",
+      "es-US",
+      "et-EE",
+      "fi-FI",
+      "fr-BE",
+      "fr-CA",
+      "fr-CH",
+      "fr-FR",
+      "hr-HR",
+      "hu-HU",
+      "it-IT",
+      "jp-JP",
+      "kr-KR",
+      "lt-LT",
+      "lv-LV",
+      "nl-BE",
+      "nl-NL",
+      "no-NO",
+      "pl-PL",
+      "pt-BR",
+      "pt-PT",
+      "ro-RO",
+      "ru-RU",
+      "sk-SK",
+      "sl-SL",
+      "sv-SE",
+      "tr-TR",
+      "tzh-HK",
+      "tzh-TW",
+      "uk-UA",
+      "wt-WT",
+      "zh-CN"
+    ]
+  },
+  "google": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": {
+      "af": {
+        "name": "Afrikaans"
+      },
+      "ar": {
+        "name": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629"
+      },
+      "be": {
+        "name": "\u0431\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f"
+      },
+      "bg": {
+        "name": "\u0431\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438"
+      },
+      "ca": {
+        "name": "catal\u00e0"
+      },
+      "cs": {
+        "name": "\u010de\u0161tina"
+      },
+      "da": {
+        "name": "dansk"
+      },
+      "de": {
+        "name": "Deutsch"
+      },
+      "el": {
+        "name": "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac"
+      },
+      "en": {
+        "name": "English"
+      },
+      "eo": {
+        "name": "esperanto"
+      },
+      "es": {
+        "name": "espa\u00f1ol"
+      },
+      "et": {
+        "name": "eesti"
+      },
+      "fa": {
+        "name": "\u0641\u0627\u0631\u0633\u06cc"
+      },
+      "fi": {
+        "name": "suomi"
+      },
+      "fr": {
+        "name": "fran\u00e7ais"
+      },
+      "hi": {
+        "name": "\u0939\u093f\u0928\u094d\u0926\u0940"
+      },
+      "hr": {
+        "name": "hrvatski"
+      },
+      "hu": {
+        "name": "magyar"
+      },
+      "hy": {
+        "name": "\u0570\u0561\u0575\u0565\u0580\u0565\u0576"
+      },
+      "id": {
+        "name": "Indonesia"
+      },
+      "is": {
+        "name": "\u00edslenska"
+      },
+      "it": {
+        "name": "italiano"
+      },
+      "iw": {
+        "name": "\u05e2\u05d1\u05e8\u05d9\u05ea"
+      },
+      "ja": {
+        "name": "\u65e5\u672c\u8a9e"
+      },
+      "ko": {
+        "name": "\ud55c\uad6d\uc5b4"
+      },
+      "lt": {
+        "name": "lietuvi\u0173"
+      },
+      "lv": {
+        "name": "latvie\u0161u"
+      },
+      "nl": {
+        "name": "Nederlands"
+      },
+      "no": {
+        "name": "norsk"
+      },
+      "pl": {
+        "name": "polski"
+      },
+      "pt": {
+        "name": "portugu\u00eas"
+      },
+      "ro": {
+        "name": "rom\u00e2n\u0103"
+      },
+      "ru": {
+        "name": "\u0440\u0443\u0441\u0441\u043a\u0438\u0439"
+      },
+      "sk": {
+        "name": "sloven\u010dina"
+      },
+      "sl": {
+        "name": "sloven\u0161\u010dina"
+      },
+      "sr": {
+        "name": "\u0441\u0440\u043f\u0441\u043a\u0438"
+      },
+      "sv": {
+        "name": "svenska"
+      },
+      "sw": {
+        "name": "Kiswahili"
+      },
+      "th": {
+        "name": "\u0e44\u0e17\u0e22"
+      },
+      "tl": {
+        "name": "Filipino"
+      },
+      "tr": {
+        "name": "T\u00fcrk\u00e7e"
+      },
+      "uk": {
+        "name": "\u0443\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"
+      },
+      "vi": {
+        "name": "Ti\u1ebfng Vi\u1ec7t"
+      },
+      "zh-CN": {
+        "name": "\u4e2d\u6587 (\u7b80\u4f53)"
+      },
+      "zh-TW": {
+        "name": "\u4e2d\u6587 (\u7e41\u9ad4)"
+      }
+    }
+  },
+  "google images": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": {
+      "af": {
+        "name": "Afrikaans"
+      },
+      "ar": {
+        "name": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629"
+      },
+      "be": {
+        "name": "\u0431\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f"
+      },
+      "bg": {
+        "name": "\u0431\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438"
+      },
+      "ca": {
+        "name": "catal\u00e0"
+      },
+      "cs": {
+        "name": "\u010de\u0161tina"
+      },
+      "da": {
+        "name": "dansk"
+      },
+      "de": {
+        "name": "Deutsch"
+      },
+      "el": {
+        "name": "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac"
+      },
+      "en": {
+        "name": "English"
+      },
+      "eo": {
+        "name": "esperanto"
+      },
+      "es": {
+        "name": "espa\u00f1ol"
+      },
+      "et": {
+        "name": "eesti"
+      },
+      "fa": {
+        "name": "\u0641\u0627\u0631\u0633\u06cc"
+      },
+      "fi": {
+        "name": "suomi"
+      },
+      "fr": {
+        "name": "fran\u00e7ais"
+      },
+      "hi": {
+        "name": "\u0939\u093f\u0928\u094d\u0926\u0940"
+      },
+      "hr": {
+        "name": "hrvatski"
+      },
+      "hu": {
+        "name": "magyar"
+      },
+      "hy": {
+        "name": "\u0570\u0561\u0575\u0565\u0580\u0565\u0576"
+      },
+      "id": {
+        "name": "Indonesia"
+      },
+      "is": {
+        "name": "\u00edslenska"
+      },
+      "it": {
+        "name": "italiano"
+      },
+      "iw": {
+        "name": "\u05e2\u05d1\u05e8\u05d9\u05ea"
+      },
+      "ja": {
+        "name": "\u65e5\u672c\u8a9e"
+      },
+      "ko": {
+        "name": "\ud55c\uad6d\uc5b4"
+      },
+      "lt": {
+        "name": "lietuvi\u0173"
+      },
+      "lv": {
+        "name": "latvie\u0161u"
+      },
+      "nl": {
+        "name": "Nederlands"
+      },
+      "no": {
+        "name": "norsk"
+      },
+      "pl": {
+        "name": "polski"
+      },
+      "pt": {
+        "name": "portugu\u00eas"
+      },
+      "ro": {
+        "name": "rom\u00e2n\u0103"
+      },
+      "ru": {
+        "name": "\u0440\u0443\u0441\u0441\u043a\u0438\u0439"
+      },
+      "sk": {
+        "name": "sloven\u010dina"
+      },
+      "sl": {
+        "name": "sloven\u0161\u010dina"
+      },
+      "sr": {
+        "name": "\u0441\u0440\u043f\u0441\u043a\u0438"
+      },
+      "sv": {
+        "name": "svenska"
+      },
+      "sw": {
+        "name": "Kiswahili"
+      },
+      "th": {
+        "name": "\u0e44\u0e17\u0e22"
+      },
+      "tl": {
+        "name": "Filipino"
+      },
+      "tr": {
+        "name": "T\u00fcrk\u00e7e"
+      },
+      "uk": {
+        "name": "\u0443\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"
+      },
+      "vi": {
+        "name": "Ti\u1ebfng Vi\u1ec7t"
+      },
+      "zh-CN": {
+        "name": "\u4e2d\u6587 (\u7b80\u4f53)"
+      },
+      "zh-TW": {
+        "name": "\u4e2d\u6587 (\u7e41\u9ad4)"
+      }
+    }
+  },
+  "google news": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": {
+      "af": {
+        "name": "Afrikaans"
+      },
+      "ar": {
+        "name": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629"
+      },
+      "be": {
+        "name": "\u0431\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f"
+      },
+      "bg": {
+        "name": "\u0431\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438"
+      },
+      "ca": {
+        "name": "catal\u00e0"
+      },
+      "cs": {
+        "name": "\u010de\u0161tina"
+      },
+      "da": {
+        "name": "dansk"
+      },
+      "de": {
+        "name": "Deutsch"
+      },
+      "el": {
+        "name": "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac"
+      },
+      "en": {
+        "name": "English"
+      },
+      "eo": {
+        "name": "esperanto"
+      },
+      "es": {
+        "name": "espa\u00f1ol"
+      },
+      "et": {
+        "name": "eesti"
+      },
+      "fa": {
+        "name": "\u0641\u0627\u0631\u0633\u06cc"
+      },
+      "fi": {
+        "name": "suomi"
+      },
+      "fr": {
+        "name": "fran\u00e7ais"
+      },
+      "hi": {
+        "name": "\u0939\u093f\u0928\u094d\u0926\u0940"
+      },
+      "hr": {
+        "name": "hrvatski"
+      },
+      "hu": {
+        "name": "magyar"
+      },
+      "hy": {
+        "name": "\u0570\u0561\u0575\u0565\u0580\u0565\u0576"
+      },
+      "id": {
+        "name": "Indonesia"
+      },
+      "is": {
+        "name": "\u00edslenska"
+      },
+      "it": {
+        "name": "italiano"
+      },
+      "iw": {
+        "name": "\u05e2\u05d1\u05e8\u05d9\u05ea"
+      },
+      "ja": {
+        "name": "\u65e5\u672c\u8a9e"
+      },
+      "ko": {
+        "name": "\ud55c\uad6d\uc5b4"
+      },
+      "lt": {
+        "name": "lietuvi\u0173"
+      },
+      "lv": {
+        "name": "latvie\u0161u"
+      },
+      "nl": {
+        "name": "Nederlands"
+      },
+      "no": {
+        "name": "norsk"
+      },
+      "pl": {
+        "name": "polski"
+      },
+      "pt": {
+        "name": "portugu\u00eas"
+      },
+      "ro": {
+        "name": "rom\u00e2n\u0103"
+      },
+      "ru": {
+        "name": "\u0440\u0443\u0441\u0441\u043a\u0438\u0439"
+      },
+      "sk": {
+        "name": "sloven\u010dina"
+      },
+      "sl": {
+        "name": "sloven\u0161\u010dina"
+      },
+      "sr": {
+        "name": "\u0441\u0440\u043f\u0441\u043a\u0438"
+      },
+      "sv": {
+        "name": "svenska"
+      },
+      "sw": {
+        "name": "Kiswahili"
+      },
+      "th": {
+        "name": "\u0e44\u0e17\u0e22"
+      },
+      "tl": {
+        "name": "Filipino"
+      },
+      "tr": {
+        "name": "T\u00fcrk\u00e7e"
+      },
+      "uk": {
+        "name": "\u0443\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"
+      },
+      "vi": {
+        "name": "Ti\u1ebfng Vi\u1ec7t"
+      },
+      "zh-CN": {
+        "name": "\u4e2d\u6587 (\u7b80\u4f53)"
+      },
+      "zh-TW": {
+        "name": "\u4e2d\u6587 (\u7e41\u9ad4)"
+      }
+    }
+  },
+  "google scholar": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": {
+      "af": {
+        "name": "Afrikaans"
+      },
+      "ar": {
+        "name": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629"
+      },
+      "be": {
+        "name": "\u0431\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f"
+      },
+      "bg": {
+        "name": "\u0431\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438"
+      },
+      "ca": {
+        "name": "catal\u00e0"
+      },
+      "cs": {
+        "name": "\u010de\u0161tina"
+      },
+      "da": {
+        "name": "dansk"
+      },
+      "de": {
+        "name": "Deutsch"
+      },
+      "el": {
+        "name": "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac"
+      },
+      "en": {
+        "name": "English"
+      },
+      "eo": {
+        "name": "esperanto"
+      },
+      "es": {
+        "name": "espa\u00f1ol"
+      },
+      "et": {
+        "name": "eesti"
+      },
+      "fa": {
+        "name": "\u0641\u0627\u0631\u0633\u06cc"
+      },
+      "fi": {
+        "name": "suomi"
+      },
+      "fr": {
+        "name": "fran\u00e7ais"
+      },
+      "hi": {
+        "name": "\u0939\u093f\u0928\u094d\u0926\u0940"
+      },
+      "hr": {
+        "name": "hrvatski"
+      },
+      "hu": {
+        "name": "magyar"
+      },
+      "hy": {
+        "name": "\u0570\u0561\u0575\u0565\u0580\u0565\u0576"
+      },
+      "id": {
+        "name": "Indonesia"
+      },
+      "is": {
+        "name": "\u00edslenska"
+      },
+      "it": {
+        "name": "italiano"
+      },
+      "iw": {
+        "name": "\u05e2\u05d1\u05e8\u05d9\u05ea"
+      },
+      "ja": {
+        "name": "\u65e5\u672c\u8a9e"
+      },
+      "ko": {
+        "name": "\ud55c\uad6d\uc5b4"
+      },
+      "lt": {
+        "name": "lietuvi\u0173"
+      },
+      "lv": {
+        "name": "latvie\u0161u"
+      },
+      "nl": {
+        "name": "Nederlands"
+      },
+      "no": {
+        "name": "norsk"
+      },
+      "pl": {
+        "name": "polski"
+      },
+      "pt": {
+        "name": "portugu\u00eas"
+      },
+      "ro": {
+        "name": "rom\u00e2n\u0103"
+      },
+      "ru": {
+        "name": "\u0440\u0443\u0441\u0441\u043a\u0438\u0439"
+      },
+      "sk": {
+        "name": "sloven\u010dina"
+      },
+      "sl": {
+        "name": "sloven\u0161\u010dina"
+      },
+      "sr": {
+        "name": "\u0441\u0440\u043f\u0441\u043a\u0438"
+      },
+      "sv": {
+        "name": "svenska"
+      },
+      "sw": {
+        "name": "Kiswahili"
+      },
+      "th": {
+        "name": "\u0e44\u0e17\u0e22"
+      },
+      "tl": {
+        "name": "Filipino"
+      },
+      "tr": {
+        "name": "T\u00fcrk\u00e7e"
+      },
+      "uk": {
+        "name": "\u0443\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"
+      },
+      "vi": {
+        "name": "Ti\u1ebfng Vi\u1ec7t"
+      },
+      "zh-CN": {
+        "name": "\u4e2d\u6587 (\u7b80\u4f53)"
+      },
+      "zh-TW": {
+        "name": "\u4e2d\u6587 (\u7e41\u9ad4)"
+      }
+    }
+  },
+  "google videos": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": {
+      "af": {
+        "name": "Afrikaans"
+      },
+      "ar": {
+        "name": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629"
+      },
+      "be": {
+        "name": "\u0431\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f"
+      },
+      "bg": {
+        "name": "\u0431\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438"
+      },
+      "ca": {
+        "name": "catal\u00e0"
+      },
+      "cs": {
+        "name": "\u010de\u0161tina"
+      },
+      "da": {
+        "name": "dansk"
+      },
+      "de": {
+        "name": "Deutsch"
+      },
+      "el": {
+        "name": "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac"
+      },
+      "en": {
+        "name": "English"
+      },
+      "eo": {
+        "name": "esperanto"
+      },
+      "es": {
+        "name": "espa\u00f1ol"
+      },
+      "et": {
+        "name": "eesti"
+      },
+      "fa": {
+        "name": "\u0641\u0627\u0631\u0633\u06cc"
+      },
+      "fi": {
+        "name": "suomi"
+      },
+      "fr": {
+        "name": "fran\u00e7ais"
+      },
+      "hi": {
+        "name": "\u0939\u093f\u0928\u094d\u0926\u0940"
+      },
+      "hr": {
+        "name": "hrvatski"
+      },
+      "hu": {
+        "name": "magyar"
+      },
+      "hy": {
+        "name": "\u0570\u0561\u0575\u0565\u0580\u0565\u0576"
+      },
+      "id": {
+        "name": "Indonesia"
+      },
+      "is": {
+        "name": "\u00edslenska"
+      },
+      "it": {
+        "name": "italiano"
+      },
+      "iw": {
+        "name": "\u05e2\u05d1\u05e8\u05d9\u05ea"
+      },
+      "ja": {
+        "name": "\u65e5\u672c\u8a9e"
+      },
+      "ko": {
+        "name": "\ud55c\uad6d\uc5b4"
+      },
+      "lt": {
+        "name": "lietuvi\u0173"
+      },
+      "lv": {
+        "name": "latvie\u0161u"
+      },
+      "nl": {
+        "name": "Nederlands"
+      },
+      "no": {
+        "name": "norsk"
+      },
+      "pl": {
+        "name": "polski"
+      },
+      "pt": {
+        "name": "portugu\u00eas"
+      },
+      "ro": {
+        "name": "rom\u00e2n\u0103"
+      },
+      "ru": {
+        "name": "\u0440\u0443\u0441\u0441\u043a\u0438\u0439"
+      },
+      "sk": {
+        "name": "sloven\u010dina"
+      },
+      "sl": {
+        "name": "sloven\u0161\u010dina"
+      },
+      "sr": {
+        "name": "\u0441\u0440\u043f\u0441\u043a\u0438"
+      },
+      "sv": {
+        "name": "svenska"
+      },
+      "sw": {
+        "name": "Kiswahili"
+      },
+      "th": {
+        "name": "\u0e44\u0e17\u0e22"
+      },
+      "tl": {
+        "name": "Filipino"
+      },
+      "tr": {
+        "name": "T\u00fcrk\u00e7e"
+      },
+      "uk": {
+        "name": "\u0443\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"
+      },
+      "vi": {
+        "name": "Ti\u1ebfng Vi\u1ec7t"
+      },
+      "zh-CN": {
+        "name": "\u4e2d\u6587 (\u7b80\u4f53)"
+      },
+      "zh-TW": {
+        "name": "\u4e2d\u6587 (\u7e41\u9ad4)"
+      }
+    }
+  },
+  "peertube": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": [
+      "ca",
+      "cs",
+      "de",
+      "el",
+      "en",
+      "eo",
+      "es",
+      "eu",
+      "fi",
+      "fr",
+      "gd",
+      "it",
+      "ja",
+      "nl",
+      "oc",
+      "pl",
+      "pt",
+      "ru",
+      "sv",
+      "zh"
+    ]
+  },
+  "qwant": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": {
+      "bg-BG": "bg_BG",
+      "ca-ES": "ca_ES",
+      "cs-CZ": "cs_CZ",
+      "da-DK": "da_DK",
+      "de-AT": "de_AT",
+      "de-CH": "de_CH",
+      "de-DE": "de_DE",
+      "el-GR": "el_GR",
+      "en-AU": "en_AU",
+      "en-CA": "en_CA",
+      "en-GB": "en_GB",
+      "en-IE": "en_IE",
+      "en-MY": "en_MY",
+      "en-NZ": "en_NZ",
+      "en-US": "en_US",
+      "es-AR": "es_AR",
+      "es-CL": "es_CL",
+      "es-ES": "es_ES",
+      "es-MX": "es_MX",
+      "et-EE": "et_EE",
+      "fi-FI": "fi_FI",
+      "fr-BE": "fr_BE",
+      "fr-CA": "fr_CA",
+      "fr-CH": "fr_CH",
+      "fr-FR": "fr_FR",
+      "hu-HU": "hu_HU",
+      "it-CH": "it_CH",
+      "it-IT": "it_IT",
+      "ko-KR": "ko_KR",
+      "nb-NO": "nb_NO",
+      "nl-BE": "nl_BE",
+      "nl-NL": "nl_NL",
+      "pl-PL": "pl_PL",
+      "pt-PT": "pt_PT",
+      "ro-RO": "ro_RO",
+      "sv-SE": "sv_SE",
+      "th-TH": "th_TH",
+      "zh-CN": "zh_CN",
+      "zh-HK": "zh_HK"
+    }
+  },
+  "qwant images": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": {
+      "bg-BG": "bg_BG",
+      "ca-ES": "ca_ES",
+      "cs-CZ": "cs_CZ",
+      "da-DK": "da_DK",
+      "de-AT": "de_AT",
+      "de-CH": "de_CH",
+      "de-DE": "de_DE",
+      "el-GR": "el_GR",
+      "en-AU": "en_AU",
+      "en-CA": "en_CA",
+      "en-GB": "en_GB",
+      "en-IE": "en_IE",
+      "en-MY": "en_MY",
+      "en-NZ": "en_NZ",
+      "en-US": "en_US",
+      "es-AR": "es_AR",
+      "es-CL": "es_CL",
+      "es-ES": "es_ES",
+      "es-MX": "es_MX",
+      "et-EE": "et_EE",
+      "fi-FI": "fi_FI",
+      "fr-BE": "fr_BE",
+      "fr-CA": "fr_CA",
+      "fr-CH": "fr_CH",
+      "fr-FR": "fr_FR",
+      "hu-HU": "hu_HU",
+      "it-CH": "it_CH",
+      "it-IT": "it_IT",
+      "ko-KR": "ko_KR",
+      "nb-NO": "nb_NO",
+      "nl-BE": "nl_BE",
+      "nl-NL": "nl_NL",
+      "pl-PL": "pl_PL",
+      "pt-PT": "pt_PT",
+      "ro-RO": "ro_RO",
+      "sv-SE": "sv_SE",
+      "th-TH": "th_TH",
+      "zh-CN": "zh_CN",
+      "zh-HK": "zh_HK"
+    }
+  },
+  "qwant news": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": {
+      "ca-ES": "ca_ES",
+      "de-AT": "de_AT",
+      "de-CH": "de_CH",
+      "de-DE": "de_DE",
+      "en-AU": "en_AU",
+      "en-CA": "en_CA",
+      "en-GB": "en_GB",
+      "en-IE": "en_IE",
+      "en-MY": "en_MY",
+      "en-NZ": "en_NZ",
+      "en-US": "en_US",
+      "es-AR": "es_AR",
+      "es-CL": "es_CL",
+      "es-ES": "es_ES",
+      "es-MX": "es_MX",
+      "fr-BE": "fr_BE",
+      "fr-CA": "fr_CA",
+      "fr-CH": "fr_CH",
+      "fr-FR": "fr_FR",
+      "it-CH": "it_CH",
+      "it-IT": "it_IT",
+      "nl-BE": "nl_BE",
+      "nl-NL": "nl_NL",
+      "pt-PT": "pt_PT"
+    }
+  },
+  "qwant videos": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": {
+      "bg-BG": "bg_BG",
+      "ca-ES": "ca_ES",
+      "cs-CZ": "cs_CZ",
+      "da-DK": "da_DK",
+      "de-AT": "de_AT",
+      "de-CH": "de_CH",
+      "de-DE": "de_DE",
+      "el-GR": "el_GR",
+      "en-AU": "en_AU",
+      "en-CA": "en_CA",
+      "en-GB": "en_GB",
+      "en-IE": "en_IE",
+      "en-MY": "en_MY",
+      "en-NZ": "en_NZ",
+      "en-US": "en_US",
+      "es-AR": "es_AR",
+      "es-CL": "es_CL",
+      "es-ES": "es_ES",
+      "es-MX": "es_MX",
+      "et-EE": "et_EE",
+      "fi-FI": "fi_FI",
+      "fr-BE": "fr_BE",
+      "fr-CA": "fr_CA",
+      "fr-CH": "fr_CH",
+      "fr-FR": "fr_FR",
+      "hu-HU": "hu_HU",
+      "it-CH": "it_CH",
+      "it-IT": "it_IT",
+      "ko-KR": "ko_KR",
+      "nb-NO": "nb_NO",
+      "nl-BE": "nl_BE",
+      "nl-NL": "nl_NL",
+      "pl-PL": "pl_PL",
+      "pt-PT": "pt_PT",
+      "ro-RO": "ro_RO",
+      "sv-SE": "sv_SE",
+      "th-TH": "th_TH",
+      "zh-CN": "zh_CN",
+      "zh-HK": "zh_HK"
+    }
+  },
+  "startpage": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": {
+      "af": {
+        "alias": "afrikaans"
+      },
+      "am": {
+        "alias": "amharic"
+      },
+      "ar": {
+        "alias": "arabic"
+      },
+      "az": {
+        "alias": "azerbaijani"
+      },
+      "be": {
+        "alias": "belarusian"
+      },
+      "bg": {
+        "alias": "bulgarian"
+      },
+      "bn": {
+        "alias": "bengali"
+      },
+      "bs": {
+        "alias": "bosnian"
+      },
+      "ca": {
+        "alias": "catalan"
+      },
+      "cs": {
+        "alias": "czech"
+      },
+      "cy": {
+        "alias": "welsh"
+      },
+      "da": {
+        "alias": "dansk"
+      },
+      "de": {
+        "alias": "deutsch"
+      },
+      "el": {
+        "alias": "greek"
+      },
+      "en": {
+        "alias": "english"
+      },
+      "en-GB": {
+        "alias": "english_uk"
+      },
+      "eo": {
+        "alias": "esperanto"
+      },
+      "es": {
+        "alias": "espanol"
+      },
+      "et": {
+        "alias": "estonian"
+      },
+      "eu": {
+        "alias": "basque"
+      },
+      "fa": {
+        "alias": "persian"
+      },
+      "fi": {
+        "alias": "suomi"
+      },
+      "fo": {
+        "alias": "faroese"
+      },
+      "fr": {
+        "alias": "francais"
+      },
+      "fy": {
+        "alias": "frisian"
+      },
+      "ga": {
+        "alias": "irish"
+      },
+      "gd": {
+        "alias": "gaelic"
+      },
+      "gl": {
+        "alias": "galician"
+      },
+      "gu": {
+        "alias": "gujarati"
+      },
+      "he": {
+        "alias": "hebrew"
+      },
+      "hi": {
+        "alias": "hindi"
+      },
+      "hr": {
+        "alias": "croatian"
+      },
+      "hu": {
+        "alias": "hungarian"
+      },
+      "ia": {
+        "alias": "interlingua"
+      },
+      "id": {
+        "alias": "indonesian"
+      },
+      "is": {
+        "alias": "icelandic"
+      },
+      "it": {
+        "alias": "italiano"
+      },
+      "ja": {
+        "alias": "nihongo"
+      },
+      "jv": {
+        "alias": "javanese"
+      },
+      "ka": {
+        "alias": "georgian"
+      },
+      "kn": {
+        "alias": "kannada"
+      },
+      "ko": {
+        "alias": "hangul"
+      },
+      "la": {
+        "alias": "latin"
+      },
+      "lt": {
+        "alias": "lithuanian"
+      },
+      "lv": {
+        "alias": "latvian"
+      },
+      "mai": {
+        "alias": "bihari"
+      },
+      "mk": {
+        "alias": "macedonian"
+      },
+      "ml": {
+        "alias": "malayalam"
+      },
+      "mr": {
+        "alias": "marathi"
+      },
+      "ms": {
+        "alias": "malay"
+      },
+      "mt": {
+        "alias": "maltese"
+      },
+      "ne": {
+        "alias": "nepali"
+      },
+      "nl": {
+        "alias": "nederlands"
+      },
+      "no": {
+        "alias": "norsk"
+      },
+      "oc": {
+        "alias": "occitan"
+      },
+      "pa": {
+        "alias": "punjabi"
+      },
+      "pl": {
+        "alias": "polski"
+      },
+      "pt": {
+        "alias": "portugues"
+      },
+      "ro": {
+        "alias": "romanian"
+      },
+      "ru": {
+        "alias": "russian"
+      },
+      "si": {
+        "alias": "sinhalese"
+      },
+      "sk": {
+        "alias": "slovak"
+      },
+      "sl": {
+        "alias": "slovenian"
+      },
+      "sq": {
+        "alias": "albanian"
+      },
+      "sr": {
+        "alias": "serbian"
+      },
+      "su": {
+        "alias": "sudanese"
+      },
+      "sv": {
+        "alias": "svenska"
+      },
+      "sw": {
+        "alias": "swahili"
+      },
+      "ta": {
+        "alias": "tamil"
+      },
+      "te": {
+        "alias": "telugu"
+      },
+      "th": {
+        "alias": "thai"
+      },
+      "ti": {
+        "alias": "tigrinya"
+      },
+      "tl": {
+        "alias": "tagalog"
+      },
+      "tr": {
+        "alias": "turkce"
+      },
+      "uk": {
+        "alias": "ukrainian"
+      },
+      "ur": {
+        "alias": "urdu"
+      },
+      "uz": {
+        "alias": "uzbek"
+      },
+      "vi": {
+        "alias": "vietnamese"
+      },
+      "xh": {
+        "alias": "xhosa"
+      },
+      "zh": {
+        "alias": "jiantizhongwen"
+      },
+      "zh-HK": {
+        "alias": "fantizhengwen"
+      },
+      "zh-TW": {
+        "alias": "fantizhengwen"
+      },
+      "zu": {
+        "alias": "zulu"
+      }
+    }
+  },
+  "wikidata": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": {
+      "ab": {
+        "english_name": "Abkhazian",
+        "name": "\u0410\u0525\u0441\u0443\u0430"
+      },
+      "ace": {
+        "english_name": "Acehnese",
+        "name": "Basa Ac\u00e8h"
+      },
+      "ady": {
+        "english_name": "Adyghe",
+        "name": "\u0410\u0434\u044b\u0433\u044d\u0431\u0437\u044d"
+      },
+      "af": {
+        "english_name": "Afrikaans",
+        "name": "Afrikaans"
+      },
+      "ak": {
+        "english_name": "Akan",
+        "name": "Akana"
+      },
+      "als": {
+        "english_name": "Alemannic",
+        "name": "Alemannisch"
+      },
+      "alt": {
+        "english_name": "Southern Altai",
+        "name": "\u0410\u043b\u0442\u0430\u0439"
+      },
+      "am": {
+        "english_name": "Amharic",
+        "name": "\u12a0\u121b\u122d\u129b"
+      },
+      "ami": {
+        "english_name": "Amis",
+        "name": "Pangcah"
+      },
+      "an": {
+        "english_name": "Aragonese",
+        "name": "Aragon\u00e9s"
+      },
+      "ang": {
+        "english_name": "Anglo-Saxon",
+        "name": "\u00c6nglisc"
+      },
+      "ar": {
+        "english_name": "Arabic",
+        "name": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629"
+      },
+      "arc": {
+        "english_name": "Aramaic",
+        "name": "\u0710\u072a\u0721\u071d\u0710"
+      },
+      "ary": {
+        "english_name": "Moroccan Arabic",
+        "name": "\u062f\u0627\u0631\u064a\u062c\u0629"
+      },
+      "arz": {
+        "english_name": "Egyptian Arabic",
+        "name": "\u0645\u0635\u0631\u0649 (Ma\u1e63ri)"
+      },
+      "as": {
+        "english_name": "Assamese",
+        "name": "\u0985\u09b8\u09ae\u09c0\u09af\u09bc\u09be"
+      },
+      "ast": {
+        "english_name": "Asturian",
+        "name": "Asturianu"
+      },
+      "atj": {
+        "english_name": "Atikamekw",
+        "name": "Atikamekw"
+      },
+      "av": {
+        "english_name": "Avar",
+        "name": "\u0410\u0432\u0430\u0440"
+      },
+      "avk": {
+        "english_name": "Kotava",
+        "name": "Kotava"
+      },
+      "awa": {
+        "english_name": "Awadhi",
+        "name": "\u0905\u0935\u0927\u0940"
+      },
+      "ay": {
+        "english_name": "Aymara",
+        "name": "Aymar"
+      },
+      "az": {
+        "english_name": "Azerbaijani",
+        "name": "Az\u0259rbaycanca"
+      },
+      "azb": {
+        "english_name": "South Azerbaijani",
+        "name": "\u062a\u06c6\u0631\u06a9\u062c\u0647"
+      },
+      "ba": {
+        "english_name": "Bashkir",
+        "name": "\u0411\u0430\u0448\u04a1\u043e\u0440\u0442"
+      },
+      "ban": {
+        "english_name": "Balinese",
+        "name": "Bali"
+      },
+      "bar": {
+        "english_name": "Bavarian",
+        "name": "Boarisch"
+      },
+      "bat-smg": {
+        "english_name": "Samogitian",
+        "name": "\u017demait\u0117\u0161ka"
+      },
+      "bcl": {
+        "english_name": "Central Bicolano",
+        "name": "Bikol"
+      },
+      "be": {
+        "english_name": "Belarusian",
+        "name": "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f"
+      },
+      "be-tarask": {
+        "english_name": "Belarusian (Tara\u0161kievica)",
+        "name": "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430)"
+      },
+      "bg": {
+        "english_name": "Bulgarian",
+        "name": "\u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438"
+      },
+      "bh": {
+        "english_name": "Bhojpuri",
+        "name": "\u092d\u094b\u091c\u092a\u0941\u0930\u0940"
+      },
+      "bi": {
+        "english_name": "Bislama",
+        "name": "Bislama"
+      },
+      "bjn": {
+        "english_name": "Banjar",
+        "name": "Bahasa Banjar"
+      },
+      "blk": {
+        "english_name": "Pa'O",
+        "name": "\u1015\u1021\u102d\u102f\u101d\u103a\u108f\u1018\u102c\u108f\u101e\u102c\u108f"
+      },
+      "bm": {
+        "english_name": "Bambara",
+        "name": "Bamanankan"
+      },
+      "bn": {
+        "english_name": "Bengali",
+        "name": "\u09ac\u09be\u0982\u09b2\u09be"
+      },
+      "bo": {
+        "english_name": "Tibetan",
+        "name": "\u0f56\u0f7c\u0f51\u0f0b\u0f66\u0f90\u0f51"
+      },
+      "bpy": {
+        "english_name": "Bishnupriya Manipuri",
+        "name": "\u0987\u09ae\u09be\u09b0 \u09a0\u09be\u09b0/\u09ac\u09bf\u09b7\u09cd\u09a3\u09c1\u09aa\u09cd\u09b0\u09bf\u09af\u09bc\u09be \u09ae\u09a3\u09bf\u09aa\u09c1\u09b0\u09c0"
+      },
+      "br": {
+        "english_name": "Breton",
+        "name": "Brezhoneg"
+      },
+      "bs": {
+        "english_name": "Bosnian",
+        "name": "Bosanski"
+      },
+      "bug": {
+        "english_name": "Buginese",
+        "name": "Basa Ugi"
+      },
+      "bxr": {
+        "english_name": "Buryat",
+        "name": "\u0411\u0443\u0440\u044f\u0430\u0434"
+      },
+      "ca": {
+        "english_name": "Catalan",
+        "name": "Catal\u00e0"
+      },
+      "cbk-zam": {
+        "english_name": "Zamboanga Chavacano",
+        "name": "Chavacano de Zamboanga"
+      },
+      "cdo": {
+        "english_name": "Min Dong",
+        "name": "M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304"
+      },
+      "ce": {
+        "english_name": "Chechen",
+        "name": "\u041d\u043e\u0445\u0447\u0438\u0439\u043d"
+      },
+      "ceb": {
+        "english_name": "Cebuano",
+        "name": "Sinugboanong Binisaya"
+      },
+      "ch": {
+        "english_name": "Chamorro",
+        "name": "Chamoru"
+      },
+      "chr": {
+        "english_name": "Cherokee",
+        "name": "\u13e3\u13b3\u13a9"
+      },
+      "chy": {
+        "english_name": "Cheyenne",
+        "name": "Tsets\u00eahest\u00e2hese"
+      },
+      "ckb": {
+        "english_name": "Sorani",
+        "name": "Soran\u00ee / \u06a9\u0648\u0631\u062f\u06cc"
+      },
+      "co": {
+        "english_name": "Corsican",
+        "name": "Corsu"
+      },
+      "cr": {
+        "english_name": "Cree",
+        "name": "Nehiyaw"
+      },
+      "crh": {
+        "english_name": "Crimean Tatar",
+        "name": "Q\u0131r\u0131mtatarca"
+      },
+      "cs": {
+        "english_name": "Czech",
+        "name": "\u010ce\u0161tina"
+      },
+      "csb": {
+        "english_name": "Kashubian",
+        "name": "Kasz\u00ebbsczi"
+      },
+      "cu": {
+        "english_name": "Old Church Slavonic",
+        "name": "\u0421\u043b\u043e\u0432\u0463\u043d\u044c\u0441\u043a\u044a"
+      },
+      "cv": {
+        "english_name": "Chuvash",
+        "name": "\u0427\u0103\u0432\u0430\u0448"
+      },
+      "cy": {
+        "english_name": "Welsh",
+        "name": "Cymraeg"
+      },
+      "da": {
+        "english_name": "Danish",
+        "name": "Dansk"
+      },
+      "dag": {
+        "english_name": "Dagbani",
+        "name": "Dagbanli"
+      },
+      "de": {
+        "english_name": "German",
+        "name": "Deutsch"
+      },
+      "din": {
+        "english_name": "Dinka",
+        "name": "Thu\u0254\u014bj\u00e4\u014b"
+      },
+      "diq": {
+        "english_name": "Zazaki",
+        "name": "Zazaki"
+      },
+      "dsb": {
+        "english_name": "Lower Sorbian",
+        "name": "Dolnoserbski"
+      },
+      "dty": {
+        "english_name": "Doteli",
+        "name": "\u0921\u094b\u091f\u0947\u0932\u0940"
+      },
+      "dv": {
+        "english_name": "Divehi",
+        "name": "\u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0"
+      },
+      "dz": {
+        "english_name": "Dzongkha",
+        "name": "\u0f47\u0f7c\u0f44\u0f0b\u0f41"
+      },
+      "ee": {
+        "english_name": "Ewe",
+        "name": "E\u028begbe"
+      },
+      "el": {
+        "english_name": "Greek",
+        "name": "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac"
+      },
+      "eml": {
+        "english_name": "Emilian-Romagnol",
+        "name": "Emili\u00e0n e rumagn\u00f2l"
+      },
+      "en": {
+        "english_name": "English",
+        "name": "English"
+      },
+      "eo": {
+        "english_name": "Esperanto",
+        "name": "Esperanto"
+      },
+      "es": {
+        "english_name": "Spanish",
+        "name": "Espa\u00f1ol"
+      },
+      "et": {
+        "english_name": "Estonian",
+        "name": "Eesti"
+      },
+      "eu": {
+        "english_name": "Basque",
+        "name": "Euskara"
+      },
+      "ext": {
+        "english_name": "Extremaduran",
+        "name": "Estreme\u00f1u"
+      },
+      "fa": {
+        "english_name": "Persian",
+        "name": "\u0641\u0627\u0631\u0633\u06cc"
+      },
+      "ff": {
+        "english_name": "Fula",
+        "name": "Fulfulde"
+      },
+      "fi": {
+        "english_name": "Finnish",
+        "name": "Suomi"
+      },
+      "fiu-vro": {
+        "english_name": "V\u00f5ro",
+        "name": "V\u00f5ro"
+      },
+      "fj": {
+        "english_name": "Fijian",
+        "name": "Na Vosa Vakaviti"
+      },
+      "fo": {
+        "english_name": "Faroese",
+        "name": "F\u00f8royskt"
+      },
+      "fr": {
+        "english_name": "French",
+        "name": "Fran\u00e7ais"
+      },
+      "frp": {
+        "english_name": "Franco-Proven\u00e7al",
+        "name": "Arpetan"
+      },
+      "frr": {
+        "english_name": "North Frisian",
+        "name": "Nordfrasch"
+      },
+      "fur": {
+        "english_name": "Friulian",
+        "name": "Furlan"
+      },
+      "fy": {
+        "english_name": "West Frisian",
+        "name": "Frysk"
+      },
+      "ga": {
+        "english_name": "Irish",
+        "name": "Gaeilge"
+      },
+      "gag": {
+        "english_name": "Gagauz",
+        "name": "Gagauz"
+      },
+      "gan": {
+        "english_name": "Gan",
+        "name": "\u8d1b\u8a9e"
+      },
+      "gcr": {
+        "english_name": "Guianan Creole",
+        "name": "Kriy\u00f2l Gwiyannen"
+      },
+      "gd": {
+        "english_name": "Scottish Gaelic",
+        "name": "G\u00e0idhlig"
+      },
+      "gl": {
+        "english_name": "Galician",
+        "name": "Galego"
+      },
+      "glk": {
+        "english_name": "Gilaki",
+        "name": "\u06af\u06cc\u0644\u06a9\u06cc"
+      },
+      "gn": {
+        "english_name": "Guarani",
+        "name": "Ava\u00f1e'\u1ebd"
+      },
+      "gom": {
+        "english_name": "Goan Konkani",
+        "name": "\u0917\u094b\u0902\u092f\u091a\u0940 \u0915\u094b\u0902\u0915\u0923\u0940 / G\u00f5ychi Konknni"
+      },
+      "gor": {
+        "english_name": "Gorontalo",
+        "name": "Hulontalo"
+      },
+      "got": {
+        "english_name": "Gothic",
+        "name": "\ud800\udf32\ud800\udf3f\ud800\udf44\ud800\udf39\ud800\udf43\ud800\udf3a"
+      },
+      "gu": {
+        "english_name": "Gujarati",
+        "name": "\u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0"
+      },
+      "guw": {
+        "english_name": "Gun",
+        "name": "Gungbe"
+      },
+      "gv": {
+        "english_name": "Manx",
+        "name": "Gaelg"
+      },
+      "ha": {
+        "english_name": "Hausa",
+        "name": "Hausa / \u0647\u064e\u0648\u064f\u0633\u064e"
+      },
+      "hak": {
+        "english_name": "Hakka",
+        "name": "Hak-k\u00e2-fa / \u5ba2\u5bb6\u8a71"
+      },
+      "haw": {
+        "english_name": "Hawaiian",
+        "name": "Hawai\u02bbi"
+      },
+      "he": {
+        "english_name": "Hebrew",
+        "name": "\u05e2\u05d1\u05e8\u05d9\u05ea"
+      },
+      "hi": {
+        "english_name": "Hindi",
+        "name": "\u0939\u093f\u0928\u094d\u0926\u0940"
+      },
+      "hif": {
+        "english_name": "Fiji Hindi",
+        "name": "Fiji Hindi"
+      },
+      "hr": {
+        "english_name": "Croatian",
+        "name": "Hrvatski"
+      },
+      "hsb": {
+        "english_name": "Upper Sorbian",
+        "name": "Hornjoserbsce"
+      },
+      "ht": {
+        "english_name": "Haitian",
+        "name": "Kr\u00e8yol ayisyen"
+      },
+      "hu": {
+        "english_name": "Hungarian",
+        "name": "Magyar"
+      },
+      "hy": {
+        "english_name": "Armenian",
+        "name": "\u0540\u0561\u0575\u0565\u0580\u0565\u0576"
+      },
+      "hyw": {
+        "english_name": "Western Armenian",
+        "name": "\u0531\u0580\u0565\u0582\u0574\u057f\u0561\u0570\u0561\u0575\u0565\u0580\u0567\u0576"
+      },
+      "ia": {
+        "english_name": "Interlingua",
+        "name": "Interlingua"
+      },
+      "id": {
+        "english_name": "Indonesian",
+        "name": "Bahasa Indonesia"
+      },
+      "ie": {
+        "english_name": "Interlingue",
+        "name": "Interlingue"
+      },
+      "ig": {
+        "english_name": "Igbo",
+        "name": "\u00ccgb\u00f2"
+      },
+      "ik": {
+        "english_name": "Inupiak",
+        "name": "I\u00f1upiatun"
+      },
+      "ilo": {
+        "english_name": "Ilokano",
+        "name": "Ilokano"
+      },
+      "inh": {
+        "english_name": "Ingush",
+        "name": "\u0413\u04c0\u0430\u043b\u0433\u04c0\u0430\u0439"
+      },
+      "io": {
+        "english_name": "Ido",
+        "name": "Ido"
+      },
+      "is": {
+        "english_name": "Icelandic",
+        "name": "\u00cdslenska"
+      },
+      "it": {
+        "english_name": "Italian",
+        "name": "Italiano"
+      },
+      "iu": {
+        "english_name": "Inuktitut",
+        "name": "\u1403\u14c4\u1483\u144e\u1450\u1466"
+      },
+      "ja": {
+        "english_name": "Japanese",
+        "name": "\u65e5\u672c\u8a9e"
+      },
+      "jam": {
+        "english_name": "Jamaican Patois",
+        "name": "Jumiekan Kryuol"
+      },
+      "jbo": {
+        "english_name": "Lojban",
+        "name": "Lojban"
+      },
+      "jv": {
+        "english_name": "Javanese",
+        "name": "Basa Jawa"
+      },
+      "ka": {
+        "english_name": "Georgian",
+        "name": "\u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8"
+      },
+      "kaa": {
+        "english_name": "Karakalpak",
+        "name": "Qaraqalpaqsha"
+      },
+      "kab": {
+        "english_name": "Kabyle",
+        "name": "Taqbaylit"
+      },
+      "kbd": {
+        "english_name": "Kabardian Circassian",
+        "name": "\u0410\u0434\u044b\u0433\u044d\u0431\u0437\u044d (Adighabze)"
+      },
+      "kbp": {
+        "english_name": "Kabiye",
+        "name": "Kab\u0269y\u025b"
+      },
+      "kcg": {
+        "english_name": "Tyap",
+        "name": "Tyap"
+      },
+      "kg": {
+        "english_name": "Kongo",
+        "name": "Kik\u00f4ngo"
+      },
+      "ki": {
+        "english_name": "Kikuyu",
+        "name": "G\u0129k\u0169y\u0169"
+      },
+      "kk": {
+        "english_name": "Kazakh",
+        "name": "\u049a\u0430\u0437\u0430\u049b\u0448\u0430"
+      },
+      "kl": {
+        "english_name": "Greenlandic",
+        "name": "Kalaallisut"
+      },
+      "km": {
+        "english_name": "Khmer",
+        "name": "\u1797\u17b6\u179f\u17b6\u1781\u17d2\u1798\u17c2\u179a"
+      },
+      "kn": {
+        "english_name": "Kannada",
+        "name": "\u0c95\u0ca8\u0ccd\u0ca8\u0ca1"
+      },
+      "ko": {
+        "english_name": "Korean",
+        "name": "\ud55c\uad6d\uc5b4"
+      },
+      "koi": {
+        "english_name": "Komi-Permyak",
+        "name": "\u041f\u0435\u0440\u0435\u043c \u041a\u043e\u043c\u0438 (Perem Komi)"
+      },
+      "krc": {
+        "english_name": "Karachay-Balkar",
+        "name": "\u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440 (Qarachay-Malqar)"
+      },
+      "ks": {
+        "english_name": "Kashmiri",
+        "name": "\u0915\u0936\u094d\u092e\u0940\u0930\u0940 / \u0643\u0634\u0645\u064a\u0631\u064a"
+      },
+      "ksh": {
+        "english_name": "Ripuarian",
+        "name": "Ripoarisch"
+      },
+      "ku": {
+        "english_name": "Kurdish",
+        "name": "Kurd\u00ee / \u0643\u0648\u0631\u062f\u06cc"
+      },
+      "kv": {
+        "english_name": "Komi",
+        "name": "\u041a\u043e\u043c\u0438"
+      },
+      "kw": {
+        "english_name": "Cornish",
+        "name": "Kernowek/Karnuack"
+      },
+      "ky": {
+        "english_name": "Kyrgyz",
+        "name": "\u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430"
+      },
+      "la": {
+        "english_name": "Latin",
+        "name": "Latina"
+      },
+      "lad": {
+        "english_name": "Ladino",
+        "name": "Dzhudezmo"
+      },
+      "lb": {
+        "english_name": "Luxembourgish",
+        "name": "L\u00ebtzebuergesch"
+      },
+      "lbe": {
+        "english_name": "Lak",
+        "name": "\u041b\u0430\u043a\u043a\u0443"
+      },
+      "lez": {
+        "english_name": "Lezgian",
+        "name": "\u041b\u0435\u0437\u0433\u0438 \u0447\u0406\u0430\u043b (Lezgi \u010d\u2019al)"
+      },
+      "lfn": {
+        "english_name": "Lingua Franca Nova",
+        "name": "Lingua franca nova"
+      },
+      "lg": {
+        "english_name": "Luganda",
+        "name": "Luganda"
+      },
+      "li": {
+        "english_name": "Limburgish",
+        "name": "Limburgs"
+      },
+      "lij": {
+        "english_name": "Ligurian",
+        "name": "L\u00ecgure"
+      },
+      "lld": {
+        "english_name": "Ladin",
+        "name": "Lingaz"
+      },
+      "lmo": {
+        "english_name": "Lombard",
+        "name": "Lumbaart"
+      },
+      "ln": {
+        "english_name": "Lingala",
+        "name": "Lingala"
+      },
+      "lo": {
+        "english_name": "Lao",
+        "name": "\u0ea5\u0eb2\u0ea7"
+      },
+      "lt": {
+        "english_name": "Lithuanian",
+        "name": "Lietuvi\u0173"
+      },
+      "ltg": {
+        "english_name": "Latgalian",
+        "name": "Latga\u013cu"
+      },
+      "lv": {
+        "english_name": "Latvian",
+        "name": "Latvie\u0161u"
+      },
+      "mad": {
+        "english_name": "Madurese",
+        "name": "Madhur\u00e2"
+      },
+      "mai": {
+        "english_name": "Maithili",
+        "name": "\u092e\u0948\u0925\u093f\u0932\u0940"
+      },
+      "map-bms": {
+        "english_name": "Banyumasan",
+        "name": "Basa Banyumasan"
+      },
+      "mdf": {
+        "english_name": "Moksha",
+        "name": "\u041c\u043e\u043a\u0448\u0435\u043d\u044c (Mokshanj K\u00e4lj)"
+      },
+      "mg": {
+        "english_name": "Malagasy",
+        "name": "Malagasy"
+      },
+      "mhr": {
+        "english_name": "Meadow Mari",
+        "name": "\u041e\u043b\u044b\u043a \u041c\u0430\u0440\u0438\u0439 (Olyk Marij)"
+      },
+      "mi": {
+        "english_name": "Maori",
+        "name": "M\u0101ori"
+      },
+      "min": {
+        "english_name": "Minangkabau",
+        "name": "Minangkabau"
+      },
+      "mk": {
+        "english_name": "Macedonian",
+        "name": "\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438"
+      },
+      "ml": {
+        "english_name": "Malayalam",
+        "name": "\u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02"
+      },
+      "mn": {
+        "english_name": "Mongolian",
+        "name": "\u041c\u043e\u043d\u0433\u043e\u043b"
+      },
+      "mni": {
+        "english_name": "Meitei",
+        "name": "\uabc3\uabe4\uabc7\uabe9\uabc2\uabe3\uabdf"
+      },
+      "mnw": {
+        "english_name": "Mon",
+        "name": "\u1019\u1014\u103a"
+      },
+      "mr": {
+        "english_name": "Marathi",
+        "name": "\u092e\u0930\u093e\u0920\u0940"
+      },
+      "mrj": {
+        "english_name": "Hill Mari",
+        "name": "\u041a\u044b\u0440\u044b\u043a \u041c\u0430\u0440\u044b (Kyryk Mary)"
+      },
+      "ms": {
+        "english_name": "Malay",
+        "name": "Bahasa Melayu"
+      },
+      "mt": {
+        "english_name": "Maltese",
+        "name": "Malti"
+      },
+      "mwl": {
+        "english_name": "Mirandese",
+        "name": "Mirand\u00e9s"
+      },
+      "my": {
+        "english_name": "Burmese",
+        "name": "\u1019\u103c\u1014\u103a\u1019\u102c\u1018\u102c\u101e\u102c"
+      },
+      "myv": {
+        "english_name": "Erzya",
+        "name": "\u042d\u0440\u0437\u044f\u043d\u044c (Erzjanj Kelj)"
+      },
+      "mzn": {
+        "english_name": "Mazandarani",
+        "name": "\u0645\u064e\u0632\u0650\u0631\u0648\u0646\u064a"
+      },
+      "na": {
+        "english_name": "Nauruan",
+        "name": "dorerin Naoero"
+      },
+      "nah": {
+        "english_name": "Nahuatl",
+        "name": "N\u0101huatl"
+      },
+      "nap": {
+        "english_name": "Neapolitan",
+        "name": "Nnapulitano"
+      },
+      "nds": {
+        "english_name": "Low Saxon",
+        "name": "Plattd\u00fc\u00fctsch"
+      },
+      "nds-nl": {
+        "english_name": "Dutch Low Saxon",
+        "name": "Nedersaksisch"
+      },
+      "ne": {
+        "english_name": "Nepali",
+        "name": "\u0928\u0947\u092a\u093e\u0932\u0940"
+      },
+      "new": {
+        "english_name": "Newar",
+        "name": "\u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e"
+      },
+      "nia": {
+        "english_name": "Nias",
+        "name": "Li Niha"
+      },
+      "nl": {
+        "english_name": "Dutch",
+        "name": "Nederlands"
+      },
+      "nn": {
+        "english_name": "Norwegian (Nynorsk)",
+        "name": "Nynorsk"
+      },
+      "no": {
+        "english_name": "Norwegian (Bokm\u00e5l)",
+        "name": "Norsk (Bokm\u00e5l)"
+      },
+      "nov": {
+        "english_name": "Novial",
+        "name": "Novial"
+      },
+      "nqo": {
+        "english_name": "N\u2019Ko",
+        "name": "\u07d2\u07de\u07cf"
+      },
+      "nrm": {
+        "english_name": "Norman",
+        "name": "Nouormand/Normaund"
+      },
+      "nso": {
+        "english_name": "Northern Sotho",
+        "name": "Sepedi"
+      },
+      "nv": {
+        "english_name": "Navajo",
+        "name": "Din\u00e9 bizaad"
+      },
+      "ny": {
+        "english_name": "Chichewa",
+        "name": "Chichewa"
+      },
+      "oc": {
+        "english_name": "Occitan",
+        "name": "Occitan"
+      },
+      "olo": {
+        "english_name": "Livvi-Karelian",
+        "name": "Karjalan"
+      },
+      "om": {
+        "english_name": "Oromo",
+        "name": "Oromoo"
+      },
+      "or": {
+        "english_name": "Oriya",
+        "name": "\u0b13\u0b21\u0b3c\u0b3f\u0b06"
+      },
+      "os": {
+        "english_name": "Ossetian",
+        "name": "\u0418\u0440\u043e\u043d\u0430\u0443"
+      },
+      "pa": {
+        "english_name": "Punjabi",
+        "name": "\u0a2a\u0a70\u0a1c\u0a3e\u0a2c\u0a40"
+      },
+      "pag": {
+        "english_name": "Pangasinan",
+        "name": "Pangasinan"
+      },
+      "pam": {
+        "english_name": "Kapampangan",
+        "name": "Kapampangan"
+      },
+      "pap": {
+        "english_name": "Papiamentu",
+        "name": "Papiamentu"
+      },
+      "pcd": {
+        "english_name": "Picard",
+        "name": "Picard"
+      },
+      "pcm": {
+        "english_name": "Nigerian Pidgin",
+        "name": "Naij\u00e1"
+      },
+      "pdc": {
+        "english_name": "Pennsylvania German",
+        "name": "Deitsch"
+      },
+      "pfl": {
+        "english_name": "Palatinate German",
+        "name": "P\u00e4lzisch"
+      },
+      "pi": {
+        "english_name": "Pali",
+        "name": "\u092a\u093e\u0934\u093f"
+      },
+      "pih": {
+        "english_name": "Norfolk",
+        "name": "Norfuk"
+      },
+      "pl": {
+        "english_name": "Polish",
+        "name": "Polski"
+      },
+      "pms": {
+        "english_name": "Piedmontese",
+        "name": "Piemont\u00e8is"
+      },
+      "pnb": {
+        "english_name": "Western Punjabi",
+        "name": "\u0634\u0627\u06c1 \u0645\u06a9\u06be\u06cc \u067e\u0646\u062c\u0627\u0628\u06cc (Sh\u0101hmukh\u012b Pa\u00f1j\u0101b\u012b)"
+      },
+      "pnt": {
+        "english_name": "Pontic",
+        "name": "\u03a0\u03bf\u03bd\u03c4\u03b9\u03b1\u03ba\u03ac"
+      },
+      "ps": {
+        "english_name": "Pashto",
+        "name": "\u067e\u069a\u062a\u0648"
+      },
+      "pt": {
+        "english_name": "Portuguese",
+        "name": "Portugu\u00eas"
+      },
+      "pwn": {
+        "english_name": "Paiwan",
+        "name": "Paiwan"
+      },
+      "qu": {
+        "english_name": "Quechua",
+        "name": "Qichwa simi"
+      },
+      "rm": {
+        "english_name": "Romansh",
+        "name": "Rumantsch"
+      },
+      "rmy": {
+        "english_name": "Romani",
+        "name": "romani - \u0930\u094b\u092e\u093e\u0928\u0940"
+      },
+      "rn": {
+        "english_name": "Kirundi",
+        "name": "Ikirundi"
+      },
+      "ro": {
+        "english_name": "Romanian",
+        "name": "Rom\u00e2n\u0103"
+      },
+      "roa-rup": {
+        "english_name": "Aromanian",
+        "name": "Arm\u00e3neashce"
+      },
+      "roa-tara": {
+        "english_name": "Tarantino",
+        "name": "Tarand\u00edne"
+      },
+      "ru": {
+        "english_name": "Russian",
+        "name": "\u0420\u0443\u0441\u0441\u043a\u0438\u0439"
+      },
+      "rue": {
+        "english_name": "Rusyn",
+        "name": "\u0420\u0443\u0441\u0438\u043d\u044c\u0441\u043a\u044b\u0439"
+      },
+      "rw": {
+        "english_name": "Kinyarwanda",
+        "name": "Ikinyarwanda"
+      },
+      "sa": {
+        "english_name": "Sanskrit",
+        "name": "\u0938\u0902\u0938\u094d\u0915\u0943\u0924\u092e\u094d"
+      },
+      "sah": {
+        "english_name": "Sakha",
+        "name": "\u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430 (Saxa Tyla)"
+      },
+      "sat": {
+        "english_name": "Santali",
+        "name": "\u1c65\u1c5f\u1c71\u1c5b\u1c5f\u1c72\u1c64"
+      },
+      "sc": {
+        "english_name": "Sardinian",
+        "name": "Sardu"
+      },
+      "scn": {
+        "english_name": "Sicilian",
+        "name": "Sicilianu"
+      },
+      "sco": {
+        "english_name": "Scots",
+        "name": "Scots"
+      },
+      "sd": {
+        "english_name": "Sindhi",
+        "name": "\u0633\u0646\u068c\u064a\u060c \u0633\u0646\u062f\u06be\u06cc \u060c \u0938\u093f\u0928\u094d\u0927"
+      },
+      "se": {
+        "english_name": "Northern Sami",
+        "name": "S\u00e1megiella"
+      },
+      "sg": {
+        "english_name": "Sango",
+        "name": "S\u00e4ng\u00f6"
+      },
+      "sh": {
+        "english_name": "Serbo-Croatian",
+        "name": "Srpskohrvatski / \u0421\u0440\u043f\u0441\u043a\u043e\u0445\u0440\u0432\u0430\u0442\u0441\u043a\u0438"
+      },
+      "shi": {
+        "english_name": "Tachelhit",
+        "name": "Tacl\u1e25it"
+      },
+      "shn": {
+        "english_name": "Shan",
+        "name": "\u101c\u102d\u1075\u103a\u1088\u1010\u1086\u1038"
+      },
+      "si": {
+        "english_name": "Sinhalese",
+        "name": "\u0dc3\u0dd2\u0d82\u0dc4\u0dbd"
+      },
+      "simple": {
+        "english_name": "Simple English",
+        "name": "Simple English"
+      },
+      "sk": {
+        "english_name": "Slovak",
+        "name": "Sloven\u010dina"
+      },
+      "skr": {
+        "english_name": "Saraiki",
+        "name": "\u0633\u0631\u0627\u0626\u06cc\u06a9\u06cc"
+      },
+      "sl": {
+        "english_name": "Slovenian",
+        "name": "Sloven\u0161\u010dina"
+      },
+      "sm": {
+        "english_name": "Samoan",
+        "name": "Gagana Samoa"
+      },
+      "smn": {
+        "english_name": "Inari Sami",
+        "name": "Anar\u00e2\u0161kiel\u00e2"
+      },
+      "sn": {
+        "english_name": "Shona",
+        "name": "chiShona"
+      },
+      "so": {
+        "english_name": "Somali",
+        "name": "Soomaali"
+      },
+      "sq": {
+        "english_name": "Albanian",
+        "name": "Shqip"
+      },
+      "sr": {
+        "english_name": "Serbian",
+        "name": "\u0421\u0440\u043f\u0441\u043a\u0438 / Srpski"
+      },
+      "srn": {
+        "english_name": "Sranan",
+        "name": "Sranantongo"
+      },
+      "ss": {
+        "english_name": "Swati",
+        "name": "SiSwati"
+      },
+      "st": {
+        "english_name": "Sesotho",
+        "name": "Sesotho"
+      },
+      "stq": {
+        "english_name": "Saterland Frisian",
+        "name": "Seeltersk"
+      },
+      "su": {
+        "english_name": "Sundanese",
+        "name": "Basa Sunda"
+      },
+      "sv": {
+        "english_name": "Swedish",
+        "name": "Svenska"
+      },
+      "sw": {
+        "english_name": "Swahili",
+        "name": "Kiswahili"
+      },
+      "szl": {
+        "english_name": "Silesian",
+        "name": "\u015al\u016fnski"
+      },
+      "szy": {
+        "english_name": "Sakizaya",
+        "name": "Sakizaya"
+      },
+      "ta": {
+        "english_name": "Tamil",
+        "name": "\u0ba4\u0bae\u0bbf\u0bb4\u0bcd"
+      },
+      "tay": {
+        "english_name": "Atayal",
+        "name": "Tayal"
+      },
+      "tcy": {
+        "english_name": "Tulu",
+        "name": "\u0ca4\u0cc1\u0cb3\u0cc1"
+      },
+      "te": {
+        "english_name": "Telugu",
+        "name": "\u0c24\u0c46\u0c32\u0c41\u0c17\u0c41"
+      },
+      "tet": {
+        "english_name": "Tetum",
+        "name": "Tetun"
+      },
+      "tg": {
+        "english_name": "Tajik",
+        "name": "\u0422\u043e\u04b7\u0438\u043a\u04e3"
+      },
+      "th": {
+        "english_name": "Thai",
+        "name": "\u0e44\u0e17\u0e22"
+      },
+      "ti": {
+        "english_name": "Tigrinya",
+        "name": "\u1275\u130d\u122d\u129b"
+      },
+      "tk": {
+        "english_name": "Turkmen",
+        "name": "T\u00fcrkmen"
+      },
+      "tl": {
+        "english_name": "Tagalog",
+        "name": "Tagalog"
+      },
+      "tn": {
+        "english_name": "Tswana",
+        "name": "Setswana"
+      },
+      "to": {
+        "english_name": "Tongan",
+        "name": "faka Tonga"
+      },
+      "tpi": {
+        "english_name": "Tok Pisin",
+        "name": "Tok Pisin"
+      },
+      "tr": {
+        "english_name": "Turkish",
+        "name": "T\u00fcrk\u00e7e"
+      },
+      "trv": {
+        "english_name": "Seediq",
+        "name": "Taroko"
+      },
+      "ts": {
+        "english_name": "Tsonga",
+        "name": "Xitsonga"
+      },
+      "tt": {
+        "english_name": "Tatar",
+        "name": "Tatar\u00e7a / \u0422\u0430\u0442\u0430\u0440\u0447\u0430"
+      },
+      "tum": {
+        "english_name": "Tumbuka",
+        "name": "chiTumbuka"
+      },
+      "tw": {
+        "english_name": "Twi",
+        "name": "Twi"
+      },
+      "ty": {
+        "english_name": "Tahitian",
+        "name": "Reo M\u0101`ohi"
+      },
+      "tyv": {
+        "english_name": "Tuvan",
+        "name": "\u0422\u044b\u0432\u0430"
+      },
+      "udm": {
+        "english_name": "Udmurt",
+        "name": "\u0423\u0434\u043c\u0443\u0440\u0442 \u043a\u044b\u043b"
+      },
+      "ug": {
+        "english_name": "Uyghur",
+        "name": "\u0626\u06c7\u064a\u063a\u06c7\u0631 \u062a\u0649\u0644\u0649"
+      },
+      "uk": {
+        "english_name": "Ukrainian",
+        "name": "\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"
+      },
+      "ur": {
+        "english_name": "Urdu",
+        "name": "\u0627\u0631\u062f\u0648"
+      },
+      "uz": {
+        "english_name": "Uzbek",
+        "name": "O\u2018zbek"
+      },
+      "ve": {
+        "english_name": "Venda",
+        "name": "Tshivenda"
+      },
+      "vec": {
+        "english_name": "Venetian",
+        "name": "V\u00e8neto"
+      },
+      "vep": {
+        "english_name": "Vepsian",
+        "name": "Veps\u00e4n"
+      },
+      "vi": {
+        "english_name": "Vietnamese",
+        "name": "Ti\u1ebfng Vi\u1ec7t"
+      },
+      "vls": {
+        "english_name": "West Flemish",
+        "name": "West-Vlams"
+      },
+      "vo": {
+        "english_name": "Volap\u00fck",
+        "name": "Volap\u00fck"
+      },
+      "wa": {
+        "english_name": "Walloon",
+        "name": "Walon"
+      },
+      "war": {
+        "english_name": "Waray-Waray",
+        "name": "Winaray"
+      },
+      "wo": {
+        "english_name": "Wolof",
+        "name": "Wolof"
+      },
+      "wuu": {
+        "english_name": "Wu",
+        "name": "\u5434\u8bed"
+      },
+      "xal": {
+        "english_name": "Kalmyk",
+        "name": "\u0425\u0430\u043b\u044c\u043c\u0433"
+      },
+      "xh": {
+        "english_name": "Xhosa",
+        "name": "isiXhosa"
+      },
+      "xmf": {
+        "english_name": "Mingrelian",
+        "name": "\u10db\u10d0\u10e0\u10d2\u10d0\u10da\u10e3\u10e0\u10d8 (Margaluri)"
+      },
+      "yi": {
+        "english_name": "Yiddish",
+        "name": "\u05d9\u05d9\u05b4\u05d3\u05d9\u05e9"
+      },
+      "yo": {
+        "english_name": "Yoruba",
+        "name": "Yor\u00f9b\u00e1"
+      },
+      "za": {
+        "english_name": "Zhuang",
+        "name": "Cuengh"
+      },
+      "zea": {
+        "english_name": "Zeelandic",
+        "name": "Ze\u00eauws"
+      },
+      "zh": {
+        "english_name": "Chinese",
+        "name": "\u4e2d\u6587"
+      },
+      "zh-classical": {
+        "english_name": "Classical Chinese",
+        "name": "\u53e4\u6587 / \u6587\u8a00\u6587"
+      },
+      "zh-min-nan": {
+        "english_name": "Min Nan",
+        "name": "B\u00e2n-l\u00e2m-g\u00fa"
+      },
+      "zh-yue": {
+        "english_name": "Cantonese",
+        "name": "\u7cb5\u8a9e"
+      },
+      "zu": {
+        "english_name": "Zulu",
+        "name": "isiZulu"
+      }
+    }
+  },
+  "wikipedia": {
+    "all_locale": null,
+    "custom": {},
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": {
+      "ab": {
+        "english_name": "Abkhazian",
+        "name": "\u0410\u0525\u0441\u0443\u0430"
+      },
+      "ace": {
+        "english_name": "Acehnese",
+        "name": "Basa Ac\u00e8h"
+      },
+      "ady": {
+        "english_name": "Adyghe",
+        "name": "\u0410\u0434\u044b\u0433\u044d\u0431\u0437\u044d"
+      },
+      "af": {
+        "english_name": "Afrikaans",
+        "name": "Afrikaans"
+      },
+      "ak": {
+        "english_name": "Akan",
+        "name": "Akana"
+      },
+      "als": {
+        "english_name": "Alemannic",
+        "name": "Alemannisch"
+      },
+      "alt": {
+        "english_name": "Southern Altai",
+        "name": "\u0410\u043b\u0442\u0430\u0439"
+      },
+      "am": {
+        "english_name": "Amharic",
+        "name": "\u12a0\u121b\u122d\u129b"
+      },
+      "ami": {
+        "english_name": "Amis",
+        "name": "Pangcah"
+      },
+      "an": {
+        "english_name": "Aragonese",
+        "name": "Aragon\u00e9s"
+      },
+      "ang": {
+        "english_name": "Anglo-Saxon",
+        "name": "\u00c6nglisc"
+      },
+      "ar": {
+        "english_name": "Arabic",
+        "name": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629"
+      },
+      "arc": {
+        "english_name": "Aramaic",
+        "name": "\u0710\u072a\u0721\u071d\u0710"
+      },
+      "ary": {
+        "english_name": "Moroccan Arabic",
+        "name": "\u062f\u0627\u0631\u064a\u062c\u0629"
+      },
+      "arz": {
+        "english_name": "Egyptian Arabic",
+        "name": "\u0645\u0635\u0631\u0649 (Ma\u1e63ri)"
+      },
+      "as": {
+        "english_name": "Assamese",
+        "name": "\u0985\u09b8\u09ae\u09c0\u09af\u09bc\u09be"
+      },
+      "ast": {
+        "english_name": "Asturian",
+        "name": "Asturianu"
+      },
+      "atj": {
+        "english_name": "Atikamekw",
+        "name": "Atikamekw"
+      },
+      "av": {
+        "english_name": "Avar",
+        "name": "\u0410\u0432\u0430\u0440"
+      },
+      "avk": {
+        "english_name": "Kotava",
+        "name": "Kotava"
+      },
+      "awa": {
+        "english_name": "Awadhi",
+        "name": "\u0905\u0935\u0927\u0940"
+      },
+      "ay": {
+        "english_name": "Aymara",
+        "name": "Aymar"
+      },
+      "az": {
+        "english_name": "Azerbaijani",
+        "name": "Az\u0259rbaycanca"
+      },
+      "azb": {
+        "english_name": "South Azerbaijani",
+        "name": "\u062a\u06c6\u0631\u06a9\u062c\u0647"
+      },
+      "ba": {
+        "english_name": "Bashkir",
+        "name": "\u0411\u0430\u0448\u04a1\u043e\u0440\u0442"
+      },
+      "ban": {
+        "english_name": "Balinese",
+        "name": "Bali"
+      },
+      "bar": {
+        "english_name": "Bavarian",
+        "name": "Boarisch"
+      },
+      "bat-smg": {
+        "english_name": "Samogitian",
+        "name": "\u017demait\u0117\u0161ka"
+      },
+      "bcl": {
+        "english_name": "Central Bicolano",
+        "name": "Bikol"
+      },
+      "be": {
+        "english_name": "Belarusian",
+        "name": "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f"
+      },
+      "be-tarask": {
+        "english_name": "Belarusian (Tara\u0161kievica)",
+        "name": "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430)"
+      },
+      "bg": {
+        "english_name": "Bulgarian",
+        "name": "\u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438"
+      },
+      "bh": {
+        "english_name": "Bhojpuri",
+        "name": "\u092d\u094b\u091c\u092a\u0941\u0930\u0940"
+      },
+      "bi": {
+        "english_name": "Bislama",
+        "name": "Bislama"
+      },
+      "bjn": {
+        "english_name": "Banjar",
+        "name": "Bahasa Banjar"
+      },
+      "blk": {
+        "english_name": "Pa'O",
+        "name": "\u1015\u1021\u102d\u102f\u101d\u103a\u108f\u1018\u102c\u108f\u101e\u102c\u108f"
+      },
+      "bm": {
+        "english_name": "Bambara",
+        "name": "Bamanankan"
+      },
+      "bn": {
+        "english_name": "Bengali",
+        "name": "\u09ac\u09be\u0982\u09b2\u09be"
+      },
+      "bo": {
+        "english_name": "Tibetan",
+        "name": "\u0f56\u0f7c\u0f51\u0f0b\u0f66\u0f90\u0f51"
+      },
+      "bpy": {
+        "english_name": "Bishnupriya Manipuri",
+        "name": "\u0987\u09ae\u09be\u09b0 \u09a0\u09be\u09b0/\u09ac\u09bf\u09b7\u09cd\u09a3\u09c1\u09aa\u09cd\u09b0\u09bf\u09af\u09bc\u09be \u09ae\u09a3\u09bf\u09aa\u09c1\u09b0\u09c0"
+      },
+      "br": {
+        "english_name": "Breton",
+        "name": "Brezhoneg"
+      },
+      "bs": {
+        "english_name": "Bosnian",
+        "name": "Bosanski"
+      },
+      "bug": {
+        "english_name": "Buginese",
+        "name": "Basa Ugi"
+      },
+      "bxr": {
+        "english_name": "Buryat",
+        "name": "\u0411\u0443\u0440\u044f\u0430\u0434"
+      },
+      "ca": {
+        "english_name": "Catalan",
+        "name": "Catal\u00e0"
+      },
+      "cbk-zam": {
+        "english_name": "Zamboanga Chavacano",
+        "name": "Chavacano de Zamboanga"
+      },
+      "cdo": {
+        "english_name": "Min Dong",
+        "name": "M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304"
+      },
+      "ce": {
+        "english_name": "Chechen",
+        "name": "\u041d\u043e\u0445\u0447\u0438\u0439\u043d"
+      },
+      "ceb": {
+        "english_name": "Cebuano",
+        "name": "Sinugboanong Binisaya"
+      },
+      "ch": {
+        "english_name": "Chamorro",
+        "name": "Chamoru"
+      },
+      "chr": {
+        "english_name": "Cherokee",
+        "name": "\u13e3\u13b3\u13a9"
+      },
+      "chy": {
+        "english_name": "Cheyenne",
+        "name": "Tsets\u00eahest\u00e2hese"
+      },
+      "ckb": {
+        "english_name": "Sorani",
+        "name": "Soran\u00ee / \u06a9\u0648\u0631\u062f\u06cc"
+      },
+      "co": {
+        "english_name": "Corsican",
+        "name": "Corsu"
+      },
+      "cr": {
+        "english_name": "Cree",
+        "name": "Nehiyaw"
+      },
+      "crh": {
+        "english_name": "Crimean Tatar",
+        "name": "Q\u0131r\u0131mtatarca"
+      },
+      "cs": {
+        "english_name": "Czech",
+        "name": "\u010ce\u0161tina"
+      },
+      "csb": {
+        "english_name": "Kashubian",
+        "name": "Kasz\u00ebbsczi"
+      },
+      "cu": {
+        "english_name": "Old Church Slavonic",
+        "name": "\u0421\u043b\u043e\u0432\u0463\u043d\u044c\u0441\u043a\u044a"
+      },
+      "cv": {
+        "english_name": "Chuvash",
+        "name": "\u0427\u0103\u0432\u0430\u0448"
+      },
+      "cy": {
+        "english_name": "Welsh",
+        "name": "Cymraeg"
+      },
+      "da": {
+        "english_name": "Danish",
+        "name": "Dansk"
+      },
+      "dag": {
+        "english_name": "Dagbani",
+        "name": "Dagbanli"
+      },
+      "de": {
+        "english_name": "German",
+        "name": "Deutsch"
+      },
+      "din": {
+        "english_name": "Dinka",
+        "name": "Thu\u0254\u014bj\u00e4\u014b"
+      },
+      "diq": {
+        "english_name": "Zazaki",
+        "name": "Zazaki"
+      },
+      "dsb": {
+        "english_name": "Lower Sorbian",
+        "name": "Dolnoserbski"
+      },
+      "dty": {
+        "english_name": "Doteli",
+        "name": "\u0921\u094b\u091f\u0947\u0932\u0940"
+      },
+      "dv": {
+        "english_name": "Divehi",
+        "name": "\u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0"
+      },
+      "dz": {
+        "english_name": "Dzongkha",
+        "name": "\u0f47\u0f7c\u0f44\u0f0b\u0f41"
+      },
+      "ee": {
+        "english_name": "Ewe",
+        "name": "E\u028begbe"
+      },
+      "el": {
+        "english_name": "Greek",
+        "name": "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac"
+      },
+      "eml": {
+        "english_name": "Emilian-Romagnol",
+        "name": "Emili\u00e0n e rumagn\u00f2l"
+      },
+      "en": {
+        "english_name": "English",
+        "name": "English"
+      },
+      "eo": {
+        "english_name": "Esperanto",
+        "name": "Esperanto"
+      },
+      "es": {
+        "english_name": "Spanish",
+        "name": "Espa\u00f1ol"
+      },
+      "et": {
+        "english_name": "Estonian",
+        "name": "Eesti"
+      },
+      "eu": {
+        "english_name": "Basque",
+        "name": "Euskara"
+      },
+      "ext": {
+        "english_name": "Extremaduran",
+        "name": "Estreme\u00f1u"
+      },
+      "fa": {
+        "english_name": "Persian",
+        "name": "\u0641\u0627\u0631\u0633\u06cc"
+      },
+      "ff": {
+        "english_name": "Fula",
+        "name": "Fulfulde"
+      },
+      "fi": {
+        "english_name": "Finnish",
+        "name": "Suomi"
+      },
+      "fiu-vro": {
+        "english_name": "V\u00f5ro",
+        "name": "V\u00f5ro"
+      },
+      "fj": {
+        "english_name": "Fijian",
+        "name": "Na Vosa Vakaviti"
+      },
+      "fo": {
+        "english_name": "Faroese",
+        "name": "F\u00f8royskt"
+      },
+      "fr": {
+        "english_name": "French",
+        "name": "Fran\u00e7ais"
+      },
+      "frp": {
+        "english_name": "Franco-Proven\u00e7al",
+        "name": "Arpetan"
+      },
+      "frr": {
+        "english_name": "North Frisian",
+        "name": "Nordfrasch"
+      },
+      "fur": {
+        "english_name": "Friulian",
+        "name": "Furlan"
+      },
+      "fy": {
+        "english_name": "West Frisian",
+        "name": "Frysk"
+      },
+      "ga": {
+        "english_name": "Irish",
+        "name": "Gaeilge"
+      },
+      "gag": {
+        "english_name": "Gagauz",
+        "name": "Gagauz"
+      },
+      "gan": {
+        "english_name": "Gan",
+        "name": "\u8d1b\u8a9e"
+      },
+      "gcr": {
+        "english_name": "Guianan Creole",
+        "name": "Kriy\u00f2l Gwiyannen"
+      },
+      "gd": {
+        "english_name": "Scottish Gaelic",
+        "name": "G\u00e0idhlig"
+      },
+      "gl": {
+        "english_name": "Galician",
+        "name": "Galego"
+      },
+      "glk": {
+        "english_name": "Gilaki",
+        "name": "\u06af\u06cc\u0644\u06a9\u06cc"
+      },
+      "gn": {
+        "english_name": "Guarani",
+        "name": "Ava\u00f1e'\u1ebd"
+      },
+      "gom": {
+        "english_name": "Goan Konkani",
+        "name": "\u0917\u094b\u0902\u092f\u091a\u0940 \u0915\u094b\u0902\u0915\u0923\u0940 / G\u00f5ychi Konknni"
+      },
+      "gor": {
+        "english_name": "Gorontalo",
+        "name": "Hulontalo"
+      },
+      "got": {
+        "english_name": "Gothic",
+        "name": "\ud800\udf32\ud800\udf3f\ud800\udf44\ud800\udf39\ud800\udf43\ud800\udf3a"
+      },
+      "gu": {
+        "english_name": "Gujarati",
+        "name": "\u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0"
+      },
+      "guw": {
+        "english_name": "Gun",
+        "name": "Gungbe"
+      },
+      "gv": {
+        "english_name": "Manx",
+        "name": "Gaelg"
+      },
+      "ha": {
+        "english_name": "Hausa",
+        "name": "Hausa / \u0647\u064e\u0648\u064f\u0633\u064e"
+      },
+      "hak": {
+        "english_name": "Hakka",
+        "name": "Hak-k\u00e2-fa / \u5ba2\u5bb6\u8a71"
+      },
+      "haw": {
+        "english_name": "Hawaiian",
+        "name": "Hawai\u02bbi"
+      },
+      "he": {
+        "english_name": "Hebrew",
+        "name": "\u05e2\u05d1\u05e8\u05d9\u05ea"
+      },
+      "hi": {
+        "english_name": "Hindi",
+        "name": "\u0939\u093f\u0928\u094d\u0926\u0940"
+      },
+      "hif": {
+        "english_name": "Fiji Hindi",
+        "name": "Fiji Hindi"
+      },
+      "hr": {
+        "english_name": "Croatian",
+        "name": "Hrvatski"
+      },
+      "hsb": {
+        "english_name": "Upper Sorbian",
+        "name": "Hornjoserbsce"
+      },
+      "ht": {
+        "english_name": "Haitian",
+        "name": "Kr\u00e8yol ayisyen"
+      },
+      "hu": {
+        "english_name": "Hungarian",
+        "name": "Magyar"
+      },
+      "hy": {
+        "english_name": "Armenian",
+        "name": "\u0540\u0561\u0575\u0565\u0580\u0565\u0576"
+      },
+      "hyw": {
+        "english_name": "Western Armenian",
+        "name": "\u0531\u0580\u0565\u0582\u0574\u057f\u0561\u0570\u0561\u0575\u0565\u0580\u0567\u0576"
+      },
+      "ia": {
+        "english_name": "Interlingua",
+        "name": "Interlingua"
+      },
+      "id": {
+        "english_name": "Indonesian",
+        "name": "Bahasa Indonesia"
+      },
+      "ie": {
+        "english_name": "Interlingue",
+        "name": "Interlingue"
+      },
+      "ig": {
+        "english_name": "Igbo",
+        "name": "\u00ccgb\u00f2"
+      },
+      "ik": {
+        "english_name": "Inupiak",
+        "name": "I\u00f1upiatun"
+      },
+      "ilo": {
+        "english_name": "Ilokano",
+        "name": "Ilokano"
+      },
+      "inh": {
+        "english_name": "Ingush",
+        "name": "\u0413\u04c0\u0430\u043b\u0433\u04c0\u0430\u0439"
+      },
+      "io": {
+        "english_name": "Ido",
+        "name": "Ido"
+      },
+      "is": {
+        "english_name": "Icelandic",
+        "name": "\u00cdslenska"
+      },
+      "it": {
+        "english_name": "Italian",
+        "name": "Italiano"
+      },
+      "iu": {
+        "english_name": "Inuktitut",
+        "name": "\u1403\u14c4\u1483\u144e\u1450\u1466"
+      },
+      "ja": {
+        "english_name": "Japanese",
+        "name": "\u65e5\u672c\u8a9e"
+      },
+      "jam": {
+        "english_name": "Jamaican Patois",
+        "name": "Jumiekan Kryuol"
+      },
+      "jbo": {
+        "english_name": "Lojban",
+        "name": "Lojban"
+      },
+      "jv": {
+        "english_name": "Javanese",
+        "name": "Basa Jawa"
+      },
+      "ka": {
+        "english_name": "Georgian",
+        "name": "\u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8"
+      },
+      "kaa": {
+        "english_name": "Karakalpak",
+        "name": "Qaraqalpaqsha"
+      },
+      "kab": {
+        "english_name": "Kabyle",
+        "name": "Taqbaylit"
+      },
+      "kbd": {
+        "english_name": "Kabardian Circassian",
+        "name": "\u0410\u0434\u044b\u0433\u044d\u0431\u0437\u044d (Adighabze)"
+      },
+      "kbp": {
+        "english_name": "Kabiye",
+        "name": "Kab\u0269y\u025b"
+      },
+      "kcg": {
+        "english_name": "Tyap",
+        "name": "Tyap"
+      },
+      "kg": {
+        "english_name": "Kongo",
+        "name": "Kik\u00f4ngo"
+      },
+      "ki": {
+        "english_name": "Kikuyu",
+        "name": "G\u0129k\u0169y\u0169"
+      },
+      "kk": {
+        "english_name": "Kazakh",
+        "name": "\u049a\u0430\u0437\u0430\u049b\u0448\u0430"
+      },
+      "kl": {
+        "english_name": "Greenlandic",
+        "name": "Kalaallisut"
+      },
+      "km": {
+        "english_name": "Khmer",
+        "name": "\u1797\u17b6\u179f\u17b6\u1781\u17d2\u1798\u17c2\u179a"
+      },
+      "kn": {
+        "english_name": "Kannada",
+        "name": "\u0c95\u0ca8\u0ccd\u0ca8\u0ca1"
+      },
+      "ko": {
+        "english_name": "Korean",
+        "name": "\ud55c\uad6d\uc5b4"
+      },
+      "koi": {
+        "english_name": "Komi-Permyak",
+        "name": "\u041f\u0435\u0440\u0435\u043c \u041a\u043e\u043c\u0438 (Perem Komi)"
+      },
+      "krc": {
+        "english_name": "Karachay-Balkar",
+        "name": "\u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440 (Qarachay-Malqar)"
+      },
+      "ks": {
+        "english_name": "Kashmiri",
+        "name": "\u0915\u0936\u094d\u092e\u0940\u0930\u0940 / \u0643\u0634\u0645\u064a\u0631\u064a"
+      },
+      "ksh": {
+        "english_name": "Ripuarian",
+        "name": "Ripoarisch"
+      },
+      "ku": {
+        "english_name": "Kurdish",
+        "name": "Kurd\u00ee / \u0643\u0648\u0631\u062f\u06cc"
+      },
+      "kv": {
+        "english_name": "Komi",
+        "name": "\u041a\u043e\u043c\u0438"
+      },
+      "kw": {
+        "english_name": "Cornish",
+        "name": "Kernowek/Karnuack"
+      },
+      "ky": {
+        "english_name": "Kyrgyz",
+        "name": "\u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430"
+      },
+      "la": {
+        "english_name": "Latin",
+        "name": "Latina"
+      },
+      "lad": {
+        "english_name": "Ladino",
+        "name": "Dzhudezmo"
+      },
+      "lb": {
+        "english_name": "Luxembourgish",
+        "name": "L\u00ebtzebuergesch"
+      },
+      "lbe": {
+        "english_name": "Lak",
+        "name": "\u041b\u0430\u043a\u043a\u0443"
+      },
+      "lez": {
+        "english_name": "Lezgian",
+        "name": "\u041b\u0435\u0437\u0433\u0438 \u0447\u0406\u0430\u043b (Lezgi \u010d\u2019al)"
+      },
+      "lfn": {
+        "english_name": "Lingua Franca Nova",
+        "name": "Lingua franca nova"
+      },
+      "lg": {
+        "english_name": "Luganda",
+        "name": "Luganda"
+      },
+      "li": {
+        "english_name": "Limburgish",
+        "name": "Limburgs"
+      },
+      "lij": {
+        "english_name": "Ligurian",
+        "name": "L\u00ecgure"
+      },
+      "lld": {
+        "english_name": "Ladin",
+        "name": "Lingaz"
+      },
+      "lmo": {
+        "english_name": "Lombard",
+        "name": "Lumbaart"
+      },
+      "ln": {
+        "english_name": "Lingala",
+        "name": "Lingala"
+      },
+      "lo": {
+        "english_name": "Lao",
+        "name": "\u0ea5\u0eb2\u0ea7"
+      },
+      "lt": {
+        "english_name": "Lithuanian",
+        "name": "Lietuvi\u0173"
+      },
+      "ltg": {
+        "english_name": "Latgalian",
+        "name": "Latga\u013cu"
+      },
+      "lv": {
+        "english_name": "Latvian",
+        "name": "Latvie\u0161u"
+      },
+      "mad": {
+        "english_name": "Madurese",
+        "name": "Madhur\u00e2"
+      },
+      "mai": {
+        "english_name": "Maithili",
+        "name": "\u092e\u0948\u0925\u093f\u0932\u0940"
+      },
+      "map-bms": {
+        "english_name": "Banyumasan",
+        "name": "Basa Banyumasan"
+      },
+      "mdf": {
+        "english_name": "Moksha",
+        "name": "\u041c\u043e\u043a\u0448\u0435\u043d\u044c (Mokshanj K\u00e4lj)"
+      },
+      "mg": {
+        "english_name": "Malagasy",
+        "name": "Malagasy"
+      },
+      "mhr": {
+        "english_name": "Meadow Mari",
+        "name": "\u041e\u043b\u044b\u043a \u041c\u0430\u0440\u0438\u0439 (Olyk Marij)"
+      },
+      "mi": {
+        "english_name": "Maori",
+        "name": "M\u0101ori"
+      },
+      "min": {
+        "english_name": "Minangkabau",
+        "name": "Minangkabau"
+      },
+      "mk": {
+        "english_name": "Macedonian",
+        "name": "\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438"
+      },
+      "ml": {
+        "english_name": "Malayalam",
+        "name": "\u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02"
+      },
+      "mn": {
+        "english_name": "Mongolian",
+        "name": "\u041c\u043e\u043d\u0433\u043e\u043b"
+      },
+      "mni": {
+        "english_name": "Meitei",
+        "name": "\uabc3\uabe4\uabc7\uabe9\uabc2\uabe3\uabdf"
+      },
+      "mnw": {
+        "english_name": "Mon",
+        "name": "\u1019\u1014\u103a"
+      },
+      "mr": {
+        "english_name": "Marathi",
+        "name": "\u092e\u0930\u093e\u0920\u0940"
+      },
+      "mrj": {
+        "english_name": "Hill Mari",
+        "name": "\u041a\u044b\u0440\u044b\u043a \u041c\u0430\u0440\u044b (Kyryk Mary)"
+      },
+      "ms": {
+        "english_name": "Malay",
+        "name": "Bahasa Melayu"
+      },
+      "mt": {
+        "english_name": "Maltese",
+        "name": "Malti"
+      },
+      "mwl": {
+        "english_name": "Mirandese",
+        "name": "Mirand\u00e9s"
+      },
+      "my": {
+        "english_name": "Burmese",
+        "name": "\u1019\u103c\u1014\u103a\u1019\u102c\u1018\u102c\u101e\u102c"
+      },
+      "myv": {
+        "english_name": "Erzya",
+        "name": "\u042d\u0440\u0437\u044f\u043d\u044c (Erzjanj Kelj)"
+      },
+      "mzn": {
+        "english_name": "Mazandarani",
+        "name": "\u0645\u064e\u0632\u0650\u0631\u0648\u0646\u064a"
+      },
+      "na": {
+        "english_name": "Nauruan",
+        "name": "dorerin Naoero"
+      },
+      "nah": {
+        "english_name": "Nahuatl",
+        "name": "N\u0101huatl"
+      },
+      "nap": {
+        "english_name": "Neapolitan",
+        "name": "Nnapulitano"
+      },
+      "nds": {
+        "english_name": "Low Saxon",
+        "name": "Plattd\u00fc\u00fctsch"
+      },
+      "nds-nl": {
+        "english_name": "Dutch Low Saxon",
+        "name": "Nedersaksisch"
+      },
+      "ne": {
+        "english_name": "Nepali",
+        "name": "\u0928\u0947\u092a\u093e\u0932\u0940"
+      },
+      "new": {
+        "english_name": "Newar",
+        "name": "\u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e"
+      },
+      "nia": {
+        "english_name": "Nias",
+        "name": "Li Niha"
+      },
+      "nl": {
+        "english_name": "Dutch",
+        "name": "Nederlands"
+      },
+      "nn": {
+        "english_name": "Norwegian (Nynorsk)",
+        "name": "Nynorsk"
+      },
+      "no": {
+        "english_name": "Norwegian (Bokm\u00e5l)",
+        "name": "Norsk (Bokm\u00e5l)"
+      },
+      "nov": {
+        "english_name": "Novial",
+        "name": "Novial"
+      },
+      "nqo": {
+        "english_name": "N\u2019Ko",
+        "name": "\u07d2\u07de\u07cf"
+      },
+      "nrm": {
+        "english_name": "Norman",
+        "name": "Nouormand/Normaund"
+      },
+      "nso": {
+        "english_name": "Northern Sotho",
+        "name": "Sepedi"
+      },
+      "nv": {
+        "english_name": "Navajo",
+        "name": "Din\u00e9 bizaad"
+      },
+      "ny": {
+        "english_name": "Chichewa",
+        "name": "Chichewa"
+      },
+      "oc": {
+        "english_name": "Occitan",
+        "name": "Occitan"
+      },
+      "olo": {
+        "english_name": "Livvi-Karelian",
+        "name": "Karjalan"
+      },
+      "om": {
+        "english_name": "Oromo",
+        "name": "Oromoo"
+      },
+      "or": {
+        "english_name": "Oriya",
+        "name": "\u0b13\u0b21\u0b3c\u0b3f\u0b06"
+      },
+      "os": {
+        "english_name": "Ossetian",
+        "name": "\u0418\u0440\u043e\u043d\u0430\u0443"
+      },
+      "pa": {
+        "english_name": "Punjabi",
+        "name": "\u0a2a\u0a70\u0a1c\u0a3e\u0a2c\u0a40"
+      },
+      "pag": {
+        "english_name": "Pangasinan",
+        "name": "Pangasinan"
+      },
+      "pam": {
+        "english_name": "Kapampangan",
+        "name": "Kapampangan"
+      },
+      "pap": {
+        "english_name": "Papiamentu",
+        "name": "Papiamentu"
+      },
+      "pcd": {
+        "english_name": "Picard",
+        "name": "Picard"
+      },
+      "pcm": {
+        "english_name": "Nigerian Pidgin",
+        "name": "Naij\u00e1"
+      },
+      "pdc": {
+        "english_name": "Pennsylvania German",
+        "name": "Deitsch"
+      },
+      "pfl": {
+        "english_name": "Palatinate German",
+        "name": "P\u00e4lzisch"
+      },
+      "pi": {
+        "english_name": "Pali",
+        "name": "\u092a\u093e\u0934\u093f"
+      },
+      "pih": {
+        "english_name": "Norfolk",
+        "name": "Norfuk"
+      },
+      "pl": {
+        "english_name": "Polish",
+        "name": "Polski"
+      },
+      "pms": {
+        "english_name": "Piedmontese",
+        "name": "Piemont\u00e8is"
+      },
+      "pnb": {
+        "english_name": "Western Punjabi",
+        "name": "\u0634\u0627\u06c1 \u0645\u06a9\u06be\u06cc \u067e\u0646\u062c\u0627\u0628\u06cc (Sh\u0101hmukh\u012b Pa\u00f1j\u0101b\u012b)"
+      },
+      "pnt": {
+        "english_name": "Pontic",
+        "name": "\u03a0\u03bf\u03bd\u03c4\u03b9\u03b1\u03ba\u03ac"
+      },
+      "ps": {
+        "english_name": "Pashto",
+        "name": "\u067e\u069a\u062a\u0648"
+      },
+      "pt": {
+        "english_name": "Portuguese",
+        "name": "Portugu\u00eas"
+      },
+      "pwn": {
+        "english_name": "Paiwan",
+        "name": "Paiwan"
+      },
+      "qu": {
+        "english_name": "Quechua",
+        "name": "Qichwa simi"
+      },
+      "rm": {
+        "english_name": "Romansh",
+        "name": "Rumantsch"
+      },
+      "rmy": {
+        "english_name": "Romani",
+        "name": "romani - \u0930\u094b\u092e\u093e\u0928\u0940"
+      },
+      "rn": {
+        "english_name": "Kirundi",
+        "name": "Ikirundi"
+      },
+      "ro": {
+        "english_name": "Romanian",
+        "name": "Rom\u00e2n\u0103"
+      },
+      "roa-rup": {
+        "english_name": "Aromanian",
+        "name": "Arm\u00e3neashce"
+      },
+      "roa-tara": {
+        "english_name": "Tarantino",
+        "name": "Tarand\u00edne"
+      },
+      "ru": {
+        "english_name": "Russian",
+        "name": "\u0420\u0443\u0441\u0441\u043a\u0438\u0439"
+      },
+      "rue": {
+        "english_name": "Rusyn",
+        "name": "\u0420\u0443\u0441\u0438\u043d\u044c\u0441\u043a\u044b\u0439"
+      },
+      "rw": {
+        "english_name": "Kinyarwanda",
+        "name": "Ikinyarwanda"
+      },
+      "sa": {
+        "english_name": "Sanskrit",
+        "name": "\u0938\u0902\u0938\u094d\u0915\u0943\u0924\u092e\u094d"
+      },
+      "sah": {
+        "english_name": "Sakha",
+        "name": "\u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430 (Saxa Tyla)"
+      },
+      "sat": {
+        "english_name": "Santali",
+        "name": "\u1c65\u1c5f\u1c71\u1c5b\u1c5f\u1c72\u1c64"
+      },
+      "sc": {
+        "english_name": "Sardinian",
+        "name": "Sardu"
+      },
+      "scn": {
+        "english_name": "Sicilian",
+        "name": "Sicilianu"
+      },
+      "sco": {
+        "english_name": "Scots",
+        "name": "Scots"
+      },
+      "sd": {
+        "english_name": "Sindhi",
+        "name": "\u0633\u0646\u068c\u064a\u060c \u0633\u0646\u062f\u06be\u06cc \u060c \u0938\u093f\u0928\u094d\u0927"
+      },
+      "se": {
+        "english_name": "Northern Sami",
+        "name": "S\u00e1megiella"
+      },
+      "sg": {
+        "english_name": "Sango",
+        "name": "S\u00e4ng\u00f6"
+      },
+      "sh": {
+        "english_name": "Serbo-Croatian",
+        "name": "Srpskohrvatski / \u0421\u0440\u043f\u0441\u043a\u043e\u0445\u0440\u0432\u0430\u0442\u0441\u043a\u0438"
+      },
+      "shi": {
+        "english_name": "Tachelhit",
+        "name": "Tacl\u1e25it"
+      },
+      "shn": {
+        "english_name": "Shan",
+        "name": "\u101c\u102d\u1075\u103a\u1088\u1010\u1086\u1038"
+      },
+      "si": {
+        "english_name": "Sinhalese",
+        "name": "\u0dc3\u0dd2\u0d82\u0dc4\u0dbd"
+      },
+      "simple": {
+        "english_name": "Simple English",
+        "name": "Simple English"
+      },
+      "sk": {
+        "english_name": "Slovak",
+        "name": "Sloven\u010dina"
+      },
+      "skr": {
+        "english_name": "Saraiki",
+        "name": "\u0633\u0631\u0627\u0626\u06cc\u06a9\u06cc"
+      },
+      "sl": {
+        "english_name": "Slovenian",
+        "name": "Sloven\u0161\u010dina"
+      },
+      "sm": {
+        "english_name": "Samoan",
+        "name": "Gagana Samoa"
+      },
+      "smn": {
+        "english_name": "Inari Sami",
+        "name": "Anar\u00e2\u0161kiel\u00e2"
+      },
+      "sn": {
+        "english_name": "Shona",
+        "name": "chiShona"
+      },
+      "so": {
+        "english_name": "Somali",
+        "name": "Soomaali"
+      },
+      "sq": {
+        "english_name": "Albanian",
+        "name": "Shqip"
+      },
+      "sr": {
+        "english_name": "Serbian",
+        "name": "\u0421\u0440\u043f\u0441\u043a\u0438 / Srpski"
+      },
+      "srn": {
+        "english_name": "Sranan",
+        "name": "Sranantongo"
+      },
+      "ss": {
+        "english_name": "Swati",
+        "name": "SiSwati"
+      },
+      "st": {
+        "english_name": "Sesotho",
+        "name": "Sesotho"
+      },
+      "stq": {
+        "english_name": "Saterland Frisian",
+        "name": "Seeltersk"
+      },
+      "su": {
+        "english_name": "Sundanese",
+        "name": "Basa Sunda"
+      },
+      "sv": {
+        "english_name": "Swedish",
+        "name": "Svenska"
+      },
+      "sw": {
+        "english_name": "Swahili",
+        "name": "Kiswahili"
+      },
+      "szl": {
+        "english_name": "Silesian",
+        "name": "\u015al\u016fnski"
+      },
+      "szy": {
+        "english_name": "Sakizaya",
+        "name": "Sakizaya"
+      },
+      "ta": {
+        "english_name": "Tamil",
+        "name": "\u0ba4\u0bae\u0bbf\u0bb4\u0bcd"
+      },
+      "tay": {
+        "english_name": "Atayal",
+        "name": "Tayal"
+      },
+      "tcy": {
+        "english_name": "Tulu",
+        "name": "\u0ca4\u0cc1\u0cb3\u0cc1"
+      },
+      "te": {
+        "english_name": "Telugu",
+        "name": "\u0c24\u0c46\u0c32\u0c41\u0c17\u0c41"
+      },
+      "tet": {
+        "english_name": "Tetum",
+        "name": "Tetun"
+      },
+      "tg": {
+        "english_name": "Tajik",
+        "name": "\u0422\u043e\u04b7\u0438\u043a\u04e3"
+      },
+      "th": {
+        "english_name": "Thai",
+        "name": "\u0e44\u0e17\u0e22"
+      },
+      "ti": {
+        "english_name": "Tigrinya",
+        "name": "\u1275\u130d\u122d\u129b"
+      },
+      "tk": {
+        "english_name": "Turkmen",
+        "name": "T\u00fcrkmen"
+      },
+      "tl": {
+        "english_name": "Tagalog",
+        "name": "Tagalog"
+      },
+      "tn": {
+        "english_name": "Tswana",
+        "name": "Setswana"
+      },
+      "to": {
+        "english_name": "Tongan",
+        "name": "faka Tonga"
+      },
+      "tpi": {
+        "english_name": "Tok Pisin",
+        "name": "Tok Pisin"
+      },
+      "tr": {
+        "english_name": "Turkish",
+        "name": "T\u00fcrk\u00e7e"
+      },
+      "trv": {
+        "english_name": "Seediq",
+        "name": "Taroko"
+      },
+      "ts": {
+        "english_name": "Tsonga",
+        "name": "Xitsonga"
+      },
+      "tt": {
+        "english_name": "Tatar",
+        "name": "Tatar\u00e7a / \u0422\u0430\u0442\u0430\u0440\u0447\u0430"
+      },
+      "tum": {
+        "english_name": "Tumbuka",
+        "name": "chiTumbuka"
+      },
+      "tw": {
+        "english_name": "Twi",
+        "name": "Twi"
+      },
+      "ty": {
+        "english_name": "Tahitian",
+        "name": "Reo M\u0101`ohi"
+      },
+      "tyv": {
+        "english_name": "Tuvan",
+        "name": "\u0422\u044b\u0432\u0430"
+      },
+      "udm": {
+        "english_name": "Udmurt",
+        "name": "\u0423\u0434\u043c\u0443\u0440\u0442 \u043a\u044b\u043b"
+      },
+      "ug": {
+        "english_name": "Uyghur",
+        "name": "\u0626\u06c7\u064a\u063a\u06c7\u0631 \u062a\u0649\u0644\u0649"
+      },
+      "uk": {
+        "english_name": "Ukrainian",
+        "name": "\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"
+      },
+      "ur": {
+        "english_name": "Urdu",
+        "name": "\u0627\u0631\u062f\u0648"
+      },
+      "uz": {
+        "english_name": "Uzbek",
+        "name": "O\u2018zbek"
+      },
+      "ve": {
+        "english_name": "Venda",
+        "name": "Tshivenda"
+      },
+      "vec": {
+        "english_name": "Venetian",
+        "name": "V\u00e8neto"
+      },
+      "vep": {
+        "english_name": "Vepsian",
+        "name": "Veps\u00e4n"
+      },
+      "vi": {
+        "english_name": "Vietnamese",
+        "name": "Ti\u1ebfng Vi\u1ec7t"
+      },
+      "vls": {
+        "english_name": "West Flemish",
+        "name": "West-Vlams"
+      },
+      "vo": {
+        "english_name": "Volap\u00fck",
+        "name": "Volap\u00fck"
+      },
+      "wa": {
+        "english_name": "Walloon",
+        "name": "Walon"
+      },
+      "war": {
+        "english_name": "Waray-Waray",
+        "name": "Winaray"
+      },
+      "wo": {
+        "english_name": "Wolof",
+        "name": "Wolof"
+      },
+      "wuu": {
+        "english_name": "Wu",
+        "name": "\u5434\u8bed"
+      },
+      "xal": {
+        "english_name": "Kalmyk",
+        "name": "\u0425\u0430\u043b\u044c\u043c\u0433"
+      },
+      "xh": {
+        "english_name": "Xhosa",
+        "name": "isiXhosa"
+      },
+      "xmf": {
+        "english_name": "Mingrelian",
+        "name": "\u10db\u10d0\u10e0\u10d2\u10d0\u10da\u10e3\u10e0\u10d8 (Margaluri)"
+      },
+      "yi": {
+        "english_name": "Yiddish",
+        "name": "\u05d9\u05d9\u05b4\u05d3\u05d9\u05e9"
+      },
+      "yo": {
+        "english_name": "Yoruba",
+        "name": "Yor\u00f9b\u00e1"
+      },
+      "za": {
+        "english_name": "Zhuang",
+        "name": "Cuengh"
+      },
+      "zea": {
+        "english_name": "Zeelandic",
+        "name": "Ze\u00eauws"
+      },
+      "zh": {
+        "english_name": "Chinese",
+        "name": "\u4e2d\u6587"
+      },
+      "zh-classical": {
+        "english_name": "Classical Chinese",
+        "name": "\u53e4\u6587 / \u6587\u8a00\u6587"
+      },
+      "zh-min-nan": {
+        "english_name": "Min Nan",
+        "name": "B\u00e2n-l\u00e2m-g\u00fa"
+      },
+      "zh-yue": {
+        "english_name": "Cantonese",
+        "name": "\u7cb5\u8a9e"
+      },
+      "zu": {
+        "english_name": "Zulu",
+        "name": "isiZulu"
+      }
+    }
+  },
+  "yahoo": {
+    "all_locale": null,
+    "data_type": "supported_languages",
+    "languages": {},
+    "regions": {},
+    "supported_languages": [
+      "ar",
+      "bg",
+      "cs",
+      "da",
+      "de",
+      "el",
+      "en",
+      "es",
+      "et",
+      "fi",
+      "fr",
+      "he",
+      "hr",
+      "hu",
+      "it",
+      "ja",
+      "ko",
+      "lt",
+      "lv",
+      "nl",
+      "no",
+      "pl",
+      "pt",
+      "ro",
+      "ru",
+      "sk",
+      "sl",
+      "sv",
+      "th",
+      "tr",
+      "zh_chs",
+      "zh_cht"
+    ]
+  }
+}

+ 0 - 4381
searx/data/engines_languages.json

@@ -1,4381 +0,0 @@
-{
-  "bing": [
-    "af",
-    "am",
-    "ar",
-    "as",
-    "az-latn",
-    "be",
-    "bg",
-    "bn",
-    "bs-latn",
-    "ca",
-    "ca-es-valencia",
-    "chr-cher",
-    "cs",
-    "cy",
-    "da",
-    "de",
-    "el",
-    "en",
-    "es",
-    "et",
-    "eu",
-    "fa",
-    "fi",
-    "fil",
-    "fr",
-    "ga",
-    "gd",
-    "gl",
-    "gu",
-    "ha-latn",
-    "he",
-    "hi",
-    "hr",
-    "hu",
-    "hy",
-    "id",
-    "ig",
-    "is",
-    "it",
-    "ja",
-    "ka",
-    "kk",
-    "km",
-    "kn",
-    "ko",
-    "kok",
-    "ku-arab",
-    "ky",
-    "lb",
-    "lo",
-    "lt",
-    "lv",
-    "mi",
-    "mk",
-    "ml",
-    "mn-Cyrl-MN",
-    "mr",
-    "ms",
-    "mt",
-    "nb",
-    "ne",
-    "nl",
-    "nn",
-    "nso",
-    "or",
-    "pa-arab",
-    "pa-guru",
-    "pl",
-    "prs",
-    "pt-BR",
-    "pt-PT",
-    "quc",
-    "quz",
-    "ro",
-    "ru",
-    "rw",
-    "sd-arab",
-    "si",
-    "sk",
-    "sl",
-    "sq",
-    "sr-cyrl",
-    "sr-latn",
-    "sv",
-    "sw",
-    "ta",
-    "te",
-    "tg-cyrl",
-    "th",
-    "ti",
-    "tk",
-    "tn",
-    "tr",
-    "tt",
-    "ug",
-    "uk",
-    "ur",
-    "uz-latn",
-    "vi",
-    "wo",
-    "xh",
-    "yo",
-    "zh-Hans",
-    "zh-Hant",
-    "zu"
-  ],
-  "bing images": [
-    "af",
-    "am",
-    "ar",
-    "as",
-    "az-latn",
-    "be",
-    "bg",
-    "bn",
-    "bs-latn",
-    "ca",
-    "ca-es-valencia",
-    "chr-cher",
-    "cs",
-    "cy",
-    "da",
-    "de",
-    "el",
-    "en",
-    "es",
-    "et",
-    "eu",
-    "fa",
-    "fi",
-    "fil",
-    "fr",
-    "ga",
-    "gd",
-    "gl",
-    "gu",
-    "ha-latn",
-    "he",
-    "hi",
-    "hr",
-    "hu",
-    "hy",
-    "id",
-    "ig",
-    "is",
-    "it",
-    "ja",
-    "ka",
-    "kk",
-    "km",
-    "kn",
-    "ko",
-    "kok",
-    "ku-arab",
-    "ky",
-    "lb",
-    "lo",
-    "lt",
-    "lv",
-    "mi",
-    "mk",
-    "ml",
-    "mn-Cyrl-MN",
-    "mr",
-    "ms",
-    "mt",
-    "nb",
-    "ne",
-    "nl",
-    "nn",
-    "nso",
-    "or",
-    "pa-arab",
-    "pa-guru",
-    "pl",
-    "prs",
-    "pt-BR",
-    "pt-PT",
-    "quc",
-    "quz",
-    "ro",
-    "ru",
-    "rw",
-    "sd-arab",
-    "si",
-    "sk",
-    "sl",
-    "sq",
-    "sr-cyrl",
-    "sr-latn",
-    "sv",
-    "sw",
-    "ta",
-    "te",
-    "tg-cyrl",
-    "th",
-    "ti",
-    "tk",
-    "tn",
-    "tr",
-    "tt",
-    "ug",
-    "uk",
-    "ur",
-    "uz-latn",
-    "vi",
-    "wo",
-    "xh",
-    "yo",
-    "zh-Hans",
-    "zh-Hant",
-    "zu"
-  ],
-  "bing news": [
-    "af",
-    "am",
-    "ar",
-    "as",
-    "az-latn",
-    "be",
-    "bg",
-    "bn",
-    "bs-latn",
-    "ca",
-    "ca-es-valencia",
-    "chr-cher",
-    "cs",
-    "cy",
-    "da",
-    "de",
-    "el",
-    "en",
-    "es",
-    "et",
-    "eu",
-    "fa",
-    "fi",
-    "fil",
-    "fr",
-    "ga",
-    "gd",
-    "gl",
-    "gu",
-    "ha-latn",
-    "he",
-    "hi",
-    "hr",
-    "hu",
-    "hy",
-    "id",
-    "ig",
-    "is",
-    "it",
-    "ja",
-    "ka",
-    "kk",
-    "km",
-    "kn",
-    "ko",
-    "kok",
-    "ku-arab",
-    "ky",
-    "lb",
-    "lo",
-    "lt",
-    "lv",
-    "mi",
-    "mk",
-    "ml",
-    "mn-Cyrl-MN",
-    "mr",
-    "ms",
-    "mt",
-    "nb",
-    "ne",
-    "nl",
-    "nn",
-    "nso",
-    "or",
-    "pa-arab",
-    "pa-guru",
-    "pl",
-    "prs",
-    "pt-BR",
-    "pt-PT",
-    "quc",
-    "quz",
-    "ro",
-    "ru",
-    "rw",
-    "sd-arab",
-    "si",
-    "sk",
-    "sl",
-    "sq",
-    "sr-cyrl",
-    "sr-latn",
-    "sv",
-    "sw",
-    "ta",
-    "te",
-    "tg-cyrl",
-    "th",
-    "ti",
-    "tk",
-    "tn",
-    "tr",
-    "tt",
-    "ug",
-    "uk",
-    "ur",
-    "uz-latn",
-    "vi",
-    "wo",
-    "xh",
-    "yo",
-    "zh-Hans",
-    "zh-Hant",
-    "zu"
-  ],
-  "bing videos": [
-    "af",
-    "am",
-    "ar",
-    "as",
-    "az-latn",
-    "be",
-    "bg",
-    "bn",
-    "bs-latn",
-    "ca",
-    "ca-es-valencia",
-    "chr-cher",
-    "cs",
-    "cy",
-    "da",
-    "de",
-    "el",
-    "en",
-    "es",
-    "et",
-    "eu",
-    "fa",
-    "fi",
-    "fil",
-    "fr",
-    "ga",
-    "gd",
-    "gl",
-    "gu",
-    "ha-latn",
-    "he",
-    "hi",
-    "hr",
-    "hu",
-    "hy",
-    "id",
-    "ig",
-    "is",
-    "it",
-    "ja",
-    "ka",
-    "kk",
-    "km",
-    "kn",
-    "ko",
-    "kok",
-    "ku-arab",
-    "ky",
-    "lb",
-    "lo",
-    "lt",
-    "lv",
-    "mi",
-    "mk",
-    "ml",
-    "mn-Cyrl-MN",
-    "mr",
-    "ms",
-    "mt",
-    "nb",
-    "ne",
-    "nl",
-    "nn",
-    "nso",
-    "or",
-    "pa-arab",
-    "pa-guru",
-    "pl",
-    "prs",
-    "pt-BR",
-    "pt-PT",
-    "quc",
-    "quz",
-    "ro",
-    "ru",
-    "rw",
-    "sd-arab",
-    "si",
-    "sk",
-    "sl",
-    "sq",
-    "sr-cyrl",
-    "sr-latn",
-    "sv",
-    "sw",
-    "ta",
-    "te",
-    "tg-cyrl",
-    "th",
-    "ti",
-    "tk",
-    "tn",
-    "tr",
-    "tt",
-    "ug",
-    "uk",
-    "ur",
-    "uz-latn",
-    "vi",
-    "wo",
-    "xh",
-    "yo",
-    "zh-Hans",
-    "zh-Hant",
-    "zu"
-  ],
-  "dailymotion": [
-    "ar_AA",
-    "ar_AE",
-    "ar_EG",
-    "ar_SA",
-    "de_AT",
-    "de_CH",
-    "de_DE",
-    "el_GR",
-    "en_AU",
-    "en_CA",
-    "en_EN",
-    "en_GB",
-    "en_HK",
-    "en_IE",
-    "en_IN",
-    "en_NG",
-    "en_PH",
-    "en_PK",
-    "en_SG",
-    "en_US",
-    "en_ZA",
-    "es_AR",
-    "es_ES",
-    "es_MX",
-    "fr_BE",
-    "fr_CA",
-    "fr_CH",
-    "fr_CI",
-    "fr_FR",
-    "fr_MA",
-    "fr_SN",
-    "fr_TN",
-    "id_ID",
-    "it_CH",
-    "it_IT",
-    "ja_JP",
-    "ko_KR",
-    "ms_MY",
-    "nl_BE",
-    "nl_NL",
-    "pl_PL",
-    "pt_BR",
-    "pt_PT",
-    "ro_RO",
-    "ru_RU",
-    "th_TH",
-    "tr_TR",
-    "vi_VN",
-    "zh_CN",
-    "zh_TW"
-  ],
-  "ddg definitions": [
-    "ar-XA",
-    "bg-BG",
-    "ca-CT",
-    "ca-ES",
-    "cs-CZ",
-    "da-DK",
-    "de-AT",
-    "de-CH",
-    "de-DE",
-    "el-GR",
-    "en-AU",
-    "en-CA",
-    "en-ID",
-    "en-IE",
-    "en-IL",
-    "en-IN",
-    "en-MY",
-    "en-NZ",
-    "en-PH",
-    "en-PK",
-    "en-SG",
-    "en-TH",
-    "en-UK",
-    "en-US",
-    "en-VN",
-    "en-ZA",
-    "es-AR",
-    "es-CL",
-    "es-CO",
-    "es-ES",
-    "es-MX",
-    "es-PE",
-    "es-US",
-    "et-EE",
-    "fi-FI",
-    "fr-BE",
-    "fr-CA",
-    "fr-CH",
-    "fr-FR",
-    "hr-HR",
-    "hu-HU",
-    "it-IT",
-    "jp-JP",
-    "kr-KR",
-    "lt-LT",
-    "lv-LV",
-    "nl-BE",
-    "nl-NL",
-    "no-NO",
-    "pl-PL",
-    "pt-BR",
-    "pt-PT",
-    "ro-RO",
-    "ru-RU",
-    "sk-SK",
-    "sl-SL",
-    "sv-SE",
-    "tr-TR",
-    "tzh-HK",
-    "tzh-TW",
-    "uk-UA",
-    "wt-WT",
-    "zh-CN"
-  ],
-  "duckduckgo": [
-    "ar-XA",
-    "bg-BG",
-    "ca-CT",
-    "ca-ES",
-    "cs-CZ",
-    "da-DK",
-    "de-AT",
-    "de-CH",
-    "de-DE",
-    "el-GR",
-    "en-AU",
-    "en-CA",
-    "en-ID",
-    "en-IE",
-    "en-IL",
-    "en-IN",
-    "en-MY",
-    "en-NZ",
-    "en-PH",
-    "en-PK",
-    "en-SG",
-    "en-TH",
-    "en-UK",
-    "en-US",
-    "en-VN",
-    "en-ZA",
-    "es-AR",
-    "es-CL",
-    "es-CO",
-    "es-ES",
-    "es-MX",
-    "es-PE",
-    "es-US",
-    "et-EE",
-    "fi-FI",
-    "fr-BE",
-    "fr-CA",
-    "fr-CH",
-    "fr-FR",
-    "hr-HR",
-    "hu-HU",
-    "it-IT",
-    "jp-JP",
-    "kr-KR",
-    "lt-LT",
-    "lv-LV",
-    "nl-BE",
-    "nl-NL",
-    "no-NO",
-    "pl-PL",
-    "pt-BR",
-    "pt-PT",
-    "ro-RO",
-    "ru-RU",
-    "sk-SK",
-    "sl-SL",
-    "sv-SE",
-    "tr-TR",
-    "tzh-HK",
-    "tzh-TW",
-    "uk-UA",
-    "wt-WT",
-    "zh-CN"
-  ],
-  "duckduckgo images": [
-    "ar-XA",
-    "bg-BG",
-    "ca-CT",
-    "ca-ES",
-    "cs-CZ",
-    "da-DK",
-    "de-AT",
-    "de-CH",
-    "de-DE",
-    "el-GR",
-    "en-AU",
-    "en-CA",
-    "en-ID",
-    "en-IE",
-    "en-IL",
-    "en-IN",
-    "en-MY",
-    "en-NZ",
-    "en-PH",
-    "en-PK",
-    "en-SG",
-    "en-TH",
-    "en-UK",
-    "en-US",
-    "en-VN",
-    "en-ZA",
-    "es-AR",
-    "es-CL",
-    "es-CO",
-    "es-ES",
-    "es-MX",
-    "es-PE",
-    "es-US",
-    "et-EE",
-    "fi-FI",
-    "fr-BE",
-    "fr-CA",
-    "fr-CH",
-    "fr-FR",
-    "hr-HR",
-    "hu-HU",
-    "it-IT",
-    "jp-JP",
-    "kr-KR",
-    "lt-LT",
-    "lv-LV",
-    "nl-BE",
-    "nl-NL",
-    "no-NO",
-    "pl-PL",
-    "pt-BR",
-    "pt-PT",
-    "ro-RO",
-    "ru-RU",
-    "sk-SK",
-    "sl-SL",
-    "sv-SE",
-    "tr-TR",
-    "tzh-HK",
-    "tzh-TW",
-    "uk-UA",
-    "wt-WT",
-    "zh-CN"
-  ],
-  "google": {
-    "af": {
-      "name": "Afrikaans"
-    },
-    "ar": {
-      "name": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629"
-    },
-    "be": {
-      "name": "\u0431\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f"
-    },
-    "bg": {
-      "name": "\u0431\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438"
-    },
-    "ca": {
-      "name": "catal\u00e0"
-    },
-    "cs": {
-      "name": "\u010de\u0161tina"
-    },
-    "da": {
-      "name": "dansk"
-    },
-    "de": {
-      "name": "Deutsch"
-    },
-    "el": {
-      "name": "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac"
-    },
-    "en": {
-      "name": "English"
-    },
-    "eo": {
-      "name": "esperanto"
-    },
-    "es": {
-      "name": "espa\u00f1ol"
-    },
-    "et": {
-      "name": "eesti"
-    },
-    "fa": {
-      "name": "\u0641\u0627\u0631\u0633\u06cc"
-    },
-    "fi": {
-      "name": "suomi"
-    },
-    "fr": {
-      "name": "fran\u00e7ais"
-    },
-    "hi": {
-      "name": "\u0939\u093f\u0928\u094d\u0926\u0940"
-    },
-    "hr": {
-      "name": "hrvatski"
-    },
-    "hu": {
-      "name": "magyar"
-    },
-    "hy": {
-      "name": "\u0570\u0561\u0575\u0565\u0580\u0565\u0576"
-    },
-    "id": {
-      "name": "Indonesia"
-    },
-    "is": {
-      "name": "\u00edslenska"
-    },
-    "it": {
-      "name": "italiano"
-    },
-    "iw": {
-      "name": "\u05e2\u05d1\u05e8\u05d9\u05ea"
-    },
-    "ja": {
-      "name": "\u65e5\u672c\u8a9e"
-    },
-    "ko": {
-      "name": "\ud55c\uad6d\uc5b4"
-    },
-    "lt": {
-      "name": "lietuvi\u0173"
-    },
-    "lv": {
-      "name": "latvie\u0161u"
-    },
-    "nl": {
-      "name": "Nederlands"
-    },
-    "no": {
-      "name": "norsk"
-    },
-    "pl": {
-      "name": "polski"
-    },
-    "pt": {
-      "name": "portugu\u00eas"
-    },
-    "ro": {
-      "name": "rom\u00e2n\u0103"
-    },
-    "ru": {
-      "name": "\u0440\u0443\u0441\u0441\u043a\u0438\u0439"
-    },
-    "sk": {
-      "name": "sloven\u010dina"
-    },
-    "sl": {
-      "name": "sloven\u0161\u010dina"
-    },
-    "sr": {
-      "name": "\u0441\u0440\u043f\u0441\u043a\u0438"
-    },
-    "sv": {
-      "name": "svenska"
-    },
-    "sw": {
-      "name": "Kiswahili"
-    },
-    "th": {
-      "name": "\u0e44\u0e17\u0e22"
-    },
-    "tl": {
-      "name": "Filipino"
-    },
-    "tr": {
-      "name": "T\u00fcrk\u00e7e"
-    },
-    "uk": {
-      "name": "\u0443\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"
-    },
-    "vi": {
-      "name": "Ti\u1ebfng Vi\u1ec7t"
-    },
-    "zh-CN": {
-      "name": "\u4e2d\u6587 (\u7b80\u4f53)"
-    },
-    "zh-TW": {
-      "name": "\u4e2d\u6587 (\u7e41\u9ad4)"
-    }
-  },
-  "google images": {
-    "af": {
-      "name": "Afrikaans"
-    },
-    "ar": {
-      "name": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629"
-    },
-    "be": {
-      "name": "\u0431\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f"
-    },
-    "bg": {
-      "name": "\u0431\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438"
-    },
-    "ca": {
-      "name": "catal\u00e0"
-    },
-    "cs": {
-      "name": "\u010de\u0161tina"
-    },
-    "da": {
-      "name": "dansk"
-    },
-    "de": {
-      "name": "Deutsch"
-    },
-    "el": {
-      "name": "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac"
-    },
-    "en": {
-      "name": "English"
-    },
-    "eo": {
-      "name": "esperanto"
-    },
-    "es": {
-      "name": "espa\u00f1ol"
-    },
-    "et": {
-      "name": "eesti"
-    },
-    "fa": {
-      "name": "\u0641\u0627\u0631\u0633\u06cc"
-    },
-    "fi": {
-      "name": "suomi"
-    },
-    "fr": {
-      "name": "fran\u00e7ais"
-    },
-    "hi": {
-      "name": "\u0939\u093f\u0928\u094d\u0926\u0940"
-    },
-    "hr": {
-      "name": "hrvatski"
-    },
-    "hu": {
-      "name": "magyar"
-    },
-    "hy": {
-      "name": "\u0570\u0561\u0575\u0565\u0580\u0565\u0576"
-    },
-    "id": {
-      "name": "Indonesia"
-    },
-    "is": {
-      "name": "\u00edslenska"
-    },
-    "it": {
-      "name": "italiano"
-    },
-    "iw": {
-      "name": "\u05e2\u05d1\u05e8\u05d9\u05ea"
-    },
-    "ja": {
-      "name": "\u65e5\u672c\u8a9e"
-    },
-    "ko": {
-      "name": "\ud55c\uad6d\uc5b4"
-    },
-    "lt": {
-      "name": "lietuvi\u0173"
-    },
-    "lv": {
-      "name": "latvie\u0161u"
-    },
-    "nl": {
-      "name": "Nederlands"
-    },
-    "no": {
-      "name": "norsk"
-    },
-    "pl": {
-      "name": "polski"
-    },
-    "pt": {
-      "name": "portugu\u00eas"
-    },
-    "ro": {
-      "name": "rom\u00e2n\u0103"
-    },
-    "ru": {
-      "name": "\u0440\u0443\u0441\u0441\u043a\u0438\u0439"
-    },
-    "sk": {
-      "name": "sloven\u010dina"
-    },
-    "sl": {
-      "name": "sloven\u0161\u010dina"
-    },
-    "sr": {
-      "name": "\u0441\u0440\u043f\u0441\u043a\u0438"
-    },
-    "sv": {
-      "name": "svenska"
-    },
-    "sw": {
-      "name": "Kiswahili"
-    },
-    "th": {
-      "name": "\u0e44\u0e17\u0e22"
-    },
-    "tl": {
-      "name": "Filipino"
-    },
-    "tr": {
-      "name": "T\u00fcrk\u00e7e"
-    },
-    "uk": {
-      "name": "\u0443\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"
-    },
-    "vi": {
-      "name": "Ti\u1ebfng Vi\u1ec7t"
-    },
-    "zh-CN": {
-      "name": "\u4e2d\u6587 (\u7b80\u4f53)"
-    },
-    "zh-TW": {
-      "name": "\u4e2d\u6587 (\u7e41\u9ad4)"
-    }
-  },
-  "google news": {
-    "af": {
-      "name": "Afrikaans"
-    },
-    "ar": {
-      "name": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629"
-    },
-    "be": {
-      "name": "\u0431\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f"
-    },
-    "bg": {
-      "name": "\u0431\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438"
-    },
-    "ca": {
-      "name": "catal\u00e0"
-    },
-    "cs": {
-      "name": "\u010de\u0161tina"
-    },
-    "da": {
-      "name": "dansk"
-    },
-    "de": {
-      "name": "Deutsch"
-    },
-    "el": {
-      "name": "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac"
-    },
-    "en": {
-      "name": "English"
-    },
-    "eo": {
-      "name": "esperanto"
-    },
-    "es": {
-      "name": "espa\u00f1ol"
-    },
-    "et": {
-      "name": "eesti"
-    },
-    "fa": {
-      "name": "\u0641\u0627\u0631\u0633\u06cc"
-    },
-    "fi": {
-      "name": "suomi"
-    },
-    "fr": {
-      "name": "fran\u00e7ais"
-    },
-    "hi": {
-      "name": "\u0939\u093f\u0928\u094d\u0926\u0940"
-    },
-    "hr": {
-      "name": "hrvatski"
-    },
-    "hu": {
-      "name": "magyar"
-    },
-    "hy": {
-      "name": "\u0570\u0561\u0575\u0565\u0580\u0565\u0576"
-    },
-    "id": {
-      "name": "Indonesia"
-    },
-    "is": {
-      "name": "\u00edslenska"
-    },
-    "it": {
-      "name": "italiano"
-    },
-    "iw": {
-      "name": "\u05e2\u05d1\u05e8\u05d9\u05ea"
-    },
-    "ja": {
-      "name": "\u65e5\u672c\u8a9e"
-    },
-    "ko": {
-      "name": "\ud55c\uad6d\uc5b4"
-    },
-    "lt": {
-      "name": "lietuvi\u0173"
-    },
-    "lv": {
-      "name": "latvie\u0161u"
-    },
-    "nl": {
-      "name": "Nederlands"
-    },
-    "no": {
-      "name": "norsk"
-    },
-    "pl": {
-      "name": "polski"
-    },
-    "pt": {
-      "name": "portugu\u00eas"
-    },
-    "ro": {
-      "name": "rom\u00e2n\u0103"
-    },
-    "ru": {
-      "name": "\u0440\u0443\u0441\u0441\u043a\u0438\u0439"
-    },
-    "sk": {
-      "name": "sloven\u010dina"
-    },
-    "sl": {
-      "name": "sloven\u0161\u010dina"
-    },
-    "sr": {
-      "name": "\u0441\u0440\u043f\u0441\u043a\u0438"
-    },
-    "sv": {
-      "name": "svenska"
-    },
-    "sw": {
-      "name": "Kiswahili"
-    },
-    "th": {
-      "name": "\u0e44\u0e17\u0e22"
-    },
-    "tl": {
-      "name": "Filipino"
-    },
-    "tr": {
-      "name": "T\u00fcrk\u00e7e"
-    },
-    "uk": {
-      "name": "\u0443\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"
-    },
-    "vi": {
-      "name": "Ti\u1ebfng Vi\u1ec7t"
-    },
-    "zh-CN": {
-      "name": "\u4e2d\u6587 (\u7b80\u4f53)"
-    },
-    "zh-TW": {
-      "name": "\u4e2d\u6587 (\u7e41\u9ad4)"
-    }
-  },
-  "google scholar": {
-    "af": {
-      "name": "Afrikaans"
-    },
-    "ar": {
-      "name": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629"
-    },
-    "be": {
-      "name": "\u0431\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f"
-    },
-    "bg": {
-      "name": "\u0431\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438"
-    },
-    "ca": {
-      "name": "catal\u00e0"
-    },
-    "cs": {
-      "name": "\u010de\u0161tina"
-    },
-    "da": {
-      "name": "dansk"
-    },
-    "de": {
-      "name": "Deutsch"
-    },
-    "el": {
-      "name": "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac"
-    },
-    "en": {
-      "name": "English"
-    },
-    "eo": {
-      "name": "esperanto"
-    },
-    "es": {
-      "name": "espa\u00f1ol"
-    },
-    "et": {
-      "name": "eesti"
-    },
-    "fa": {
-      "name": "\u0641\u0627\u0631\u0633\u06cc"
-    },
-    "fi": {
-      "name": "suomi"
-    },
-    "fr": {
-      "name": "fran\u00e7ais"
-    },
-    "hi": {
-      "name": "\u0939\u093f\u0928\u094d\u0926\u0940"
-    },
-    "hr": {
-      "name": "hrvatski"
-    },
-    "hu": {
-      "name": "magyar"
-    },
-    "hy": {
-      "name": "\u0570\u0561\u0575\u0565\u0580\u0565\u0576"
-    },
-    "id": {
-      "name": "Indonesia"
-    },
-    "is": {
-      "name": "\u00edslenska"
-    },
-    "it": {
-      "name": "italiano"
-    },
-    "iw": {
-      "name": "\u05e2\u05d1\u05e8\u05d9\u05ea"
-    },
-    "ja": {
-      "name": "\u65e5\u672c\u8a9e"
-    },
-    "ko": {
-      "name": "\ud55c\uad6d\uc5b4"
-    },
-    "lt": {
-      "name": "lietuvi\u0173"
-    },
-    "lv": {
-      "name": "latvie\u0161u"
-    },
-    "nl": {
-      "name": "Nederlands"
-    },
-    "no": {
-      "name": "norsk"
-    },
-    "pl": {
-      "name": "polski"
-    },
-    "pt": {
-      "name": "portugu\u00eas"
-    },
-    "ro": {
-      "name": "rom\u00e2n\u0103"
-    },
-    "ru": {
-      "name": "\u0440\u0443\u0441\u0441\u043a\u0438\u0439"
-    },
-    "sk": {
-      "name": "sloven\u010dina"
-    },
-    "sl": {
-      "name": "sloven\u0161\u010dina"
-    },
-    "sr": {
-      "name": "\u0441\u0440\u043f\u0441\u043a\u0438"
-    },
-    "sv": {
-      "name": "svenska"
-    },
-    "sw": {
-      "name": "Kiswahili"
-    },
-    "th": {
-      "name": "\u0e44\u0e17\u0e22"
-    },
-    "tl": {
-      "name": "Filipino"
-    },
-    "tr": {
-      "name": "T\u00fcrk\u00e7e"
-    },
-    "uk": {
-      "name": "\u0443\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"
-    },
-    "vi": {
-      "name": "Ti\u1ebfng Vi\u1ec7t"
-    },
-    "zh-CN": {
-      "name": "\u4e2d\u6587 (\u7b80\u4f53)"
-    },
-    "zh-TW": {
-      "name": "\u4e2d\u6587 (\u7e41\u9ad4)"
-    }
-  },
-  "google videos": {
-    "af": {
-      "name": "Afrikaans"
-    },
-    "ar": {
-      "name": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629"
-    },
-    "be": {
-      "name": "\u0431\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f"
-    },
-    "bg": {
-      "name": "\u0431\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438"
-    },
-    "ca": {
-      "name": "catal\u00e0"
-    },
-    "cs": {
-      "name": "\u010de\u0161tina"
-    },
-    "da": {
-      "name": "dansk"
-    },
-    "de": {
-      "name": "Deutsch"
-    },
-    "el": {
-      "name": "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac"
-    },
-    "en": {
-      "name": "English"
-    },
-    "eo": {
-      "name": "esperanto"
-    },
-    "es": {
-      "name": "espa\u00f1ol"
-    },
-    "et": {
-      "name": "eesti"
-    },
-    "fa": {
-      "name": "\u0641\u0627\u0631\u0633\u06cc"
-    },
-    "fi": {
-      "name": "suomi"
-    },
-    "fr": {
-      "name": "fran\u00e7ais"
-    },
-    "hi": {
-      "name": "\u0939\u093f\u0928\u094d\u0926\u0940"
-    },
-    "hr": {
-      "name": "hrvatski"
-    },
-    "hu": {
-      "name": "magyar"
-    },
-    "hy": {
-      "name": "\u0570\u0561\u0575\u0565\u0580\u0565\u0576"
-    },
-    "id": {
-      "name": "Indonesia"
-    },
-    "is": {
-      "name": "\u00edslenska"
-    },
-    "it": {
-      "name": "italiano"
-    },
-    "iw": {
-      "name": "\u05e2\u05d1\u05e8\u05d9\u05ea"
-    },
-    "ja": {
-      "name": "\u65e5\u672c\u8a9e"
-    },
-    "ko": {
-      "name": "\ud55c\uad6d\uc5b4"
-    },
-    "lt": {
-      "name": "lietuvi\u0173"
-    },
-    "lv": {
-      "name": "latvie\u0161u"
-    },
-    "nl": {
-      "name": "Nederlands"
-    },
-    "no": {
-      "name": "norsk"
-    },
-    "pl": {
-      "name": "polski"
-    },
-    "pt": {
-      "name": "portugu\u00eas"
-    },
-    "ro": {
-      "name": "rom\u00e2n\u0103"
-    },
-    "ru": {
-      "name": "\u0440\u0443\u0441\u0441\u043a\u0438\u0439"
-    },
-    "sk": {
-      "name": "sloven\u010dina"
-    },
-    "sl": {
-      "name": "sloven\u0161\u010dina"
-    },
-    "sr": {
-      "name": "\u0441\u0440\u043f\u0441\u043a\u0438"
-    },
-    "sv": {
-      "name": "svenska"
-    },
-    "sw": {
-      "name": "Kiswahili"
-    },
-    "th": {
-      "name": "\u0e44\u0e17\u0e22"
-    },
-    "tl": {
-      "name": "Filipino"
-    },
-    "tr": {
-      "name": "T\u00fcrk\u00e7e"
-    },
-    "uk": {
-      "name": "\u0443\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"
-    },
-    "vi": {
-      "name": "Ti\u1ebfng Vi\u1ec7t"
-    },
-    "zh-CN": {
-      "name": "\u4e2d\u6587 (\u7b80\u4f53)"
-    },
-    "zh-TW": {
-      "name": "\u4e2d\u6587 (\u7e41\u9ad4)"
-    }
-  },
-  "peertube": [
-    "ca",
-    "cs",
-    "de",
-    "el",
-    "en",
-    "eo",
-    "es",
-    "eu",
-    "fi",
-    "fr",
-    "gd",
-    "it",
-    "ja",
-    "nl",
-    "oc",
-    "pl",
-    "pt",
-    "ru",
-    "sv",
-    "zh"
-  ],
-  "qwant": {
-    "bg-BG": "bg_BG",
-    "ca-ES": "ca_ES",
-    "cs-CZ": "cs_CZ",
-    "da-DK": "da_DK",
-    "de-AT": "de_AT",
-    "de-CH": "de_CH",
-    "de-DE": "de_DE",
-    "el-GR": "el_GR",
-    "en-AU": "en_AU",
-    "en-CA": "en_CA",
-    "en-GB": "en_GB",
-    "en-IE": "en_IE",
-    "en-MY": "en_MY",
-    "en-NZ": "en_NZ",
-    "en-US": "en_US",
-    "es-AR": "es_AR",
-    "es-CL": "es_CL",
-    "es-ES": "es_ES",
-    "es-MX": "es_MX",
-    "et-EE": "et_EE",
-    "fi-FI": "fi_FI",
-    "fr-BE": "fr_BE",
-    "fr-CA": "fr_CA",
-    "fr-CH": "fr_CH",
-    "fr-FR": "fr_FR",
-    "hu-HU": "hu_HU",
-    "it-CH": "it_CH",
-    "it-IT": "it_IT",
-    "ko-KR": "ko_KR",
-    "nb-NO": "nb_NO",
-    "nl-BE": "nl_BE",
-    "nl-NL": "nl_NL",
-    "pl-PL": "pl_PL",
-    "pt-PT": "pt_PT",
-    "ro-RO": "ro_RO",
-    "sv-SE": "sv_SE",
-    "th-TH": "th_TH",
-    "zh-CN": "zh_CN",
-    "zh-HK": "zh_HK"
-  },
-  "qwant images": {
-    "bg-BG": "bg_BG",
-    "ca-ES": "ca_ES",
-    "cs-CZ": "cs_CZ",
-    "da-DK": "da_DK",
-    "de-AT": "de_AT",
-    "de-CH": "de_CH",
-    "de-DE": "de_DE",
-    "el-GR": "el_GR",
-    "en-AU": "en_AU",
-    "en-CA": "en_CA",
-    "en-GB": "en_GB",
-    "en-IE": "en_IE",
-    "en-MY": "en_MY",
-    "en-NZ": "en_NZ",
-    "en-US": "en_US",
-    "es-AR": "es_AR",
-    "es-CL": "es_CL",
-    "es-ES": "es_ES",
-    "es-MX": "es_MX",
-    "et-EE": "et_EE",
-    "fi-FI": "fi_FI",
-    "fr-BE": "fr_BE",
-    "fr-CA": "fr_CA",
-    "fr-CH": "fr_CH",
-    "fr-FR": "fr_FR",
-    "hu-HU": "hu_HU",
-    "it-CH": "it_CH",
-    "it-IT": "it_IT",
-    "ko-KR": "ko_KR",
-    "nb-NO": "nb_NO",
-    "nl-BE": "nl_BE",
-    "nl-NL": "nl_NL",
-    "pl-PL": "pl_PL",
-    "pt-PT": "pt_PT",
-    "ro-RO": "ro_RO",
-    "sv-SE": "sv_SE",
-    "th-TH": "th_TH",
-    "zh-CN": "zh_CN",
-    "zh-HK": "zh_HK"
-  },
-  "qwant news": {
-    "ca-ES": "ca_ES",
-    "de-AT": "de_AT",
-    "de-CH": "de_CH",
-    "de-DE": "de_DE",
-    "en-AU": "en_AU",
-    "en-CA": "en_CA",
-    "en-GB": "en_GB",
-    "en-IE": "en_IE",
-    "en-MY": "en_MY",
-    "en-NZ": "en_NZ",
-    "en-US": "en_US",
-    "es-AR": "es_AR",
-    "es-CL": "es_CL",
-    "es-ES": "es_ES",
-    "es-MX": "es_MX",
-    "fr-BE": "fr_BE",
-    "fr-CA": "fr_CA",
-    "fr-CH": "fr_CH",
-    "fr-FR": "fr_FR",
-    "it-CH": "it_CH",
-    "it-IT": "it_IT",
-    "nl-BE": "nl_BE",
-    "nl-NL": "nl_NL",
-    "pt-PT": "pt_PT"
-  },
-  "qwant videos": {
-    "bg-BG": "bg_BG",
-    "ca-ES": "ca_ES",
-    "cs-CZ": "cs_CZ",
-    "da-DK": "da_DK",
-    "de-AT": "de_AT",
-    "de-CH": "de_CH",
-    "de-DE": "de_DE",
-    "el-GR": "el_GR",
-    "en-AU": "en_AU",
-    "en-CA": "en_CA",
-    "en-GB": "en_GB",
-    "en-IE": "en_IE",
-    "en-MY": "en_MY",
-    "en-NZ": "en_NZ",
-    "en-US": "en_US",
-    "es-AR": "es_AR",
-    "es-CL": "es_CL",
-    "es-ES": "es_ES",
-    "es-MX": "es_MX",
-    "et-EE": "et_EE",
-    "fi-FI": "fi_FI",
-    "fr-BE": "fr_BE",
-    "fr-CA": "fr_CA",
-    "fr-CH": "fr_CH",
-    "fr-FR": "fr_FR",
-    "hu-HU": "hu_HU",
-    "it-CH": "it_CH",
-    "it-IT": "it_IT",
-    "ko-KR": "ko_KR",
-    "nb-NO": "nb_NO",
-    "nl-BE": "nl_BE",
-    "nl-NL": "nl_NL",
-    "pl-PL": "pl_PL",
-    "pt-PT": "pt_PT",
-    "ro-RO": "ro_RO",
-    "sv-SE": "sv_SE",
-    "th-TH": "th_TH",
-    "zh-CN": "zh_CN",
-    "zh-HK": "zh_HK"
-  },
-  "startpage": {
-    "af": {
-      "alias": "afrikaans"
-    },
-    "am": {
-      "alias": "amharic"
-    },
-    "ar": {
-      "alias": "arabic"
-    },
-    "az": {
-      "alias": "azerbaijani"
-    },
-    "be": {
-      "alias": "belarusian"
-    },
-    "bg": {
-      "alias": "bulgarian"
-    },
-    "bn": {
-      "alias": "bengali"
-    },
-    "bs": {
-      "alias": "bosnian"
-    },
-    "ca": {
-      "alias": "catalan"
-    },
-    "cs": {
-      "alias": "czech"
-    },
-    "cy": {
-      "alias": "welsh"
-    },
-    "da": {
-      "alias": "dansk"
-    },
-    "de": {
-      "alias": "deutsch"
-    },
-    "el": {
-      "alias": "greek"
-    },
-    "en": {
-      "alias": "english"
-    },
-    "en-GB": {
-      "alias": "english_uk"
-    },
-    "eo": {
-      "alias": "esperanto"
-    },
-    "es": {
-      "alias": "espanol"
-    },
-    "et": {
-      "alias": "estonian"
-    },
-    "eu": {
-      "alias": "basque"
-    },
-    "fa": {
-      "alias": "persian"
-    },
-    "fi": {
-      "alias": "suomi"
-    },
-    "fo": {
-      "alias": "faroese"
-    },
-    "fr": {
-      "alias": "francais"
-    },
-    "fy": {
-      "alias": "frisian"
-    },
-    "ga": {
-      "alias": "irish"
-    },
-    "gd": {
-      "alias": "gaelic"
-    },
-    "gl": {
-      "alias": "galician"
-    },
-    "gu": {
-      "alias": "gujarati"
-    },
-    "he": {
-      "alias": "hebrew"
-    },
-    "hi": {
-      "alias": "hindi"
-    },
-    "hr": {
-      "alias": "croatian"
-    },
-    "hu": {
-      "alias": "hungarian"
-    },
-    "ia": {
-      "alias": "interlingua"
-    },
-    "id": {
-      "alias": "indonesian"
-    },
-    "is": {
-      "alias": "icelandic"
-    },
-    "it": {
-      "alias": "italiano"
-    },
-    "ja": {
-      "alias": "nihongo"
-    },
-    "jv": {
-      "alias": "javanese"
-    },
-    "ka": {
-      "alias": "georgian"
-    },
-    "kn": {
-      "alias": "kannada"
-    },
-    "ko": {
-      "alias": "hangul"
-    },
-    "la": {
-      "alias": "latin"
-    },
-    "lt": {
-      "alias": "lithuanian"
-    },
-    "lv": {
-      "alias": "latvian"
-    },
-    "mai": {
-      "alias": "bihari"
-    },
-    "mk": {
-      "alias": "macedonian"
-    },
-    "ml": {
-      "alias": "malayalam"
-    },
-    "mr": {
-      "alias": "marathi"
-    },
-    "ms": {
-      "alias": "malay"
-    },
-    "mt": {
-      "alias": "maltese"
-    },
-    "ne": {
-      "alias": "nepali"
-    },
-    "nl": {
-      "alias": "nederlands"
-    },
-    "no": {
-      "alias": "norsk"
-    },
-    "oc": {
-      "alias": "occitan"
-    },
-    "pa": {
-      "alias": "punjabi"
-    },
-    "pl": {
-      "alias": "polski"
-    },
-    "pt": {
-      "alias": "portugues"
-    },
-    "ro": {
-      "alias": "romanian"
-    },
-    "ru": {
-      "alias": "russian"
-    },
-    "si": {
-      "alias": "sinhalese"
-    },
-    "sk": {
-      "alias": "slovak"
-    },
-    "sl": {
-      "alias": "slovenian"
-    },
-    "sq": {
-      "alias": "albanian"
-    },
-    "sr": {
-      "alias": "serbian"
-    },
-    "su": {
-      "alias": "sudanese"
-    },
-    "sv": {
-      "alias": "svenska"
-    },
-    "sw": {
-      "alias": "swahili"
-    },
-    "ta": {
-      "alias": "tamil"
-    },
-    "te": {
-      "alias": "telugu"
-    },
-    "th": {
-      "alias": "thai"
-    },
-    "ti": {
-      "alias": "tigrinya"
-    },
-    "tl": {
-      "alias": "tagalog"
-    },
-    "tr": {
-      "alias": "turkce"
-    },
-    "uk": {
-      "alias": "ukrainian"
-    },
-    "ur": {
-      "alias": "urdu"
-    },
-    "uz": {
-      "alias": "uzbek"
-    },
-    "vi": {
-      "alias": "vietnamese"
-    },
-    "xh": {
-      "alias": "xhosa"
-    },
-    "zh": {
-      "alias": "jiantizhongwen"
-    },
-    "zh-HK": {
-      "alias": "fantizhengwen"
-    },
-    "zh-TW": {
-      "alias": "fantizhengwen"
-    },
-    "zu": {
-      "alias": "zulu"
-    }
-  },
-  "wikidata": {
-    "ab": {
-      "english_name": "Abkhazian",
-      "name": "\u0410\u0525\u0441\u0443\u0430"
-    },
-    "ace": {
-      "english_name": "Acehnese",
-      "name": "Basa Ac\u00e8h"
-    },
-    "ady": {
-      "english_name": "Adyghe",
-      "name": "\u0410\u0434\u044b\u0433\u044d\u0431\u0437\u044d"
-    },
-    "af": {
-      "english_name": "Afrikaans",
-      "name": "Afrikaans"
-    },
-    "ak": {
-      "english_name": "Akan",
-      "name": "Akana"
-    },
-    "als": {
-      "english_name": "Alemannic",
-      "name": "Alemannisch"
-    },
-    "alt": {
-      "english_name": "Southern Altai",
-      "name": "\u0410\u043b\u0442\u0430\u0439"
-    },
-    "am": {
-      "english_name": "Amharic",
-      "name": "\u12a0\u121b\u122d\u129b"
-    },
-    "ami": {
-      "english_name": "Amis",
-      "name": "Pangcah"
-    },
-    "an": {
-      "english_name": "Aragonese",
-      "name": "Aragon\u00e9s"
-    },
-    "ang": {
-      "english_name": "Anglo-Saxon",
-      "name": "\u00c6nglisc"
-    },
-    "ar": {
-      "english_name": "Arabic",
-      "name": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629"
-    },
-    "arc": {
-      "english_name": "Aramaic",
-      "name": "\u0710\u072a\u0721\u071d\u0710"
-    },
-    "ary": {
-      "english_name": "Moroccan Arabic",
-      "name": "\u062f\u0627\u0631\u064a\u062c\u0629"
-    },
-    "arz": {
-      "english_name": "Egyptian Arabic",
-      "name": "\u0645\u0635\u0631\u0649 (Ma\u1e63ri)"
-    },
-    "as": {
-      "english_name": "Assamese",
-      "name": "\u0985\u09b8\u09ae\u09c0\u09af\u09bc\u09be"
-    },
-    "ast": {
-      "english_name": "Asturian",
-      "name": "Asturianu"
-    },
-    "atj": {
-      "english_name": "Atikamekw",
-      "name": "Atikamekw"
-    },
-    "av": {
-      "english_name": "Avar",
-      "name": "\u0410\u0432\u0430\u0440"
-    },
-    "avk": {
-      "english_name": "Kotava",
-      "name": "Kotava"
-    },
-    "awa": {
-      "english_name": "Awadhi",
-      "name": "\u0905\u0935\u0927\u0940"
-    },
-    "ay": {
-      "english_name": "Aymara",
-      "name": "Aymar"
-    },
-    "az": {
-      "english_name": "Azerbaijani",
-      "name": "Az\u0259rbaycanca"
-    },
-    "azb": {
-      "english_name": "South Azerbaijani",
-      "name": "\u062a\u06c6\u0631\u06a9\u062c\u0647"
-    },
-    "ba": {
-      "english_name": "Bashkir",
-      "name": "\u0411\u0430\u0448\u04a1\u043e\u0440\u0442"
-    },
-    "ban": {
-      "english_name": "Balinese",
-      "name": "Bali"
-    },
-    "bar": {
-      "english_name": "Bavarian",
-      "name": "Boarisch"
-    },
-    "bat-smg": {
-      "english_name": "Samogitian",
-      "name": "\u017demait\u0117\u0161ka"
-    },
-    "bcl": {
-      "english_name": "Central Bicolano",
-      "name": "Bikol"
-    },
-    "be": {
-      "english_name": "Belarusian",
-      "name": "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f"
-    },
-    "be-tarask": {
-      "english_name": "Belarusian (Tara\u0161kievica)",
-      "name": "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430)"
-    },
-    "bg": {
-      "english_name": "Bulgarian",
-      "name": "\u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438"
-    },
-    "bh": {
-      "english_name": "Bhojpuri",
-      "name": "\u092d\u094b\u091c\u092a\u0941\u0930\u0940"
-    },
-    "bi": {
-      "english_name": "Bislama",
-      "name": "Bislama"
-    },
-    "bjn": {
-      "english_name": "Banjar",
-      "name": "Bahasa Banjar"
-    },
-    "blk": {
-      "english_name": "Pa'O",
-      "name": "\u1015\u1021\u102d\u102f\u101d\u103a\u108f\u1018\u102c\u108f\u101e\u102c\u108f"
-    },
-    "bm": {
-      "english_name": "Bambara",
-      "name": "Bamanankan"
-    },
-    "bn": {
-      "english_name": "Bengali",
-      "name": "\u09ac\u09be\u0982\u09b2\u09be"
-    },
-    "bo": {
-      "english_name": "Tibetan",
-      "name": "\u0f56\u0f7c\u0f51\u0f0b\u0f66\u0f90\u0f51"
-    },
-    "bpy": {
-      "english_name": "Bishnupriya Manipuri",
-      "name": "\u0987\u09ae\u09be\u09b0 \u09a0\u09be\u09b0/\u09ac\u09bf\u09b7\u09cd\u09a3\u09c1\u09aa\u09cd\u09b0\u09bf\u09af\u09bc\u09be \u09ae\u09a3\u09bf\u09aa\u09c1\u09b0\u09c0"
-    },
-    "br": {
-      "english_name": "Breton",
-      "name": "Brezhoneg"
-    },
-    "bs": {
-      "english_name": "Bosnian",
-      "name": "Bosanski"
-    },
-    "bug": {
-      "english_name": "Buginese",
-      "name": "Basa Ugi"
-    },
-    "bxr": {
-      "english_name": "Buryat",
-      "name": "\u0411\u0443\u0440\u044f\u0430\u0434"
-    },
-    "ca": {
-      "english_name": "Catalan",
-      "name": "Catal\u00e0"
-    },
-    "cbk-zam": {
-      "english_name": "Zamboanga Chavacano",
-      "name": "Chavacano de Zamboanga"
-    },
-    "cdo": {
-      "english_name": "Min Dong",
-      "name": "M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304"
-    },
-    "ce": {
-      "english_name": "Chechen",
-      "name": "\u041d\u043e\u0445\u0447\u0438\u0439\u043d"
-    },
-    "ceb": {
-      "english_name": "Cebuano",
-      "name": "Sinugboanong Binisaya"
-    },
-    "ch": {
-      "english_name": "Chamorro",
-      "name": "Chamoru"
-    },
-    "chr": {
-      "english_name": "Cherokee",
-      "name": "\u13e3\u13b3\u13a9"
-    },
-    "chy": {
-      "english_name": "Cheyenne",
-      "name": "Tsets\u00eahest\u00e2hese"
-    },
-    "ckb": {
-      "english_name": "Sorani",
-      "name": "Soran\u00ee / \u06a9\u0648\u0631\u062f\u06cc"
-    },
-    "co": {
-      "english_name": "Corsican",
-      "name": "Corsu"
-    },
-    "cr": {
-      "english_name": "Cree",
-      "name": "Nehiyaw"
-    },
-    "crh": {
-      "english_name": "Crimean Tatar",
-      "name": "Q\u0131r\u0131mtatarca"
-    },
-    "cs": {
-      "english_name": "Czech",
-      "name": "\u010ce\u0161tina"
-    },
-    "csb": {
-      "english_name": "Kashubian",
-      "name": "Kasz\u00ebbsczi"
-    },
-    "cu": {
-      "english_name": "Old Church Slavonic",
-      "name": "\u0421\u043b\u043e\u0432\u0463\u043d\u044c\u0441\u043a\u044a"
-    },
-    "cv": {
-      "english_name": "Chuvash",
-      "name": "\u0427\u0103\u0432\u0430\u0448"
-    },
-    "cy": {
-      "english_name": "Welsh",
-      "name": "Cymraeg"
-    },
-    "da": {
-      "english_name": "Danish",
-      "name": "Dansk"
-    },
-    "dag": {
-      "english_name": "Dagbani",
-      "name": "Dagbanli"
-    },
-    "de": {
-      "english_name": "German",
-      "name": "Deutsch"
-    },
-    "din": {
-      "english_name": "Dinka",
-      "name": "Thu\u0254\u014bj\u00e4\u014b"
-    },
-    "diq": {
-      "english_name": "Zazaki",
-      "name": "Zazaki"
-    },
-    "dsb": {
-      "english_name": "Lower Sorbian",
-      "name": "Dolnoserbski"
-    },
-    "dty": {
-      "english_name": "Doteli",
-      "name": "\u0921\u094b\u091f\u0947\u0932\u0940"
-    },
-    "dv": {
-      "english_name": "Divehi",
-      "name": "\u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0"
-    },
-    "dz": {
-      "english_name": "Dzongkha",
-      "name": "\u0f47\u0f7c\u0f44\u0f0b\u0f41"
-    },
-    "ee": {
-      "english_name": "Ewe",
-      "name": "E\u028begbe"
-    },
-    "el": {
-      "english_name": "Greek",
-      "name": "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac"
-    },
-    "eml": {
-      "english_name": "Emilian-Romagnol",
-      "name": "Emili\u00e0n e rumagn\u00f2l"
-    },
-    "en": {
-      "english_name": "English",
-      "name": "English"
-    },
-    "eo": {
-      "english_name": "Esperanto",
-      "name": "Esperanto"
-    },
-    "es": {
-      "english_name": "Spanish",
-      "name": "Espa\u00f1ol"
-    },
-    "et": {
-      "english_name": "Estonian",
-      "name": "Eesti"
-    },
-    "eu": {
-      "english_name": "Basque",
-      "name": "Euskara"
-    },
-    "ext": {
-      "english_name": "Extremaduran",
-      "name": "Estreme\u00f1u"
-    },
-    "fa": {
-      "english_name": "Persian",
-      "name": "\u0641\u0627\u0631\u0633\u06cc"
-    },
-    "ff": {
-      "english_name": "Fula",
-      "name": "Fulfulde"
-    },
-    "fi": {
-      "english_name": "Finnish",
-      "name": "Suomi"
-    },
-    "fiu-vro": {
-      "english_name": "V\u00f5ro",
-      "name": "V\u00f5ro"
-    },
-    "fj": {
-      "english_name": "Fijian",
-      "name": "Na Vosa Vakaviti"
-    },
-    "fo": {
-      "english_name": "Faroese",
-      "name": "F\u00f8royskt"
-    },
-    "fr": {
-      "english_name": "French",
-      "name": "Fran\u00e7ais"
-    },
-    "frp": {
-      "english_name": "Franco-Proven\u00e7al",
-      "name": "Arpetan"
-    },
-    "frr": {
-      "english_name": "North Frisian",
-      "name": "Nordfrasch"
-    },
-    "fur": {
-      "english_name": "Friulian",
-      "name": "Furlan"
-    },
-    "fy": {
-      "english_name": "West Frisian",
-      "name": "Frysk"
-    },
-    "ga": {
-      "english_name": "Irish",
-      "name": "Gaeilge"
-    },
-    "gag": {
-      "english_name": "Gagauz",
-      "name": "Gagauz"
-    },
-    "gan": {
-      "english_name": "Gan",
-      "name": "\u8d1b\u8a9e"
-    },
-    "gcr": {
-      "english_name": "Guianan Creole",
-      "name": "Kriy\u00f2l Gwiyannen"
-    },
-    "gd": {
-      "english_name": "Scottish Gaelic",
-      "name": "G\u00e0idhlig"
-    },
-    "gl": {
-      "english_name": "Galician",
-      "name": "Galego"
-    },
-    "glk": {
-      "english_name": "Gilaki",
-      "name": "\u06af\u06cc\u0644\u06a9\u06cc"
-    },
-    "gn": {
-      "english_name": "Guarani",
-      "name": "Ava\u00f1e'\u1ebd"
-    },
-    "gom": {
-      "english_name": "Goan Konkani",
-      "name": "\u0917\u094b\u0902\u092f\u091a\u0940 \u0915\u094b\u0902\u0915\u0923\u0940 / G\u00f5ychi Konknni"
-    },
-    "gor": {
-      "english_name": "Gorontalo",
-      "name": "Hulontalo"
-    },
-    "got": {
-      "english_name": "Gothic",
-      "name": "\ud800\udf32\ud800\udf3f\ud800\udf44\ud800\udf39\ud800\udf43\ud800\udf3a"
-    },
-    "gu": {
-      "english_name": "Gujarati",
-      "name": "\u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0"
-    },
-    "guw": {
-      "english_name": "Gun",
-      "name": "Gungbe"
-    },
-    "gv": {
-      "english_name": "Manx",
-      "name": "Gaelg"
-    },
-    "ha": {
-      "english_name": "Hausa",
-      "name": "Hausa / \u0647\u064e\u0648\u064f\u0633\u064e"
-    },
-    "hak": {
-      "english_name": "Hakka",
-      "name": "Hak-k\u00e2-fa / \u5ba2\u5bb6\u8a71"
-    },
-    "haw": {
-      "english_name": "Hawaiian",
-      "name": "Hawai\u02bbi"
-    },
-    "he": {
-      "english_name": "Hebrew",
-      "name": "\u05e2\u05d1\u05e8\u05d9\u05ea"
-    },
-    "hi": {
-      "english_name": "Hindi",
-      "name": "\u0939\u093f\u0928\u094d\u0926\u0940"
-    },
-    "hif": {
-      "english_name": "Fiji Hindi",
-      "name": "Fiji Hindi"
-    },
-    "hr": {
-      "english_name": "Croatian",
-      "name": "Hrvatski"
-    },
-    "hsb": {
-      "english_name": "Upper Sorbian",
-      "name": "Hornjoserbsce"
-    },
-    "ht": {
-      "english_name": "Haitian",
-      "name": "Kr\u00e8yol ayisyen"
-    },
-    "hu": {
-      "english_name": "Hungarian",
-      "name": "Magyar"
-    },
-    "hy": {
-      "english_name": "Armenian",
-      "name": "\u0540\u0561\u0575\u0565\u0580\u0565\u0576"
-    },
-    "hyw": {
-      "english_name": "Western Armenian",
-      "name": "\u0531\u0580\u0565\u0582\u0574\u057f\u0561\u0570\u0561\u0575\u0565\u0580\u0567\u0576"
-    },
-    "ia": {
-      "english_name": "Interlingua",
-      "name": "Interlingua"
-    },
-    "id": {
-      "english_name": "Indonesian",
-      "name": "Bahasa Indonesia"
-    },
-    "ie": {
-      "english_name": "Interlingue",
-      "name": "Interlingue"
-    },
-    "ig": {
-      "english_name": "Igbo",
-      "name": "\u00ccgb\u00f2"
-    },
-    "ik": {
-      "english_name": "Inupiak",
-      "name": "I\u00f1upiatun"
-    },
-    "ilo": {
-      "english_name": "Ilokano",
-      "name": "Ilokano"
-    },
-    "inh": {
-      "english_name": "Ingush",
-      "name": "\u0413\u04c0\u0430\u043b\u0433\u04c0\u0430\u0439"
-    },
-    "io": {
-      "english_name": "Ido",
-      "name": "Ido"
-    },
-    "is": {
-      "english_name": "Icelandic",
-      "name": "\u00cdslenska"
-    },
-    "it": {
-      "english_name": "Italian",
-      "name": "Italiano"
-    },
-    "iu": {
-      "english_name": "Inuktitut",
-      "name": "\u1403\u14c4\u1483\u144e\u1450\u1466"
-    },
-    "ja": {
-      "english_name": "Japanese",
-      "name": "\u65e5\u672c\u8a9e"
-    },
-    "jam": {
-      "english_name": "Jamaican Patois",
-      "name": "Jumiekan Kryuol"
-    },
-    "jbo": {
-      "english_name": "Lojban",
-      "name": "Lojban"
-    },
-    "jv": {
-      "english_name": "Javanese",
-      "name": "Basa Jawa"
-    },
-    "ka": {
-      "english_name": "Georgian",
-      "name": "\u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8"
-    },
-    "kaa": {
-      "english_name": "Karakalpak",
-      "name": "Qaraqalpaqsha"
-    },
-    "kab": {
-      "english_name": "Kabyle",
-      "name": "Taqbaylit"
-    },
-    "kbd": {
-      "english_name": "Kabardian Circassian",
-      "name": "\u0410\u0434\u044b\u0433\u044d\u0431\u0437\u044d (Adighabze)"
-    },
-    "kbp": {
-      "english_name": "Kabiye",
-      "name": "Kab\u0269y\u025b"
-    },
-    "kcg": {
-      "english_name": "Tyap",
-      "name": "Tyap"
-    },
-    "kg": {
-      "english_name": "Kongo",
-      "name": "Kik\u00f4ngo"
-    },
-    "ki": {
-      "english_name": "Kikuyu",
-      "name": "G\u0129k\u0169y\u0169"
-    },
-    "kk": {
-      "english_name": "Kazakh",
-      "name": "\u049a\u0430\u0437\u0430\u049b\u0448\u0430"
-    },
-    "kl": {
-      "english_name": "Greenlandic",
-      "name": "Kalaallisut"
-    },
-    "km": {
-      "english_name": "Khmer",
-      "name": "\u1797\u17b6\u179f\u17b6\u1781\u17d2\u1798\u17c2\u179a"
-    },
-    "kn": {
-      "english_name": "Kannada",
-      "name": "\u0c95\u0ca8\u0ccd\u0ca8\u0ca1"
-    },
-    "ko": {
-      "english_name": "Korean",
-      "name": "\ud55c\uad6d\uc5b4"
-    },
-    "koi": {
-      "english_name": "Komi-Permyak",
-      "name": "\u041f\u0435\u0440\u0435\u043c \u041a\u043e\u043c\u0438 (Perem Komi)"
-    },
-    "krc": {
-      "english_name": "Karachay-Balkar",
-      "name": "\u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440 (Qarachay-Malqar)"
-    },
-    "ks": {
-      "english_name": "Kashmiri",
-      "name": "\u0915\u0936\u094d\u092e\u0940\u0930\u0940 / \u0643\u0634\u0645\u064a\u0631\u064a"
-    },
-    "ksh": {
-      "english_name": "Ripuarian",
-      "name": "Ripoarisch"
-    },
-    "ku": {
-      "english_name": "Kurdish",
-      "name": "Kurd\u00ee / \u0643\u0648\u0631\u062f\u06cc"
-    },
-    "kv": {
-      "english_name": "Komi",
-      "name": "\u041a\u043e\u043c\u0438"
-    },
-    "kw": {
-      "english_name": "Cornish",
-      "name": "Kernowek/Karnuack"
-    },
-    "ky": {
-      "english_name": "Kyrgyz",
-      "name": "\u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430"
-    },
-    "la": {
-      "english_name": "Latin",
-      "name": "Latina"
-    },
-    "lad": {
-      "english_name": "Ladino",
-      "name": "Dzhudezmo"
-    },
-    "lb": {
-      "english_name": "Luxembourgish",
-      "name": "L\u00ebtzebuergesch"
-    },
-    "lbe": {
-      "english_name": "Lak",
-      "name": "\u041b\u0430\u043a\u043a\u0443"
-    },
-    "lez": {
-      "english_name": "Lezgian",
-      "name": "\u041b\u0435\u0437\u0433\u0438 \u0447\u0406\u0430\u043b (Lezgi \u010d\u2019al)"
-    },
-    "lfn": {
-      "english_name": "Lingua Franca Nova",
-      "name": "Lingua franca nova"
-    },
-    "lg": {
-      "english_name": "Luganda",
-      "name": "Luganda"
-    },
-    "li": {
-      "english_name": "Limburgish",
-      "name": "Limburgs"
-    },
-    "lij": {
-      "english_name": "Ligurian",
-      "name": "L\u00ecgure"
-    },
-    "lld": {
-      "english_name": "Ladin",
-      "name": "Lingaz"
-    },
-    "lmo": {
-      "english_name": "Lombard",
-      "name": "Lumbaart"
-    },
-    "ln": {
-      "english_name": "Lingala",
-      "name": "Lingala"
-    },
-    "lo": {
-      "english_name": "Lao",
-      "name": "\u0ea5\u0eb2\u0ea7"
-    },
-    "lt": {
-      "english_name": "Lithuanian",
-      "name": "Lietuvi\u0173"
-    },
-    "ltg": {
-      "english_name": "Latgalian",
-      "name": "Latga\u013cu"
-    },
-    "lv": {
-      "english_name": "Latvian",
-      "name": "Latvie\u0161u"
-    },
-    "mad": {
-      "english_name": "Madurese",
-      "name": "Madhur\u00e2"
-    },
-    "mai": {
-      "english_name": "Maithili",
-      "name": "\u092e\u0948\u0925\u093f\u0932\u0940"
-    },
-    "map-bms": {
-      "english_name": "Banyumasan",
-      "name": "Basa Banyumasan"
-    },
-    "mdf": {
-      "english_name": "Moksha",
-      "name": "\u041c\u043e\u043a\u0448\u0435\u043d\u044c (Mokshanj K\u00e4lj)"
-    },
-    "mg": {
-      "english_name": "Malagasy",
-      "name": "Malagasy"
-    },
-    "mhr": {
-      "english_name": "Meadow Mari",
-      "name": "\u041e\u043b\u044b\u043a \u041c\u0430\u0440\u0438\u0439 (Olyk Marij)"
-    },
-    "mi": {
-      "english_name": "Maori",
-      "name": "M\u0101ori"
-    },
-    "min": {
-      "english_name": "Minangkabau",
-      "name": "Minangkabau"
-    },
-    "mk": {
-      "english_name": "Macedonian",
-      "name": "\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438"
-    },
-    "ml": {
-      "english_name": "Malayalam",
-      "name": "\u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02"
-    },
-    "mn": {
-      "english_name": "Mongolian",
-      "name": "\u041c\u043e\u043d\u0433\u043e\u043b"
-    },
-    "mni": {
-      "english_name": "Meitei",
-      "name": "\uabc3\uabe4\uabc7\uabe9\uabc2\uabe3\uabdf"
-    },
-    "mnw": {
-      "english_name": "Mon",
-      "name": "\u1019\u1014\u103a"
-    },
-    "mr": {
-      "english_name": "Marathi",
-      "name": "\u092e\u0930\u093e\u0920\u0940"
-    },
-    "mrj": {
-      "english_name": "Hill Mari",
-      "name": "\u041a\u044b\u0440\u044b\u043a \u041c\u0430\u0440\u044b (Kyryk Mary)"
-    },
-    "ms": {
-      "english_name": "Malay",
-      "name": "Bahasa Melayu"
-    },
-    "mt": {
-      "english_name": "Maltese",
-      "name": "Malti"
-    },
-    "mwl": {
-      "english_name": "Mirandese",
-      "name": "Mirand\u00e9s"
-    },
-    "my": {
-      "english_name": "Burmese",
-      "name": "\u1019\u103c\u1014\u103a\u1019\u102c\u1018\u102c\u101e\u102c"
-    },
-    "myv": {
-      "english_name": "Erzya",
-      "name": "\u042d\u0440\u0437\u044f\u043d\u044c (Erzjanj Kelj)"
-    },
-    "mzn": {
-      "english_name": "Mazandarani",
-      "name": "\u0645\u064e\u0632\u0650\u0631\u0648\u0646\u064a"
-    },
-    "na": {
-      "english_name": "Nauruan",
-      "name": "dorerin Naoero"
-    },
-    "nah": {
-      "english_name": "Nahuatl",
-      "name": "N\u0101huatl"
-    },
-    "nap": {
-      "english_name": "Neapolitan",
-      "name": "Nnapulitano"
-    },
-    "nds": {
-      "english_name": "Low Saxon",
-      "name": "Plattd\u00fc\u00fctsch"
-    },
-    "nds-nl": {
-      "english_name": "Dutch Low Saxon",
-      "name": "Nedersaksisch"
-    },
-    "ne": {
-      "english_name": "Nepali",
-      "name": "\u0928\u0947\u092a\u093e\u0932\u0940"
-    },
-    "new": {
-      "english_name": "Newar",
-      "name": "\u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e"
-    },
-    "nia": {
-      "english_name": "Nias",
-      "name": "Li Niha"
-    },
-    "nl": {
-      "english_name": "Dutch",
-      "name": "Nederlands"
-    },
-    "nn": {
-      "english_name": "Norwegian (Nynorsk)",
-      "name": "Nynorsk"
-    },
-    "no": {
-      "english_name": "Norwegian (Bokm\u00e5l)",
-      "name": "Norsk (Bokm\u00e5l)"
-    },
-    "nov": {
-      "english_name": "Novial",
-      "name": "Novial"
-    },
-    "nqo": {
-      "english_name": "N\u2019Ko",
-      "name": "\u07d2\u07de\u07cf"
-    },
-    "nrm": {
-      "english_name": "Norman",
-      "name": "Nouormand/Normaund"
-    },
-    "nso": {
-      "english_name": "Northern Sotho",
-      "name": "Sepedi"
-    },
-    "nv": {
-      "english_name": "Navajo",
-      "name": "Din\u00e9 bizaad"
-    },
-    "ny": {
-      "english_name": "Chichewa",
-      "name": "Chichewa"
-    },
-    "oc": {
-      "english_name": "Occitan",
-      "name": "Occitan"
-    },
-    "olo": {
-      "english_name": "Livvi-Karelian",
-      "name": "Karjalan"
-    },
-    "om": {
-      "english_name": "Oromo",
-      "name": "Oromoo"
-    },
-    "or": {
-      "english_name": "Oriya",
-      "name": "\u0b13\u0b21\u0b3c\u0b3f\u0b06"
-    },
-    "os": {
-      "english_name": "Ossetian",
-      "name": "\u0418\u0440\u043e\u043d\u0430\u0443"
-    },
-    "pa": {
-      "english_name": "Punjabi",
-      "name": "\u0a2a\u0a70\u0a1c\u0a3e\u0a2c\u0a40"
-    },
-    "pag": {
-      "english_name": "Pangasinan",
-      "name": "Pangasinan"
-    },
-    "pam": {
-      "english_name": "Kapampangan",
-      "name": "Kapampangan"
-    },
-    "pap": {
-      "english_name": "Papiamentu",
-      "name": "Papiamentu"
-    },
-    "pcd": {
-      "english_name": "Picard",
-      "name": "Picard"
-    },
-    "pcm": {
-      "english_name": "Nigerian Pidgin",
-      "name": "Naij\u00e1"
-    },
-    "pdc": {
-      "english_name": "Pennsylvania German",
-      "name": "Deitsch"
-    },
-    "pfl": {
-      "english_name": "Palatinate German",
-      "name": "P\u00e4lzisch"
-    },
-    "pi": {
-      "english_name": "Pali",
-      "name": "\u092a\u093e\u0934\u093f"
-    },
-    "pih": {
-      "english_name": "Norfolk",
-      "name": "Norfuk"
-    },
-    "pl": {
-      "english_name": "Polish",
-      "name": "Polski"
-    },
-    "pms": {
-      "english_name": "Piedmontese",
-      "name": "Piemont\u00e8is"
-    },
-    "pnb": {
-      "english_name": "Western Punjabi",
-      "name": "\u0634\u0627\u06c1 \u0645\u06a9\u06be\u06cc \u067e\u0646\u062c\u0627\u0628\u06cc (Sh\u0101hmukh\u012b Pa\u00f1j\u0101b\u012b)"
-    },
-    "pnt": {
-      "english_name": "Pontic",
-      "name": "\u03a0\u03bf\u03bd\u03c4\u03b9\u03b1\u03ba\u03ac"
-    },
-    "ps": {
-      "english_name": "Pashto",
-      "name": "\u067e\u069a\u062a\u0648"
-    },
-    "pt": {
-      "english_name": "Portuguese",
-      "name": "Portugu\u00eas"
-    },
-    "pwn": {
-      "english_name": "Paiwan",
-      "name": "Paiwan"
-    },
-    "qu": {
-      "english_name": "Quechua",
-      "name": "Qichwa simi"
-    },
-    "rm": {
-      "english_name": "Romansh",
-      "name": "Rumantsch"
-    },
-    "rmy": {
-      "english_name": "Romani",
-      "name": "romani - \u0930\u094b\u092e\u093e\u0928\u0940"
-    },
-    "rn": {
-      "english_name": "Kirundi",
-      "name": "Ikirundi"
-    },
-    "ro": {
-      "english_name": "Romanian",
-      "name": "Rom\u00e2n\u0103"
-    },
-    "roa-rup": {
-      "english_name": "Aromanian",
-      "name": "Arm\u00e3neashce"
-    },
-    "roa-tara": {
-      "english_name": "Tarantino",
-      "name": "Tarand\u00edne"
-    },
-    "ru": {
-      "english_name": "Russian",
-      "name": "\u0420\u0443\u0441\u0441\u043a\u0438\u0439"
-    },
-    "rue": {
-      "english_name": "Rusyn",
-      "name": "\u0420\u0443\u0441\u0438\u043d\u044c\u0441\u043a\u044b\u0439"
-    },
-    "rw": {
-      "english_name": "Kinyarwanda",
-      "name": "Ikinyarwanda"
-    },
-    "sa": {
-      "english_name": "Sanskrit",
-      "name": "\u0938\u0902\u0938\u094d\u0915\u0943\u0924\u092e\u094d"
-    },
-    "sah": {
-      "english_name": "Sakha",
-      "name": "\u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430 (Saxa Tyla)"
-    },
-    "sat": {
-      "english_name": "Santali",
-      "name": "\u1c65\u1c5f\u1c71\u1c5b\u1c5f\u1c72\u1c64"
-    },
-    "sc": {
-      "english_name": "Sardinian",
-      "name": "Sardu"
-    },
-    "scn": {
-      "english_name": "Sicilian",
-      "name": "Sicilianu"
-    },
-    "sco": {
-      "english_name": "Scots",
-      "name": "Scots"
-    },
-    "sd": {
-      "english_name": "Sindhi",
-      "name": "\u0633\u0646\u068c\u064a\u060c \u0633\u0646\u062f\u06be\u06cc \u060c \u0938\u093f\u0928\u094d\u0927"
-    },
-    "se": {
-      "english_name": "Northern Sami",
-      "name": "S\u00e1megiella"
-    },
-    "sg": {
-      "english_name": "Sango",
-      "name": "S\u00e4ng\u00f6"
-    },
-    "sh": {
-      "english_name": "Serbo-Croatian",
-      "name": "Srpskohrvatski / \u0421\u0440\u043f\u0441\u043a\u043e\u0445\u0440\u0432\u0430\u0442\u0441\u043a\u0438"
-    },
-    "shi": {
-      "english_name": "Tachelhit",
-      "name": "Tacl\u1e25it"
-    },
-    "shn": {
-      "english_name": "Shan",
-      "name": "\u101c\u102d\u1075\u103a\u1088\u1010\u1086\u1038"
-    },
-    "si": {
-      "english_name": "Sinhalese",
-      "name": "\u0dc3\u0dd2\u0d82\u0dc4\u0dbd"
-    },
-    "simple": {
-      "english_name": "Simple English",
-      "name": "Simple English"
-    },
-    "sk": {
-      "english_name": "Slovak",
-      "name": "Sloven\u010dina"
-    },
-    "skr": {
-      "english_name": "Saraiki",
-      "name": "\u0633\u0631\u0627\u0626\u06cc\u06a9\u06cc"
-    },
-    "sl": {
-      "english_name": "Slovenian",
-      "name": "Sloven\u0161\u010dina"
-    },
-    "sm": {
-      "english_name": "Samoan",
-      "name": "Gagana Samoa"
-    },
-    "smn": {
-      "english_name": "Inari Sami",
-      "name": "Anar\u00e2\u0161kiel\u00e2"
-    },
-    "sn": {
-      "english_name": "Shona",
-      "name": "chiShona"
-    },
-    "so": {
-      "english_name": "Somali",
-      "name": "Soomaali"
-    },
-    "sq": {
-      "english_name": "Albanian",
-      "name": "Shqip"
-    },
-    "sr": {
-      "english_name": "Serbian",
-      "name": "\u0421\u0440\u043f\u0441\u043a\u0438 / Srpski"
-    },
-    "srn": {
-      "english_name": "Sranan",
-      "name": "Sranantongo"
-    },
-    "ss": {
-      "english_name": "Swati",
-      "name": "SiSwati"
-    },
-    "st": {
-      "english_name": "Sesotho",
-      "name": "Sesotho"
-    },
-    "stq": {
-      "english_name": "Saterland Frisian",
-      "name": "Seeltersk"
-    },
-    "su": {
-      "english_name": "Sundanese",
-      "name": "Basa Sunda"
-    },
-    "sv": {
-      "english_name": "Swedish",
-      "name": "Svenska"
-    },
-    "sw": {
-      "english_name": "Swahili",
-      "name": "Kiswahili"
-    },
-    "szl": {
-      "english_name": "Silesian",
-      "name": "\u015al\u016fnski"
-    },
-    "szy": {
-      "english_name": "Sakizaya",
-      "name": "Sakizaya"
-    },
-    "ta": {
-      "english_name": "Tamil",
-      "name": "\u0ba4\u0bae\u0bbf\u0bb4\u0bcd"
-    },
-    "tay": {
-      "english_name": "Atayal",
-      "name": "Tayal"
-    },
-    "tcy": {
-      "english_name": "Tulu",
-      "name": "\u0ca4\u0cc1\u0cb3\u0cc1"
-    },
-    "te": {
-      "english_name": "Telugu",
-      "name": "\u0c24\u0c46\u0c32\u0c41\u0c17\u0c41"
-    },
-    "tet": {
-      "english_name": "Tetum",
-      "name": "Tetun"
-    },
-    "tg": {
-      "english_name": "Tajik",
-      "name": "\u0422\u043e\u04b7\u0438\u043a\u04e3"
-    },
-    "th": {
-      "english_name": "Thai",
-      "name": "\u0e44\u0e17\u0e22"
-    },
-    "ti": {
-      "english_name": "Tigrinya",
-      "name": "\u1275\u130d\u122d\u129b"
-    },
-    "tk": {
-      "english_name": "Turkmen",
-      "name": "T\u00fcrkmen"
-    },
-    "tl": {
-      "english_name": "Tagalog",
-      "name": "Tagalog"
-    },
-    "tn": {
-      "english_name": "Tswana",
-      "name": "Setswana"
-    },
-    "to": {
-      "english_name": "Tongan",
-      "name": "faka Tonga"
-    },
-    "tpi": {
-      "english_name": "Tok Pisin",
-      "name": "Tok Pisin"
-    },
-    "tr": {
-      "english_name": "Turkish",
-      "name": "T\u00fcrk\u00e7e"
-    },
-    "trv": {
-      "english_name": "Seediq",
-      "name": "Taroko"
-    },
-    "ts": {
-      "english_name": "Tsonga",
-      "name": "Xitsonga"
-    },
-    "tt": {
-      "english_name": "Tatar",
-      "name": "Tatar\u00e7a / \u0422\u0430\u0442\u0430\u0440\u0447\u0430"
-    },
-    "tum": {
-      "english_name": "Tumbuka",
-      "name": "chiTumbuka"
-    },
-    "tw": {
-      "english_name": "Twi",
-      "name": "Twi"
-    },
-    "ty": {
-      "english_name": "Tahitian",
-      "name": "Reo M\u0101`ohi"
-    },
-    "tyv": {
-      "english_name": "Tuvan",
-      "name": "\u0422\u044b\u0432\u0430"
-    },
-    "udm": {
-      "english_name": "Udmurt",
-      "name": "\u0423\u0434\u043c\u0443\u0440\u0442 \u043a\u044b\u043b"
-    },
-    "ug": {
-      "english_name": "Uyghur",
-      "name": "\u0626\u06c7\u064a\u063a\u06c7\u0631 \u062a\u0649\u0644\u0649"
-    },
-    "uk": {
-      "english_name": "Ukrainian",
-      "name": "\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"
-    },
-    "ur": {
-      "english_name": "Urdu",
-      "name": "\u0627\u0631\u062f\u0648"
-    },
-    "uz": {
-      "english_name": "Uzbek",
-      "name": "O\u2018zbek"
-    },
-    "ve": {
-      "english_name": "Venda",
-      "name": "Tshivenda"
-    },
-    "vec": {
-      "english_name": "Venetian",
-      "name": "V\u00e8neto"
-    },
-    "vep": {
-      "english_name": "Vepsian",
-      "name": "Veps\u00e4n"
-    },
-    "vi": {
-      "english_name": "Vietnamese",
-      "name": "Ti\u1ebfng Vi\u1ec7t"
-    },
-    "vls": {
-      "english_name": "West Flemish",
-      "name": "West-Vlams"
-    },
-    "vo": {
-      "english_name": "Volap\u00fck",
-      "name": "Volap\u00fck"
-    },
-    "wa": {
-      "english_name": "Walloon",
-      "name": "Walon"
-    },
-    "war": {
-      "english_name": "Waray-Waray",
-      "name": "Winaray"
-    },
-    "wo": {
-      "english_name": "Wolof",
-      "name": "Wolof"
-    },
-    "wuu": {
-      "english_name": "Wu",
-      "name": "\u5434\u8bed"
-    },
-    "xal": {
-      "english_name": "Kalmyk",
-      "name": "\u0425\u0430\u043b\u044c\u043c\u0433"
-    },
-    "xh": {
-      "english_name": "Xhosa",
-      "name": "isiXhosa"
-    },
-    "xmf": {
-      "english_name": "Mingrelian",
-      "name": "\u10db\u10d0\u10e0\u10d2\u10d0\u10da\u10e3\u10e0\u10d8 (Margaluri)"
-    },
-    "yi": {
-      "english_name": "Yiddish",
-      "name": "\u05d9\u05d9\u05b4\u05d3\u05d9\u05e9"
-    },
-    "yo": {
-      "english_name": "Yoruba",
-      "name": "Yor\u00f9b\u00e1"
-    },
-    "za": {
-      "english_name": "Zhuang",
-      "name": "Cuengh"
-    },
-    "zea": {
-      "english_name": "Zeelandic",
-      "name": "Ze\u00eauws"
-    },
-    "zh": {
-      "english_name": "Chinese",
-      "name": "\u4e2d\u6587"
-    },
-    "zh-classical": {
-      "english_name": "Classical Chinese",
-      "name": "\u53e4\u6587 / \u6587\u8a00\u6587"
-    },
-    "zh-min-nan": {
-      "english_name": "Min Nan",
-      "name": "B\u00e2n-l\u00e2m-g\u00fa"
-    },
-    "zh-yue": {
-      "english_name": "Cantonese",
-      "name": "\u7cb5\u8a9e"
-    },
-    "zu": {
-      "english_name": "Zulu",
-      "name": "isiZulu"
-    }
-  },
-  "wikipedia": {
-    "ab": {
-      "english_name": "Abkhazian",
-      "name": "\u0410\u0525\u0441\u0443\u0430"
-    },
-    "ace": {
-      "english_name": "Acehnese",
-      "name": "Basa Ac\u00e8h"
-    },
-    "ady": {
-      "english_name": "Adyghe",
-      "name": "\u0410\u0434\u044b\u0433\u044d\u0431\u0437\u044d"
-    },
-    "af": {
-      "english_name": "Afrikaans",
-      "name": "Afrikaans"
-    },
-    "ak": {
-      "english_name": "Akan",
-      "name": "Akana"
-    },
-    "als": {
-      "english_name": "Alemannic",
-      "name": "Alemannisch"
-    },
-    "alt": {
-      "english_name": "Southern Altai",
-      "name": "\u0410\u043b\u0442\u0430\u0439"
-    },
-    "am": {
-      "english_name": "Amharic",
-      "name": "\u12a0\u121b\u122d\u129b"
-    },
-    "ami": {
-      "english_name": "Amis",
-      "name": "Pangcah"
-    },
-    "an": {
-      "english_name": "Aragonese",
-      "name": "Aragon\u00e9s"
-    },
-    "ang": {
-      "english_name": "Anglo-Saxon",
-      "name": "\u00c6nglisc"
-    },
-    "ar": {
-      "english_name": "Arabic",
-      "name": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629"
-    },
-    "arc": {
-      "english_name": "Aramaic",
-      "name": "\u0710\u072a\u0721\u071d\u0710"
-    },
-    "ary": {
-      "english_name": "Moroccan Arabic",
-      "name": "\u062f\u0627\u0631\u064a\u062c\u0629"
-    },
-    "arz": {
-      "english_name": "Egyptian Arabic",
-      "name": "\u0645\u0635\u0631\u0649 (Ma\u1e63ri)"
-    },
-    "as": {
-      "english_name": "Assamese",
-      "name": "\u0985\u09b8\u09ae\u09c0\u09af\u09bc\u09be"
-    },
-    "ast": {
-      "english_name": "Asturian",
-      "name": "Asturianu"
-    },
-    "atj": {
-      "english_name": "Atikamekw",
-      "name": "Atikamekw"
-    },
-    "av": {
-      "english_name": "Avar",
-      "name": "\u0410\u0432\u0430\u0440"
-    },
-    "avk": {
-      "english_name": "Kotava",
-      "name": "Kotava"
-    },
-    "awa": {
-      "english_name": "Awadhi",
-      "name": "\u0905\u0935\u0927\u0940"
-    },
-    "ay": {
-      "english_name": "Aymara",
-      "name": "Aymar"
-    },
-    "az": {
-      "english_name": "Azerbaijani",
-      "name": "Az\u0259rbaycanca"
-    },
-    "azb": {
-      "english_name": "South Azerbaijani",
-      "name": "\u062a\u06c6\u0631\u06a9\u062c\u0647"
-    },
-    "ba": {
-      "english_name": "Bashkir",
-      "name": "\u0411\u0430\u0448\u04a1\u043e\u0440\u0442"
-    },
-    "ban": {
-      "english_name": "Balinese",
-      "name": "Bali"
-    },
-    "bar": {
-      "english_name": "Bavarian",
-      "name": "Boarisch"
-    },
-    "bat-smg": {
-      "english_name": "Samogitian",
-      "name": "\u017demait\u0117\u0161ka"
-    },
-    "bcl": {
-      "english_name": "Central Bicolano",
-      "name": "Bikol"
-    },
-    "be": {
-      "english_name": "Belarusian",
-      "name": "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f"
-    },
-    "be-tarask": {
-      "english_name": "Belarusian (Tara\u0161kievica)",
-      "name": "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430)"
-    },
-    "bg": {
-      "english_name": "Bulgarian",
-      "name": "\u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438"
-    },
-    "bh": {
-      "english_name": "Bhojpuri",
-      "name": "\u092d\u094b\u091c\u092a\u0941\u0930\u0940"
-    },
-    "bi": {
-      "english_name": "Bislama",
-      "name": "Bislama"
-    },
-    "bjn": {
-      "english_name": "Banjar",
-      "name": "Bahasa Banjar"
-    },
-    "blk": {
-      "english_name": "Pa'O",
-      "name": "\u1015\u1021\u102d\u102f\u101d\u103a\u108f\u1018\u102c\u108f\u101e\u102c\u108f"
-    },
-    "bm": {
-      "english_name": "Bambara",
-      "name": "Bamanankan"
-    },
-    "bn": {
-      "english_name": "Bengali",
-      "name": "\u09ac\u09be\u0982\u09b2\u09be"
-    },
-    "bo": {
-      "english_name": "Tibetan",
-      "name": "\u0f56\u0f7c\u0f51\u0f0b\u0f66\u0f90\u0f51"
-    },
-    "bpy": {
-      "english_name": "Bishnupriya Manipuri",
-      "name": "\u0987\u09ae\u09be\u09b0 \u09a0\u09be\u09b0/\u09ac\u09bf\u09b7\u09cd\u09a3\u09c1\u09aa\u09cd\u09b0\u09bf\u09af\u09bc\u09be \u09ae\u09a3\u09bf\u09aa\u09c1\u09b0\u09c0"
-    },
-    "br": {
-      "english_name": "Breton",
-      "name": "Brezhoneg"
-    },
-    "bs": {
-      "english_name": "Bosnian",
-      "name": "Bosanski"
-    },
-    "bug": {
-      "english_name": "Buginese",
-      "name": "Basa Ugi"
-    },
-    "bxr": {
-      "english_name": "Buryat",
-      "name": "\u0411\u0443\u0440\u044f\u0430\u0434"
-    },
-    "ca": {
-      "english_name": "Catalan",
-      "name": "Catal\u00e0"
-    },
-    "cbk-zam": {
-      "english_name": "Zamboanga Chavacano",
-      "name": "Chavacano de Zamboanga"
-    },
-    "cdo": {
-      "english_name": "Min Dong",
-      "name": "M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304"
-    },
-    "ce": {
-      "english_name": "Chechen",
-      "name": "\u041d\u043e\u0445\u0447\u0438\u0439\u043d"
-    },
-    "ceb": {
-      "english_name": "Cebuano",
-      "name": "Sinugboanong Binisaya"
-    },
-    "ch": {
-      "english_name": "Chamorro",
-      "name": "Chamoru"
-    },
-    "chr": {
-      "english_name": "Cherokee",
-      "name": "\u13e3\u13b3\u13a9"
-    },
-    "chy": {
-      "english_name": "Cheyenne",
-      "name": "Tsets\u00eahest\u00e2hese"
-    },
-    "ckb": {
-      "english_name": "Sorani",
-      "name": "Soran\u00ee / \u06a9\u0648\u0631\u062f\u06cc"
-    },
-    "co": {
-      "english_name": "Corsican",
-      "name": "Corsu"
-    },
-    "cr": {
-      "english_name": "Cree",
-      "name": "Nehiyaw"
-    },
-    "crh": {
-      "english_name": "Crimean Tatar",
-      "name": "Q\u0131r\u0131mtatarca"
-    },
-    "cs": {
-      "english_name": "Czech",
-      "name": "\u010ce\u0161tina"
-    },
-    "csb": {
-      "english_name": "Kashubian",
-      "name": "Kasz\u00ebbsczi"
-    },
-    "cu": {
-      "english_name": "Old Church Slavonic",
-      "name": "\u0421\u043b\u043e\u0432\u0463\u043d\u044c\u0441\u043a\u044a"
-    },
-    "cv": {
-      "english_name": "Chuvash",
-      "name": "\u0427\u0103\u0432\u0430\u0448"
-    },
-    "cy": {
-      "english_name": "Welsh",
-      "name": "Cymraeg"
-    },
-    "da": {
-      "english_name": "Danish",
-      "name": "Dansk"
-    },
-    "dag": {
-      "english_name": "Dagbani",
-      "name": "Dagbanli"
-    },
-    "de": {
-      "english_name": "German",
-      "name": "Deutsch"
-    },
-    "din": {
-      "english_name": "Dinka",
-      "name": "Thu\u0254\u014bj\u00e4\u014b"
-    },
-    "diq": {
-      "english_name": "Zazaki",
-      "name": "Zazaki"
-    },
-    "dsb": {
-      "english_name": "Lower Sorbian",
-      "name": "Dolnoserbski"
-    },
-    "dty": {
-      "english_name": "Doteli",
-      "name": "\u0921\u094b\u091f\u0947\u0932\u0940"
-    },
-    "dv": {
-      "english_name": "Divehi",
-      "name": "\u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0"
-    },
-    "dz": {
-      "english_name": "Dzongkha",
-      "name": "\u0f47\u0f7c\u0f44\u0f0b\u0f41"
-    },
-    "ee": {
-      "english_name": "Ewe",
-      "name": "E\u028begbe"
-    },
-    "el": {
-      "english_name": "Greek",
-      "name": "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac"
-    },
-    "eml": {
-      "english_name": "Emilian-Romagnol",
-      "name": "Emili\u00e0n e rumagn\u00f2l"
-    },
-    "en": {
-      "english_name": "English",
-      "name": "English"
-    },
-    "eo": {
-      "english_name": "Esperanto",
-      "name": "Esperanto"
-    },
-    "es": {
-      "english_name": "Spanish",
-      "name": "Espa\u00f1ol"
-    },
-    "et": {
-      "english_name": "Estonian",
-      "name": "Eesti"
-    },
-    "eu": {
-      "english_name": "Basque",
-      "name": "Euskara"
-    },
-    "ext": {
-      "english_name": "Extremaduran",
-      "name": "Estreme\u00f1u"
-    },
-    "fa": {
-      "english_name": "Persian",
-      "name": "\u0641\u0627\u0631\u0633\u06cc"
-    },
-    "ff": {
-      "english_name": "Fula",
-      "name": "Fulfulde"
-    },
-    "fi": {
-      "english_name": "Finnish",
-      "name": "Suomi"
-    },
-    "fiu-vro": {
-      "english_name": "V\u00f5ro",
-      "name": "V\u00f5ro"
-    },
-    "fj": {
-      "english_name": "Fijian",
-      "name": "Na Vosa Vakaviti"
-    },
-    "fo": {
-      "english_name": "Faroese",
-      "name": "F\u00f8royskt"
-    },
-    "fr": {
-      "english_name": "French",
-      "name": "Fran\u00e7ais"
-    },
-    "frp": {
-      "english_name": "Franco-Proven\u00e7al",
-      "name": "Arpetan"
-    },
-    "frr": {
-      "english_name": "North Frisian",
-      "name": "Nordfrasch"
-    },
-    "fur": {
-      "english_name": "Friulian",
-      "name": "Furlan"
-    },
-    "fy": {
-      "english_name": "West Frisian",
-      "name": "Frysk"
-    },
-    "ga": {
-      "english_name": "Irish",
-      "name": "Gaeilge"
-    },
-    "gag": {
-      "english_name": "Gagauz",
-      "name": "Gagauz"
-    },
-    "gan": {
-      "english_name": "Gan",
-      "name": "\u8d1b\u8a9e"
-    },
-    "gcr": {
-      "english_name": "Guianan Creole",
-      "name": "Kriy\u00f2l Gwiyannen"
-    },
-    "gd": {
-      "english_name": "Scottish Gaelic",
-      "name": "G\u00e0idhlig"
-    },
-    "gl": {
-      "english_name": "Galician",
-      "name": "Galego"
-    },
-    "glk": {
-      "english_name": "Gilaki",
-      "name": "\u06af\u06cc\u0644\u06a9\u06cc"
-    },
-    "gn": {
-      "english_name": "Guarani",
-      "name": "Ava\u00f1e'\u1ebd"
-    },
-    "gom": {
-      "english_name": "Goan Konkani",
-      "name": "\u0917\u094b\u0902\u092f\u091a\u0940 \u0915\u094b\u0902\u0915\u0923\u0940 / G\u00f5ychi Konknni"
-    },
-    "gor": {
-      "english_name": "Gorontalo",
-      "name": "Hulontalo"
-    },
-    "got": {
-      "english_name": "Gothic",
-      "name": "\ud800\udf32\ud800\udf3f\ud800\udf44\ud800\udf39\ud800\udf43\ud800\udf3a"
-    },
-    "gu": {
-      "english_name": "Gujarati",
-      "name": "\u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0"
-    },
-    "guw": {
-      "english_name": "Gun",
-      "name": "Gungbe"
-    },
-    "gv": {
-      "english_name": "Manx",
-      "name": "Gaelg"
-    },
-    "ha": {
-      "english_name": "Hausa",
-      "name": "Hausa / \u0647\u064e\u0648\u064f\u0633\u064e"
-    },
-    "hak": {
-      "english_name": "Hakka",
-      "name": "Hak-k\u00e2-fa / \u5ba2\u5bb6\u8a71"
-    },
-    "haw": {
-      "english_name": "Hawaiian",
-      "name": "Hawai\u02bbi"
-    },
-    "he": {
-      "english_name": "Hebrew",
-      "name": "\u05e2\u05d1\u05e8\u05d9\u05ea"
-    },
-    "hi": {
-      "english_name": "Hindi",
-      "name": "\u0939\u093f\u0928\u094d\u0926\u0940"
-    },
-    "hif": {
-      "english_name": "Fiji Hindi",
-      "name": "Fiji Hindi"
-    },
-    "hr": {
-      "english_name": "Croatian",
-      "name": "Hrvatski"
-    },
-    "hsb": {
-      "english_name": "Upper Sorbian",
-      "name": "Hornjoserbsce"
-    },
-    "ht": {
-      "english_name": "Haitian",
-      "name": "Kr\u00e8yol ayisyen"
-    },
-    "hu": {
-      "english_name": "Hungarian",
-      "name": "Magyar"
-    },
-    "hy": {
-      "english_name": "Armenian",
-      "name": "\u0540\u0561\u0575\u0565\u0580\u0565\u0576"
-    },
-    "hyw": {
-      "english_name": "Western Armenian",
-      "name": "\u0531\u0580\u0565\u0582\u0574\u057f\u0561\u0570\u0561\u0575\u0565\u0580\u0567\u0576"
-    },
-    "ia": {
-      "english_name": "Interlingua",
-      "name": "Interlingua"
-    },
-    "id": {
-      "english_name": "Indonesian",
-      "name": "Bahasa Indonesia"
-    },
-    "ie": {
-      "english_name": "Interlingue",
-      "name": "Interlingue"
-    },
-    "ig": {
-      "english_name": "Igbo",
-      "name": "\u00ccgb\u00f2"
-    },
-    "ik": {
-      "english_name": "Inupiak",
-      "name": "I\u00f1upiatun"
-    },
-    "ilo": {
-      "english_name": "Ilokano",
-      "name": "Ilokano"
-    },
-    "inh": {
-      "english_name": "Ingush",
-      "name": "\u0413\u04c0\u0430\u043b\u0433\u04c0\u0430\u0439"
-    },
-    "io": {
-      "english_name": "Ido",
-      "name": "Ido"
-    },
-    "is": {
-      "english_name": "Icelandic",
-      "name": "\u00cdslenska"
-    },
-    "it": {
-      "english_name": "Italian",
-      "name": "Italiano"
-    },
-    "iu": {
-      "english_name": "Inuktitut",
-      "name": "\u1403\u14c4\u1483\u144e\u1450\u1466"
-    },
-    "ja": {
-      "english_name": "Japanese",
-      "name": "\u65e5\u672c\u8a9e"
-    },
-    "jam": {
-      "english_name": "Jamaican Patois",
-      "name": "Jumiekan Kryuol"
-    },
-    "jbo": {
-      "english_name": "Lojban",
-      "name": "Lojban"
-    },
-    "jv": {
-      "english_name": "Javanese",
-      "name": "Basa Jawa"
-    },
-    "ka": {
-      "english_name": "Georgian",
-      "name": "\u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8"
-    },
-    "kaa": {
-      "english_name": "Karakalpak",
-      "name": "Qaraqalpaqsha"
-    },
-    "kab": {
-      "english_name": "Kabyle",
-      "name": "Taqbaylit"
-    },
-    "kbd": {
-      "english_name": "Kabardian Circassian",
-      "name": "\u0410\u0434\u044b\u0433\u044d\u0431\u0437\u044d (Adighabze)"
-    },
-    "kbp": {
-      "english_name": "Kabiye",
-      "name": "Kab\u0269y\u025b"
-    },
-    "kcg": {
-      "english_name": "Tyap",
-      "name": "Tyap"
-    },
-    "kg": {
-      "english_name": "Kongo",
-      "name": "Kik\u00f4ngo"
-    },
-    "ki": {
-      "english_name": "Kikuyu",
-      "name": "G\u0129k\u0169y\u0169"
-    },
-    "kk": {
-      "english_name": "Kazakh",
-      "name": "\u049a\u0430\u0437\u0430\u049b\u0448\u0430"
-    },
-    "kl": {
-      "english_name": "Greenlandic",
-      "name": "Kalaallisut"
-    },
-    "km": {
-      "english_name": "Khmer",
-      "name": "\u1797\u17b6\u179f\u17b6\u1781\u17d2\u1798\u17c2\u179a"
-    },
-    "kn": {
-      "english_name": "Kannada",
-      "name": "\u0c95\u0ca8\u0ccd\u0ca8\u0ca1"
-    },
-    "ko": {
-      "english_name": "Korean",
-      "name": "\ud55c\uad6d\uc5b4"
-    },
-    "koi": {
-      "english_name": "Komi-Permyak",
-      "name": "\u041f\u0435\u0440\u0435\u043c \u041a\u043e\u043c\u0438 (Perem Komi)"
-    },
-    "krc": {
-      "english_name": "Karachay-Balkar",
-      "name": "\u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440 (Qarachay-Malqar)"
-    },
-    "ks": {
-      "english_name": "Kashmiri",
-      "name": "\u0915\u0936\u094d\u092e\u0940\u0930\u0940 / \u0643\u0634\u0645\u064a\u0631\u064a"
-    },
-    "ksh": {
-      "english_name": "Ripuarian",
-      "name": "Ripoarisch"
-    },
-    "ku": {
-      "english_name": "Kurdish",
-      "name": "Kurd\u00ee / \u0643\u0648\u0631\u062f\u06cc"
-    },
-    "kv": {
-      "english_name": "Komi",
-      "name": "\u041a\u043e\u043c\u0438"
-    },
-    "kw": {
-      "english_name": "Cornish",
-      "name": "Kernowek/Karnuack"
-    },
-    "ky": {
-      "english_name": "Kyrgyz",
-      "name": "\u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430"
-    },
-    "la": {
-      "english_name": "Latin",
-      "name": "Latina"
-    },
-    "lad": {
-      "english_name": "Ladino",
-      "name": "Dzhudezmo"
-    },
-    "lb": {
-      "english_name": "Luxembourgish",
-      "name": "L\u00ebtzebuergesch"
-    },
-    "lbe": {
-      "english_name": "Lak",
-      "name": "\u041b\u0430\u043a\u043a\u0443"
-    },
-    "lez": {
-      "english_name": "Lezgian",
-      "name": "\u041b\u0435\u0437\u0433\u0438 \u0447\u0406\u0430\u043b (Lezgi \u010d\u2019al)"
-    },
-    "lfn": {
-      "english_name": "Lingua Franca Nova",
-      "name": "Lingua franca nova"
-    },
-    "lg": {
-      "english_name": "Luganda",
-      "name": "Luganda"
-    },
-    "li": {
-      "english_name": "Limburgish",
-      "name": "Limburgs"
-    },
-    "lij": {
-      "english_name": "Ligurian",
-      "name": "L\u00ecgure"
-    },
-    "lld": {
-      "english_name": "Ladin",
-      "name": "Lingaz"
-    },
-    "lmo": {
-      "english_name": "Lombard",
-      "name": "Lumbaart"
-    },
-    "ln": {
-      "english_name": "Lingala",
-      "name": "Lingala"
-    },
-    "lo": {
-      "english_name": "Lao",
-      "name": "\u0ea5\u0eb2\u0ea7"
-    },
-    "lt": {
-      "english_name": "Lithuanian",
-      "name": "Lietuvi\u0173"
-    },
-    "ltg": {
-      "english_name": "Latgalian",
-      "name": "Latga\u013cu"
-    },
-    "lv": {
-      "english_name": "Latvian",
-      "name": "Latvie\u0161u"
-    },
-    "mad": {
-      "english_name": "Madurese",
-      "name": "Madhur\u00e2"
-    },
-    "mai": {
-      "english_name": "Maithili",
-      "name": "\u092e\u0948\u0925\u093f\u0932\u0940"
-    },
-    "map-bms": {
-      "english_name": "Banyumasan",
-      "name": "Basa Banyumasan"
-    },
-    "mdf": {
-      "english_name": "Moksha",
-      "name": "\u041c\u043e\u043a\u0448\u0435\u043d\u044c (Mokshanj K\u00e4lj)"
-    },
-    "mg": {
-      "english_name": "Malagasy",
-      "name": "Malagasy"
-    },
-    "mhr": {
-      "english_name": "Meadow Mari",
-      "name": "\u041e\u043b\u044b\u043a \u041c\u0430\u0440\u0438\u0439 (Olyk Marij)"
-    },
-    "mi": {
-      "english_name": "Maori",
-      "name": "M\u0101ori"
-    },
-    "min": {
-      "english_name": "Minangkabau",
-      "name": "Minangkabau"
-    },
-    "mk": {
-      "english_name": "Macedonian",
-      "name": "\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438"
-    },
-    "ml": {
-      "english_name": "Malayalam",
-      "name": "\u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02"
-    },
-    "mn": {
-      "english_name": "Mongolian",
-      "name": "\u041c\u043e\u043d\u0433\u043e\u043b"
-    },
-    "mni": {
-      "english_name": "Meitei",
-      "name": "\uabc3\uabe4\uabc7\uabe9\uabc2\uabe3\uabdf"
-    },
-    "mnw": {
-      "english_name": "Mon",
-      "name": "\u1019\u1014\u103a"
-    },
-    "mr": {
-      "english_name": "Marathi",
-      "name": "\u092e\u0930\u093e\u0920\u0940"
-    },
-    "mrj": {
-      "english_name": "Hill Mari",
-      "name": "\u041a\u044b\u0440\u044b\u043a \u041c\u0430\u0440\u044b (Kyryk Mary)"
-    },
-    "ms": {
-      "english_name": "Malay",
-      "name": "Bahasa Melayu"
-    },
-    "mt": {
-      "english_name": "Maltese",
-      "name": "Malti"
-    },
-    "mwl": {
-      "english_name": "Mirandese",
-      "name": "Mirand\u00e9s"
-    },
-    "my": {
-      "english_name": "Burmese",
-      "name": "\u1019\u103c\u1014\u103a\u1019\u102c\u1018\u102c\u101e\u102c"
-    },
-    "myv": {
-      "english_name": "Erzya",
-      "name": "\u042d\u0440\u0437\u044f\u043d\u044c (Erzjanj Kelj)"
-    },
-    "mzn": {
-      "english_name": "Mazandarani",
-      "name": "\u0645\u064e\u0632\u0650\u0631\u0648\u0646\u064a"
-    },
-    "na": {
-      "english_name": "Nauruan",
-      "name": "dorerin Naoero"
-    },
-    "nah": {
-      "english_name": "Nahuatl",
-      "name": "N\u0101huatl"
-    },
-    "nap": {
-      "english_name": "Neapolitan",
-      "name": "Nnapulitano"
-    },
-    "nds": {
-      "english_name": "Low Saxon",
-      "name": "Plattd\u00fc\u00fctsch"
-    },
-    "nds-nl": {
-      "english_name": "Dutch Low Saxon",
-      "name": "Nedersaksisch"
-    },
-    "ne": {
-      "english_name": "Nepali",
-      "name": "\u0928\u0947\u092a\u093e\u0932\u0940"
-    },
-    "new": {
-      "english_name": "Newar",
-      "name": "\u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e"
-    },
-    "nia": {
-      "english_name": "Nias",
-      "name": "Li Niha"
-    },
-    "nl": {
-      "english_name": "Dutch",
-      "name": "Nederlands"
-    },
-    "nn": {
-      "english_name": "Norwegian (Nynorsk)",
-      "name": "Nynorsk"
-    },
-    "no": {
-      "english_name": "Norwegian (Bokm\u00e5l)",
-      "name": "Norsk (Bokm\u00e5l)"
-    },
-    "nov": {
-      "english_name": "Novial",
-      "name": "Novial"
-    },
-    "nqo": {
-      "english_name": "N\u2019Ko",
-      "name": "\u07d2\u07de\u07cf"
-    },
-    "nrm": {
-      "english_name": "Norman",
-      "name": "Nouormand/Normaund"
-    },
-    "nso": {
-      "english_name": "Northern Sotho",
-      "name": "Sepedi"
-    },
-    "nv": {
-      "english_name": "Navajo",
-      "name": "Din\u00e9 bizaad"
-    },
-    "ny": {
-      "english_name": "Chichewa",
-      "name": "Chichewa"
-    },
-    "oc": {
-      "english_name": "Occitan",
-      "name": "Occitan"
-    },
-    "olo": {
-      "english_name": "Livvi-Karelian",
-      "name": "Karjalan"
-    },
-    "om": {
-      "english_name": "Oromo",
-      "name": "Oromoo"
-    },
-    "or": {
-      "english_name": "Oriya",
-      "name": "\u0b13\u0b21\u0b3c\u0b3f\u0b06"
-    },
-    "os": {
-      "english_name": "Ossetian",
-      "name": "\u0418\u0440\u043e\u043d\u0430\u0443"
-    },
-    "pa": {
-      "english_name": "Punjabi",
-      "name": "\u0a2a\u0a70\u0a1c\u0a3e\u0a2c\u0a40"
-    },
-    "pag": {
-      "english_name": "Pangasinan",
-      "name": "Pangasinan"
-    },
-    "pam": {
-      "english_name": "Kapampangan",
-      "name": "Kapampangan"
-    },
-    "pap": {
-      "english_name": "Papiamentu",
-      "name": "Papiamentu"
-    },
-    "pcd": {
-      "english_name": "Picard",
-      "name": "Picard"
-    },
-    "pcm": {
-      "english_name": "Nigerian Pidgin",
-      "name": "Naij\u00e1"
-    },
-    "pdc": {
-      "english_name": "Pennsylvania German",
-      "name": "Deitsch"
-    },
-    "pfl": {
-      "english_name": "Palatinate German",
-      "name": "P\u00e4lzisch"
-    },
-    "pi": {
-      "english_name": "Pali",
-      "name": "\u092a\u093e\u0934\u093f"
-    },
-    "pih": {
-      "english_name": "Norfolk",
-      "name": "Norfuk"
-    },
-    "pl": {
-      "english_name": "Polish",
-      "name": "Polski"
-    },
-    "pms": {
-      "english_name": "Piedmontese",
-      "name": "Piemont\u00e8is"
-    },
-    "pnb": {
-      "english_name": "Western Punjabi",
-      "name": "\u0634\u0627\u06c1 \u0645\u06a9\u06be\u06cc \u067e\u0646\u062c\u0627\u0628\u06cc (Sh\u0101hmukh\u012b Pa\u00f1j\u0101b\u012b)"
-    },
-    "pnt": {
-      "english_name": "Pontic",
-      "name": "\u03a0\u03bf\u03bd\u03c4\u03b9\u03b1\u03ba\u03ac"
-    },
-    "ps": {
-      "english_name": "Pashto",
-      "name": "\u067e\u069a\u062a\u0648"
-    },
-    "pt": {
-      "english_name": "Portuguese",
-      "name": "Portugu\u00eas"
-    },
-    "pwn": {
-      "english_name": "Paiwan",
-      "name": "Paiwan"
-    },
-    "qu": {
-      "english_name": "Quechua",
-      "name": "Qichwa simi"
-    },
-    "rm": {
-      "english_name": "Romansh",
-      "name": "Rumantsch"
-    },
-    "rmy": {
-      "english_name": "Romani",
-      "name": "romani - \u0930\u094b\u092e\u093e\u0928\u0940"
-    },
-    "rn": {
-      "english_name": "Kirundi",
-      "name": "Ikirundi"
-    },
-    "ro": {
-      "english_name": "Romanian",
-      "name": "Rom\u00e2n\u0103"
-    },
-    "roa-rup": {
-      "english_name": "Aromanian",
-      "name": "Arm\u00e3neashce"
-    },
-    "roa-tara": {
-      "english_name": "Tarantino",
-      "name": "Tarand\u00edne"
-    },
-    "ru": {
-      "english_name": "Russian",
-      "name": "\u0420\u0443\u0441\u0441\u043a\u0438\u0439"
-    },
-    "rue": {
-      "english_name": "Rusyn",
-      "name": "\u0420\u0443\u0441\u0438\u043d\u044c\u0441\u043a\u044b\u0439"
-    },
-    "rw": {
-      "english_name": "Kinyarwanda",
-      "name": "Ikinyarwanda"
-    },
-    "sa": {
-      "english_name": "Sanskrit",
-      "name": "\u0938\u0902\u0938\u094d\u0915\u0943\u0924\u092e\u094d"
-    },
-    "sah": {
-      "english_name": "Sakha",
-      "name": "\u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430 (Saxa Tyla)"
-    },
-    "sat": {
-      "english_name": "Santali",
-      "name": "\u1c65\u1c5f\u1c71\u1c5b\u1c5f\u1c72\u1c64"
-    },
-    "sc": {
-      "english_name": "Sardinian",
-      "name": "Sardu"
-    },
-    "scn": {
-      "english_name": "Sicilian",
-      "name": "Sicilianu"
-    },
-    "sco": {
-      "english_name": "Scots",
-      "name": "Scots"
-    },
-    "sd": {
-      "english_name": "Sindhi",
-      "name": "\u0633\u0646\u068c\u064a\u060c \u0633\u0646\u062f\u06be\u06cc \u060c \u0938\u093f\u0928\u094d\u0927"
-    },
-    "se": {
-      "english_name": "Northern Sami",
-      "name": "S\u00e1megiella"
-    },
-    "sg": {
-      "english_name": "Sango",
-      "name": "S\u00e4ng\u00f6"
-    },
-    "sh": {
-      "english_name": "Serbo-Croatian",
-      "name": "Srpskohrvatski / \u0421\u0440\u043f\u0441\u043a\u043e\u0445\u0440\u0432\u0430\u0442\u0441\u043a\u0438"
-    },
-    "shi": {
-      "english_name": "Tachelhit",
-      "name": "Tacl\u1e25it"
-    },
-    "shn": {
-      "english_name": "Shan",
-      "name": "\u101c\u102d\u1075\u103a\u1088\u1010\u1086\u1038"
-    },
-    "si": {
-      "english_name": "Sinhalese",
-      "name": "\u0dc3\u0dd2\u0d82\u0dc4\u0dbd"
-    },
-    "simple": {
-      "english_name": "Simple English",
-      "name": "Simple English"
-    },
-    "sk": {
-      "english_name": "Slovak",
-      "name": "Sloven\u010dina"
-    },
-    "skr": {
-      "english_name": "Saraiki",
-      "name": "\u0633\u0631\u0627\u0626\u06cc\u06a9\u06cc"
-    },
-    "sl": {
-      "english_name": "Slovenian",
-      "name": "Sloven\u0161\u010dina"
-    },
-    "sm": {
-      "english_name": "Samoan",
-      "name": "Gagana Samoa"
-    },
-    "smn": {
-      "english_name": "Inari Sami",
-      "name": "Anar\u00e2\u0161kiel\u00e2"
-    },
-    "sn": {
-      "english_name": "Shona",
-      "name": "chiShona"
-    },
-    "so": {
-      "english_name": "Somali",
-      "name": "Soomaali"
-    },
-    "sq": {
-      "english_name": "Albanian",
-      "name": "Shqip"
-    },
-    "sr": {
-      "english_name": "Serbian",
-      "name": "\u0421\u0440\u043f\u0441\u043a\u0438 / Srpski"
-    },
-    "srn": {
-      "english_name": "Sranan",
-      "name": "Sranantongo"
-    },
-    "ss": {
-      "english_name": "Swati",
-      "name": "SiSwati"
-    },
-    "st": {
-      "english_name": "Sesotho",
-      "name": "Sesotho"
-    },
-    "stq": {
-      "english_name": "Saterland Frisian",
-      "name": "Seeltersk"
-    },
-    "su": {
-      "english_name": "Sundanese",
-      "name": "Basa Sunda"
-    },
-    "sv": {
-      "english_name": "Swedish",
-      "name": "Svenska"
-    },
-    "sw": {
-      "english_name": "Swahili",
-      "name": "Kiswahili"
-    },
-    "szl": {
-      "english_name": "Silesian",
-      "name": "\u015al\u016fnski"
-    },
-    "szy": {
-      "english_name": "Sakizaya",
-      "name": "Sakizaya"
-    },
-    "ta": {
-      "english_name": "Tamil",
-      "name": "\u0ba4\u0bae\u0bbf\u0bb4\u0bcd"
-    },
-    "tay": {
-      "english_name": "Atayal",
-      "name": "Tayal"
-    },
-    "tcy": {
-      "english_name": "Tulu",
-      "name": "\u0ca4\u0cc1\u0cb3\u0cc1"
-    },
-    "te": {
-      "english_name": "Telugu",
-      "name": "\u0c24\u0c46\u0c32\u0c41\u0c17\u0c41"
-    },
-    "tet": {
-      "english_name": "Tetum",
-      "name": "Tetun"
-    },
-    "tg": {
-      "english_name": "Tajik",
-      "name": "\u0422\u043e\u04b7\u0438\u043a\u04e3"
-    },
-    "th": {
-      "english_name": "Thai",
-      "name": "\u0e44\u0e17\u0e22"
-    },
-    "ti": {
-      "english_name": "Tigrinya",
-      "name": "\u1275\u130d\u122d\u129b"
-    },
-    "tk": {
-      "english_name": "Turkmen",
-      "name": "T\u00fcrkmen"
-    },
-    "tl": {
-      "english_name": "Tagalog",
-      "name": "Tagalog"
-    },
-    "tn": {
-      "english_name": "Tswana",
-      "name": "Setswana"
-    },
-    "to": {
-      "english_name": "Tongan",
-      "name": "faka Tonga"
-    },
-    "tpi": {
-      "english_name": "Tok Pisin",
-      "name": "Tok Pisin"
-    },
-    "tr": {
-      "english_name": "Turkish",
-      "name": "T\u00fcrk\u00e7e"
-    },
-    "trv": {
-      "english_name": "Seediq",
-      "name": "Taroko"
-    },
-    "ts": {
-      "english_name": "Tsonga",
-      "name": "Xitsonga"
-    },
-    "tt": {
-      "english_name": "Tatar",
-      "name": "Tatar\u00e7a / \u0422\u0430\u0442\u0430\u0440\u0447\u0430"
-    },
-    "tum": {
-      "english_name": "Tumbuka",
-      "name": "chiTumbuka"
-    },
-    "tw": {
-      "english_name": "Twi",
-      "name": "Twi"
-    },
-    "ty": {
-      "english_name": "Tahitian",
-      "name": "Reo M\u0101`ohi"
-    },
-    "tyv": {
-      "english_name": "Tuvan",
-      "name": "\u0422\u044b\u0432\u0430"
-    },
-    "udm": {
-      "english_name": "Udmurt",
-      "name": "\u0423\u0434\u043c\u0443\u0440\u0442 \u043a\u044b\u043b"
-    },
-    "ug": {
-      "english_name": "Uyghur",
-      "name": "\u0626\u06c7\u064a\u063a\u06c7\u0631 \u062a\u0649\u0644\u0649"
-    },
-    "uk": {
-      "english_name": "Ukrainian",
-      "name": "\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430"
-    },
-    "ur": {
-      "english_name": "Urdu",
-      "name": "\u0627\u0631\u062f\u0648"
-    },
-    "uz": {
-      "english_name": "Uzbek",
-      "name": "O\u2018zbek"
-    },
-    "ve": {
-      "english_name": "Venda",
-      "name": "Tshivenda"
-    },
-    "vec": {
-      "english_name": "Venetian",
-      "name": "V\u00e8neto"
-    },
-    "vep": {
-      "english_name": "Vepsian",
-      "name": "Veps\u00e4n"
-    },
-    "vi": {
-      "english_name": "Vietnamese",
-      "name": "Ti\u1ebfng Vi\u1ec7t"
-    },
-    "vls": {
-      "english_name": "West Flemish",
-      "name": "West-Vlams"
-    },
-    "vo": {
-      "english_name": "Volap\u00fck",
-      "name": "Volap\u00fck"
-    },
-    "wa": {
-      "english_name": "Walloon",
-      "name": "Walon"
-    },
-    "war": {
-      "english_name": "Waray-Waray",
-      "name": "Winaray"
-    },
-    "wo": {
-      "english_name": "Wolof",
-      "name": "Wolof"
-    },
-    "wuu": {
-      "english_name": "Wu",
-      "name": "\u5434\u8bed"
-    },
-    "xal": {
-      "english_name": "Kalmyk",
-      "name": "\u0425\u0430\u043b\u044c\u043c\u0433"
-    },
-    "xh": {
-      "english_name": "Xhosa",
-      "name": "isiXhosa"
-    },
-    "xmf": {
-      "english_name": "Mingrelian",
-      "name": "\u10db\u10d0\u10e0\u10d2\u10d0\u10da\u10e3\u10e0\u10d8 (Margaluri)"
-    },
-    "yi": {
-      "english_name": "Yiddish",
-      "name": "\u05d9\u05d9\u05b4\u05d3\u05d9\u05e9"
-    },
-    "yo": {
-      "english_name": "Yoruba",
-      "name": "Yor\u00f9b\u00e1"
-    },
-    "za": {
-      "english_name": "Zhuang",
-      "name": "Cuengh"
-    },
-    "zea": {
-      "english_name": "Zeelandic",
-      "name": "Ze\u00eauws"
-    },
-    "zh": {
-      "english_name": "Chinese",
-      "name": "\u4e2d\u6587"
-    },
-    "zh-classical": {
-      "english_name": "Classical Chinese",
-      "name": "\u53e4\u6587 / \u6587\u8a00\u6587"
-    },
-    "zh-min-nan": {
-      "english_name": "Min Nan",
-      "name": "B\u00e2n-l\u00e2m-g\u00fa"
-    },
-    "zh-yue": {
-      "english_name": "Cantonese",
-      "name": "\u7cb5\u8a9e"
-    },
-    "zu": {
-      "english_name": "Zulu",
-      "name": "isiZulu"
-    }
-  },
-  "yahoo": [
-    "ar",
-    "bg",
-    "cs",
-    "da",
-    "de",
-    "el",
-    "en",
-    "es",
-    "et",
-    "fi",
-    "fr",
-    "he",
-    "hr",
-    "hu",
-    "it",
-    "ja",
-    "ko",
-    "lt",
-    "lv",
-    "nl",
-    "no",
-    "pl",
-    "pt",
-    "ro",
-    "ru",
-    "sk",
-    "sl",
-    "sv",
-    "th",
-    "tr",
-    "zh_chs",
-    "zh_cht"
-  ]
-}

+ 143 - 0
searx/enginelib/__init__.py

@@ -0,0 +1,143 @@
+# SPDX-License-Identifier: AGPL-3.0-or-later
+# lint: pylint
+"""Engine related implementations
+
+.. note::
+
+   The long term goal is to modularize all relevant implementations to the
+   engines here in this Python package.  In addition to improved modularization,
+   this will also be necessary in part because the probability of circular
+   imports will increase due to the increased typification of implementations in
+   the future.
+
+   ToDo:
+
+   - move :py:obj:`searx.engines.load_engine` to a new module `searx.enginelib`.
+"""
+
+
+from __future__ import annotations
+from typing import Union, Dict, List, Callable, TYPE_CHECKING
+
+if TYPE_CHECKING:
+    from searx.enginelib import traits
+
+
+class Engine:  # pylint: disable=too-few-public-methods
+    """Class of engine instances build from YAML settings.
+
+    Further documentation see :ref:`general engine configuration`.
+
+    .. hint::
+
+       This class is currently never initialized and only used for type hinting.
+    """
+
+    # Common options in the engine module
+
+    engine_type: str
+    """Type of the engine (:origin:`searx/search/processors`)"""
+
+    paging: bool
+    """Engine supports multiple pages."""
+
+    time_range_support: bool
+    """Engine supports search time range."""
+
+    safesearch: bool
+    """Engine supports SafeSearch"""
+
+    language_support: bool
+    """Engine supports languages (locales) search."""
+
+    language: str
+    """For an engine, when there is ``language: ...`` in the YAML settings the engine
+    does support only this one language:
+
+    .. code:: yaml
+
+      - name: google french
+        engine: google
+        language: fr
+    """
+
+    region: str
+    """For an engine, when there is ``region: ...`` in the YAML settings the engine
+    does support only this one region::
+
+    .. code:: yaml
+
+      - name: google belgium
+        engine: google
+        region: fr-BE
+    """
+
+    fetch_traits: Callable
+    """Function to to fetch engine's traits from origin."""
+
+    traits: traits.EngineTraits
+    """Traits of the engine."""
+
+    # settings.yml
+
+    categories: List[str]
+    """Tabs, in which the engine is working."""
+
+    name: str
+    """Name that will be used across SearXNG to define this engine.  In settings, on
+    the result page .."""
+
+    engine: str
+    """Name of the python file used to handle requests and responses to and from
+    this search engine (file name from :origin:`searx/engines` without
+    ``.py``)."""
+
+    enable_http: bool
+    """Enable HTTP (by default only HTTPS is enabled)."""
+
+    shortcut: str
+    """Code used to execute bang requests (``!foo``)"""
+
+    timeout: float
+    """Specific timeout for search-engine."""
+
+    display_error_messages: bool
+    """Display error messages on the web UI."""
+
+    proxies: dict
+    """Set proxies for a specific engine (YAML):
+
+    .. code:: yaml
+
+       proxies :
+         http:  socks5://proxy:port
+         https: socks5://proxy:port
+    """
+
+    disabled: bool
+    """To disable by default the engine, but not deleting it.  It will allow the
+    user to manually activate it in the settings."""
+
+    inactive: bool
+    """Remove the engine from the settings (*disabled & removed*)."""
+
+    about: dict
+    """Additional fileds describing the engine.
+
+    .. code:: yaml
+
+       about:
+          website: https://example.com
+          wikidata_id: Q306656
+          official_api_documentation: https://example.com/api-doc
+          use_official_api: true
+          require_api_key: true
+          results: HTML
+    """
+
+    # deprecated properties
+
+    _fetch_supported_languages: Callable  # deprecated use fetch_traits
+    supported_languages: Union[List[str], Dict[str, str]]  # deprecated use traits
+    language_aliases: Dict[str, str]  # deprecated not needed when using triats
+    supported_languages_url: str  # deprecated not needed when using triats

+ 387 - 0
searx/enginelib/traits.py

@@ -0,0 +1,387 @@
+# SPDX-License-Identifier: AGPL-3.0-or-later
+# lint: pylint
+"""Engine's traits are fetched from the origin engines and stored in a JSON file
+in the *data folder*.  Most often traits are languages and region codes and
+their mapping from SearXNG's representation to the representation in the origin
+search engine.  For new traits new properties can be added to the class
+:py:class:`EngineTraits`.
+
+To load traits from the persistence :py:obj:`EngineTraitsMap.from_data` can be
+used.
+"""
+
+from __future__ import annotations
+import json
+import dataclasses
+from typing import Dict, Union, List, Callable, Optional, TYPE_CHECKING
+from typing_extensions import Literal, Self
+
+from babel.localedata import locale_identifiers
+
+from searx import locales
+from searx.data import data_dir, ENGINE_TRAITS
+
+if TYPE_CHECKING:
+    from . import Engine
+
+
+class EngineTraitsEncoder(json.JSONEncoder):
+    """Encodes :class:`EngineTraits` to a serializable object, see
+    :class:`json.JSONEncoder`."""
+
+    def default(self, o):
+        """Return dictionary of a :class:`EngineTraits` object."""
+        if isinstance(o, EngineTraits):
+            return o.__dict__
+        return super().default(o)
+
+
+@dataclasses.dataclass
+class EngineTraits:
+    """The class is intended to be instantiated for each engine."""
+
+    regions: Dict[str, str] = dataclasses.field(default_factory=dict)
+    """Maps SearXNG's internal representation of a region to the one of the engine.
+
+    SearXNG's internal representation can be parsed by babel and the value is
+    send to the engine:
+
+    .. code:: python
+
+       regions ={
+           'fr-BE' : <engine's region name>,
+       }
+
+       for key, egnine_region regions.items():
+          searxng_region = babel.Locale.parse(key, sep='-')
+          ...
+    """
+
+    languages: Dict[str, str] = dataclasses.field(default_factory=dict)
+    """Maps SearXNG's internal representation of a language to the one of the engine.
+
+    SearXNG's internal representation can be parsed by babel and the value is
+    send to the engine:
+
+    .. code:: python
+
+       languages = {
+           'ca' : <engine's language name>,
+       }
+
+       for key, egnine_lang in languages.items():
+          searxng_lang = babel.Locale.parse(key)
+          ...
+    """
+
+    all_locale: Optional[str] = None
+    """To which locale value SearXNG's ``all`` language is mapped (shown a "Default
+    language").
+    """
+
+    data_type: Literal['traits_v1', 'supported_languages'] = 'traits_v1'
+    """Data type, default is 'traits_v1' for vintage use 'supported_languages'.
+
+    .. hint::
+
+       For the transition period until the *fetch* functions of all the engines
+       are converted there will be the data_type 'supported_languages', which
+       maps the old logic unchanged 1:1.
+
+       Instances of data_type 'supported_languages' do not implement methods
+       like ``self.get_language(..)`` and ``self.get_region(..)``
+
+    """
+
+    custom: Dict[str, Dict] = dataclasses.field(default_factory=dict)
+    """A place to store engine's custom traits, not related to the SearXNG core
+
+    """
+
+    def get_language(self, searxng_locale: str, default=None):
+        """Return engine's language string that *best fits* to SearXNG's locale.
+
+        :param searxng_locale: SearXNG's internal representation of locale
+          selected by the user.
+
+        :param default: engine's default language
+
+        The *best fits* rules are implemented in
+        :py:obj:`locales.get_engine_locale`.  Except for the special value ``all``
+        which is determined from :py:obj`EngineTraits.all_language`.
+        """
+        if searxng_locale == 'all' and self.all_locale is not None:
+            return self.all_locale
+        return locales.get_engine_locale(searxng_locale, self.languages, default=default)
+
+    def get_region(self, searxng_locale: str, default=None):
+        """Return engine's region string that best fits to SearXNG's locale.
+
+        :param searxng_locale: SearXNG's internal representation of locale
+          selected by the user.
+
+        :param default: engine's default region
+
+        The *best fits* rules are implemented in
+        :py:obj:`locales.get_engine_locale`.  Except for the special value ``all``
+        which is determined from :py:obj`EngineTraits.all_language`.
+        """
+        if searxng_locale == 'all' and self.all_locale is not None:
+            return self.all_locale
+        return locales.get_engine_locale(searxng_locale, self.regions, default=default)
+
+    def is_locale_supported(self, searxng_locale: str) -> bool:
+        """A *locale* (SearXNG's internal representation) is considered to be supported
+        by the engine if the *region* or the *language* is supported by the
+        engine.  For verification the functions :py:func:`self.get_region` and
+        :py:func:`self.get_region` are used.
+        """
+        if self.data_type == 'traits_v1':
+            return bool(self.get_region(searxng_locale) or self.get_language(searxng_locale))
+
+        if self.data_type == 'supported_languages':  # vintage / deprecated
+            # pylint: disable=import-outside-toplevel
+            from searx.utils import match_language
+
+            if searxng_locale == 'all':
+                return True
+            x = match_language(searxng_locale, self.supported_languages, self.language_aliases, None)
+            return bool(x)
+
+            # return bool(self.get_supported_language(searxng_locale))
+        raise TypeError('engine traits of type %s is unknown' % self.data_type)
+
+    def copy(self):
+        """Create a copy of the dataclass object."""
+        return EngineTraits(**dataclasses.asdict(self))
+
+    @classmethod
+    def fetch_traits(cls, engine: Engine) -> Union[Self, None]:
+        """Call a function ``fetch_traits(engine_traits)`` from engines namespace to fetch
+        and set properties from the origin engine in the object ``engine_traits``.  If
+        function does not exists, ``None`` is returned.
+        """
+
+        fetch_traits = getattr(engine, 'fetch_traits', None)
+        engine_traits = None
+
+        if fetch_traits:
+            engine_traits = cls()
+            fetch_traits(engine_traits)
+        return engine_traits
+
+    def set_traits(self, engine: Engine):
+        """Set traits from self object in a :py:obj:`.Engine` namespace.
+
+        :param engine: engine instance build by :py:func:`searx.engines.load_engine`
+        """
+
+        if self.data_type == 'traits_v1':
+            self._set_traits_v1(engine)
+
+        elif self.data_type == 'supported_languages':  # vintage / deprecated
+            self._set_supported_languages(engine)
+
+        else:
+            raise TypeError('engine traits of type %s is unknown' % self.data_type)
+
+    def _set_traits_v1(self, engine: Engine):
+        # For an engine, when there is `language: ...` in the YAML settings the engine
+        # does support only this one language (region)::
+        #
+        #   - name: google italian
+        #     engine: google
+        #     language: it
+        #     region: it-IT
+
+        traits = self.copy()
+
+        _msg = "settings.yml - engine: '%s' / %s: '%s' not supported"
+
+        languages = traits.languages
+        if hasattr(engine, 'language'):
+            if engine.language not in languages:
+                raise ValueError(_msg % (engine.name, 'language', engine.language))
+            traits.languages = {engine.language: languages[engine.language]}
+
+        regions = traits.regions
+        if hasattr(engine, 'region'):
+            if engine.region not in regions:
+                raise ValueError(_msg % (engine.name, 'region', engine.region))
+            traits.regions = {engine.region: regions[engine.region]}
+
+        engine.language_support = bool(traits.languages or traits.regions)
+
+        # set the copied & modified traits in engine's namespace
+        engine.traits = traits
+
+    # -------------------------------------------------------------------------
+    # The code below is deprecated an can hopefully be deleted at one day
+    # -------------------------------------------------------------------------
+
+    supported_languages: Union[List[str], Dict[str, str]] = dataclasses.field(default_factory=dict)
+    """depricated: does not work for engines that do support languages based on a
+    region.  With this type it is not guaranteed that the key values can be
+    parsed by :py:obj:`babel.Locale.parse`!
+    """
+
+    # language_aliases: Dict[str, str] = dataclasses.field(default_factory=dict)
+    # """depricated: does not work for engines that do support languages based on a
+    # region.  With this type it is not guaranteed that the key values can be
+    # parsed by :py:obj:`babel.Locale.parse`!
+    # """
+
+    BABEL_LANGS = [
+        lang_parts[0] + '-' + lang_parts[-1] if len(lang_parts) > 1 else lang_parts[0]
+        for lang_parts in (lang_code.split('_') for lang_code in locale_identifiers())
+    ]
+
+    # def get_supported_language(self, searxng_locale, default=None):  # vintage / deprecated
+    #     """Return engine's language string that *best fits* to SearXNG's locale."""
+    #     if searxng_locale == 'all' and self.all_locale is not None:
+    #         return self.all_locale
+    #     return locales.get_engine_locale(searxng_locale, self.supported_languages, default=default)
+
+    @classmethod  # vintage / deprecated
+    def fetch_supported_languages(cls, engine: Engine) -> Union[Self, None]:
+        """DEPRECATED: Calls a function ``_fetch_supported_languages`` from engine's
+        namespace to fetch languages from the origin engine.  If function does
+        not exists, ``None`` is returned.
+        """
+
+        # pylint: disable=import-outside-toplevel
+        from searx import network
+        from searx.utils import gen_useragent
+
+        fetch_languages = getattr(engine, '_fetch_supported_languages', None)
+        if fetch_languages is None:
+            return None
+
+        # The headers has been moved here from commit 9b6ffed06: Some engines (at
+        # least bing and startpage) return a different result list of supported
+        # languages depending on the IP location where the HTTP request comes from.
+        # The IP based results (from bing) can be avoided by setting a
+        # 'Accept-Language' in the HTTP request.
+
+        headers = {
+            'User-Agent': gen_useragent(),
+            'Accept-Language': "en-US,en;q=0.5",  # bing needs to set the English language
+        }
+        resp = network.get(engine.supported_languages_url, headers=headers)
+        supported_languages = fetch_languages(resp)
+        if isinstance(supported_languages, list):
+            supported_languages.sort()
+
+        engine_traits = cls()
+        engine_traits.data_type = 'supported_languages'
+        engine_traits.supported_languages = supported_languages
+        return engine_traits
+
+    def _set_supported_languages(self, engine: Engine):  # vintage / deprecated
+        traits = self.copy()
+
+        # pylint: disable=import-outside-toplevel
+        from searx.utils import match_language
+
+        _msg = "settings.yml - engine: '%s' / %s: '%s' not supported"
+
+        if hasattr(engine, 'language'):
+            if engine.language not in self.supported_languages:
+                raise ValueError(_msg % (engine.name, 'language', engine.language))
+
+            if isinstance(self.supported_languages, dict):
+                traits.supported_languages = {engine.language: self.supported_languages[engine.language]}
+            else:
+                traits.supported_languages = [engine.language]
+
+        engine.language_support = bool(traits.supported_languages)
+        engine.supported_languages = traits.supported_languages
+
+        # find custom aliases for non standard language codes
+        traits.language_aliases = {}  # pylint: disable=attribute-defined-outside-init
+
+        for engine_lang in getattr(engine, 'language_aliases', {}):
+            iso_lang = match_language(engine_lang, self.BABEL_LANGS, fallback=None)
+            if (
+                iso_lang
+                and iso_lang != engine_lang
+                and not engine_lang.startswith(iso_lang)
+                and iso_lang not in self.supported_languages
+            ):
+                traits.language_aliases[iso_lang] = engine_lang
+
+        engine.language_aliases = traits.language_aliases
+
+        # set the copied & modified traits in engine's namespace
+        engine.traits = traits
+
+
+class EngineTraitsMap(Dict[str, EngineTraits]):
+    """A python dictionary to map :class:`EngineTraits` by engine name."""
+
+    ENGINE_TRAITS_FILE = (data_dir / 'engine_traits.json').resolve()
+    """File with persistence of the :py:obj:`EngineTraitsMap`."""
+
+    def save_data(self):
+        """Store EngineTraitsMap in in file :py:obj:`self.ENGINE_TRAITS_FILE`"""
+        with open(self.ENGINE_TRAITS_FILE, 'w', encoding='utf-8') as f:
+            json.dump(self, f, indent=2, sort_keys=True, cls=EngineTraitsEncoder)
+
+    @classmethod
+    def from_data(cls) -> Self:
+        """Instantiate :class:`EngineTraitsMap` object from :py:obj:`ENGINE_TRAITS`"""
+        obj = cls()
+        for k, v in ENGINE_TRAITS.items():
+            obj[k] = EngineTraits(**v)
+        return obj
+
+    @classmethod
+    def fetch_traits(cls, log: Callable) -> Self:
+        from searx import engines  # pylint: disable=cyclic-import, import-outside-toplevel
+
+        names = list(engines.engines)
+        names.sort()
+        obj = cls()
+
+        for engine_name in names:
+            engine = engines.engines[engine_name]
+
+            traits = EngineTraits.fetch_traits(engine)
+            if traits is not None:
+                log("%-20s: SearXNG languages --> %s " % (engine_name, len(traits.languages)))
+                log("%-20s: SearXNG regions   --> %s" % (engine_name, len(traits.regions)))
+                obj[engine_name] = traits
+
+            # vintage / deprecated
+            _traits = EngineTraits.fetch_supported_languages(engine)
+            if _traits is not None:
+                log("%-20s: %s supported_languages (deprecated)" % (engine_name, len(_traits.supported_languages)))
+                if traits is not None:
+                    traits.supported_languages = _traits.supported_languages
+                    obj[engine_name] = traits
+                else:
+                    obj[engine_name] = _traits
+                continue
+
+        return obj
+
+    def set_traits(self, engine: Engine):
+        """Set traits in a :py:obj:`Engine` namespace.
+
+        :param engine: engine instance build by :py:func:`searx.engines.load_engine`
+        """
+
+        engine_traits = EngineTraits(data_type='traits_v1')
+        if engine.name in self.keys():
+            engine_traits = self[engine.name]
+
+        elif engine.engine in self.keys():
+            # The key of the dictionary traits_map is the *engine name*
+            # configured in settings.xml.  When multiple engines are configured
+            # in settings.yml to use the same origin engine (python module)
+            # these additional engines can use the languages from the origin
+            # engine.  For this use the configured ``engine: ...`` from
+            # settings.yml
+            engine_traits = self[engine.engine]
+
+        engine_traits.set_traits(engine)

+ 17 - 85
searx/engines/__init__.py

@@ -11,24 +11,22 @@ usage::
 
 
 """
 """
 
 
+from __future__ import annotations
+
 import sys
 import sys
 import copy
 import copy
-from typing import Dict, List, Optional
-
 from os.path import realpath, dirname
 from os.path import realpath, dirname
-from babel.localedata import locale_identifiers
+
+from typing import TYPE_CHECKING, Dict, Optional
+
 from searx import logger, settings
 from searx import logger, settings
-from searx.data import ENGINES_LANGUAGES
-from searx.network import get
-from searx.utils import load_module, match_language, gen_useragent
+from searx.utils import load_module
 
 
+if TYPE_CHECKING:
+    from searx.enginelib import Engine
 
 
 logger = logger.getChild('engines')
 logger = logger.getChild('engines')
 ENGINE_DIR = dirname(realpath(__file__))
 ENGINE_DIR = dirname(realpath(__file__))
-BABEL_LANGS = [
-    lang_parts[0] + '-' + lang_parts[-1] if len(lang_parts) > 1 else lang_parts[0]
-    for lang_parts in (lang_code.split('_') for lang_code in locale_identifiers())
-]
 ENGINE_DEFAULT_ARGS = {
 ENGINE_DEFAULT_ARGS = {
     "engine_type": "online",
     "engine_type": "online",
     "inactive": False,
     "inactive": False,
@@ -36,8 +34,6 @@ ENGINE_DEFAULT_ARGS = {
     "timeout": settings["outgoing"]["request_timeout"],
     "timeout": settings["outgoing"]["request_timeout"],
     "shortcut": "-",
     "shortcut": "-",
     "categories": ["general"],
     "categories": ["general"],
-    "supported_languages": [],
-    "language_aliases": {},
     "paging": False,
     "paging": False,
     "safesearch": False,
     "safesearch": False,
     "time_range_support": False,
     "time_range_support": False,
@@ -47,29 +43,13 @@ ENGINE_DEFAULT_ARGS = {
     "send_accept_language_header": False,
     "send_accept_language_header": False,
     "tokens": [],
     "tokens": [],
     "about": {},
     "about": {},
+    "supported_languages": [],  # deprecated use traits
+    "language_aliases": {},  # deprecated not needed when using traits
 }
 }
 # set automatically when an engine does not have any tab category
 # set automatically when an engine does not have any tab category
 OTHER_CATEGORY = 'other'
 OTHER_CATEGORY = 'other'
 
 
 
 
-class Engine:  # pylint: disable=too-few-public-methods
-    """This class is currently never initialized and only used for type hinting."""
-
-    name: str
-    engine: str
-    shortcut: str
-    categories: List[str]
-    supported_languages: List[str]
-    about: dict
-    inactive: bool
-    disabled: bool
-    language_support: bool
-    paging: bool
-    safesearch: bool
-    time_range_support: bool
-    timeout: float
-
-
 # Defaults for the namespace of an engine module, see :py:func:`load_engine`
 # Defaults for the namespace of an engine module, see :py:func:`load_engine`
 
 
 categories = {'general': []}
 categories = {'general': []}
@@ -136,9 +116,15 @@ def load_engine(engine_data: dict) -> Optional[Engine]:
         return None
         return None
 
 
     update_engine_attributes(engine, engine_data)
     update_engine_attributes(engine, engine_data)
-    set_language_attributes(engine)
     update_attributes_for_tor(engine)
     update_attributes_for_tor(engine)
 
 
+    # avoid cyclic imports
+    # pylint: disable=import-outside-toplevel
+    from searx.enginelib.traits import EngineTraitsMap
+
+    trait_map = EngineTraitsMap.from_data()
+    trait_map.set_traits(engine)
+
     if not is_engine_active(engine):
     if not is_engine_active(engine):
         return None
         return None
 
 
@@ -190,60 +176,6 @@ def update_engine_attributes(engine: Engine, engine_data):
             setattr(engine, arg_name, copy.deepcopy(arg_value))
             setattr(engine, arg_name, copy.deepcopy(arg_value))
 
 
 
 
-def set_language_attributes(engine: Engine):
-    # assign supported languages from json file
-    if engine.name in ENGINES_LANGUAGES:
-        engine.supported_languages = ENGINES_LANGUAGES[engine.name]
-
-    elif engine.engine in ENGINES_LANGUAGES:
-        # The key of the dictionary ENGINES_LANGUAGES is the *engine name*
-        # configured in settings.xml.  When multiple engines are configured in
-        # settings.yml to use the same origin engine (python module) these
-        # additional engines can use the languages from the origin engine.
-        # For this use the configured ``engine: ...`` from settings.yml
-        engine.supported_languages = ENGINES_LANGUAGES[engine.engine]
-
-    if hasattr(engine, 'language'):
-        # For an engine, when there is `language: ...` in the YAML settings, the
-        # engine supports only one language, in this case
-        # engine.supported_languages should contains this value defined in
-        # settings.yml
-        if engine.language not in engine.supported_languages:
-            raise ValueError(
-                "settings.yml - engine: '%s' / language: '%s' not supported" % (engine.name, engine.language)
-            )
-
-        if isinstance(engine.supported_languages, dict):
-            engine.supported_languages = {engine.language: engine.supported_languages[engine.language]}
-        else:
-            engine.supported_languages = [engine.language]
-
-    # find custom aliases for non standard language codes
-    for engine_lang in engine.supported_languages:
-        iso_lang = match_language(engine_lang, BABEL_LANGS, fallback=None)
-        if (
-            iso_lang
-            and iso_lang != engine_lang
-            and not engine_lang.startswith(iso_lang)
-            and iso_lang not in engine.supported_languages
-        ):
-            engine.language_aliases[iso_lang] = engine_lang
-
-    # language_support
-    engine.language_support = len(engine.supported_languages) > 0
-
-    # assign language fetching method if auxiliary method exists
-    if hasattr(engine, '_fetch_supported_languages'):
-        headers = {
-            'User-Agent': gen_useragent(),
-            'Accept-Language': "en-US,en;q=0.5",  # bing needs to set the English language
-        }
-        engine.fetch_supported_languages = (
-            # pylint: disable=protected-access
-            lambda: engine._fetch_supported_languages(get(engine.supported_languages_url, headers=headers))
-        )
-
-
 def update_attributes_for_tor(engine: Engine) -> bool:
 def update_attributes_for_tor(engine: Engine) -> bool:
     if using_tor_proxy(engine) and hasattr(engine, 'onion_url'):
     if using_tor_proxy(engine) and hasattr(engine, 'onion_url'):
         engine.search_url = engine.onion_url + getattr(engine, 'search_path', '')
         engine.search_url = engine.onion_url + getattr(engine, 'search_path', '')

+ 1 - 1
searx/engines/demo_offline.py

@@ -63,7 +63,7 @@ def search(query, request_params):
     for row in result_list:
     for row in result_list:
         entry = {
         entry = {
             'query': query,
             'query': query,
-            'language': request_params['language'],
+            'language': request_params['searxng_locale'],
             'value': row.get("value"),
             'value': row.get("value"),
             # choose a result template or comment out to use the *default*
             # choose a result template or comment out to use the *default*
             'template': 'key-value.html',
             'template': 'key-value.html',

+ 71 - 11
searx/locales.py

@@ -8,7 +8,7 @@ from typing import Set
 import os
 import os
 import pathlib
 import pathlib
 
 
-from babel import Locale
+import babel
 from babel.support import Translations
 from babel.support import Translations
 import babel.languages
 import babel.languages
 import babel.core
 import babel.core
@@ -134,7 +134,7 @@ def locales_initialize(directory=None):
     flask_babel.get_translations = get_translations
     flask_babel.get_translations = get_translations
 
 
     for tag, descr in ADDITIONAL_TRANSLATIONS.items():
     for tag, descr in ADDITIONAL_TRANSLATIONS.items():
-        locale = Locale.parse(LOCALE_BEST_MATCH[tag], sep='-')
+        locale = babel.Locale.parse(LOCALE_BEST_MATCH[tag], sep='-')
         LOCALE_NAMES[tag] = descr
         LOCALE_NAMES[tag] = descr
         if locale.text_direction == 'rtl':
         if locale.text_direction == 'rtl':
             RTL_LOCALES.add(tag)
             RTL_LOCALES.add(tag)
@@ -142,7 +142,7 @@ def locales_initialize(directory=None):
     for tag in LOCALE_BEST_MATCH:
     for tag in LOCALE_BEST_MATCH:
         descr = LOCALE_NAMES.get(tag)
         descr = LOCALE_NAMES.get(tag)
         if not descr:
         if not descr:
-            locale = Locale.parse(tag, sep='-')
+            locale = babel.Locale.parse(tag, sep='-')
             LOCALE_NAMES[tag] = get_locale_descr(locale, tag.replace('-', '_'))
             LOCALE_NAMES[tag] = get_locale_descr(locale, tag.replace('-', '_'))
             if locale.text_direction == 'rtl':
             if locale.text_direction == 'rtl':
                 RTL_LOCALES.add(tag)
                 RTL_LOCALES.add(tag)
@@ -154,12 +154,66 @@ def locales_initialize(directory=None):
         tag = dirname.replace('_', '-')
         tag = dirname.replace('_', '-')
         descr = LOCALE_NAMES.get(tag)
         descr = LOCALE_NAMES.get(tag)
         if not descr:
         if not descr:
-            locale = Locale.parse(dirname)
+            locale = babel.Locale.parse(dirname)
             LOCALE_NAMES[tag] = get_locale_descr(locale, dirname)
             LOCALE_NAMES[tag] = get_locale_descr(locale, dirname)
             if locale.text_direction == 'rtl':
             if locale.text_direction == 'rtl':
                 RTL_LOCALES.add(tag)
                 RTL_LOCALES.add(tag)
 
 
 
 
+def region_tag(locale: babel.Locale) -> str:
+    """Returns SearXNG's region tag from the locale (e.g. zh-TW , en-US)."""
+    if not locale.territory:
+        raise ValueError('%s missed a territory')
+    return locale.language + '-' + locale.territory
+
+
+def language_tag(locale: babel.Locale) -> str:
+    """Returns SearXNG's language tag from the locale and if exits, the tag
+    includes the script name (e.g. en, zh_Hant).
+    """
+    sxng_lang = locale.language
+    if locale.script:
+        sxng_lang += '_' + locale.script
+    return sxng_lang
+
+
+def get_offical_locales(
+    territory: str, languages=None, regional: bool = False, de_facto: bool = True
+) -> Set[babel.Locale]:
+    """Returns a list of :py:obj:`babel.Locale` with languages from
+    :py:obj:`babel.languages.get_official_languages`.
+
+    :param territory: The territory (country or region) code.
+
+    :param languages: A list of language codes the languages from
+      :py:obj:`babel.languages.get_official_languages` should be in
+      (intersection).  If this argument is ``None``, all official languages in
+      this territory are used.
+
+    :param regional: If the regional flag is set, then languages which are
+      regionally official are also returned.
+
+    :param de_facto: If the de_facto flag is set to `False`, then languages
+      which are “de facto” official are not returned.
+
+    """
+    ret_val = set()
+    o_languages = babel.languages.get_official_languages(territory, regional=regional, de_facto=de_facto)
+
+    if languages:
+        languages = [l.lower() for l in languages]
+        o_languages = set(l for l in o_languages if l.lower() in languages)
+
+    for lang in o_languages:
+        try:
+            locale = babel.Locale.parse(lang + '_' + territory)
+            ret_val.add(locale)
+        except babel.UnknownLocaleError:
+            continue
+
+    return ret_val
+
+
 def get_engine_locale(searxng_locale, engine_locales, default=None):
 def get_engine_locale(searxng_locale, engine_locales, default=None):
     """Return engine's language (aka locale) string that best fits to argument
     """Return engine's language (aka locale) string that best fits to argument
     ``searxng_locale``.
     ``searxng_locale``.
@@ -177,6 +231,10 @@ def get_engine_locale(searxng_locale, engine_locales, default=None):
           ...
           ...
           'pl-PL'          : 'pl_PL',
           'pl-PL'          : 'pl_PL',
           'pt-PT'          : 'pt_PT'
           'pt-PT'          : 'pt_PT'
+          ..
+          'zh'             : 'zh'
+          'zh_Hans'        : 'zh'
+          'zh_Hant'        : 'zh-classical'
       }
       }
 
 
     .. hint::
     .. hint::
@@ -210,13 +268,13 @@ def get_engine_locale(searxng_locale, engine_locales, default=None):
       engine.
       engine.
 
 
     """
     """
-    # pylint: disable=too-many-branches
+    # pylint: disable=too-many-branches, too-many-return-statements
 
 
     engine_locale = engine_locales.get(searxng_locale)
     engine_locale = engine_locales.get(searxng_locale)
 
 
     if engine_locale is not None:
     if engine_locale is not None:
-        # There was a 1:1 mapping (e.g. "fr-BE --> fr_BE" or "fr --> fr_FR"), no
-        # need to narrow language nor territory.
+        # There was a 1:1 mapping (e.g. a region "fr-BE --> fr_BE" or a language
+        # "zh --> zh"), no need to narrow language-script nor territory.
         return engine_locale
         return engine_locale
 
 
     try:
     try:
@@ -227,6 +285,12 @@ def get_engine_locale(searxng_locale, engine_locales, default=None):
         except babel.core.UnknownLocaleError:
         except babel.core.UnknownLocaleError:
             return default
             return default
 
 
+    searxng_lang = language_tag(locale)
+    engine_locale = engine_locales.get(searxng_lang)
+    if engine_locale is not None:
+        # There was a 1:1 mapping (e.g. "zh-HK --> zh_Hant" or "zh-CN --> zh_Hans")
+        return engine_locale
+
     # SearXNG's selected locale is not supported by the engine ..
     # SearXNG's selected locale is not supported by the engine ..
 
 
     if locale.territory:
     if locale.territory:
@@ -247,10 +311,6 @@ def get_engine_locale(searxng_locale, engine_locales, default=None):
 
 
     if locale.language:
     if locale.language:
 
 
-        searxng_lang = locale.language
-        if locale.script:
-            searxng_lang += '_' + locale.script
-
         terr_lang_dict = {}
         terr_lang_dict = {}
         for territory, langs in babel.core.get_global("territory_languages").items():
         for territory, langs in babel.core.get_global("territory_languages").items():
             if not langs.get(searxng_lang, {}).get('official_status'):
             if not langs.get(searxng_lang, {}).get('official_status'):

+ 1 - 1
searx/preferences.py

@@ -13,7 +13,7 @@ from typing import Iterable, Dict, List
 import flask
 import flask
 
 
 from searx import settings, autocomplete
 from searx import settings, autocomplete
-from searx.engines import Engine
+from searx.enginelib import Engine
 from searx.plugins import Plugin
 from searx.plugins import Plugin
 from searx.locales import LOCALE_NAMES
 from searx.locales import LOCALE_NAMES
 from searx.webutils import VALID_LANGUAGE_CODE
 from searx.webutils import VALID_LANGUAGE_CODE

+ 4 - 1
searx/search/processors/__init__.py

@@ -30,7 +30,10 @@ from .abstract import EngineProcessor
 
 
 logger = logger.getChild('search.processors')
 logger = logger.getChild('search.processors')
 PROCESSORS: Dict[str, EngineProcessor] = {}
 PROCESSORS: Dict[str, EngineProcessor] = {}
-"""Cache request processores, stored by *engine-name* (:py:func:`initialize`)"""
+"""Cache request processores, stored by *engine-name* (:py:func:`initialize`)
+
+:meta hide-value:
+"""
 
 
 
 
 def get_processor_class(engine_type):
 def get_processor_class(engine_type):

+ 11 - 1
searx/search/processors/abstract.py

@@ -138,7 +138,8 @@ class EngineProcessor(ABC):
         return False
         return False
 
 
     def get_params(self, search_query, engine_category):
     def get_params(self, search_query, engine_category):
-        """Returns a set of *request params* or ``None`` if request is not supported.
+        """Returns a set of (see :ref:`request params <engine request arguments>`) or
+        ``None`` if request is not supported.
 
 
         Not supported conditions (``None`` is returned):
         Not supported conditions (``None`` is returned):
 
 
@@ -159,11 +160,20 @@ class EngineProcessor(ABC):
         params['safesearch'] = search_query.safesearch
         params['safesearch'] = search_query.safesearch
         params['time_range'] = search_query.time_range
         params['time_range'] = search_query.time_range
         params['engine_data'] = search_query.engine_data.get(self.engine_name, {})
         params['engine_data'] = search_query.engine_data.get(self.engine_name, {})
+        params['searxng_locale'] = search_query.lang
+
+        # deprecated / vintage --> use params['searxng_locale']
+        #
+        # Conditions related to engine's traits are implemented in engine.traits
+        # module. Don't do 'locale' decissions here in the abstract layer of the
+        # search processor, just pass the value from user's choice unchanged to
+        # the engine request.
 
 
         if hasattr(self.engine, 'language') and self.engine.language:
         if hasattr(self.engine, 'language') and self.engine.language:
             params['language'] = self.engine.language
             params['language'] = self.engine.language
         else:
         else:
             params['language'] = search_query.lang
             params['language'] = search_query.lang
+
         return params
         return params
 
 
     @abstractmethod
     @abstractmethod

+ 3 - 0
searx/search/processors/online.py

@@ -51,6 +51,9 @@ class OnlineProcessor(EngineProcessor):
         super().initialize()
         super().initialize()
 
 
     def get_params(self, search_query, engine_category):
     def get_params(self, search_query, engine_category):
+        """Returns a set of :ref:`request params <engine request online>` or ``None``
+        if request is not supported.
+        """
         params = super().get_params(search_query, engine_category)
         params = super().get_params(search_query, engine_category)
         if params is None:
         if params is None:
             return None
             return None

+ 2 - 2
searx/search/processors/online_currency.py

@@ -38,8 +38,8 @@ class OnlineCurrencyProcessor(OnlineProcessor):
     engine_type = 'online_currency'
     engine_type = 'online_currency'
 
 
     def get_params(self, search_query, engine_category):
     def get_params(self, search_query, engine_category):
-        """Returns a set of *request params* or ``None`` if search query does not match
-        to :py:obj:`parser_re`."""
+        """Returns a set of :ref:`request params <engine request online_currency>`
+        or ``None`` if search query does not match to :py:obj:`parser_re`."""
 
 
         params = super().get_params(search_query, engine_category)
         params = super().get_params(search_query, engine_category)
         if params is None:
         if params is None:

+ 3 - 2
searx/search/processors/online_dictionary.py

@@ -18,8 +18,9 @@ class OnlineDictionaryProcessor(OnlineProcessor):
     engine_type = 'online_dictionary'
     engine_type = 'online_dictionary'
 
 
     def get_params(self, search_query, engine_category):
     def get_params(self, search_query, engine_category):
-        """Returns a set of *request params* or ``None`` if search query does not match
-        to :py:obj:`parser_re`."""
+        """Returns a set of :ref:`request params <engine request online_dictionary>` or
+        ``None`` if search query does not match to :py:obj:`parser_re`.
+        """
         params = super().get_params(search_query, engine_category)
         params = super().get_params(search_query, engine_category)
         if params is None:
         if params is None:
             return None
             return None

+ 3 - 2
searx/search/processors/online_url_search.py

@@ -20,9 +20,10 @@ class OnlineUrlSearchProcessor(OnlineProcessor):
     engine_type = 'online_url_search'
     engine_type = 'online_url_search'
 
 
     def get_params(self, search_query, engine_category):
     def get_params(self, search_query, engine_category):
-        """Returns a set of *request params* or ``None`` if search query does not match
-        to at least one of :py:obj:`re_search_urls`.
+        """Returns a set of :ref:`request params <engine request online>` or ``None`` if
+        search query does not match to :py:obj:`re_search_urls`.
         """
         """
+
         params = super().get_params(search_query, engine_category)
         params = super().get_params(search_query, engine_category)
         if params is None:
         if params is None:
             return None
             return None

+ 17 - 25
searx/webapp.py

@@ -907,16 +907,11 @@ def autocompleter():
     # and there is a query part
     # and there is a query part
     if len(raw_text_query.autocomplete_list) == 0 and len(sug_prefix) > 0:
     if len(raw_text_query.autocomplete_list) == 0 and len(sug_prefix) > 0:
 
 
-        # get language from cookie
-        language = request.preferences.get_value('language')
-        if not language or language == 'all':
-            language = 'en'
-        else:
-            language = language.split('-')[0]
+        # get SearXNG's locale and autocomplete backend from cookie
+        sxng_locale = request.preferences.get_value('language')
+        backend_name = request.preferences.get_value('autocomplete')
 
 
-        # run autocompletion
-        raw_results = search_autocomplete(request.preferences.get_value('autocomplete'), sug_prefix, language)
-        for result in raw_results:
+        for result in search_autocomplete(backend_name, sug_prefix, sxng_locale):
             # attention: this loop will change raw_text_query object and this is
             # attention: this loop will change raw_text_query object and this is
             # the reason why the sug_prefix was stored before (see above)
             # the reason why the sug_prefix was stored before (see above)
             if result != sug_prefix:
             if result != sug_prefix:
@@ -1001,7 +996,9 @@ def preferences():
             'rate80': rate80,
             'rate80': rate80,
             'rate95': rate95,
             'rate95': rate95,
             'warn_timeout': e.timeout > settings['outgoing']['request_timeout'],
             'warn_timeout': e.timeout > settings['outgoing']['request_timeout'],
-            'supports_selected_language': _is_selected_language_supported(e, request.preferences),
+            'supports_selected_language': e.traits.is_locale_supported(
+                str(request.preferences.get_value('language') or 'all')
+            ),
             'result_count': result_count,
             'result_count': result_count,
         }
         }
     # end of stats
     # end of stats
@@ -1052,7 +1049,9 @@ def preferences():
     # supports
     # supports
     supports = {}
     supports = {}
     for _, e in filtered_engines.items():
     for _, e in filtered_engines.items():
-        supports_selected_language = _is_selected_language_supported(e, request.preferences)
+        supports_selected_language = e.traits.is_locale_supported(
+            str(request.preferences.get_value('language') or 'all')
+        )
         safesearch = e.safesearch
         safesearch = e.safesearch
         time_range_support = e.time_range_support
         time_range_support = e.time_range_support
         for checker_test_name in checker_results.get(e.name, {}).get('errors', {}):
         for checker_test_name in checker_results.get(e.name, {}).get('errors', {}):
@@ -1099,16 +1098,6 @@ def preferences():
     )
     )
 
 
 
 
-def _is_selected_language_supported(engine, preferences: Preferences):  # pylint: disable=redefined-outer-name
-    language = preferences.get_value('language')
-    if language == 'all':
-        return True
-    x = match_language(
-        language, getattr(engine, 'supported_languages', []), getattr(engine, 'language_aliases', {}), None
-    )
-    return bool(x)
-
-
 @app.route('/image_proxy', methods=['GET'])
 @app.route('/image_proxy', methods=['GET'])
 def image_proxy():
 def image_proxy():
     # pylint: disable=too-many-return-statements, too-many-branches
     # pylint: disable=too-many-return-statements, too-many-branches
@@ -1327,9 +1316,11 @@ def config():
         if not request.preferences.validate_token(engine):
         if not request.preferences.validate_token(engine):
             continue
             continue
 
 
-        supported_languages = engine.supported_languages
-        if isinstance(engine.supported_languages, dict):
-            supported_languages = list(engine.supported_languages.keys())
+        _languages = engine.traits.languages.keys()
+        if engine.traits.data_type == 'supported_languages':  # vintage / deprecated
+            _languages = engine.traits.supported_languages
+            if isinstance(_languages, dict):
+                _languages = _languages.keys()
 
 
         _engines.append(
         _engines.append(
             {
             {
@@ -1339,7 +1330,8 @@ def config():
                 'enabled': not engine.disabled,
                 'enabled': not engine.disabled,
                 'paging': engine.paging,
                 'paging': engine.paging,
                 'language_support': engine.language_support,
                 'language_support': engine.language_support,
-                'supported_languages': supported_languages,
+                'languages': list(_languages),
+                'regions': list(engine.traits.regions.keys()),
                 'safesearch': engine.safesearch,
                 'safesearch': engine.safesearch,
                 'time_range_support': engine.time_range_support,
                 'time_range_support': engine.time_range_support,
                 'timeout': engine.timeout,
                 'timeout': engine.timeout,

+ 7 - 2
searx/webutils.py

@@ -1,4 +1,6 @@
 # -*- coding: utf-8 -*-
 # -*- coding: utf-8 -*-
+from __future__ import annotations
+
 import os
 import os
 import pathlib
 import pathlib
 import csv
 import csv
@@ -8,7 +10,7 @@ import re
 import inspect
 import inspect
 import itertools
 import itertools
 from datetime import datetime, timedelta
 from datetime import datetime, timedelta
-from typing import Iterable, List, Tuple, Dict
+from typing import Iterable, List, Tuple, Dict, TYPE_CHECKING
 
 
 from io import StringIO
 from io import StringIO
 from codecs import getincrementalencoder
 from codecs import getincrementalencoder
@@ -16,7 +18,10 @@ from codecs import getincrementalencoder
 from flask_babel import gettext, format_date
 from flask_babel import gettext, format_date
 
 
 from searx import logger, settings
 from searx import logger, settings
-from searx.engines import Engine, OTHER_CATEGORY
+from searx.engines import OTHER_CATEGORY
+
+if TYPE_CHECKING:
+    from searx.enginelib import Engine
 
 
 
 
 VALID_LANGUAGE_CODE = re.compile(r'^[a-z]{2,3}(-[a-zA-Z]{2})?$')
 VALID_LANGUAGE_CODE = re.compile(r'^[a-z]{2,3}(-[a-zA-Z]{2})?$')

+ 75 - 52
searxng_extra/update/update_languages.py → searxng_extra/update/update_engine_traits.py

@@ -1,19 +1,21 @@
 #!/usr/bin/env python
 #!/usr/bin/env python
 # lint: pylint
 # lint: pylint
-
 # SPDX-License-Identifier: AGPL-3.0-or-later
 # SPDX-License-Identifier: AGPL-3.0-or-later
-"""This script generates languages.py from intersecting each engine's supported
-languages.
+"""Update :py:obj:`searx.enginelib.traits.EngineTraitsMap` and :origin:`searx/languages.py`
+
+:py:obj:`searx.enginelib.traits.EngineTraitsMap.ENGINE_TRAITS_FILE`:
+  Persistence of engines traits, fetched from the engines.
 
 
-Output files: :origin:`searx/data/engines_languages.json` and
-:origin:`searx/languages.py` (:origin:`CI Update data ...
-<.github/workflows/data-update.yml>`).
+:origin:`searx/languages.py`
+  Is generated  from intersecting each engine's supported traits.
+
+The script :origin:`searxng_extra/update/update_engine_traits.py` is called in
+the :origin:`CI Update data ... <.github/workflows/data-update.yml>`
 
 
 """
 """
 
 
 # pylint: disable=invalid-name
 # pylint: disable=invalid-name
 from unicodedata import lookup
 from unicodedata import lookup
-import json
 from pathlib import Path
 from pathlib import Path
 from pprint import pformat
 from pprint import pformat
 from babel import Locale, UnknownLocaleError
 from babel import Locale, UnknownLocaleError
@@ -21,36 +23,26 @@ from babel.languages import get_global
 from babel.core import parse_locale
 from babel.core import parse_locale
 
 
 from searx import settings, searx_dir
 from searx import settings, searx_dir
+from searx import network
 from searx.engines import load_engines, engines
 from searx.engines import load_engines, engines
-from searx.network import set_timeout_for_thread
+from searx.enginelib.traits import EngineTraitsMap
 
 
 # Output files.
 # Output files.
-engines_languages_file = Path(searx_dir) / 'data' / 'engines_languages.json'
 languages_file = Path(searx_dir) / 'languages.py'
 languages_file = Path(searx_dir) / 'languages.py'
 
 
 
 
-# Fetches supported languages for each engine and writes json file with those.
-def fetch_supported_languages():
-    set_timeout_for_thread(10.0)
-
-    engines_languages = {}
-    names = list(engines)
-    names.sort()
+def fetch_traits_map():
+    """Fetchs supported languages for each engine and writes json file with those."""
+    network.set_timeout_for_thread(10.0)
 
 
-    for engine_name in names:
-        if hasattr(engines[engine_name], 'fetch_supported_languages'):
-            engines_languages[engine_name] = engines[engine_name].fetch_supported_languages()
-            print("fetched %s languages from engine %s" % (len(engines_languages[engine_name]), engine_name))
-            if type(engines_languages[engine_name]) == list:  # pylint: disable=unidiomatic-typecheck
-                engines_languages[engine_name] = sorted(engines_languages[engine_name])
+    def log(msg):
+        print(msg)
 
 
-    print("fetched languages from %s engines" % len(engines_languages))
-
-    # write json file
-    with open(engines_languages_file, 'w', encoding='utf-8') as f:
-        json.dump(engines_languages, f, indent=2, sort_keys=True)
-
-    return engines_languages
+    traits_map = EngineTraitsMap.fetch_traits(log=log)
+    print("fetched properties from %s engines" % len(traits_map))
+    print("write json file: %s" % traits_map.ENGINE_TRAITS_FILE)
+    traits_map.save_data()
+    return traits_map
 
 
 
 
 # Get babel Locale object from lang_code if possible.
 # Get babel Locale object from lang_code if possible.
@@ -124,17 +116,43 @@ def get_territory_name(lang_code):
     return country_name
     return country_name
 
 
 
 
-# Join all language lists.
-def join_language_lists(engines_languages):
+def join_language_lists(traits_map: EngineTraitsMap):
+    """Join all languages of the engines into one list.  The returned language list
+    contains language codes (``zh``) and region codes (``zh-TW``).  The codes can
+    be parsed by babel::
+
+      babel.Locale.parse(language_list[n])
+    """
+    # pylint: disable=too-many-branches
     language_list = {}
     language_list = {}
-    for engine_name in engines_languages:
-        for lang_code in engines_languages[engine_name]:
 
 
-            # apply custom fixes if necessary
-            if lang_code in getattr(engines[engine_name], 'language_aliases', {}).values():
-                lang_code = next(
-                    lc for lc, alias in engines[engine_name].language_aliases.items() if lang_code == alias
-                )
+    for eng_name, eng_traits in traits_map.items():
+        eng = engines[eng_name]
+        eng_codes = set()
+
+        if eng_traits.data_type == 'traits_v1':
+            # items of type 'engine_traits' do have regions & languages, the
+            # list of eng_codes should contain both.
+            eng_codes.update(eng_traits.regions.keys())
+            eng_codes.update(eng_traits.languages.keys())
+
+        elif eng_traits.data_type == 'supported_languages':
+            # vintage / deprecated
+            _codes = set()
+            if isinstance(eng_traits.supported_languages, dict):
+                _codes.update(eng_traits.supported_languages.keys())
+            elif isinstance(eng_traits.supported_languages, list):
+                _codes.update(eng_traits.supported_languages)
+            else:
+                raise TypeError('engine.supported_languages type %s is unknown' % type(eng_traits.supported_languages))
+
+            for lang_code in _codes:
+                # apply custom fixes if necessary
+                if lang_code in getattr(eng, 'language_aliases', {}).values():
+                    lang_code = next(lc for lc, alias in eng.language_aliases.items() if lang_code == alias)
+                eng_codes.add(lang_code)
+
+        for lang_code in eng_codes:
 
 
             locale = get_locale(lang_code)
             locale = get_locale(lang_code)
 
 
@@ -149,10 +167,10 @@ def join_language_lists(engines_languages):
                     # get language's data from babel's Locale object
                     # get language's data from babel's Locale object
                     language_name = locale.get_language_name().title()
                     language_name = locale.get_language_name().title()
                     english_name = locale.english_name.split(' (')[0]
                     english_name = locale.english_name.split(' (')[0]
-                elif short_code in engines_languages['wikipedia']:
+                elif short_code in traits_map['wikipedia'].supported_languages:
                     # get language's data from wikipedia if not known by babel
                     # get language's data from wikipedia if not known by babel
-                    language_name = engines_languages['wikipedia'][short_code]['name']
-                    english_name = engines_languages['wikipedia'][short_code]['english_name']
+                    language_name = traits_map['wikipedia'].supported_languages[short_code]['name']
+                    english_name = traits_map['wikipedia'].supported_languages[short_code]['english_name']
                 else:
                 else:
                     language_name = None
                     language_name = None
                     english_name = None
                     english_name = None
@@ -182,15 +200,15 @@ def join_language_lists(engines_languages):
                 }
                 }
 
 
             # count engine for both language_country combination and language alone
             # count engine for both language_country combination and language alone
-            language_list[short_code]['counter'].add(engine_name)
+            language_list[short_code]['counter'].add(eng_name)
             if lang_code != short_code:
             if lang_code != short_code:
-                language_list[short_code]['countries'][lang_code]['counter'].add(engine_name)
+                language_list[short_code]['countries'][lang_code]['counter'].add(eng_name)
 
 
     return language_list
     return language_list
 
 
 
 
 # Filter language list so it only includes the most supported languages and countries
 # Filter language list so it only includes the most supported languages and countries
-def filter_language_list(all_languages):
+def filter_language_list(joined_languages_map):
     min_engines_per_lang = 12
     min_engines_per_lang = 12
     min_engines_per_country = 7
     min_engines_per_country = 7
     # pylint: disable=consider-using-dict-items, consider-iterating-dictionary
     # pylint: disable=consider-using-dict-items, consider-iterating-dictionary
@@ -198,6 +216,7 @@ def filter_language_list(all_languages):
         engine_name
         engine_name
         for engine_name in engines.keys()
         for engine_name in engines.keys()
         if 'general' in engines[engine_name].categories
         if 'general' in engines[engine_name].categories
+        and hasattr(engines[engine_name], 'supported_languages')
         and engines[engine_name].supported_languages
         and engines[engine_name].supported_languages
         and not engines[engine_name].disabled
         and not engines[engine_name].disabled
     ]
     ]
@@ -205,7 +224,7 @@ def filter_language_list(all_languages):
     # filter list to include only languages supported by most engines or all default general engines
     # filter list to include only languages supported by most engines or all default general engines
     filtered_languages = {
     filtered_languages = {
         code: lang
         code: lang
-        for code, lang in all_languages.items()
+        for code, lang in joined_languages_map.items()
         if (
         if (
             len(lang['counter']) >= min_engines_per_lang
             len(lang['counter']) >= min_engines_per_lang
             or all(main_engine in lang['counter'] for main_engine in main_engines)
             or all(main_engine in lang['counter'] for main_engine in main_engines)
@@ -214,8 +233,8 @@ def filter_language_list(all_languages):
 
 
     def _copy_lang_data(lang, country_name=None):
     def _copy_lang_data(lang, country_name=None):
         new_dict = {}
         new_dict = {}
-        new_dict['name'] = all_languages[lang]['name']
-        new_dict['english_name'] = all_languages[lang]['english_name']
+        new_dict['name'] = joined_languages_map[lang]['name']
+        new_dict['english_name'] = joined_languages_map[lang]['english_name']
         if country_name:
         if country_name:
             new_dict['country_name'] = country_name
             new_dict['country_name'] = country_name
         return new_dict
         return new_dict
@@ -305,9 +324,13 @@ def write_languages_file(languages):
         new_file.close()
         new_file.close()
 
 
 
 
-if __name__ == "__main__":
+def main():
     load_engines(settings['engines'])
     load_engines(settings['engines'])
-    _engines_languages = fetch_supported_languages()
-    _all_languages = join_language_lists(_engines_languages)
-    _filtered_languages = filter_language_list(_all_languages)
-    write_languages_file(_filtered_languages)
+    traits_map = fetch_traits_map()
+    joined_languages_map = join_language_lists(traits_map)
+    filtered_languages = filter_language_list(joined_languages_map)
+    write_languages_file(filtered_languages)
+
+
+if __name__ == "__main__":
+    main()