[Python-ideas] Fix the DRY problem (was Re: PEP 501 - i18n with marked strings)

Guido van Rossum guido at python.org
Thu Aug 13 06:37:01 CEST 2015


On Wed, Aug 12, 2015 at 6:06 PM, Barry Warsaw <barry at python.org> wrote:

> [...]
> On Aug 12, 2015, at 08:50 AM, Guido van Rossum wrote:
> >It also has the same problems as locals(), sys._getframe(), etc., which is
> >that their presence makes certain optimizations harder (in IronPython IIRC
> >the creation of frame objects is normally skipped to speed up function
> >calls, but the optimizer must detect the presence of those functions in
> >order to disable that optimization). That doesn't mean I'm opposed to it
> (I
> >don't have a problem with locals()), but it does mean that I think their
> >use should probably not be encouraged.
>
> I'm much less concerned about the performance impact loss of optimization
> provides because I think i18n is already generally slower... and that's
> okay!
> I mean _() has to at least do a dictionary look (assuming the catalog is
> warmed in memory) and then a piece-wise interpolation into the resulting
> translated string.  So you're already paying runtime penalty to do i18n.
>

Fair enough. (Though IMO the real cost of i18n is that it introduces a
feeling of programming in molasses.)


> [...]
> i18n is one of those places where DRY really is a limiting factor.  You
> just
> can't force coders to pass in all the arguments to their translated
> strings,
> say into the _() function.  The code looked horrible, it's way too much
> typing, and people (well, *I* ;) just won't do it.  After implementing the
> sys._getframe() hack, it made i18n just so much more pleasant and easy to
> write, you almost couldn't not do it.
>

Agreed. At Dropbox we use %(name)s in our i18n strings and the code always
ends up looking ugly.


> One of the things that intrigues me about this whole idea of syntactic and
> compiler support is the ability to narrow down the set of substitution
> values
> available for interpolation, by parsing the source string and passing them
> into the interpolation call.
>
> Currently, _() is forced to expose all of locals and global to
> interpolation,
> although I guess it could also parse out the $-placeholders in the source
> string too[1].  Not doing this does open an information leak vector via
> maliciously translated strings.  If the source string were parsed and
> *only*
> those names were available for interpolation, a maliciously translated
> string
> couldn't be used to expose additional information because the keys in the
> interpolation dictionary would be limited.
>

Yes, this is a real advantage of pursuing the current set of ideas further.


> This mythical scope() could take arguments which would name the variables
> in
> the enclosing scopes it should export.  It would still be a PITA if used
> explicitly, but could work nicely if i-strings essentially boiled down to:
>
>     placeholders = source_string.extract_placeholders()
>     substitutions = scope(*placeholders)
>     translated_string = i18n.lookup(source_string)
>     return translated_string.safe_substitute(substitutions)
>
> That would actually be quite useful.
>

Agreed. But whereas you are quite happy having only simple variable names
in i18n templates, the feature required for the non-i18n use case really
needs arbitrary expressions. If we marry the two, your i18n code will just
have to yell at the programmer if they use something too complex for the
translators as a substitution. So possibly PEP 501 can be rescued. But I
think we need separate prefixes for the PEP 498 and PEP 501 use cases;
perhaps f'{...}' and _'{...}'. (But it would not be up to the compiler to
limit the substitution syntax in _'{...}')

-- 
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20150813/7399c10c/attachment.html>


More information about the Python-ideas mailing list