Я пытаюсь добавить поддержку арабских языков на сайт, над которым я работаю, поэтому в настоящее время мои шаблоны похожи
/templates
/accounts/
/includes/
/rtl
/accounts/
/includes/
...
...
django-allauth попытается загрузить шаблоны из /templates/accounts
независимо от того, что (жестко запрограммировано в их представлениях), но я хочу загрузить версию RTL (справа налево) на основе контекстной переменной, когда это необходимо, поэтому я подумал о четырех решениях, но ни один из них не кажется мне достаточно хорошим (я не говорю, что я их не буду делать, я говорю, что я не могу найти лучший способ, если он есть)
-
Задайте условие в моих переопределениях для загрузки версий LTR или RTL (для которых требуется условное значение в
/templates/accounts
, версия LTR с шаблоном где-то еще и версия RTL в/templates/rtl/accounts
. -
Создайте тег шаблона, который имеет параметр с именем шаблона и динамически загружает шаблон, это выглядит как пустая трата ресурсов
-
Создайте беспорядок в основных шаблонах с тоннами логики, чтобы он переключался между LTR и RTL, когда это было необходимо (для этого потребуется тонна логики в шаблоне, что не очень хорошо)
-
Вилка allauth в мой проект и добавить логику к представлениям. Я действительно не хочу этого делать, потому что в будущем это будет поддерживать ад.
Я не использую стандартный django i18n, поэтому я не могу использовать настройки BIDI.
У кого-то есть лучший подход к этому?
Решив это, я в конце концов должен был использовать пользовательский загрузчик шаблонов для изменения каталога шаблонов на лету в момент запроса. Я последовал за очень полезным учебным пособием от ребята в разное время: http://opensource.washingtontimes.com/blog/2010/feb/17/loading-templates-based-request-headers-django/
Мне не очень нравится идея создания локального потока для хранения запроса (в моем случае значение контекста), но кажется, что единственный способ фактически передать данные загрузчику шаблонов.
Мой код:
<projectname>/settings/defaults.py
Мы загружаем загрузчик шаблонов FIRST, поэтому мы можем обрабатывать данные, прежде чем django загрузит что-нибудь. Если в нашем коде что-то не получится, оно вернется к загрузчикам django по умолчанию.
TEMPLATE_LOADERS = (
'projectname.templateloaders.arabic.load_template_source',
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
#'django.template.loaders.eggs.Loader',
)
<имя_проекта>/middleware/templaterequest.py
# -*- coding: utf-8 -*-
try:
from threading import local
except ImportError:
from django.utils._threading_local import local
from apps.locales.models import Locale
from apps.markets.models import Market
# for more info:
# http://opensource.washingtontimes.com/blog/2010/feb/17/loading-templates-based-request-headers-django/
_thread_locals = local()
def get_current_request():
return getattr(_thread_locals, 'arabic', None)
class RequestMiddleware(object):
"""
This middleware will store the market.rtl value at each request that is made.
Basically here you can do anything that you can get from the request.
In this case we get the locale and the market settings and extract the RTL
value, which we store in a local thread in memory an will be retrieved
later by the template loader when calling for get_current_request()
"""
def process_request(self, request):
site = request.META['HTTP_HOST']
locale = Locale.objects.get(site=site)
market = Market.objects.get(locale=locale)
_thread_locals.arabic = market.rtl
<имя_проекта>/templateloaders/arabic.py
# -*- coding: utf-8 -*-
from django.conf import settings
from django.template.loader import BaseLoader, TemplateDoesNotExist
from django.utils._os import safe_join
from tipx.middleware.templaterequest import get_current_request
def get_template_sources(template_name, template_dirs=None):
"""
This class will modify the template directory in case the market has
RTL activated in the market settings. If RTL if False it will pass and
let the standard django template loaders to work.
Explanation of how it behaves (it weird...) the request comes trough and
hits first our code, tries to determine if the market is arabic or not.
It it arabic it changes the template directory to /rtl/, but for example
third party templates are not there (except for the overrides), so it will
continue processing through the template loaders until it finds the right
template. This guarantees that no matter how twisted our template locations
are, it will always load the right templates in the right moment even
when the templates have includes from RTL to english.
"""
arabic = get_current_request()
if arabic:
# Loop through the template dirs
for directory in settings.TEMPLATE_DIRS:
new_directory = directory + '/rtl/'
yield safe_join(new_directory, template_name)
def load_template_source(template_name, template_dirs=None):
for filepath in get_template_sources(template_name, template_dirs):
try:
file = open(filepath)
try:
return (file.read().decode(settings.FILE_CHARSET), filepath)
finally:
file.close()
except IOError:
pass
raise TemplateDoesNotExist(template_name)
load_template_source.is_usable = True
Последнее, что нужно иметь нашу папку шаблонов RTL. Если какой-либо из ваших шаблонов включает, вам нужно будет добавить имя папки, которое у вас есть для вашей арабской версии, например:
Оригинал включает:
{% include 'whatever/template.html' %}
RTL включает:
{% include 'rtl/whatever/template' %}
Если кто-то найдет этот ответ неполным, просто скажите мне! 🙂