meeb / django-distill

Minimal configuration static site generator for Django
MIT License
441 stars 35 forks source link

Generate pages for all languages #80

Closed GergelyKalmar closed 5 months ago

GergelyKalmar commented 1 year ago

Currently django-distill only generates the pages for the language that is set in settings.LANGUAGE_CODE. It would be great if django-distill could generate pages for URLs that are in i18n_patterns for each language in settings.LANGUAGES.

That is, having this settings file:

LANGUAGES = [
    ('en-us', 'English (United States)'),
    ('en-gb', 'English (United Kingdom)'),
]
LANGUAGE_CODE = 'en-us'

and this urls.py file:

from django.conf.urls.i18n import i18n_patterns
from django.utils.translation import gettext_lazy as _
from django_distill import distill_path

urlpatterns = [
    *i18n_patterns(distill_path(route=_('localization/'), view=..., name='localization')),
]

We should get the following files:

output/en-us/localization/index.html
output/en-gb/localisation/index.html

Note that the appropriate links already work with runserver, we would only need to identify internationalized pages and generate them somehow.

meeb commented 1 year ago

Thanks for the suggestion. That is probably not that much work to add so I'll pop it on the wishlist for the next release.

meeb commented 5 months ago

I've added this such that if settings.USE_I18N is True and settings.DISTILL_LANGUAGES is populated, while your URLs are registered via i18n_patterns then your output pages should be called with the language code prefix correctly. Just don't use distill_file to override the file path or the automagic language prefix file names will be overwritten. I'll bundle this into the next release. See:

https://github.com/meeb/django-distill?tab=readme-ov-file#internationalization

GergelyKalmar commented 4 months ago

This is awesome, thank you! I can confirm it works as expected in my use case. There's only one question I'd have: why use a separate DISTILL_LANGUAGES option instead of just relying on the standard LANGUAGES option? Right now I need to mention the languages twice in my settings:

    # Internationalization
    LANGUAGES = [
        ('en-us', _('English (United States)')),
        ('en-gb', _('English (United Kingdom)')),
    ]
    DISTILL_LANGUAGES = ['en-us', 'en-gb']

I'd just use the standard config option, with the option to perhaps override it with DISTILL_LANGUAGES. What do you think of that?

meeb commented 4 months ago

This is because the default settings.LANGUAGES in Django has an ever expanding massive list of languages by default if you don't set it manually:

>>> len(settings.LANGUAGES)
96

If I had just used LANGUAGES anyone who was not building multi-language sites and overriding LANGUAGES (like yourself) would suddenly have had all of their static pages generate 96 (or however many languages their version of Django has in its default languages) times each when rendering the site after upgrading distill. I did actually use LANGUAGES in my first commit, then had to change it when I noticed it was suddenly rendering every page 96 times outside of the test suite. The change from settings.LANGUAGES to settings.DISTILL_LANGUAGES is here: https://github.com/meeb/django-distill/commit/c242eb17c93a4fae8803b847c101a3d7b1315cfb

I missed this myself initially as I override LANGUAGES in the test suite settings.py. While the extra settings constant isn't as "clean" and I don't particularly like things like DISTILL_LANGUAGES = [cc for (cc, name) in LANGUAGES] in my settings.py there wasn't much alternative.

GergelyKalmar commented 4 months ago

Ah, interesting! You are right, I forgot about this default as well. Okay, how about defaulting to LANGUAGES if it does not match the Django default (I assume it can be compared against in https://github.com/django/django/blob/main/django/conf/global_settings.py)? Or does that add too much magic?

This way people who explicitly set the LANGUAGES will need to do it only once, and for all the others it will just generate the one that LANGUAGE_CODE specifies.

meeb commented 4 months ago

Sure that sounds reasonable. I've added that feature with the above commit. It does add quite a bit of "magic" but it's unlikely to trip anyone up given it's more on the syntactic sugar end of magic and not incomprehensible madness magic.

settings.LANGUAGES will be listened to if they are different to global_settings.LANGUAGES, however settings.DISTILL_LANGUAGES will also be listened to so it doesn't replace any existing options. In your use case, you could just use LANGUAGES as you want.

I'll merge this into the next release.

GergelyKalmar commented 4 months ago

Amazing, thank you very much!