Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Double translation #329

Open
viktordick opened this issue Jul 23, 2020 · 2 comments
Open

Double translation #329

viktordick opened this issue Jul 23, 2020 · 2 comments

Comments

@viktordick
Copy link

After the discussion in #328, I switched our translation service to return any messages that are not of type str, yielding mostly the expected result. However, if we do set an i18n attribute on a tag that obtains the content from something other than a string, the translation is called twice. To demonstrate, I adjusted an example of Dieter Maurer:

from chameleon.zpt.template import PageTemplate

def translate(msgid, *args, **kw):
    print('translate called with', msgid.__class__, msgid)
    if not isinstance(msgid, str):
        return msgid
    return "translated"

class Something:
  def __init__(self, text):
      self.text = text
  def __str__(self):
      return self.text

x = Something("x")

ts = """<div i18n:translate="" tal:content="x" />"""
t = PageTemplate(ts)
t(translate=translate, x=x)

This yields

translate called with <class '__main__.Something'> x
translate called with <class '__main__.Something'> x

When looking into the cache file created by Chameleon, this is due to the following two lines:

__content = translate(__content, default=None, domain=__i18n_domain, context=__i18n_context, target_language=getitem('
__content = __quote(__content, None, '\xad', None, None)

If these two lines were switched, I would get the desired result - __quote would find that __content is not a string or number and has no __html__ method, so it would call the translation. Since the translation returned the original object, __quote would fall back to returning str(target), so the call to translate that is due to the explicit i18n:translate attrlibute would be handled a string and actually do a translation.

Is there a reason for this order? Also, I cannot imagine that it is intended that the translation is called twice here. Maybe the specification that everything that is not a string or has an __html__ method is considered to be a message to be translated could be reconsidered?

@malthe
Copy link
Owner

malthe commented Jul 24, 2020

I think you're supposed to always return a string from the translate function. This would then mean that __quote would not attempt to convert (i.e. translate) twice.

If in doubt, consult z3c.pt which has existed as an option for people in Zope/Plone to use Chameleon for ages.

@viktordick
Copy link
Author

The chameleon cache file contains inside __quote the lines

__converted = convert(target)
target = (str(target) if (target is __converted) else __converted)

suggesting that the translation (convert is a partial on translate) is allowed to return the object itself to indicate that it will not handle it.
Anyhow, if I return str(msgid) instead of msgid in the case of msgid not being a string, the translation is only called once, but I still am unable to differentiate between

<div i18n:translate="" tal:content="x"></div>

and

<div tal:content="x"></div>

Of course, this is actually what the documentation says. x is considered to be in need of translation irrespective of the explict i18n:translate attribute simply due to it being neither a string nor an object with an __html__ method. Whether an explicit translation requesting attribute was also given, is then irrelevant and my translate function is not given any information about whether the attribute is in fact present (short of inspecting the call stack).

I can live with this since in the context of Zope 4, I can only cause this behavior if naming a File object as content for a tag and at the same time requesting a translation using an explicit i18n:translate. I doubt that we actually have this situation anywhere in our code. It is just something that is now different than it was in Zope 2 due to this different definition of what needs to be translated.

Maybe if more such problems arise, you could consider a chameleon flag that changes this behavior to be more compatible to Zope, so it only translates messages with explicit i18n attributes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants