diff --git a/tryton/common/htmltextbuffer.py b/tryton/common/htmltextbuffer.py
index 44344d9308..a47c9e2187 100644
--- a/tryton/common/htmltextbuffer.py
+++ b/tryton/common/htmltextbuffer.py
@@ -9,6 +9,17 @@ from html.parser import HTMLParser
from gi.repository import Gtk, Gdk, Pango
+
+def guess_decode(bytes, errors='strict'):
+ for encoding in [sys.getfilesystemencoding(), 'utf-8', 'utf-16', 'utf-32']:
+ try:
+ return bytes.decode(encoding)
+ except UnicodeDecodeError:
+ continue
+ else:
+ return bytes.decode('ascii', errors=errors)
+
+
MIME = Gdk.Atom.intern('text/html', False)
# Disable serialize/deserialize registration function because it does not work
# on GTK-3, the "guint8 *data" is converted into a Gtk.TextIter
@@ -269,15 +280,7 @@ def serialize(register, content, start, end, data):
def deserialize(register, content, iter_, text, create_tags, data):
if not isinstance(text, str):
- for encoding in [sys.getfilesystemencoding(),
- 'utf-8', 'utf-16', 'utf-32']:
- try:
- text = text.decode(encoding)
- except UnicodeDecodeError:
- continue
- break
- else:
- text = text.decode('ascii', errors='replace')
+ text = guess_decode(text, errors='replace')
text, tags = parse_markup(normalize_markup(text, method='xml'))
offset = iter_.get_offset()
content.insert(iter_, text)
diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py
index 48281cc231..65e9a5b6a4 100644
--- a/tryton/gui/window/view_form/model/field.py
+++ b/tryton/gui/window/view_form/model/field.py
@@ -3,6 +3,7 @@
import os
from itertools import chain
import tempfile
+import logging
import locale
from tryton.common import \
domain_inversion, eval_domain, localize_domain, \
@@ -15,9 +16,12 @@ import decimal
from decimal import Decimal
import math
from tryton.common import RPCExecute, RPCException
+from tryton.common.htmltextbuffer import guess_decode
from tryton.pyson import PYSONDecoder
from tryton.config import CONFIG
+logger = logging.getLogger(__name__)
+
class Field(object):
'''
@@ -203,6 +207,17 @@ class CharField(Field):
def get(self, record):
return super(CharField, self).get(record) or self._default
+ def set_client(self, record, value, force_change=False):
+ if isinstance(value, bytes):
+ try:
+ value = guess_decode(value)
+ except UnicodeDecodeError:
+ logger.warning(
+ "The encoding can not be guessed for field '%(name)s'",
+ {'name': self.name})
+ value = None
+ super().set_client(record, value, force_change)
+
class SelectionField(Field):