1 # SPDX-License-Identifier: GPL-3.0-or-later
 
   3 # This file is part of Nominatim. (https://nominatim.org)
 
   5 # Copyright (C) 2025 by the Nominatim developer community.
 
   6 # For a full list of authors see the git log.
 
   8 Test functions for adapting results to the user's locale.
 
  12 from nominatim_api import Locales
 
  15 def test_display_name_empty_names():
 
  16     loc = Locales(['en', 'de'])
 
  18     assert loc.display_name(None) == ''
 
  19     assert loc.display_name({}) == ''
 
  22 def test_display_name_none_localized():
 
  25     assert loc.display_name({}) == ''
 
  26     assert loc.display_name({'name:de': 'DE', 'name': 'ALL'}) == 'ALL'
 
  27     assert loc.display_name({'ref': '34', 'name:de': 'DE'}) == '34'
 
  30 def test_output_names_none_localized():
 
  34         'name', '_place_name', 'brand', '_place_brand', 'official_name', '_place_official_name',
 
  35         'short_name', '_place_short_name', 'ref', '_place_ref'
 
  38     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
 
  41 def test_output_names_none_localized_and_custom_output_names(monkeypatch):
 
  43         'NOMINATIM_OUTPUT_NAMES',
 
  44         'name:XX,entrance:XX,name,brand,test_tag,'
 
  45         'official_name:XX,short_name:XX,alt_name:XX'
 
  50         'name', '_place_name', 'brand', '_place_brand', 'test_tag', '_place_test_tag'
 
  53     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
 
  56 def test_output_names_none_localized_and_custom_output_names_more_than_two_changes(monkeypatch):
 
  58         'NOMINATIM_OUTPUT_NAMES',
 
  59         'name:XX,brand,test_tag:XX,official_name,short_name:XX,'
 
  60         'alt_name,another_tag_with:XX,another_tag_withoutXX'
 
  65         'brand', '_place_brand', 'official_name', '_place_official_name', 'alt_name',
 
  66         '_place_alt_name', 'another_tag_withoutXX', '_place_another_tag_withoutXX'
 
  69     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
 
  72 def test_output_names_none_localized_and_custom_output_names_including_space(monkeypatch):
 
  74         'NOMINATIM_OUTPUT_NAMES',
 
  75         'name:XX,name ,short_name:XX, short_name'
 
  80         'name', '_place_name', 'short_name', '_place_short_name'
 
  83     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
 
  86 def test_display_name_localized():
 
  87     loc = Locales(['en', 'de'])
 
  89     assert loc.display_name({}) == ''
 
  90     assert loc.display_name({'name:de': 'DE', 'name': 'ALL'}) == 'DE'
 
  91     assert loc.display_name({'ref': '34', 'name:de': 'DE'}) == 'DE'
 
  94 def test_output_names_localized():
 
  95     loc = Locales(['en', 'es'])
 
  98         'name:en', '_place_name:en', 'name:es', '_place_name:es', 'name', '_place_name', 'brand',
 
  99         '_place_brand', 'official_name:en', '_place_official_name:en', 'official_name:es',
 
 100         '_place_official_name:es', 'short_name:en', '_place_short_name:en', 'short_name:es',
 
 101         '_place_short_name:es', 'official_name', '_place_official_name', 'short_name',
 
 102         '_place_short_name', 'ref', '_place_ref'
 
 105     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
 
 108 def test_output_names_localized_and_custom_output_names_including_space(monkeypatch):
 
 110         'NOMINATIM_OUTPUT_NAMES',
 
 111         'name:XX,name ,short_name:XX, short_name'
 
 113     loc = Locales(['en', 'es'])
 
 116         'name:en', '_place_name:en', 'name:es', '_place_name:es',
 
 117         'name', '_place_name',
 
 118         'short_name:en', '_place_short_name:en', 'short_name:es', '_place_short_name:es',
 
 119         'short_name', '_place_short_name'
 
 122     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
 
 125 def test_output_names_localized_and_custom_output_names(monkeypatch):
 
 127         'NOMINATIM_OUTPUT_NAMES',
 
 128         'name:XX,entrance:XX,name,brand,test_tag,official_name:XX,short_name:XX,alt_name:XX'
 
 130     loc = Locales(['en', 'es'])
 
 133         'name:en', '_place_name:en', 'name:es', '_place_name:es', 'entrance:en',
 
 134         '_place_entrance:en', 'entrance:es', '_place_entrance:es', 'name', '_place_name',
 
 135         'brand', '_place_brand', 'test_tag', '_place_test_tag', 'official_name:en',
 
 136         '_place_official_name:en', 'official_name:es', '_place_official_name:es',
 
 137         'short_name:en', '_place_short_name:en', 'short_name:es', '_place_short_name:es',
 
 138         'alt_name:en', '_place_alt_name:en', 'alt_name:es', '_place_alt_name:es'
 
 141     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
 
 144 def test_output_names_localized_and_custom_output_names_start_with_tag_that_has_no_XX(monkeypatch):
 
 146         'NOMINATIM_OUTPUT_NAMES',
 
 147         'name,brand,test_tag,official_name:XX,short_name:XX,alt_name:XX'
 
 149     loc = Locales(['en', 'es'])
 
 152         'name', '_place_name', 'brand', '_place_brand', 'test_tag', '_place_test_tag',
 
 153         'official_name:en', '_place_official_name:en', 'official_name:es',
 
 154         '_place_official_name:es', 'short_name:en', '_place_short_name:en', 'short_name:es',
 
 155         '_place_short_name:es', 'alt_name:en', '_place_alt_name:en', 'alt_name:es',
 
 159     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
 
 162 def test_output_names_localized_and_custom_output_names_no_named_tags(monkeypatch):
 
 164         'NOMINATIM_OUTPUT_NAMES',
 
 165         'name,brand,test_tag'
 
 167     loc = Locales(['en', 'es'])
 
 170         'name', '_place_name', 'brand', '_place_brand', 'test_tag', '_place_test_tag'
 
 173     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
 
 176 def test_output_names_localized_and_custom_output_names_only_named_tags(monkeypatch):
 
 178         'NOMINATIM_OUTPUT_NAMES',
 
 179         'name:XX,entrance:XX,official_name:XX,short_name:XX,alt_name:XX'
 
 181     loc = Locales(['en', 'es'])
 
 184         'name:en', '_place_name:en', 'name:es', '_place_name:es', 'entrance:en',
 
 185         '_place_entrance:en', 'entrance:es', '_place_entrance:es', 'official_name:en',
 
 186         '_place_official_name:en', 'official_name:es', '_place_official_name:es',
 
 187         'short_name:en', '_place_short_name:en', 'short_name:es', '_place_short_name:es',
 
 188         'alt_name:en', '_place_alt_name:en', 'alt_name:es', '_place_alt_name:es'
 
 191     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
 
 194 def test_output_names_localized_and_custom_output_names_more_than_two_changes(monkeypatch):
 
 196         'NOMINATIM_OUTPUT_NAMES',
 
 197         'name:XX,brand,test_tag:XX,official_name,short_name:XX,'
 
 198         'alt_name,another_tag_with:XX,another_tag_withoutXX'
 
 200     loc = Locales(['en', 'es'])
 
 203         'name:en', '_place_name:en', 'name:es', '_place_name:es', 'brand', '_place_brand',
 
 204         'test_tag:en', '_place_test_tag:en', 'test_tag:es', '_place_test_tag:es', 'official_name',
 
 205         '_place_official_name', 'short_name:en', '_place_short_name:en', 'short_name:es',
 
 206         '_place_short_name:es', 'alt_name', '_place_alt_name', 'another_tag_with:en',
 
 207         '_place_another_tag_with:en', 'another_tag_with:es', '_place_another_tag_with:es',
 
 208         'another_tag_withoutXX', '_place_another_tag_withoutXX'
 
 211     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
 
 214 def test_output_names_localized_and_custom_output_names_XX_in_the_middle(monkeypatch):
 
 216         'NOMINATIM_OUTPUT_NAMES',
 
 217         'name:XX,br:XXand,test_tag:XX,official_name,sh:XXort_name:XX,'
 
 218         'alt_name,another_tag_with:XX,another_tag_withoutXX'
 
 220     loc = Locales(['en', 'es'])
 
 223         'name:en', '_place_name:en', 'name:es', '_place_name:es', 'br:XXand', '_place_br:XXand',
 
 224         'test_tag:en', '_place_test_tag:en', 'test_tag:es', '_place_test_tag:es', 'official_name',
 
 225         '_place_official_name', 'sh:XXort_name:en', '_place_sh:XXort_name:en', 'sh:XXort_name:es',
 
 226         '_place_sh:XXort_name:es', 'alt_name', '_place_alt_name', 'another_tag_with:en',
 
 227         '_place_another_tag_with:en', 'another_tag_with:es', '_place_another_tag_with:es',
 
 228         'another_tag_withoutXX', '_place_another_tag_withoutXX'
 
 231     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
 
 234 def test_display_name_preference():
 
 235     loc = Locales(['en', 'de'])
 
 237     assert loc.display_name({}) == ''
 
 238     assert loc.display_name({'name:de': 'DE', 'name:en': 'EN'}) == 'EN'
 
 239     assert loc.display_name({'official_name:en': 'EN', 'name:de': 'DE'}) == 'DE'
 
 242 @pytest.mark.parametrize('langstr,langlist',
 
 244                           ('fr-FR', ['fr-FR', 'fr']),
 
 245                           ('de,fr-FR', ['de', 'fr-FR', 'fr']),
 
 246                           ('fr,de,fr-FR', ['fr', 'de', 'fr-FR']),
 
 247                           ('en;q=0.5,fr', ['fr', 'en']),
 
 248                           ('en;q=0.5,fr,en-US', ['fr', 'en-US', 'en']),
 
 249                           ('en,fr;garbage,de', ['en', 'de'])])
 
 250 def test_from_language_preferences(langstr, langlist):
 
 251     assert Locales.from_accept_languages(langstr).languages == langlist