mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-02-26 11:08:13 +00:00
Locales and localization refactor with Locales as a localizer object.
Removed auto-localization from search/search_address APIs (now explicit), simplified AddressLines to subclass List[AddressLine], made display_name a computed property in Results instead of field and removed result-localization circular dependencies
This commit is contained in:
@@ -11,7 +11,10 @@ Data classes are part of the public API while the functions are for
|
||||
internal use only. That's why they are implemented as free-standing functions
|
||||
instead of member functions.
|
||||
"""
|
||||
from typing import Optional, Tuple, Dict, Sequence, TypeVar, Type, List, cast, Callable
|
||||
from typing import (
|
||||
Optional, Tuple, Dict, Sequence, TypeVar, Type, List,
|
||||
cast, Callable
|
||||
)
|
||||
import enum
|
||||
import dataclasses
|
||||
import datetime as dt
|
||||
@@ -23,7 +26,6 @@ from .sql.sqlalchemy_types import Geometry
|
||||
from .types import Point, Bbox, LookupDetails
|
||||
from .connection import SearchConnection
|
||||
from .logging import log
|
||||
from .localization import Locales
|
||||
|
||||
# This file defines complex result data classes.
|
||||
|
||||
@@ -130,27 +132,21 @@ class AddressLine:
|
||||
[Localization](Result-Handling.md#localization) below.
|
||||
"""
|
||||
|
||||
@property
|
||||
def display_name(self) -> Optional[str]:
|
||||
""" Dynamically compute the display name for the Address Line component
|
||||
"""
|
||||
if self.local_name:
|
||||
return self.local_name
|
||||
elif 'name' in self.names:
|
||||
return self.names['name']
|
||||
elif self.names:
|
||||
return next(iter(self.names.values()), None)
|
||||
return None
|
||||
|
||||
|
||||
class AddressLines(List[AddressLine]):
|
||||
""" Sequence of address lines order in descending order by their rank.
|
||||
"""
|
||||
|
||||
def localize(self, locales: Locales) -> List[str]:
|
||||
""" Set the local name of address parts according to the chosen
|
||||
locale. Return the list of local names without duplicates.
|
||||
|
||||
Only address parts that are marked as isaddress are localized
|
||||
and returned.
|
||||
"""
|
||||
label_parts: List[str] = []
|
||||
|
||||
for line in self:
|
||||
if line.isaddress and line.names:
|
||||
line.local_name = locales.display_name(line.names)
|
||||
if not label_parts or label_parts[-1] != line.local_name:
|
||||
label_parts.append(line.local_name)
|
||||
|
||||
return label_parts
|
||||
""" A wrapper around a list of AddressLine objects."""
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
@@ -189,7 +185,6 @@ class BaseResult:
|
||||
admin_level: int = 15
|
||||
|
||||
locale_name: Optional[str] = None
|
||||
display_name: Optional[str] = None
|
||||
|
||||
names: Optional[Dict[str, str]] = None
|
||||
address: Optional[Dict[str, str]] = None
|
||||
@@ -225,6 +220,35 @@ class BaseResult:
|
||||
"""
|
||||
return self.centroid[0]
|
||||
|
||||
@property
|
||||
def display_name(self) -> Optional[str]:
|
||||
""" Dynamically compute the display name for the result place
|
||||
and, if available, its address information..
|
||||
"""
|
||||
if self.address_rows: # if this is true we need additional processing
|
||||
label_parts: List[str] = []
|
||||
|
||||
for line in self.address_rows: # assume locale_name is set by external formatter
|
||||
if line.isaddress and line.names:
|
||||
address_name = line.display_name
|
||||
|
||||
if address_name and (not label_parts or label_parts[-1] != address_name):
|
||||
label_parts.append(address_name)
|
||||
|
||||
if label_parts:
|
||||
return ', '.join(label_parts)
|
||||
|
||||
# Now adding additional information for reranking
|
||||
if self.locale_name:
|
||||
return self.locale_name
|
||||
elif self.names and 'name' in self.names:
|
||||
return self.names['name']
|
||||
elif self.names:
|
||||
return next(iter(self.names.values()))
|
||||
elif self.housenumber:
|
||||
return self.housenumber
|
||||
return None
|
||||
|
||||
def calculated_importance(self) -> float:
|
||||
""" Get a valid importance value. This is either the stored importance
|
||||
of the value or an artificial value computed from the place's
|
||||
@@ -232,16 +256,6 @@ class BaseResult:
|
||||
"""
|
||||
return self.importance or (0.40001 - (self.rank_search/75.0))
|
||||
|
||||
def localize(self, locales: Locales) -> None:
|
||||
""" Fill the locale_name and the display_name field for the
|
||||
place and, if available, its address information.
|
||||
"""
|
||||
self.locale_name = locales.display_name(self.names)
|
||||
if self.address_rows:
|
||||
self.display_name = ', '.join(self.address_rows.localize(locales))
|
||||
else:
|
||||
self.display_name = self.locale_name
|
||||
|
||||
|
||||
BaseResultT = TypeVar('BaseResultT', bound=BaseResult)
|
||||
|
||||
@@ -456,8 +470,6 @@ async def add_result_details(conn: SearchConnection, results: List[BaseResultT],
|
||||
log().comment('Query keywords')
|
||||
for result in results:
|
||||
await complete_keywords(conn, result)
|
||||
for result in results:
|
||||
result.localize(details.locales)
|
||||
|
||||
|
||||
def _result_row_to_address_row(row: SaRow, isaddress: Optional[bool] = None) -> AddressLine:
|
||||
|
||||
Reference in New Issue
Block a user