Internationalization

nti.app.pyramid_zope.i18n

Support for application-level (request, context and user based) internationalization.

Negotiation

The process of finding a locale to use is somewhat complex. It is all driven around the interface zope.i18n.interfaces.IUserPreferredLanguages and its mutable subclass zope.i18n.interfaces.IModifiableUserPreferredLanguages. These are combined with a zope.i18n.interfaces.INegotiator, given a context and a list of available languages, to determine the best matching locale to use by taking the intersection of the preferred languages of the context with the available languages (individual translation utilities handle fallback and default languages).

Zope provides an implementation of preferred languages for (Zope) requests in zope.publisher.browser.ModifiableBrowserLanguages. This uses the HTTP Accept-Language header to determine a language. We let Pyramid requests also have this implementation through our compatibility shims in nti.pyramid_zope.i18n.

However, there are cases where we may not want to rely on the browser to have the right setting, either for testing, or to support broken browsers, or to explicitly enable user preferences. Supporting user preferences is easy: provide a IUserPreferredLanguages adapter for your IPrincipal implementation. For temporary testing or for the use of unauthenticated users, we can also look at the HTTP cookies _LOCALE_ (Pyramid’s default) and I18N_LANGUAGE (Zope/Plone default), or the _LOCALE_ request parameter (or request attribute); we can even use the ++lang++ namespace to set a language during traversal.

The complexity comes in combining all of these policies. Almost all uses of the translation functions pass the current request as the context, and by default that’s just going to use the Accept-Language based picker. Our solution is to define a new interface nti.app.pyramid_zope.i18n.interfaces.IPreferredLanguagesRequest, deriving from pyramid.interfaces.IRequest and register a policy for that interface. When the pyramid.interfaces.IContextFound event is fired, if the cookies are present or an authenticated user is present, we make the request object provide that interface. In this way, our policy is used to override anything else.

Pyramid/Zope Integration

The Zope I18N system is more powerful and flexible than the Pyramid system. The Pyramid system is based simply on providing one locale name and a list of directories containing translations. We implement Pyramid’s pyramid.interfaces.ILocaleNegotiator and pyramid.interfaces.ITranslationDirectories based on the information we gather from Zope. In this way, the Pyramid Chameleon support, for example, uses the same information as other places.

Important

Make sure and include <include package="nti.app.pyramid_zope.i18n" file="pyramid.zcml" /> from your root pyramid.zcml to register the negotiator.

nti.app.pyramid_zope.i18n.adapters

I18N related adapters.

EnglishUserPreferredLanguages(unused_user)[source]

An implementation of IUserPreferredLanguages that always returns English.

This is registered as the least-specific adapter for generic objects.

class PreferredLanguagesPolicy(request)[source]

Bases: object

Implements the preferred languages policy as documented for this package: an explicit request parameter or cookie will be used first, followed by something set during traversal, followed by a non-default persistent user preference, followed by the value set from the HTTP headers.

preferred_language_locale_negotiator(request)[source]

A pyramid locale negotiator that piggybacks off the preferred language support. We return a valid locale name consisting of at most language-territory, but at least language. A valid locale is one for which we have available locale data, not necessarily one for which any translation data is available.

class ZopeTranslationDirectories[source]

Bases: object

Implements the readable contract of Pyramid’s translation directory list by querying for the zope translation domain objects. This way we don’t have to repeat the configuration.

Note

This queries just once, the first time it is used.

Note

We lose the order or registrations, if that mattered.

nti.app.pyramid_zope.i18n.subscribers

I18N related subscribers.

adjust_request_interface_for_preferred_languages(event)[source]

Checks the conditions outlined in this package’s documentation and adds a marker interface (IPreferredLanguagesRequest) to the request if they hold true.

This is registered as a subscriber for Pyramid’s IContextFound event by this package’s configure.zcml