diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py --- a/mercurial/dispatch.py +++ b/mercurial/dispatch.py @@ -811,10 +811,8 @@ "option -R has to be separated from other options (e.g. not " "-qR) and --repository may only be abbreviated as --repo!")) - if options["encoding"]: - encoding.encoding = options["encoding"] - if options["encodingmode"]: - encoding.encodingmode = options["encodingmode"] + encoding.setencoding(options["encoding"], options["encodingmode"]) + if options["time"]: def get_times(): t = os.times() diff --git a/mercurial/encoding.py b/mercurial/encoding.py --- a/mercurial/encoding.py +++ b/mercurial/encoding.py @@ -581,6 +581,20 @@ r += c return r +# used by i18n to clean its message cache after encoding change +setencodingcallbacks = [] + +def setencoding(newencoding=None, newencodingmode=None): + global encoding, encodingmode + oldvalues = (encoding, encodingmode) + if newencoding: + encoding = newencoding + if newencodingmode: + encodingmode = newencodingmode + if oldvalues != (encoding, encodingmode): + for func in setencodingcallbacks: + func() + if pycompat.ispy3: class strio(io.TextIOWrapper): """Wrapper around TextIOWrapper that respects hg's encoding assumptions. diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py --- a/mercurial/hgweb/hgweb_mod.py +++ b/mercurial/hgweb/hgweb_mod.py @@ -320,7 +320,7 @@ rctx = requestcontext(self, repo) # This state is global across all threads. - encoding.encoding = rctx.config('web', 'encoding') + encoding.setencoding(rctx.config('web', 'encoding')) rctx.repo.ui.environ = req.env if rctx.csp: diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py --- a/mercurial/hgweb/hgwebdir_mod.py +++ b/mercurial/hgweb/hgwebdir_mod.py @@ -173,7 +173,7 @@ self.repos = repos self.ui = u - encoding.encoding = self.ui.config('web', 'encoding') + encoding.setencoding(self.ui.config('web', 'encoding')) self.style = self.ui.config('web', 'style') self.templatepath = self.ui.config('web', 'templates', untrusted=False) self.stripecount = self.ui.config('web', 'stripes') diff --git a/mercurial/i18n.py b/mercurial/i18n.py --- a/mercurial/i18n.py +++ b/mercurial/i18n.py @@ -60,6 +60,8 @@ _msgcache = {} +encoding.setencodingcallbacks.append(_msgcache.clear) + def gettext(message): """Translate message. diff --git a/tests/test-commit-interactive.t b/tests/test-commit-interactive.t --- a/tests/test-commit-interactive.t +++ b/tests/test-commit-interactive.t @@ -913,7 +913,7 @@ > ? > q > EOF - y - \x82\xb1\x82\xcc\x95\xcf\x8dX\x82\xf0\x8bL\x98^(yes) + y - ???????(yes) $ LANGUAGE= #endif diff --git a/tests/test-i18n.t b/tests/test-i18n.t --- a/tests/test-i18n.t +++ b/tests/test-i18n.t @@ -48,3 +48,23 @@ $ $PYTHON check-translation.py *.po $ $PYTHON check-translation.py --doctest $ cd $TESTTMP + +Check i18n cache gets invalidated correctly with encoding change: + + $ cat > $TESTTMP/encodingchange.py << EOF + > from mercurial import encoding, registrar + > from mercurial.i18n import _ + > cmdtable = {} + > command = registrar.command(cmdtable) + > @command('encodingchange', norepo=True) + > def encodingchange(ui): + > for encode in ('ascii', 'UTF-8', 'ascii', 'UTF-8'): + > encoding.setencoding(encode) + > ui.write('%s\n' % encoding.jsonescape(_('(EXPERIMENTAL)'))) + > EOF + + $ LANGUAGE=ja hg --config extensions.encodingchange=$TESTTMP/encodingchange.py encodingchange + (?????) + (\xe5\xae\x9f\xe9\xa8\x93\xe7\x9a\x84\xe5\xae\x9f\xe8\xa3\x85) (esc) + (?????) + (\xe5\xae\x9f\xe9\xa8\x93\xe7\x9a\x84\xe5\xae\x9f\xe8\xa3\x85) (esc)