1

我正在尝试向我正在处理的网站添加对阿拉伯语的支持,所以目前我的模板就像

/templates
    /accounts/
    /includes/
    /rtl
        /accounts/
        /includes/
        ...
    ...

django-allauth 无论如何都会尝试加载模板/templates/accounts(在他们的视图中是硬编码的),但我想在必要时基于上下文变量加载 RTL(从右到左)版本,所以我考虑了四种解决方案,但没有一个它们对我来说似乎已经足够好了(我并不是说我不会这样做,我是说我想不出更好的方法,如果有的话

  1. 在我的覆盖中设置条件以加载 LTR 或 RTL 版本(这将需要条件 in /templates/accounts、带有模板的 LTR 版本以及/templates/rtl/accounts.

  2. 创建一个带有模板名称参数的模板标签并动态加载模板,这看起来很浪费资源

  3. 在具有大量逻辑的主模板中创建混乱,以便在需要时在 LTR 和 RTL 之间切换(这将需要模板中的大量逻辑,这不好)

  4. 将 allauth 分叉到我的项目中并将逻辑添加到视图中。我真的不想这样做,因为这会让将来的维护变得很糟糕。

我没有使用标准的 django i18n,所以我不能使用 BIDI 设置。

有人对此有更好的方法吗?

4

1 回答 1

1

解决了它,最后我不得不使用自定义模板加载器在请求时即时更改模板目录。我在华盛顿时代遵循了一个非常有用的教程:http: //opensource.washingtontimes.com/blog/2010/feb/17/loading-templates-based-request-headers-django/

我并不觉得创建一个本地线程来存储请求(在我的例子中是一个上下文值)的想法真的很有趣,但似乎这是将数据实际传递给模板加载器的唯一方法。

我的代码:

<项目名称>/settings/defaults.py

我们首先加载我们的模板加载器,这样我们就可以在 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's weird...) the request comes trough and
    hits first our code, tries to determine if the market is arabic or not.
    It it's 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' %}

如果有人发现这个答案不完整,请告诉我!:)

于 2014-07-28T14:56:09.807 回答