]> git.openstreetmap.org Git - nominatim.git/blob - test/python/api/test_localization.py
Merge remote-tracking branch 'upstream/master'
[nominatim.git] / test / python / api / test_localization.py
1 # SPDX-License-Identifier: GPL-3.0-or-later
2 #
3 # This file is part of Nominatim. (https://nominatim.org)
4 #
5 # Copyright (C) 2025 by the Nominatim developer community.
6 # For a full list of authors see the git log.
7 """
8 Test functions for adapting results to the user's locale.
9 """
10 import pytest
11
12 from nominatim_api import Locales
13
14
15 def test_display_name_empty_names():
16     loc = Locales(['en', 'de'])
17
18     assert loc.display_name(None) == ''
19     assert loc.display_name({}) == ''
20
21
22 def test_display_name_none_localized():
23     loc = Locales()
24
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'
28
29
30 def test_output_names_none_localized():
31     loc = Locales()
32
33     expected_tags = [
34         'name', '_place_name'
35     ]
36
37     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
38
39
40 def test_output_names_none_localized_and_custom_output_names():
41     loc = Locales(names='name:XX,entrance:XX,name,brand,test_tag,'
42                   'official_name:XX,short_name:XX,alt_name:XX')
43
44     expected_tags = [
45         'name', '_place_name', 'brand', '_place_brand', 'test_tag', '_place_test_tag'
46     ]
47
48     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
49
50
51 def test_output_names_none_localized_and_custom_output_names_more_than_two_changes():
52     loc = Locales(names='name:XX,brand,test_tag:XX,official_name,short_name:XX,'
53                   'alt_name,another_tag_with:XX,another_tag_withoutXX')
54
55     expected_tags = [
56         'brand', '_place_brand', 'official_name', '_place_official_name', 'alt_name',
57         '_place_alt_name', 'another_tag_withoutXX', '_place_another_tag_withoutXX'
58     ]
59
60     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
61
62
63 def test_output_names_none_localized_and_custom_output_names_including_space():
64     loc = Locales(names='name:XX,name ,short_name:XX, short_name')
65
66     expected_tags = [
67         'name', '_place_name', 'short_name', '_place_short_name'
68     ]
69
70     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
71
72
73 def test_display_name_localized():
74     loc = Locales(['en', 'de'])
75
76     assert loc.display_name({}) == ''
77     assert loc.display_name({'name:de': 'DE', 'name': 'ALL'}) == 'DE'
78     assert loc.display_name({'ref': '34', 'name:de': 'DE'}) == 'DE'
79
80
81 def test_output_names_localized():
82     loc = Locales(['en', 'es'])
83
84     expected_tags = [
85         'name:en', '_place_name:en', 'name:es', '_place_name:es', 'name', '_place_name'
86     ]
87
88     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
89
90
91 def test_output_names_localized_and_empty_names():
92     loc = Locales(['en'], "")
93     expected_tags = []
94
95     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
96
97
98 def test_output_names_localized_and_custom_names_ordering_logic():
99     loc = Locales(['en', 'fr'], "name:XX,ref")
100
101     expected = [
102         'name:en', '_place_name:en',
103         'name:fr', '_place_name:fr',
104         'ref', '_place_ref'
105     ]
106     assert loc.name_tags == expected
107
108
109 def test_output_names_localized_and_custom_output_names_including_space():
110     loc = Locales(['en', 'es'], names='name:XX,name ,short_name:XX, short_name')
111
112     expected_tags = [
113         'name:en', '_place_name:en', 'name:es', '_place_name:es',
114         'name', '_place_name',
115         'short_name:en', '_place_short_name:en', 'short_name:es', '_place_short_name:es',
116         'short_name', '_place_short_name'
117     ]
118
119     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
120
121
122 def test_output_names_localized_and_custom_output_names():
123     loc = Locales(['en', 'es'], names='name:XX,entrance:XX,name,brand,test_tag,'
124                   'official_name:XX,short_name:XX,alt_name:XX')
125
126     expected_tags = [
127         'name:en', '_place_name:en', 'name:es', '_place_name:es', 'entrance:en',
128         '_place_entrance:en', 'entrance:es', '_place_entrance:es', 'name', '_place_name',
129         'brand', '_place_brand', 'test_tag', '_place_test_tag', 'official_name:en',
130         '_place_official_name:en', 'official_name:es', '_place_official_name:es',
131         'short_name:en', '_place_short_name:en', 'short_name:es', '_place_short_name:es',
132         'alt_name:en', '_place_alt_name:en', 'alt_name:es', '_place_alt_name:es'
133     ]
134
135     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
136
137
138 def test_output_names_localized_and_custom_output_names_start_with_tag_that_has_no_XX():
139     loc = Locales(['en', 'es'],
140                   names='name,brand,test_tag,official_name:XX,short_name:XX,alt_name:XX')
141
142     expected_tags = [
143         'name', '_place_name', 'brand', '_place_brand', 'test_tag', '_place_test_tag',
144         'official_name:en', '_place_official_name:en', 'official_name:es',
145         '_place_official_name:es', 'short_name:en', '_place_short_name:en', 'short_name:es',
146         '_place_short_name:es', 'alt_name:en', '_place_alt_name:en', 'alt_name:es',
147         '_place_alt_name:es'
148     ]
149
150     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
151
152
153 def test_output_names_localized_and_custom_output_names_no_named_tags():
154     loc = Locales(['en', 'es'], names='name,brand,test_tag')
155
156     expected_tags = [
157         'name', '_place_name', 'brand', '_place_brand', 'test_tag', '_place_test_tag'
158     ]
159
160     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
161
162
163 def test_output_names_localized_and_custom_output_names_only_named_tags():
164     loc = Locales(['en', 'es'],
165                   names='name:XX,entrance:XX,official_name:XX,short_name:XX,alt_name:XX')
166
167     expected_tags = [
168         'name:en', '_place_name:en', 'name:es', '_place_name:es', 'entrance:en',
169         '_place_entrance:en', 'entrance:es', '_place_entrance:es', 'official_name:en',
170         '_place_official_name:en', 'official_name:es', '_place_official_name:es',
171         'short_name:en', '_place_short_name:en', 'short_name:es', '_place_short_name:es',
172         'alt_name:en', '_place_alt_name:en', 'alt_name:es', '_place_alt_name:es'
173     ]
174
175     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
176
177
178 def test_output_names_localized_and_custom_output_names_more_than_two_changes():
179     loc = Locales(['en', 'es'], names='name:XX,brand,test_tag:XX,official_name,'
180                   'short_name:XX,alt_name,another_tag_with:XX,another_tag_withoutXX')
181
182     expected_tags = [
183         'name:en', '_place_name:en', 'name:es', '_place_name:es', 'brand', '_place_brand',
184         'test_tag:en', '_place_test_tag:en', 'test_tag:es', '_place_test_tag:es', 'official_name',
185         '_place_official_name', 'short_name:en', '_place_short_name:en', 'short_name:es',
186         '_place_short_name:es', 'alt_name', '_place_alt_name', 'another_tag_with:en',
187         '_place_another_tag_with:en', 'another_tag_with:es', '_place_another_tag_with:es',
188         'another_tag_withoutXX', '_place_another_tag_withoutXX'
189     ]
190
191     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
192
193
194 def test_output_names_localized_and_custom_output_names_XX_in_the_middle():
195     loc = Locales(['en', 'es'], names='name:XX,br:XXand,test_tag:XX,official_name,'
196                   'sh:XXort_name:XX,alt_name,another_tag_with:XX,another_tag_withoutXX')
197
198     expected_tags = [
199         'name:en', '_place_name:en', 'name:es', '_place_name:es', 'br:XXand', '_place_br:XXand',
200         'test_tag:en', '_place_test_tag:en', 'test_tag:es', '_place_test_tag:es', 'official_name',
201         '_place_official_name', 'sh:XXort_name:en', '_place_sh:XXort_name:en', 'sh:XXort_name:es',
202         '_place_sh:XXort_name:es', 'alt_name', '_place_alt_name', 'another_tag_with:en',
203         '_place_another_tag_with:en', 'another_tag_with:es', '_place_another_tag_with:es',
204         'another_tag_withoutXX', '_place_another_tag_withoutXX'
205     ]
206
207     assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
208
209
210 def test_display_name_preference():
211     loc = Locales(['en', 'de'])
212
213     assert loc.display_name({}) == ''
214     assert loc.display_name({'name:de': 'DE', 'name:en': 'EN'}) == 'EN'
215     assert loc.display_name({'official_name:en': 'EN', 'name:de': 'DE'}) == 'DE'
216
217
218 @pytest.mark.parametrize('langstr,langlist',
219                          [('fr', ['fr']),
220                           ('fr-FR', ['fr-FR', 'fr']),
221                           ('de,fr-FR', ['de', 'fr-FR', 'fr']),
222                           ('fr,de,fr-FR', ['fr', 'de', 'fr-FR']),
223                           ('en;q=0.5,fr', ['fr', 'en']),
224                           ('en;q=0.5,fr,en-US', ['fr', 'en-US', 'en']),
225                           ('en,fr;garbage,de', ['en', 'de'])])
226 def test_from_language_preferences(langstr, langlist):
227     assert Locales.from_accept_languages(langstr).languages == langlist