|
1 # |
|
2 # Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net> |
|
3 # All Rights Reserved. |
|
4 # |
|
5 # This software is subject to the provisions of the Zope Public License, |
|
6 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. |
|
7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED |
|
8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS |
|
10 # FOR A PARTICULAR PURPOSE. |
|
11 # |
|
12 |
|
13 __docformat__ = 'restructuredtext' |
|
14 |
|
15 |
|
16 # import standard library |
|
17 |
|
18 # import interfaces |
|
19 |
|
20 # import packages |
|
21 |
|
22 |
|
23 def normalize_lang(lang): |
|
24 lang = lang.strip().lower() |
|
25 lang = lang.replace('_', '-') |
|
26 lang = lang.replace(' ', '') |
|
27 return lang |
|
28 |
|
29 |
|
30 def get_browser_language(request): |
|
31 """Custom locale negotiator |
|
32 |
|
33 Copied from zope.publisher code |
|
34 """ |
|
35 accept_langs = request.headers.get('Accept-Language', '').split(',') |
|
36 |
|
37 # Normalize lang strings |
|
38 accept_langs = [normalize_lang(l) for l in accept_langs] |
|
39 # Then filter out empty ones |
|
40 accept_langs = [l for l in accept_langs if l] |
|
41 |
|
42 accepts = [] |
|
43 for index, lang in enumerate(accept_langs): |
|
44 l = lang.split(';', 2) |
|
45 |
|
46 # If not supplied, quality defaults to 1... |
|
47 quality = 1.0 |
|
48 |
|
49 if len(l) == 2: |
|
50 q = l[1] |
|
51 if q.startswith('q='): |
|
52 q = q.split('=', 2)[1] |
|
53 try: |
|
54 quality = float(q) |
|
55 except ValueError: |
|
56 # malformed quality value, skip it. |
|
57 continue |
|
58 |
|
59 if quality == 1.0: |
|
60 # ... but we use 1.9 - 0.001 * position to |
|
61 # keep the ordering between all items with |
|
62 # 1.0 quality, which may include items with no quality |
|
63 # defined, and items with quality defined as 1. |
|
64 quality = 1.9 - (0.001 * index) |
|
65 |
|
66 accepts.append((quality, l[0])) |
|
67 |
|
68 # Filter langs with q=0, which means |
|
69 # unwanted lang according to the spec |
|
70 # See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4 |
|
71 accepts = [acc for acc in accepts if acc[0]] |
|
72 |
|
73 accepts.sort() |
|
74 accepts.reverse() |
|
75 |
|
76 return [lang for qual, lang in accepts][0] if accepts else None |