Opened 17 years ago

Closed 12 years ago

Last modified 12 years ago

#6195 closed New feature (fixed)

Allow caching of the javascript translation library by the client browser

Reported by: jdetaeye Owned by: Aymeric Augustin
Component: Documentation Version: dev
Severity: Normal Keywords: i18 javascript
Cc: charette.s@… Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

A i18 javascript is dynamically generated by django. The script is recreated with every (admin) view using this library, which doesn't make much sense: the same translation dictionary is returned over and over again to the user, increasing the response times and wasting cpu and bandwidth.

This patch allows the client browser to cache this dictionary locally.

Caveats:

  • If a user switches languages on the fly or uses multiple languages at the same time, the javascript library isn't updated automatically to the new language. (A more advanced patch could use the Etag header to cover this case)
  • I put a hard-coded value of one day as the maximum time the user's browser can cache the page. This could be made a setting, with a default of infinite?

I'm putting the ticket in 'design decision required' for the core team to evaluate the usefulness of a patch like this and a choosing the good design for a more solid patch.

Attachments (1)

i18js_caching.patch (592 bytes ) - added by jdetaeye 17 years ago.
simple patch

Download all attachments as: .zip

Change History (17)

by jdetaeye, 17 years ago

Attachment: i18js_caching.patch added

simple patch

comment:1 by jdetaeye, 17 years ago

Patch needs improvement: set
Triage Stage: UnreviewedDesign decision needed

comment:2 by arien, 17 years ago

There isn't much of a case for admin views for this change, I think.

For any non-admin view this can be done using the django.views.decorators.http.conditional_page, django.views.decorators.cache.cache_page and django.views.decorators.vary.vary_on_headers decorators AFAICT. Maybe wrapping the last two up in e.g. django.views.decorators.i18n.cached would be an idea?

(Obviously, the same decorators could be used for the admin's i18n_view as well.)

You could try the group and see what people there think.

comment:3 by Malcolm Tredinnick, 17 years ago

You certainly have to work around the first problem you mention. If the user changes the language, the translations they see must all be updated correctly.

comment:4 by Malcolm Tredinnick, 17 years ago

Triage Stage: Design decision neededSomeday/Maybe

in reply to:  3 comment:5 by Ramiro Morales, 15 years ago

Replying to jdetaeye:

Caveats:

  • If a user switches languages on the fly or uses multiple languages at the same time, the javascript library isn't updated automatically to the new language. (A more advanced patch could use the Etag header to cover this case)

Replying to mtredinnick:

You certainly have to work around the first problem you mention. If the user changes the language, the translations they see must all be updated correctly.

#5691 proposes adding the language name to the cache key.

comment:6 by Gabriel Hurley, 14 years ago

Severity: Normal
Type: New feature

comment:7 by Aymeric Augustin, 13 years ago

UI/UX: unset

Change UI/UX from NULL to False.

comment:8 by Aymeric Augustin, 13 years ago

Easy pickings: unset

Change Easy pickings from NULL to False.

comment:9 by Aymeric Augustin, 12 years ago

Resolution: wontfix
Status: newclosed

I investigated this issue a few months ago for a project of mine.

I found three non-exclusive ways to decorate javascript_catalog to provide caching.

For providing translations in more than one language, the easiest is to include the language code in the URL with i18n_patterns.

1) Server-side caching

key_prefix = 'js18n-%s' % get_version()
@cache_page(86400, key_prefix=key_prefix)

You need a get_version() function that returns a different result whenever the translations change. In production, this isn't difficult, but it depends on your deployment strategy, making it hard for Django to provide a generic solution. In development, you have to use the dummy cache to avoid stale translations.

The full translations catalog will be resent every time, but you'll save the generation cost.

2) Client-side caching with If-Modified-Since:

last_modified_date = timezone.now()
@last_modified(lambda req, **kw: last_modified_date)

last_modified_date changes whenever the server is reloaded (in production, because the code was updated; in development, because the dev server auto-reloaded). It's even better if you can set last_modified_date to the software release date, but that's a bit more difficult to get right than version numbers.

3) Client-side caching with Etag:

etag_value = 'js18n-%s' % get_version()
@etag(lambda req, **kw: etag_value)

In production, this is perfect. Unfortunately, it doesn't work well in development, because it's hard to generate an etag_value that's guaranteed to change when you just edit .po and .mo files.


Neither of these techniques can provide proper cache invalidation without application-supplied information about the software version. Therefore, I think it's best to leave the implementation of caching to application developers. The cache framework provides tools to add caching with one-liners.

comment:10 by Simon Charette, 12 years ago

Cc: charette.s@… added

comment:11 by Aymeric Augustin, 12 years ago

Component: InternationalizationDocumentation
Resolution: wontfix
Status: closednew
Triage Stage: Someday/MaybeAccepted

At the Utrecht sprint we agreed that it's be a good idea to suggest caching in the docs.

Requalifying as a docs ticket and reopening.

comment:12 by Aymeric Augustin, 12 years ago

Owner: changed from nobody to Aymeric Augustin
Status: newassigned

comment:13 by michi88, 12 years ago

Added docs as discussed on the django sprint (Utrecht)
pull request here: https://github.com/django/django/pull/779

As discussed I am not referencing https://pypi.python.org/pypi/django-statici18n but it is a great way to pre-generate the files and serve them as static.
I use this for my own projects.

comment:14 by Aymeric Augustin, 12 years ago

Thanks for your work on this patch!

I'd like to keep this digression on caching relatively short. I'll summarize a bit.

The BDFL lifted the restriction on linking to third-party projects. I'll restore the link to django-statici18n.

comment:15 by Aymeric Augustin <aymeric.augustin@…>, 12 years ago

Resolution: fixed
Status: assignedclosed

In 0836670c5cd8bb17322504c46e07d3944add63c3:

Fixed #6195 -- Documented caching options for javascript_catalog.

comment:16 by Aymeric Augustin <aymeric.augustin@…>, 12 years ago

In 1742fd08f5e2f7353b67b58b4ef9185121ce300e:

[1.5.x] Fixed #6195 -- Documented caching options for javascript_catalog.

Backport of 0836670 from master

Note: See TracTickets for help on using tickets.
Back to Top