Hi Mariano,

On 5 May 2015 at 20:21, Mariano Reingart <reing...@gmail.com> wrote:
> Or using a pure python implementation already in the stdlib?
>
> https://hg.python.org/cpython/file/2.7/Lib/gettext.py

Ah, yes.  This comes with potential performance issues, but let's not
focus on performance to start with, as it is easily changed later.  So
it can be done by writing, in RPython, code like that---this is
hackish and not terribly fast, but it should work, running the code
within the multi-line quoted string as regular Python:

    w_translated_string = space.appexec([w_string],
    """(message):
        import gettext
        return gettext.dgettext('python', message)
    """)

You can get started by adding this to the class OpErrFmtNoArgs in
pypy/interpreter/error.py, to get translations for the calls ``raise
oefmt(..., "string")`` that have no ``%`` argument at all:

    def get_w_value(self, space):
        w_value = self._w_value
        if w_value is None:
            # here 'self._value' is a string; turn it into an
app-level string object
            w_value = space.wrap(self._value)
            # translate it!
            w_value = space.appexec([w_value], ...)
            self._w_value = w_value
        return w_value

It can be tried (and tested!) without doing any compilation.  Try it
out by running

    pypy/bin/pyinteractive.py --withmod-struct -S

and trying an example like typing ``float(None)``.  This error message
is in objspace/std/floatobject.py built with oefmt() and no ``%``, so
should go via gettext now.  (Be patient; it is running the complete
PyPy on top of CPython.)  When you get the basics started, write it as
unit tests rather than just trying them out interactively: see for
example pypy/interpreter/test/test_argument.py, class AppTestArgument,
which tries to get random exceptions and checks the message.

>> * I think the sanest is to assume that the language doesn't change
>> dynamically, so that we can use caching techniques; for now it can be
>> done by adding "@jit.elidable" as a decorator, which mean that at
>> least the JIT will constant-fold calls to dgettext().
>
> Ok, I'll investigate this...

This is also "a performance issue for later". :-)

> dgettext is mainly a lookup and interpolation, cannot it just be used to
> return the final string?

Yes, of course we cannot use gettext to translate parts of the string
--- this is not going to work, translation-wise.  The issue I discuss
here is purely technical: the string "got more than %d args" is
written like that in the RPython source, but actually split and stored
in the pypy binary as two strings, the left and right parts.  We need
to fix this by doing this at *runtime* instead: from the full string
"got more than %d args", we'd invoke gettext and go to its translation
(possibly using "%$2d" or some other convention to reorder the
parameters); then split the result; and finally cache these pieces of
strings and the reordering of the arguments.  The actual splitting is
only an optimization, but it needs to be done once at runtime instead
of being done earlier.

> BTW, I see a lot of heads in the mercurial repo, which version should I use?
> tip?

Yes, and make a new branch if you want to commit.

> I prefer communication using mailing list as I gives more time to properly
> reply

That's fine!


Armin
_______________________________________________
pypy-dev mailing list
pypy-dev@python.org
https://mail.python.org/mailman/listinfo/pypy-dev

Reply via email to