| 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 | }} |