Fixing translation problems

ipa rpc server did set the LANG environment variable on each
request and it was not thread safe which led to unpredictable
mixed languages output. Also, there were mistakes regarding
setting the Accept-Language HTTP header.

Now on each request we're setting the "languages" property
in the context thread local variable and client is setting
the Accept-Language HTTP header correctly.

Also, as the server is caching the schema and the schema can
be generated for several languages it's good to store different
schema fingerprint for each language separately.

pagure: https://pagure.io/freeipa/issue/7238
Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
Reviewed-By: Tibor Dudlak <tdudlak@redhat.com>
This commit is contained in:
Aleksei Slaikovskii 2018-01-23 14:41:25 +01:00 committed by Tibor Dudlák
parent 1235f5958d
commit 6c5a7464b2
No known key found for this signature in database
GPG Key ID: 12B8BD343576CDF5
4 changed files with 21 additions and 16 deletions

View File

@ -30,9 +30,9 @@ class ServerInfo(collections.MutableMapping):
# copy-paste from ipalib/rpc.py
try:
self._language = (
locale.setlocale(locale.LC_ALL, '').split('.')[0].lower()
)
self._language = locale.setlocale(
locale.LC_MESSAGES, ''
).split('.')[0].lower()
except locale.Error:
self._language = 'en_us'

View File

@ -536,7 +536,9 @@ class LanguageAwareTransport(MultiProtocolTransport):
self, host)
try:
lang = locale.setlocale(locale.LC_ALL, '').split('.')[0].lower()
lang = locale.setlocale(
locale.LC_MESSAGES, ''
).split('.')[0].lower()
except locale.Error:
# fallback to default locale
lang = 'en_us'

View File

@ -16,6 +16,7 @@ from ipalib.frontend import Command, Local, Method, Object
from ipalib.output import Entry, ListOfEntries, ListOfPrimaryKeys, PrimaryKey
from ipalib.parameters import Bool, Dict, Flag, Str
from ipalib.plugable import Registry
from ipalib.request import context
from ipalib.text import _
from ipapython.version import API_VERSION
@ -833,11 +834,15 @@ class schema(Command):
return schema
def execute(self, *args, **kwargs):
try:
schema = self.api._schema
except AttributeError:
langs = "".join(getattr(context, "languages", []))
if getattr(self.api, "_schema", None) is None:
setattr(self.api, "_schema", {})
schema = self.api._schema.get(langs)
if schema is None:
schema = self._generate_schema(**kwargs)
setattr(self.api, '_schema', schema)
self.api._schema[langs] = schema
schema['ttl'] = SCHEMA_TTL

View File

@ -334,7 +334,6 @@ class WSGIExecutioner(Executioner):
result = None
error = None
_id = None
lang = os.environ['LANG']
name = None
args = ()
options = {}
@ -349,12 +348,9 @@ class WSGIExecutioner(Executioner):
if ('HTTP_ACCEPT_LANGUAGE' in environ):
lang_reg_w_q = environ['HTTP_ACCEPT_LANGUAGE'].split(',')[0]
lang_reg = lang_reg_w_q.split(';')[0]
lang_ = lang_reg.split('-')[0]
if '-' in lang_reg:
reg = lang_reg.split('-')[1].upper()
else:
reg = lang_.upper()
os.environ['LANG'] = '%s_%s' % (lang_, reg)
lang = lang_reg.split('-')[0]
setattr(context, "languages", [lang])
if (
environ.get('CONTENT_TYPE', '').startswith(self.content_type)
and environ['REQUEST_METHOD'] == 'POST'
@ -363,6 +359,7 @@ class WSGIExecutioner(Executioner):
(name, args, options, _id) = self.unmarshal(data)
else:
(name, args, options, _id) = self.simple_unmarshal(environ)
if name in self._system_commands:
result = self._system_commands[name](self, *args, **options)
else:
@ -379,7 +376,8 @@ class WSGIExecutioner(Executioner):
)
error = InternalError()
finally:
os.environ['LANG'] = lang
if hasattr(context, "languages"):
delattr(context, "languages")
principal = getattr(context, 'principal', 'UNKNOWN')
if command is not None: