| | 270 | |
| | 271 | == Page Generation with Localized Templates == |
| | 272 | |
| | 273 | In order to use the modified Template stream, we basically need to do some processing before the normal Genshi mechanism takes over... |
| | 274 | |
| | 275 | This class allows inclusion of "prefilters" that operate before the Template stream's standard filters (you can't just use a filter to do this, it causes problems): |
| | 276 | {{{ |
| | 277 | #!python |
| | 278 | class PrefilterMarkupTemplate(genshi.template.MarkupTemplate): |
| | 279 | """Derived markup template that can receive prefilters in its generate method""" |
| | 280 | # TODO: try and upstream this into genshi |
| | 281 | def generate(self, prefilters, *args, **kwargs): |
| | 282 | """Apply the template to the given context data. |
| | 283 | |
| | 284 | Any keyword arguments are made available to the template as context |
| | 285 | data. |
| | 286 | |
| | 287 | Only one positional argument is accepted: if it is provided, it must be |
| | 288 | an instance of the `Context` class, and keyword arguments are ignored. |
| | 289 | This calling style is used for internal processing. |
| | 290 | |
| | 291 | @return: a markup event stream representing the result of applying |
| | 292 | the template to the context data. |
| | 293 | """ |
| | 294 | if args: |
| | 295 | assert len(args) == 1 |
| | 296 | ctxt = args[0] |
| | 297 | if ctxt is None: |
| | 298 | ctxt = genshi.template.Context(**kwargs) |
| | 299 | assert isinstance(ctxt, genshi.template.Context) |
| | 300 | else: |
| | 301 | ctxt = genshi.template.Context(**kwargs) |
| | 302 | |
| | 303 | stream = self.stream |
| | 304 | for prefilter in prefilters: |
| | 305 | # TODO: add support for context in prefilters |
| | 306 | stream = prefilter(iter(stream)) |
| | 307 | for filter_ in self.filters: |
| | 308 | stream = filter_(iter(stream), ctxt) |
| | 309 | return genshi.core.Stream(stream) |
| | 310 | }} |
| | 311 | |
| | 312 | This derived class then allows you to call the above localization function as a prefilter on templates. It uses the domain_name as a parameter (this corresponds to which PO/MO file to use for translation, but assumes you can construct or retrieve a translation object for the current user on the fly using a get_translation function (not described here): |
| | 313 | {{ |
| | 314 | #!python |
| | 315 | class LocalizeMarkupTemplate(PrefilterMarkupTemplate): |
| | 316 | """Derived markup template that can handle localizing before stream generation""" |
| | 317 | def __init__(self, source, basedir=None, filename=None, loader=None, |
| | 318 | encoding=None, domain_name=None): |
| | 319 | """Initialize a template from either a string or a file-like object.""" |
| | 320 | super(LocalizeMarkupTemplate, self).__init__(source, basedir=basedir, filename=filename, loader=loader, encoding=encoding) |
| | 321 | self.domain_name = domain_name |
| | 322 | |
| | 323 | def localize_prefilter(self, stream): |
| | 324 | """prefilter for localizing...""" |
| | 325 | translation = get_translation(self.domain_name) |
| | 326 | stream = genshi.core.Stream(stream) |
| | 327 | localized_stream = genshigettext.localize_template(stream, translation.ugettext) |
| | 328 | return list(iter(localized_stream)) |
| | 329 | |
| | 330 | # TODO: try and persuade genshi to accept a stream directly here instead of using self.stream - or accept prefilters |
| | 331 | # then we won't use such fragile copied code... |
| | 332 | def generate(self, prefilters, *args, **kwargs): |
| | 333 | """Apply the template to the given context data. |
| | 334 | |
| | 335 | Any keyword arguments are made available to the template as context |
| | 336 | data. |
| | 337 | |
| | 338 | Only one positional argument is accepted: if it is provided, it must be |
| | 339 | an instance of the `Context` class, and keyword arguments are ignored. |
| | 340 | This calling style is used for internal processing. |
| | 341 | |
| | 342 | @return: a markup event stream representing the result of applying |
| | 343 | the template to the context data. |
| | 344 | """ |
| | 345 | return super(LocalizeMarkupTemplate, self).generate(prefilters + [self.localize_prefilter], *args, **kwargs) |
| | 346 | }} |