Repository: liberapay/liberapay.com

Issue:
Users can't choose language of emails
`email_lang` is filled automatically but the UI doesn't allow users to modify it.



Discussion:
I think this is a fairly important bug to fix. I can't read any emails I receive from Liberapay and have to use Google Translate to make sense of them.
@iangilfillan Yes, this issue is next on my list, sorry about the delay.

Resolving patch:
diff --git a/liberapay/models/participant.py b/liberapay/models/participant.py
--- a/liberapay/models/participant.py
+++ b/liberapay/models/participant.py
@@ -896,16 +896,12 @@ def _dequeue_emails(cls, cursor):
                 sleep(1)
             last_id = messages[-1].id
 
-    def set_email_lang(self, accept_lang, cursor=None):
-        if not accept_lang:
-            return
-        if isinstance(accept_lang, bytes):
-            accept_lang = accept_lang.decode('ascii', 'replace')
+    def set_email_lang(self, lang, cursor=None):
         (cursor or self.db).run(
             "UPDATE participants SET email_lang=%s WHERE id=%s",
-            (accept_lang, self.id)
+            (lang, self.id)
         )
-        self.set_attributes(email_lang=accept_lang)
+        self.set_attributes(email_lang=lang)
 
 
     # Notifications
diff --git a/liberapay/security/authentication.py b/liberapay/security/authentication.py
--- a/liberapay/security/authentication.py
+++ b/liberapay/security/authentication.py
@@ -106,7 +106,7 @@ def sign_in_with_form_data(body, state):
                 kind, body.pop('sign-in.username', None),
                 body.pop('sign-in.password', None), currency=currency, cursor=c,
             )
-            p.set_email_lang(state['request'].headers.get(b'Accept-Language'), cursor=c)
+            p.set_email_lang(state['locale'].language, cursor=c)
             p.add_email(email, cursor=c)
         p.authenticated = True
 
diff --git a/liberapay/wireup.py b/liberapay/wireup.py
--- a/liberapay/wireup.py
+++ b/liberapay/wireup.py
@@ -605,11 +605,13 @@ def load_i18n(canonical_host, canonical_scheme, project_root, tell_sentry):
 
     # Prepare a unique and sorted list for use in the language switcher
     percent = lambda l, total: sum((percent(s, len(s)) if isinstance(s, tuple) else 1) for s in l if s) / total
-    for l in locales.values():
+    for l in list(locales.values()):
         if l.language == 'en':
             l.completion = 1
             continue
         l.completion = percent([m.string for m in l.catalog if m.id and not m.fuzzy], len(l.catalog))
+        if l.completion == 0:
+            del locales[l.language]
     loc_url = canonical_scheme+'://%s.'+canonical_host
     domain, port = (canonical_host.split(':') + [None])[:2]
     port = int(port) if port else socket.getservbyname(canonical_scheme, 'tcp')


Test patch:
diff --git a/liberapay/testing/__init__.py b/liberapay/testing/__init__.py
--- a/liberapay/testing/__init__.py
+++ b/liberapay/testing/__init__.py
@@ -184,6 +184,7 @@ def make_participant(self, username, **kw):
             kw['username'] = username
         if 'join_time' not in kw:
             kw['join_time'] = utcnow()
+        kw.setdefault('email_lang', 'en')
         cols, vals = zip(*kw.items())
         cols = ', '.join(cols)
         placeholders = ', '.join(['%s']*len(vals))