如何配置Django网站默认俄语并支持用户切换至英文(基于i18n)
Hey there! Your current configuration is already 90% of the way there—let's refine it and add the necessary pieces to make the language switch work seamlessly for your users.
1. Confirm Your Core Configuration is Correct
First, let's double-check your settings to ensure they align with your goal. Here's the validated version with key context:
import os from django.utils.translation import gettext_lazy as _ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', # Critical: LocaleMiddleware needs to come after this 'django.middleware.locale.LocaleMiddleware', # Your placement here is perfect! 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] LANGUAGE_CODE = 'ru' # Forces Russian as the default language for all first-time visitors LANGUAGES = ( ('ru', _('Russian')), ('en', _('English')), ) LOCALE_PATHS = ( os.path.join(BASE_DIR, 'locale'), # Where your translation files are stored ) TIME_ZONE = 'Europe/Kiev' USE_I18N = True USE_L10N = True USE_TZ = True
Key Notes:
- The
LocaleMiddlewareposition matters: it must sit afterSessionMiddleware(to remember user preferences) and beforeCommonMiddleware(to apply language settings to requests). - Using
gettext_lazy as _ensures the language names (like "Russian" or "English") are translatable if you ever want to localize those labels.
2. Add Language Switch Functionality
To let users toggle to English, you need two key components: a URL route for the language switch view, and a template form to trigger it.
Step 2.1: Update Your URLconf
Add this line to your project's main urls.py to enable Django's built-in language switch view:
from django.conf.urls import include # Your existing URL patterns here # Add this to activate the set_language endpoint urlpatterns += [ path('i18n/', include('django.conf.urls.i18n')), ] # Optional: If you want URL prefixes (e.g., /en/ or /ru/), use i18n_patterns # urlpatterns += i18n_patterns( # path('', include('your_app.urls')), # )
Step 2.2: Add a Language Switch Form in Your Template
Insert this form wherever users should access the language toggle (e.g., site header, footer):
<form action="{% url 'set_language' %}" method="post"> {% csrf_token %} <input name="next" type="hidden" value="{{ request.path }}"> <select name="language" onchange="this.form.submit()"> {% get_current_language as LANGUAGE_CODE %} {% get_available_languages as LANGUAGES %} {% get_language_info_list for LANGUAGES as languages %} {% for language in languages %} <option value="{{ language.code }}" {% if language.code == LANGUAGE_CODE %}selected{% endif %}> {{ language.name_local }} ({{ language.code }}) </option> {% endfor %} </select> </form>
How this works:
- The form submits to Django's
set_languageview, which saves the user's language preference in their session. - The
nexthidden input ensures users stay on the same page after switching languages. - The dropdown shows languages with their local names (e.g., "Русский" for Russian, "English" for English) for better user clarity.
3. Validate Your Translation Files
Make sure your translation files are properly set up:
- Extract translatable strings into
.pofiles:python manage.py makemessages -l ru -l en - Edit the
.pofiles inlocale/ru/LC_MESSAGES/django.poandlocale/en/LC_MESSAGES/django.poto add your translated content. - Compile the
.pofiles into binary.mofiles (Django uses these to load translations):python manage.py compilemessages
Final Checks
- Test your site: First-time visitors should see Russian by default.
- Use the dropdown to switch to English—your session will remember this preference on subsequent visits.
- If you use
i18n_patterns, URLs will automatically get language prefixes (like/en/about), which is great for SEO and direct linking.
内容的提问来源于stack exchange,提问作者yaschk1

