mirror of
https://github.com/searxng/searxng.git
synced 2025-07-12 15:59:21 +02:00
[mod] replace utils.match_language by locales.match_locale
This patch replaces the *full of magic* ``utils.match_language`` function by a ``locales.match_locale``. The ``locales.match_locale`` function is based on the ``locales.build_engine_locales`` introduced in9ae409a0
[1]. In the past SearXNG did only support a search by a language but not in a region. This has been changed a long time ago and regions have been added to SearXNG core but not to the engines. The ``utils.match_language`` was the function to handle the different aspects of language/regions in SearXNG core and the supported *languages* in the engine. The ``utils.match_language`` did it with some magic and works good for most use cases but fails in some edge case. To replace the concurrence of languages and regions in the SearXNG core the ``locales.build_engine_locales`` was introduced in9ae409a0
[1]. With the last patches all engines has been migrated to a ``fetch_traits`` and a language/region concept that is based on ``locales.build_engine_locales``. To summarize: there is no longer a need for the ``locales.match_language``. [1] https://github.com/searxng/searxng/pull/1652 Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>
This commit is contained in:
parent
4d4aa13e1f
commit
16f0db4493
6 changed files with 240 additions and 138 deletions
108
searx/locales.py
108
searx/locales.py
|
@ -4,7 +4,7 @@
|
|||
"""Initialize :py:obj:`LOCALE_NAMES`, :py:obj:`RTL_LOCALES`.
|
||||
"""
|
||||
|
||||
from typing import Set
|
||||
from typing import Set, Optional, List
|
||||
import os
|
||||
import pathlib
|
||||
|
||||
|
@ -177,6 +177,17 @@ def language_tag(locale: babel.Locale) -> str:
|
|||
return sxng_lang
|
||||
|
||||
|
||||
def get_locale(locale_tag: str) -> Optional[babel.Locale]:
|
||||
"""Returns a :py:obj:`babel.Locale` object parsed from argument
|
||||
``locale_tag``"""
|
||||
try:
|
||||
locale = babel.Locale.parse(locale_tag, sep='-')
|
||||
return locale
|
||||
|
||||
except babel.core.UnknownLocaleError:
|
||||
return None
|
||||
|
||||
|
||||
def get_offical_locales(
|
||||
territory: str, languages=None, regional: bool = False, de_facto: bool = True
|
||||
) -> Set[babel.Locale]:
|
||||
|
@ -363,3 +374,98 @@ def get_engine_locale(searxng_locale, engine_locales, default=None):
|
|||
engine_locale = default
|
||||
|
||||
return default
|
||||
|
||||
|
||||
def match_locale(searxng_locale: str, locale_tag_list: List[str], fallback: Optional[str] = None) -> Optional[str]:
|
||||
"""Return tag from ``locale_tag_list`` that best fits to ``searxng_locale``.
|
||||
|
||||
:param str searxng_locale: SearXNG's internal representation of locale (de,
|
||||
de-DE, fr-BE, zh, zh-CN, zh-TW ..).
|
||||
|
||||
:param list locale_tag_list: The list of locale tags to select from
|
||||
|
||||
:param str fallback: fallback locale tag (if unset --> ``None``)
|
||||
|
||||
The rules to find a match are implemented in :py:obj:`get_engine_locale`,
|
||||
the ``engine_locales`` is build up by :py:obj:`build_engine_locales`.
|
||||
|
||||
.. hint::
|
||||
|
||||
The *SearXNG locale* string and the members of ``locale_tag_list`` has to
|
||||
be known by babel! The :py:obj:`ADDITIONAL_TRANSLATIONS` are used in the
|
||||
UI and are not known by babel --> will be ignored.
|
||||
"""
|
||||
|
||||
# searxng_locale = 'es'
|
||||
# locale_tag_list = ['es-AR', 'es-ES', 'es-MX']
|
||||
|
||||
if not searxng_locale:
|
||||
return fallback
|
||||
|
||||
locale = get_locale(searxng_locale)
|
||||
if locale is None:
|
||||
return fallback
|
||||
|
||||
# normalize to a SearXNG locale that can be passed to get_engine_locale
|
||||
|
||||
searxng_locale = language_tag(locale)
|
||||
if locale.territory:
|
||||
searxng_locale = region_tag(locale)
|
||||
|
||||
# clean up locale_tag_list
|
||||
|
||||
tag_list = []
|
||||
for tag in locale_tag_list:
|
||||
if tag in ('all', 'auto') or tag in ADDITIONAL_TRANSLATIONS:
|
||||
continue
|
||||
tag_list.append(tag)
|
||||
|
||||
# emulate fetch_traits
|
||||
engine_locales = build_engine_locales(tag_list)
|
||||
return get_engine_locale(searxng_locale, engine_locales, default=fallback)
|
||||
|
||||
|
||||
def build_engine_locales(tag_list: List[str]):
|
||||
"""From a list of locale tags a dictionary is build that can be passed by
|
||||
argument ``engine_locales`` to :py:obj:`get_engine_locale`. This function
|
||||
is mainly used by :py:obj:`match_locale` and is similar to what the
|
||||
``fetch_traits(..)`` function of engines do.
|
||||
|
||||
If there are territory codes in the ``tag_list`` that have a *script code*
|
||||
additional keys are added to the returned dictionary.
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> import locales
|
||||
>>> engine_locales = locales.build_engine_locales(['en', 'en-US', 'zh', 'zh-CN', 'zh-TW'])
|
||||
>>> engine_locales
|
||||
{
|
||||
'en': 'en', 'en-US': 'en-US',
|
||||
'zh': 'zh', 'zh-CN': 'zh-CN', 'zh_Hans': 'zh-CN',
|
||||
'zh-TW': 'zh-TW', 'zh_Hant': 'zh-TW'
|
||||
}
|
||||
>>> get_engine_locale('zh-Hans', engine_locales)
|
||||
'zh-CN'
|
||||
|
||||
This function is a good example to understand the language/region model
|
||||
of SearXNG:
|
||||
|
||||
SearXNG only distinguishes between **search languages** and **search
|
||||
regions**, by adding the *script-tags*, languages with *script-tags* can
|
||||
be assigned to the **regions** that SearXNG supports.
|
||||
|
||||
"""
|
||||
engine_locales = {}
|
||||
|
||||
for tag in tag_list:
|
||||
locale = get_locale(tag)
|
||||
if locale is None:
|
||||
logger.warn("build_engine_locales: skip locale tag %s / unknown by babel", tag)
|
||||
continue
|
||||
if locale.territory:
|
||||
engine_locales[region_tag(locale)] = tag
|
||||
if locale.script:
|
||||
engine_locales[language_tag(locale)] = tag
|
||||
else:
|
||||
engine_locales[language_tag(locale)] = tag
|
||||
return engine_locales
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue