cherrypy-foundation 1.0.0a8__py3-none-any.whl → 1.0.0a9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,6 @@
1
1
  {# def field, floating=False #}
2
+ {#css vendor/bootstrap5/css/bootstrap.min.css #}
3
+ {#js vendor/jquery/jquery.min.js, vendor/popper/popper.min.js, vendor/bootstrap5/js/bootstrap.min.js #}
2
4
  {# djlint:off #}
3
5
  {% set bootstrap_class_table = {
4
6
  "CheckboxInput": ("form-check-input", "form-check-label", False, True),
@@ -1,6 +1,4 @@
1
1
  {# def form, floating=False #}
2
- {#css vendor/bootstrap5/css/bootstrap.min.css #}
3
- {#js vendor/jquery/jquery.min.js, vendor/popper/popper.min.js, vendor/bootstrap5/js/bootstrap.min.js #}
4
2
  <div class="row">
5
3
  {% for id, field in form._fields.items() %}<Field field={{ field }} floating={{ floating }} />{% endfor %}
6
4
  </div>
@@ -162,7 +162,7 @@ def preferred_timezone(timezone):
162
162
 
163
163
 
164
164
  @lru_cache(maxsize=10)
165
- def _search_translation(dirname, domain, *langs):
165
+ def _search_translation(dirname, domain, *locales):
166
166
  """
167
167
  Loads the first existing translations for known locale.
168
168
 
@@ -177,15 +177,19 @@ def _search_translation(dirname, domain, *langs):
177
177
 
178
178
  :returns: Translations, the corresponding Locale object.
179
179
  """
180
- if not isinstance(langs, (list, tuple)):
181
- langs = [langs]
182
- t = Translations.load(dirname, langs, domain)
180
+ if not isinstance(locales, (list, tuple)):
181
+ locales = [locales]
182
+ t = Translations.load(dirname, locales, domain)
183
183
  # Ignore null translation
184
184
  if t.__class__ is NullTranslations:
185
185
  return None
186
- # Get Locale from file name
187
- lang = t.files[0].split('/')[-3]
188
- t.locale = Locale.parse(lang)
186
+ # Assign prefered local to this translation to know the current locale.
187
+ trans_locale = Locale.parse(t.files[0].split('/')[-3])
188
+ for locale in locales:
189
+ locale = Locale.parse(locale)
190
+ if trans_locale == locale or trans_locale.language == locale.language:
191
+ t.locale = locale
192
+ break
189
193
  return t
190
194
 
191
195
 
@@ -424,7 +428,9 @@ def _set_content_language(**kwargs):
424
428
  language of `cherrypy.response.i18n.locale`.
425
429
  """
426
430
  if 'Content-Language' not in cherrypy.response.headers:
427
- cherrypy.response.headers['Content-Language'] = str(get_translation().locale)
431
+ locale = get_translation().locale
432
+ language_tag = f"{locale.language}-{locale.territory}" if locale.territory else locale.language
433
+ cherrypy.response.headers['Content-Language'] = language_tag
428
434
 
429
435
 
430
436
  class I18nTool(cherrypy.Tool):
@@ -0,0 +1,15 @@
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: \n"
4
+ "POT-Creation-Date: \n"
5
+ "PO-Revision-Date: \n"
6
+ "Last-Translator: \n"
7
+ "Language-Team: \n"
8
+ "Language: de\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 3.6\n"
13
+
14
+ msgid "Some text to translate"
15
+ msgstr "Einige zu übersetzende Texte"
@@ -83,6 +83,13 @@ class AbstractI18nTest(helper.CPWebCase):
83
83
 
84
84
  class TestI18nWebCase(AbstractI18nTest):
85
85
 
86
+ def test_language_with_invalid(self):
87
+ # Query the page without login-in
88
+ self.getPage("/", headers=[("Accept-Language", "invalid")])
89
+ self.assertStatus('200 OK')
90
+ self.assertHeaderItemValue("Content-Language", "en")
91
+ self.assertInBody(TEXT_EN)
92
+
86
93
  def test_language_with_unknown(self):
87
94
  # Query the page without login-in
88
95
  self.getPage("/", headers=[("Accept-Language", "it")])
@@ -93,13 +100,13 @@ class TestI18nWebCase(AbstractI18nTest):
93
100
  def test_language_en(self):
94
101
  self.getPage("/", headers=[("Accept-Language", "en-US,en;q=0.8")])
95
102
  self.assertStatus('200 OK')
96
- self.assertHeaderItemValue("Content-Language", "en")
103
+ self.assertHeaderItemValue("Content-Language", "en-US")
97
104
  self.assertInBody(TEXT_EN)
98
105
 
99
106
  def test_language_en_fr(self):
100
107
  self.getPage("/", headers=[("Accept-Language", "en-US,en;q=0.8,fr-CA;q=0.8")])
101
108
  self.assertStatus('200 OK')
102
- self.assertHeaderItemValue("Content-Language", "en")
109
+ self.assertHeaderItemValue("Content-Language", "en-US")
103
110
  self.assertInBody(TEXT_EN)
104
111
 
105
112
  def test_language_fr(self):
@@ -107,7 +114,7 @@ class TestI18nWebCase(AbstractI18nTest):
107
114
  self.assertInBody(TEXT_EN)
108
115
  self.getPage("/", headers=[("Accept-Language", "fr-CA;q=0.8,fr;q=0.6")])
109
116
  self.assertStatus('200 OK')
110
- self.assertHeaderItemValue("Content-Language", "fr")
117
+ self.assertHeaderItemValue("Content-Language", "fr-CA")
111
118
  self.assertInBody(TEXT_FR)
112
119
 
113
120
  def test_with_preferred_lang(self):
@@ -125,6 +132,42 @@ class TestI18nWebCase(AbstractI18nTest):
125
132
  self.assertEqual(TEXT_EN, i18n.ugettext(TEXT_EN))
126
133
  self.assertIn('March', i18n.format_datetime(date, format='long'))
127
134
 
135
+ def test_format_datetime_locales(self):
136
+ date = datetime.fromtimestamp(1680111611, timezone.utc)
137
+ with i18n.preferred_timezone('utc'):
138
+ with i18n.preferred_lang('fr'):
139
+ self.assertEqual('29 mars 2023, 17:40:11 TU', i18n.format_datetime(date, format='long'))
140
+ with i18n.preferred_lang('en'):
141
+ self.assertEqual('March 29, 2023, 5:40:11\u202fPM UTC', i18n.format_datetime(date, format='long'))
142
+ with i18n.preferred_lang('en_US'):
143
+ self.assertEqual('March 29, 2023, 5:40:11\u202fPM UTC', i18n.format_datetime(date, format='long'))
144
+ with i18n.preferred_lang('en_GB'):
145
+ self.assertEqual('29 March 2023, 17:40:11 UTC', i18n.format_datetime(date, format='long'))
146
+ with i18n.preferred_lang('en_CH'):
147
+ self.assertEqual('29 March 2023, 17:40:11 UTC', i18n.format_datetime(date, format='long'))
148
+ with i18n.preferred_lang('de'):
149
+ self.assertEqual('29. März 2023, 17:40:11 UTC', i18n.format_datetime(date, format='long'))
150
+ with i18n.preferred_lang('de_CH'):
151
+ self.assertEqual('29. März 2023, 17:40:11 UTC', i18n.format_datetime(date, format='long'))
152
+
153
+ with i18n.preferred_timezone('CET'):
154
+ with i18n.preferred_lang('fr'):
155
+ self.assertEqual('29 mars 2023, 19:40:11 +0200', i18n.format_datetime(date, format='long'))
156
+ with i18n.preferred_lang('fr_CH'):
157
+ self.assertEqual('29 mars 2023, 19:40:11 +0200', i18n.format_datetime(date, format='long'))
158
+ with i18n.preferred_lang('en'):
159
+ self.assertEqual('March 29, 2023, 7:40:11\u202fPM +0200', i18n.format_datetime(date, format='long'))
160
+ with i18n.preferred_lang('en_US'):
161
+ self.assertEqual('March 29, 2023, 7:40:11\u202fPM +0200', i18n.format_datetime(date, format='long'))
162
+ with i18n.preferred_lang('en_GB'):
163
+ self.assertEqual('29 March 2023, 19:40:11 CEST', i18n.format_datetime(date, format='long'))
164
+ with i18n.preferred_lang('en_CH'):
165
+ self.assertEqual('29 March 2023, 19:40:11 CEST', i18n.format_datetime(date, format='long'))
166
+ with i18n.preferred_lang('de'):
167
+ self.assertEqual('29. März 2023, 19:40:11 MESZ', i18n.format_datetime(date, format='long'))
168
+ with i18n.preferred_lang('de_CH'):
169
+ self.assertEqual('29. März 2023, 19:40:11 MESZ', i18n.format_datetime(date, format='long'))
170
+
128
171
 
129
172
  class TestI18nDefaultLangWebCase(AbstractI18nTest):
130
173
  default_lang = 'FR'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cherrypy-foundation
3
- Version: 1.0.0a8
3
+ Version: 1.0.0a9
4
4
  Summary: CherryPy Foundation
5
5
  Author-email: Patrik Dufresne <patrik@ikus-soft.com>
6
6
  License: GPLv3
@@ -11,9 +11,9 @@ cherrypy_foundation/components/Datatable.css,sha256=7wSwgdA61vYCdEuQ0bp2o0oSvu5m
11
11
  cherrypy_foundation/components/Datatable.jinja,sha256=K-24vpN5TO8Jk2COvuC5uBaCj3PFLd6ubr28JHFq3KM,3375
12
12
  cherrypy_foundation/components/Datatable.js,sha256=jiV78bJPNMTLcjrX03vaYcsEdRbI6ctzSvCo880H8Hw,12072
13
13
  cherrypy_foundation/components/Field.css,sha256=CtOkvIbix7ykrOKLJxQJLJsWfEwFqfducJ1BH2vlMvA,244
14
- cherrypy_foundation/components/Field.jinja,sha256=R-ZUm88XXOb3zi_hysTuwFUCGGR67A59P4TT5d1Qo_o,3152
14
+ cherrypy_foundation/components/Field.jinja,sha256=-oaFdyZe32kBg3iO2w48yYPnKwxl0tyFr8HrYUm9H0U,3305
15
15
  cherrypy_foundation/components/Field.js,sha256=SFixZ62WlLq7SSCEazMAGhSnc9EnQ1wg6PZX4ayO6ZE,2047
16
- cherrypy_foundation/components/Fields.jinja,sha256=UDu1txwMguvr7dyga9PXepEhFvz9C6ZvchBnhQCWgHI,318
16
+ cherrypy_foundation/components/Fields.jinja,sha256=_8Or6DOlciKjRao-sdBpLs--bx5V-K80X3hDEA1VKCQ,165
17
17
  cherrypy_foundation/components/Flash.jinja,sha256=COy44drQsXpbZajjJS4w_9NMPYFdMfUNdfhd7SbFdYA,442
18
18
  cherrypy_foundation/components/Icon.jinja,sha256=Z1RGYBg5xlDEoUy3glqb_k_LEjkJHeCxQXqDEvWzEF4,135
19
19
  cherrypy_foundation/components/SideBySideMultiSelect.css,sha256=_poMY9O8rvDsOh01pQLf9qtg1Gm4eCM2HsM_ekC5zkk,503
@@ -103,7 +103,7 @@ cherrypy_foundation/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
103
103
  cherrypy_foundation/tools/auth.py,sha256=lTSajxCiReMzm-Fl-xhTByi4yFnInEWOoNsmUMnHQhs,9761
104
104
  cherrypy_foundation/tools/auth_mfa.py,sha256=VaLvBz9wo6jTx-2mCGqFXPxl-z14f8UMWvd6_xeXd40,9212
105
105
  cherrypy_foundation/tools/errors.py,sha256=ELpAj0N9kIxC22QW5xDQJz60zMpCwgm-Twu2WpELM1A,1005
106
- cherrypy_foundation/tools/i18n.py,sha256=5pcyr7AleaqSj9rCESthvMIbNIORp-8351uJgmi2xog,14172
106
+ cherrypy_foundation/tools/i18n.py,sha256=TpyYYCtgXblGcnB9rybaoiH1y7IEKFH6jvbitrKtxfk,14535
107
107
  cherrypy_foundation/tools/jinja2.py,sha256=nppYnk2ASDsyfNHF9m83W4foiN3MhcwDJvo5baEgnGU,5520
108
108
  cherrypy_foundation/tools/ratelimit.py,sha256=pT7vZRmjltNeuiQpdyXOmnpG9BcXjLaj-AXJ0e2x_zw,8300
109
109
  cherrypy_foundation/tools/secure_headers.py,sha256=Yh-iA_Js4MUsx5nq4ilbc-iWy90ZC0oMb3TJJD_UwYo,3921
@@ -111,11 +111,13 @@ cherrypy_foundation/tools/sessions_timeout.py,sha256=6iBWJntPMk_Qt94fBSfBISf1IXI
111
111
  cherrypy_foundation/tools/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
112
112
  cherrypy_foundation/tools/tests/test_auth.py,sha256=oeM5t38M8DUC9dYn59dcf00jdGY6Ry0jZWhQd_PYQUk,2847
113
113
  cherrypy_foundation/tools/tests/test_auth_mfa.py,sha256=911hnBbdg5CKb613uIBrlggoTAyBU9SoL7Sxd-tIKS0,15008
114
- cherrypy_foundation/tools/tests/test_i18n.py,sha256=-bJuKn8PHHidBWhoFSVr4PdX96m3A50YY4i5osyU7DY,6251
114
+ cherrypy_foundation/tools/tests/test_i18n.py,sha256=urkOnXYQDxoxeBOm_Ud5IK0n50rJM59X6tEtEjQqRUM,9082
115
115
  cherrypy_foundation/tools/tests/test_jinja2.py,sha256=_dkRJpjB0ybDV6YO0uEFFO8LAcWgVu3VBB8_vWthQ48,4296
116
116
  cherrypy_foundation/tools/tests/test_ratelimit.py,sha256=rrqybwMbh1GFlF2-Ut57zHPAc1uqX88aqea6VS_6p5E,3449
117
117
  cherrypy_foundation/tools/tests/components/Button.jinja,sha256=uSLp1GpEIgZNXK_GWglu0E_a1c3jHpDLI66MRfMqGhE,95
118
118
  cherrypy_foundation/tools/tests/locales/messages.pot,sha256=5K9piTRL7H5MxDXFIWJsCccSJRA0HwfCQQU8b8VYo30,40
119
+ cherrypy_foundation/tools/tests/locales/de/LC_MESSAGES/messages.mo,sha256=bsJTVL4OefevkxeHDS3VcW3egP6Yq18LFXwjSyoqIng,336
120
+ cherrypy_foundation/tools/tests/locales/de/LC_MESSAGES/messages.po,sha256=glzYY96jmCaGyxYtMqmNF-1q-OYWXBIkMysvbXO4L6E,351
119
121
  cherrypy_foundation/tools/tests/locales/en/LC_MESSAGES/messages.mo,sha256=cdyG2Js1TIU6eenDX1ICH8uP45yvl0OLN0-SMUXTBa4,259
120
122
  cherrypy_foundation/tools/tests/locales/en/LC_MESSAGES/messages.po,sha256=JCpiRLLHUSYQhzta8ZYjfB50NmpwPGNCTNwo2Glww14,322
121
123
  cherrypy_foundation/tools/tests/locales/fr/LC_MESSAGES/messages.mo,sha256=u3_kl_nqZ3FNaSyKVQKmu4KJzN3xOxxJNVmcdhw37jA,327
@@ -123,8 +125,8 @@ cherrypy_foundation/tools/tests/locales/fr/LC_MESSAGES/messages.po,sha256=6_Sk9I
123
125
  cherrypy_foundation/tools/tests/templates/test_jinja2.html,sha256=v9AHxksbBvzE7sesPqE61HMhsvU4juXt3E0ZQo-zXVQ,190
124
126
  cherrypy_foundation/tools/tests/templates/test_jinja2_i18n.html,sha256=98S51dgG7Vb4rvMZNZvomw1D9pBiM4g6pdlxAgvrxXA,373
125
127
  cherrypy_foundation/tools/tests/templates/test_jinjax.html,sha256=NT19UaUzm8FRKOIc6H6HNGPDJU6KATnakd8zf3BCeAs,153
126
- cherrypy_foundation-1.0.0a8.dist-info/licenses/LICENSE.md,sha256=trSLYs5qlaow_bBwsLTRKpmTXsXzFksM_YUCMqrgAJQ,35149
127
- cherrypy_foundation-1.0.0a8.dist-info/METADATA,sha256=7aXt2rwg_HACqXWiWHeFxkJN0wrVNWylVJZbf9M-L-8,2022
128
- cherrypy_foundation-1.0.0a8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
129
- cherrypy_foundation-1.0.0a8.dist-info/top_level.txt,sha256=B1vQPTLYhpKJ6W0JkRCWyAf8RPcnwJWdYxixv75-4ew,20
130
- cherrypy_foundation-1.0.0a8.dist-info/RECORD,,
128
+ cherrypy_foundation-1.0.0a9.dist-info/licenses/LICENSE.md,sha256=trSLYs5qlaow_bBwsLTRKpmTXsXzFksM_YUCMqrgAJQ,35149
129
+ cherrypy_foundation-1.0.0a9.dist-info/METADATA,sha256=kkEaxI9-7XJc32TpM7GXcnkoQmkG1nXCPsshgKl96OM,2022
130
+ cherrypy_foundation-1.0.0a9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
131
+ cherrypy_foundation-1.0.0a9.dist-info/top_level.txt,sha256=B1vQPTLYhpKJ6W0JkRCWyAf8RPcnwJWdYxixv75-4ew,20
132
+ cherrypy_foundation-1.0.0a9.dist-info/RECORD,,