Django i18n_patterns — как предотвратить префикс неактивных языков

В моем файле django settings.py у меня есть шесть активных языков:

LANGUAGES = (
('de', gettext_noop('German')),
('en', gettext_noop('English')),
('es', gettext_noop('Spanish')),
('fr', gettext_noop('French')),
('nl', gettext_noop('Dutch')),
('pt', gettext_noop('Portuguese')),
)

Эти страницы отлично работают при использовании шаблонов i18n:

 http://exmaple.com/de/main
 http://exmaple.com/nl/main
 etc...

Однако, если вы выполните поиск на моем сайте в Google, вы увидите несколько страниц с языковыми префиксами. Некоторые для языков, которые я не поддерживаю. Некоторые из которых даже не существуют:

http://examble.com/ch/main
http://exmaple.com/zz/main
etc..

Я не уверен, почему эти страницы индексируются. Их нет в моей карте сайта. Однако Django служит им как страницами.

Вопрос: как лучше всего изменить i18n_patterns, чтобы он разрешал только действительные активные языки, определенные в settings.py? Я хотел бы, чтобы все остальные 2-символьные префиксы были 404.


person keithhackbarth    schedule 14.10.2014    source источник
comment
Вы используете CMS для этих страниц, и если да, то какую?   -  person maazza    schedule 22.10.2014
comment
и какую версию вы используете?   -  person maazza    schedule 22.10.2014


Ответы (2)


Лучшее решение (я знаю) — использовать solid-i18n-urls.

Установите пакет:

pip install solid_i18n

Немного изменить настройки:

# Default language, that will be used for requests without language prefix
LANGUAGE_CODE = 'en'

# supported languages
LANGUAGES = (
    ('en', 'English'),
    ('ru', 'Russian'),
)

# enable django translation
USE_I18N = True

#Add SolidLocaleMiddleware instead of LocaleMiddleware to MIDDLEWARE_CLASSES:
MIDDLEWARE_CLASSES = (
   'django.contrib.sessions.middleware.SessionMiddleware',
   'solid_i18n.middleware.SolidLocaleMiddleware',
   'django.middleware.common.CommonMiddleware',
)

Используйте solid_i18n_patterns вместо i18n_patterns

from django.conf.urls import patterns, include, url
from solid_i18n.urls import solid_i18n_patterns

urlpatterns = solid_i18n_patterns('',
    url(r'^main/$', 'about.view', name='about'),
)

Теперь, если вы перейдете к example.com/en/main, он будет работать нормально, так как en указан в списке языков, но если вы перейдете к example.com/ch/main, он выдает ошибку 404 страница не найдена.

person ChillarAnand    schedule 18.10.2014
comment
Извините, @ChillarAnand. Я полагаю, вы не понимаете мой вопрос или не понимаете, что делает solid il8n. В приведенном выше примере я бы хотел, чтобы www.example.com/es/main показывал 404 вместо 200. Solid i8ln не делает этого за вас. Проверено тестированием вашего кода на моем сайте. - person keithhackbarth; 23.10.2014
comment
@keithhackbarth Поправьте меня, если я ошибаюсь. Используя описанную выше процедуру, я сделал рабочий пример, который соответствует вашим требованиям. Просто клонируйте, установите требования, запустите сервер, вот и все. github.com/ChillarAnand/django-internationalization-example . - person ChillarAnand; 23.10.2014
comment
Я искренне извиняюсь, после тестирования вашего примера, я получил его для работы. Моя проблема заключалась в том, что я не удалил ранее существовавший «django.middleware.locale.LocaleMiddleware» из файла настроек. БОЛЬШОЕ ВАМ СПАСИБО ЗА ВАШУ ПОМОЩЬ! - person keithhackbarth; 23.10.2014
comment
Начиная с Django 1.10 это можно сделать без твердых i18n-urls. - person guival; 26.06.2019

Это не прямое решение, но может помочь вам или указать на хорошее решение.

  • Как насчет пользовательского промежуточного ПО?

Здесь у нас есть 2 варианта:

  1. Промежуточное программное обеспечение, в котором вы проверяете страну пользователя и перенаправляете в разрешенные страны (если страна пользователя не разрешена, вы можете перенаправить на собственный URL-адрес или показать ошибку 404)

  2. Промежуточное программное обеспечение, в котором вы проверяете URL-адрес клиента, поэтому у вас будет /country_code/url, и вы можете сделать, как указано выше, если путь не разрешен, вы можете перенаправить на пользовательский URL-адрес или показать ошибку 404.

Маленькие примеры:

1. Промежуточное ПО для проверки страны

pygeoIP используется в примере для получения страны по IP

import pygeoip

class CountryMiddleware:
    def process_request(self, request):
        allowed_countries = ['GB','ES', 'FR']  # Add your allowed countries
        gi = pygeoip.GeoIP('/usr/share/GeoIP/GeoIP.dat', pygeoip.MEMORY_CACHE)
        ip = request.META.get('REMOTE_ADDR')
        user_country = gi.country_code_by_addr(ip)

        if user_country not in allowed_countries:
            return HttpResponse... # Here you decide what to do if the url is not allowed
            # Show 404 error
            # or Redirect to other page... 

2. Промежуточное ПО для проверки URL

class DomainMiddleware:
    def process_request(self, request):
        """Parse out the subdomain from the request"""        
        # You especify full path or root paths
        # If you specify '/en' as allowed paths, '/en/whatever' are allowed
        ALLOWED_PATHS = ['/en','/fr', '/es']  # You add here allowed paths'
        path = request.path
        can_access = False
        for url in ALLOWED_PATHS:  # Find if the path is an allowed url 
            if url in path:  # If any allowed url is in path
                can_access=True
                break

        if not can_access:  # If user url is not allowed
            return HttpResponse... # Here you decide what to do if the url is not allowed
            # Show 404 error
            # or Redirect to other page... 

Если вы решите использовать любой из этих вариантов, вы должны помнить:

  • Вам нужно добавить файлы промежуточного ПО по пути your_project/middleware/middlewarefile.py
  • Вам нужно добавить промежуточное ПО в файл settings.py:

    MIDDLEWARE_CLASSES = (

    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    # etc.....
    'yourproject.middleware.domainmiddleware.DomainMiddleware',
    

    )

  • Код, который я показал здесь, не завершен и не протестирован, это ориентир, который поможет вам найти хорошее решение.

person AlvaroAV    schedule 23.10.2014