Merge branch 'release-0.11.0'
[tor-bridgedb.git] / bridgedb / parse / headers.py
blob29dd091f5b943273de1cf067c2b50df4cbdef8f9
1 # -*- coding: utf-8 -*-
3 # This file is part of BridgeDB, a Tor bridge distribution system.
5 # :authors: Isis Lovecruft 0xA3ADB67A2CDB8B35 <isis@torproject.org>
6 # please also see AUTHORS file
7 # :copyright: (c) 2013 Isis Lovecruft
8 # (c) 2007-2013, The Tor Project, Inc.
9 # (c) 2007-2013, all entities within the AUTHORS file
10 # :license: 3-clause BSD, see included LICENSE for information
12 """Parsers for HTTP and Email headers.
14 .. py:module:: bridgedb.parse.headers
15 :synopsis: Parsers for HTTP and Email headers.
17 bridgedb.parse.headers
18 =======================
21 parseAcceptLanguage - Parse the contents of a client 'Accept-Language' header
23 """
25 def parseAcceptLanguage(header):
26 """Parse the contents of a client 'Accept-Language' header.
28 Parse the header in the following manner:
30 1. If ``header`` is None or an empty string, return an empty list.
31 2. Split the ``header`` string on any commas.
32 3. Chop of the RFC2616 quality/level suffix. We ignore these, and just
33 use the order of the list as the preference order, without any
34 parsing of quality/level assignments.
35 4. Add a fallback language of the same type if it is missing. For
36 example, if we only got ['es-ES', 'de-DE'], add 'es' after 'es-ES'
37 and add 'de' after 'de-DE'.
38 5. Change all hyphens to underscores.
40 :param string header: The contents of an 'Accept-Language' header, i.e. as
41 if taken from :api:`twisted.web.server.Request.getHeader`.
42 :rtype: list
43 :returns: A list of language codes (with and without locales), in order of
44 preference.
45 """
46 langs = []
48 if not header:
49 return langs
51 langHeader = header.split(',')
53 for lang in langHeader:
54 if lang.find(';') != -1:
55 # Chop off the RFC2616 Accept `q=` and `level=` feilds
56 code, _ = lang.split(';')
57 langs.append(code)
58 else:
59 langs.append(lang)
61 # Add a fallback language of the same type if it is missing.
62 langsWithLocales = filter(lambda x: '-' in x, langs)
63 langsOnly = map(lambda x: x.split('-')[0], langsWithLocales)
64 for only in langsOnly:
65 if only not in langs:
66 # Add the fallback after the other languages like it:
67 insertAfter = list(filter(lambda x: x.startswith(only),
68 [x for x in langs]))
69 if insertAfter:
70 placement = langs.index(insertAfter[0]) + 1
71 langs.insert(placement, only)
72 continue
73 # Otherwise just put it at the end
74 langs.append(only)
76 # Gettext wants underderscores, because that is how it creates the
77 # directories under i18n/, not hyphens:
78 return list(map(lambda x: x.replace('-', '_'), [x for x in langs]))