Jeremy Selier

Déterminer en Python la langue du visiteur avec le header Accept-Language

Ayant l'intention de lancer deux versions de ce blog, une version française (vous êtes dessus) et une anglaise (qui arrive bientôt), je me suis penché sur les différents moyens de detecter la langue de l'utilisateur. J'ai d'abord regardé du côté du JavaScript, mais je me suis vite rabattu sur la variable Accept-Language qui est passée par le navigateur en header de chaque requête envoyé au serveur.

Voici l'allure du header envoyé par les navigateurs : Accept-Language: fr, fr-fr;q=0.8, en-us;q=0.7,en;q=0.5. Je vous invite à lire la RFC2616 (spécifications HTTP1.1), et plus particulièrement la section 14 sur la définition des champs Header afin de comprendre par quel moyen nous pouvons prioriser la liste reçue. J'ai donc développé une petite fonction qui me retourne une liste comprenant, par ordre de préférence, la liste des langues acceptées par le navigateur. Etant donné que ce blog tourne sur Google AppEngine, c'est en Python, voici le code :

def parse_accept_header(accept_header):
    """Determines the user's locale from Accept-Language header value passed
    as a parameter.

    Note: It should work fine for getting Accept, Accept-Charset or
    Accept-Encoding headers but you will need to take care of special values 
    such as */*, /*, and "level=X" to prioritizing your results. See 
    http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4 for 
    more details on Accept-Languages and 
    http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1 to 
    check all available Accept headers.
    """
    accepts = []
    for line in accept_header.replace(' ','').split(','):
        values = line.split(';q=')
        if len(values) > 1:
            try:
                prio = float(values[1])
            except (ValueError, TypeError):
                prio = 0.0
        else:
            prio = 1.0
        accepts.append((values[0], prio))
    accepts.sort(key=lambda (l, s): s, reverse=True)
    accept_headers = [l[0] for l in accepts]
    return accept_headers

All posts >