Günümüz web siteleri artık çok daha geniş kitlelere hitap etmektedir. Bu sebeple bir web sitesi yaparken çoğunlukla birden fazla dil desteğinin olması öngörülür. Django, uluslararasılaştırma (internationalization) ve yerelleştirme (localization) için güçlü bir çerçeve sunar. Bu çerçeve sayesinde, uygulamanızı birden çok dile çevirebilir ve kullanıcıların kendi dillerini seçmesine izin verebilirsiniz.
Bu yazımda sizlere Django web sitesine çoklu dil desteği ekleme nasıl yapılır tüm detaylarıyla anlatacağım. Yani sadece Django'nun dahili çoklu dil desteği sistemini değil, aynı zamanda işinizi oldukça kolaylaştıracak Rosetta (django-rosetta
) ve Parler (django-parler
) gibi ek kütüphanelerden de bahsedeğiz.
İçindekiler:
- Internationalization (i18n) / Uluslararasılaştırma Nedir?
- Localization (L10N) Yerelleştirme Nedir?
- Django'da Çoklu Dil Kullanımı
- Django Rosetta Çeviri Arayüzü
- Django Parler İle Modelleri Çevirin
- Son Söz
Internationalization (i18n) / Uluslararasılaştırma Nedir?
Uluslararasılaştırma, uygulamanızın farklı diller için hazır duruma getirilmesidir. Bu, uygulamanızdaki metinlerin ve diğer yerelleştirilebilir verilerin, yani çevirilebilir yazıların, farklı dillere çevrilmeye hazır bir şekilde yazılımcı tarafından düzenlenmesini içerir. Kafanızda çok fazla birşey canlanmadıysa endişelenmeyin. Yazı sonunda hepsine hakim olacaksınız.
Django'da uluslararasılaştırmayı etkinleştirmek için, settings.py
dosyasında aşağıdaki ayarları yapmanız gerekir:
# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/
LANGUAGE_CODE = 'tr'
TIME_ZONE = 'Europe/Istanbul'
USE_I18N = True
USE_L10N = True
USE_TZ = True
Bu ayarlar, uygulamanızın birden çok dile çevrilebileceğini belirtir. Gelin yukarıdaki ayarları biraz daha açıklayalım:
LANGUAGE_CODE değişkeni ile aslen sitemizin hangi dilde olacağını, yani varsayılan dilini tanımlıyoruz. Varsayılan olarak en-us
yerele özgü (locale-specific) tanımıyla gelir. Bunun genel (generic) tanımı ise en
şeklinde yazılır. Türkçe için genel tanım tr
olacaktır.
Not: LANGUAGE_CODE
'un aktif olabilmesi için ayrıca Django'nun çeviri sistemini etkinleştiren USE_I18N
değişkeninin True
olarak ayarlanmış olması gerekmektedir.
TIME_ZONE varsayılan olarak America/Chicago
tanımıyla gelir. Tüm tz veritabanı saat dilimlerinin listesi burada yer almaktadır. USE_TZ
değişkeni False
olduğunda bu, Django'nun tüm "datetimes
" verilerinin depolayacağı saat dilimidir. USE_TZ
değişkeni True
olduğunda bu, Django'nun şablonlarda "datetimes
" görüntülemek ve formlara girilen "datetimes
" yorumlamak için kullanacağı varsayılan saat dilimidir. Türkiye için Europe/Istanbul
saat dilimini yazıyoruz.
USE_TZ varsayılan olarak False
tanımıyla gelir. Django çoklu dil kullanımında True
tanımını tavsiye eder. Aktif olduğunda datetimes
saat dilimine duyarlı olur.
USE_I18N varsayılan olarak True
tanımıyla gelir. Yukarıda da bahsettiğim üzere çoklu dil mekanizmasının çalışması için bu değişkenin True
olarak tanımlanması gerekmektedir.
USE_L10N varsayılan olarak True
tanımıyla gelir. Yerelleştirme mekanizmasının çalışması için için bu değişkenin True
olarak tanımlanması şarttır.
Localization (L10N) Yerelleştirme Nedir?
Yerelleştirme, uygulamanızın farklı dillere uyarlanmasıdır, yani sitenize birden fazla dilin tanımlanmasını sağlar. Bu, uygulamanızın kullanıcı arayüzü, hata mesajları ve diğer yerelleştirilebilir verilerin, farklı dillere göre uyarlanmasını içerir.
Django'da yerelleştirmeyi yapmak için, uygulamanız için dil dosyaları oluşturmanız gerekir. Bu dosyalar, uygulamanızdaki metinlerin ve diğer yerelleştirilebilir verilerin, farklı dillere çevrilmiş halini içerir.
Django yerelleştirme mekanizması .po dosyalarının derlenmesi için gettext fonksiyonunu kullanır.
Windows ve Linux'te Gettext Yükleme
Windows kullanıcıları için gettext
yüklemek için buraya tıklayabilirsiniz. Ubuntu Linux'te gettext
yüklemek için aşağıdaki komutu kullanabilirsiniz:
sudo apt update -y
sudo apt install -y gettext
Yerelleştirme Ayarları
Öncelikle sitemizde tanımlamak istediğimiz dilleri settings.py
dosyamızda tanımlıyoruz.
from django.utils.translation import gettext_lazy as _
LANGUAGES = (
('tr', _('Türkçe')),
('en', _('İngilizce')),
)
LANGUAGE_CODE
tanımımızda varsayılan dil olarak Türkçe'yi ayarladığımız için ilk sıraya da onu yazıyoruz ve dil isimlerini de varsayılan dilde yazıyoruz. Burada dikkatinizi "_
" alt çizgi işareti çekmiş olmalı. Bu gettext
kütüphanesinin çeviri olarak tanımlayacağımız alanları işaretlememize yarayan fonksiyon. Bu sayede çevirilerimizi derlediğimizde gettext bu alanların çeviriye dahil edileceğini bilir. Bir diğer önemli husus ise, django çeviri sisteminden bu fonksiyonu gettext_lazy
ile çağırmış olmamız. Bu sayede circular import
(dairesel yükleme) hatalarının önüne geçebiliyoruz.
Yerelleştirme sistemini kullanmadan önce settings.py
dosyanızdaki MIDDLEWARE
ayarlarında aşağıdaki gibi LocaleMiddleware
tanımını SessionMiddleware
den sonra ve CommonMiddleware
den önce eklendiğinizden emin olun.
MIDDLEWARE = [
...
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware', # çoklu dil desteği için eklenmeli
'django.middleware.common.CommonMiddleware',
...
]
Django, makemessages
komutunu kullanarak dil dosyaları oluşturmanıza yardımcı olur. Bu komut, uygulamanızdaki tüm yerelleştirilebilir verileri tarar ve bunları, locale/
dizini altında bulunan dil dosyalarına dönüştürür.
Ancak öncesinde settings.py dosyamızda LOCALE_PATHS
yolunun tanımlamasını yapmamız gerekmektedir.
LOCALE_PATHS = [
BASE_DIR / 'locale/',
]
Bu kod sayesinde gettext
ile oluşturulan çeviri dosyalarımız projemizin anadizininin locale/
klasöründe olduğunu belirtmiş oluruz.
Dil Dosyalarını Oluşturma
Dil dosyalarını oluşturmak için, Linux'te aşağıdaki komutu çalıştırın:
python manage.py makemessages -l tr -l en
Bu komut, Türkçe ve İngilizce dilleri için dil dosyaları oluşturacaktır. Dilerseniz dilleri ayrı ayrı yazmadan tüm dillerin oluşturulmasını aşağıdaki komutla da sağlayabilirsiniz.
python manage.py makemessages --all
PyCharm gibi bir IDE içindeki terminalde kullanım için aşağıdaki komutu kullanabilirsiniz:
django-admin makemessages --all --ignore=env
Bu komutlardan sonra gettext belirlediğimiz tüm çeviri alanlarını tespit edecek ve projenizin anadizininde aşağıdaki gibi klasörler oluşacaktır:
locale
└── en
└── LC_MESSAGES
└── django.po
.po dosyalarımızı *.po dosya formatını düzenleyebilen bir editörde açabilir veya IDE içerisinde açıp text olarak düzenleyebilirsiniz. Örnek olarak:
msgid "Türkçe"
msgstr "Turkish"
Varsayılan dilimiz Türkçe olduğundan ve haricinde sadece İngilizce dili olduğundan en/ klasörü oluşturuldu ve dolayısıyla .po dosyasındaki msgstr
alanına da İngilizce karşılıklarını yazıyoruz.
Dil Dosyalarını Derleme
Dil dosyalarını oluşturduktan sonra, bunları compilemessages
komutunu kullanarak derlemeniz gerekir. Bu komut, dil dosyalarını, uygulamanız tarafından kullanılabilecek bir formata dönüştürür.
Dil dosyalarını derlemek için, Linux'te aşağıdaki komutu çalıştırın:
python manage.py compilemessages
PyCharm gibi bir IDE içindeki terminalde kullanım için aşağıdaki komutu kullanabilirsiniz:
django-admin compilemessages --ignore=env
Django'da Çoklu Dil Kullanımı
Django'da çoklu dil kullanmak için, uygulamanızdaki metinleri ve diğer yerelleştirilebilir verileri modellerde, görünümlerde, formlarda ve template şablonlarında işaretlememiz gerekmektedir. Bunu size nasıl yapacağımızı size aşağıda detaylı olarak anlatacağım.
Çeviri Alanlarını İşaretleme
Django'da çeviri alanlarını işaretlemek için gettext
veya gettext_lazy
fonksiyonu kullanıyoruz. Ben size gettext_lazy
fonksiyonunu kullanmanızı yukarıda tavsiye etmiştim. Örneklerimizi de bu şekilde vereceğiz. gettext_lazy
fonksiyonunu çağırmak için aşağıdaki kodu çağırmak gerekir:
from django.utils.translation import gettext_lazy as _
Fark ettiyseniz çağırırken gettext_lazy
'yi "_
" alt tire ismiyle çağır dedik. Bu sayede çevirilecek alanları işaretlerken sadece başına "_
" alt tire koymamız yeterli olacak. settings.py
dosyamızda ayarladığımız LANGUAGE
değişkeninde dilleri nasıl tanımladığımızı hatırlayın:
LANGUAGES = (
('tr', _('Türkçe')),
('en', _('İngilizce')),
)
"_
" alt tire ile başlayan ve sonrasında parantez içerisinde belirttiğimiz ifade artık çeviri için işaretlenmiş oldu. Bunu tüm string
(str) verilerimizde uygulayabilmemiz mümkün. Dil dosyasını makemessages
komutu ile oluşturduğumuzda otomatik olarak bu alanlar çeviri dosyamıza eklenecek.
Model İçinde Çeviri İşaretleme
Django'da model.py dosyalarımızda çevrilmesini istediğimiz alanları aşağıdaki şekilde kolayca işaretleyebiliriz.
from django.db import models
from django.utils.translation import gettext_lazy as _
class Blog(models.Model):
title = models.CharField(_('Sayfa Başlığı'), max_length=150, unique=True)
short_description = models.TextField(_('Kısa Açıklama'), max_length=300)
published_date = models.DateTimeField(_('Yayınlanma Tarihi'), default=timezone.now)
def __str__(self):
return self.title
Görünümlerin (Views) ve Formların (Forms) İçinde Çeviri İşaretleme
Model içinde işaretlemeyle aynı mantıktadır. Çevirisini yapmak istediğiniz ifadenin önünü "_
" işareti ile ifadeyi parantez içine almanız yeterlidir. Bir örnek de formlar için verelim.
from django import forms
from django.utils.translation import gettext_lazy as _
class OrnekForm(forms.Form):
first_name = forms.CharField(label=_('İsim'))
Yukarıdaki örneklerde gördüğünüz üzere çeviri işaretleme oldukça basit. Gelin bir de bunun şablonlar (templates
) içerisinde nasıl yapıldığını öğrenelim.
Şablonlar (Templates) İçinde Çeviri İşaretleme
Şablonların içinde çeviri alanı işaretleme model, görünüm veya diğer alanlardaki "_
" işaretiyle işaretlemeden biraz daha farklıdır. Django şablonlar için bize {% translate %}
ve {% blocktranslate %}
isminde iki tamplate tag (şablon etiketi) sunar. Bu şablon etiketlerini kullanabilmek için HTML kodunuzun en üstüne {% load i18n %}
kodunu eklemeniz yeterli olacaktır.
Örnek olarak aşağıdaki gibi bir kodumuz olsun:
...
<meta name="title" content="Test Blog Sayfası Başlığı">
<h1>Test Blog Yazısı</h1>
<a href="#" title="">{{ post.title }} yazını oku.</a>
<div>Yayınlanma Tarihi:<br>{{ post.published_date }}</div>
...
Bu kodu işaretlemek için şu şekilde düzenleme yapmamız gerekirdi.
{% load i18n %}
...
<meta name="title" content="{% translate "Test Blog Sayfası Başlığı" %}">
<h1>{% translate "Test Blog Yazısı" %}</h1>
<a href="#" title="">{% blocktranslate %}'{{ post.title }}' yazını oku.{% endblocktranslate %}</a>
<div>{% blocktranslate %}Yayınlanma Tarihi:<br>{{ post.published_date }}{% endblocktranslate %}</div>
...
Gördüğünüz gibi translate
etiketini kullanırken içerisinde string (metin) dışında herhangi bir ifade bulunmazken, blocktranslate
etiketinin içerisinde şablon değişkeni veya html kodu kullanabiliyoruz.
İşaretlemeleriniz bittikten sonra yukarıdaki Dil Dosyasını Oluşturma bölümünde de anlattığım makemessages
komutuyla çeviri dosyanızı oluşturabilir ve oluşturulan .po
dosyanızın içerisindeki "msgstr
" alanlarına ilgili çevirileri ekledikten sonra Dil Dosyalarını Derleme bölümünde anlattığım compilemessages
komutunu kullanarak çevirilerinizi derleyebilirsiniz.
Django herhangi bir ek uygulama gerektirmeden dil dosyalarımızı oluşturup derlememize olanak sağlıyor. Ancak bunu çok daha güzel ve kolay şekilde yapmanın yöntemi de var. .po
dosyasının içerisinde msgstr
değişkenlerini düzenlemek yerine, doğrudan Django admin panelinden bu işlemleri göster bir arayüz kullanarak da yapabilirsiniz. Bunun için projemize Rosetta kütüphanesini dahil etmemiz gerekiyor.
URL Modelleri İçin Dil Ön Eki (prefix) Ekleme ve URL Çeviri İşaretleme
Django çoklu dil kullanımında URL katmanı için de oldukça geniş imkanlar sunar. Eğer sitenize çoklu dil eklemek istiyorsanız, url adresinizin sonunda dil tanımının da gözükmesi doğru olacaktır. Örnek olarak: siteadresi.com/tr/ veya siteadresi.com/en/ şeklinde dili ifade edecek prefix eklenmesi gerek kullanıcılar açısından, gerek ise SEO açısından doğru tercih olacaktır. Bu işlevi tanımlayabilmek için projemizin ana dizinindeki urls.py
dosyamızda ufak bir değişikliğe ihtiyacımız olacak. Django bunun için bize i18n_patterns
fonksiyonunu sunuyor.
... # diğer eklediğiniz modüller
from django.urls import path, include
from django.conf.urls.i18n import i18n_patterns
urlpatterns = i18n_patterns(
path('admin/', admin.site.urls),
path('', include('mainsite.urls')),
)
i18n_patterns()
fonksiyonu ile projemizin ana url dosyasında yukarıdaki gibi tanımlama yaptığımızda, web sitesinin tüm sayfalarının url adresinde aktif dil prefix'i eklenmiş olacak. Ancak bazı durumlarda url dosyamızda ekleyebileceğimiz url'lerin dil prefix'ini göstermesini istemeyebilirsiniz. Bunun için şöyle bir düzenleme yapabilirsiniz:
... # diğer eklediğiniz modüller
from django.urls import path, include
from django.conf.urls.i18n import i18n_patterns
urlpatterns = i18n_patterns(
path('admin/', admin.site.urls),
path('', include('mainsite.urls')),
) + [
path('sitemap.xml', sitemap, {'sitemaps': sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
path('robots.txt', TemplateView.as_view(template_name="robots.txt", content_type='text/plain')),
path('service-worker.js', TemplateView.as_view(template_name="service-worker.js", content_type='text/javascript')),
]
Ayrıca istersek herhangi bir sayfamızın url adresini dile göre çevirebiliriz de. Bunun için de dilediğiniz url dosyasında aşağıdaki gibi değişiklik yapmanız yeterli olur.
from django.urls import path
from django.utils.translation import gettext_lazy as _
from mainsite.views import IndexView, AboutmeView
app_name = 'mainsite'
urlpatterns = [
path('', IndexView.as_view(), name='index'),
path(_('hakkimda/'), AboutmeView.as_view(), name='about-me'),
]
Fark ettiğiniz gibi url'ler için de çeviri işaretleme aynı diğer katmanlarda olduğu gibi gettext_lazy
ile "_
" tanımını kullanarak yapılıyor. İşaretleme sonrası aynı diğer katmanlarda yaptığımız gibi makemessages
komutuyla çeviri dosyanızı oluşturabilir ve oluşturulan .po
dosyanızın içerisindeki "msgstr
" alanlarına ilgili çevirileri ekledikten sonra compilemessages
komutunu kullanarak çevirilerinizi derleyebilirsiniz. Türkçe dil seçeneği ile sitenize giren kullanıcı siteadresi.com/tr/hakkimda/ url'ini görecekken, İngilizce diliyle giren kullanıcı siteadresi.com/en/about-me/ url'ini görecektir.
Kullanıcıların Dil Değiştirmesini Sağlama
Django web sitemizde kullanıcıların mevcut dilleri görüp diller arası geçiş yapmasını sağlamak oldukça kolaydır. Bunun birkaç farklı yöntemi olmakla birlikte, aslında bunlar yöntemden çok tarz veya arayüz beklentileri ile alakalıdır. Aşağıda bunun için size iki farklı örnek vereceğim.
{% get_current_language as CURRENT_LANGUAGE %}
{% get_available_languages as AVAILABLE_LANGUAGES %}
{% get_language_info_list for AVAILABLE_LANGUAGES as languages %}
<div>
<p>{% trans "Dil Seçenekleri" %}:</p>
<ul>
{% for language in languages %}
<li>
<a href="/{{ language.code }}/"
{% if language.code == CURRENT_LANGUAGE %} class="active"{% endif %}>
{{ language.name }}
</a>
</li>
{% endfor %}
</ul>
</div>
Yukarıdaki kodda Django'dan get_current_language
şablon etiketi ile aktif olan dili CURRENT_LANGUAGE
değişkenine tanımlayarak aldık. Ardından get_available_languages
şablon etiketini AVAILABLE_LANGUAGES
değişkeni ile tanımlayarak tüm dil seçeneklerini aldık. Sonra da get_language_info_list
şablon etiketi ile tüm dil seçeneklerinin içinden açıklama bilgilerini languages
değişkeni ile aldık.
Sonrasında html kodlarımızda Django şablon dilini kullanarak tüm mevcut dil seçeneklerini yazdırdık. if
koşuluyla da eğer döngü içerisindeki dil mevcut aktif dil ise bunun bağlantı class
'ı için active
etiketini eklettik. Çıktımız aşağıdaki gibi olacaktır:
Dil Seçenekleri:
- Türkçe
- İngilizce
Bir diğer örnek ise şöyle:
{% get_current_language as CURRENT_LANGUAGE %}
<li>
<div>
<img class="flag-icon" src="{% static 'img/flag-usa-16.webp' %}" alt="English" title="English"><a class="{% if CURRENT_LANGUAGE == "en" %}pe-none text-decoration-none{% endif %}" href="/{{ language.code }}/" title="English"><span>English</span></a>
<img class="flag-icon" src="{% static 'img/flag-turkey-16.webp' %}" alt="Türkçe" title="Türkçe"><a class="lang-menu-text {% if CURRENT_LANGUAGE == "tr" %}pe-none text-decoration-none{% endif %}" href="/{{ language.code }}/" title="Türkçe"><span>Türkçe</span></a>
</div>
</li>
Bu örnekler ihtiyaçlarımıza göre değiştirlebilir. Burada önemli olan Django'nun bize hangi etiketleri ve daha doğrusu imkanları sunduğuna vakıf olabilmektir. Bunun için detaylı bilgiye Django'nun dökümentasyonundan buraya tıklayarak ulaşabilirsiniz. Tüm detaylı bilgileri öğrenebileceğiniz Django'nun Translation (Çeviri) Dökümentasyonu için buraya tıklayabilirsiniz.
Django Rosetta Çeviri Arayüzü
Rosetta .po
uzantılı dil dosyalarının kolayca Django admin arayüzü üzerinden düzenlemesine olanak sağlayan üçüncü taraf kütüphanedir.
Django Rosetta Kurulumu
django-rosetta
kütüphanesini projemizin çevresine (environment
) ekleyebilmek için öncelikle environment'in aktif edilmesi sonra kurulum için komutların çalıştırılması gerekmektedir.
python3 -m venv env # bu komutla eğer daha önce oluşturmadıysak projemize environment oluşturuyoruz
source env/bin/activate # bu komutla environmen'imizi aktif ediyoruz
pip install django-rosetta # bu komutla django-rosetta kütüphanesini yüklüyoruz
Ardından settings.py
dosyamızdaki INSTALLED_APPS değişkenimize rosetta
uygulamasını dahil ediyoruz.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'mainsite.apps.MainsiteConfig',
# third party
'rosetta',
]
Yine settings.py dosyamızın içine projeniz için eğer ana dil olarak İngilizce kullanmıyorsanız, mesela örneklerimizde biz anadil olarak Türkçe kullandık, Rosetta'ya özel iki ayar eklemek gerekir.
ROSETTA_MESSAGES_SOURCE_LANGUAGE_CODE = 'tr'
ROSETTA_MESSAGES_SOURCE_LANGUAGE_NAME = 'Turkish'
Bu ve diğer tüm ayarlara Rosetta'nın dökümentasyonundan buraya tıklayarak ulaşabilirsiniz.
Daha sonra projemizin ana urls.py
dosyası içine rosstta'nın url adresini dahil ediyoruz.
from django.conf import settings
from django.conf.urls import include, path
if 'rosetta' in settings.INSTALLED_APPS:
urlpatterns += [
path('rosetta/', include('rosetta.urls'))
]
Bu işlemleri tamamladıktan sonra veritabanını güncelleyebiliriz.
(env)$ python manage.py makemigrations
(env)$ python manage.py migrate
Veri tabanını güncelledikten sonra projemizi yeniden başlatmayı unutmayın. PyCharm gibi bir IDE editör kullanıyorsanız bu işlem basit. Ancak üretim modundaysanız Ubuntu gibi bir linux dağıtımı için bunu aşağıdaki komutla gunicorn
'u yeniden başlatarak da yapabilirsiniz.
sudo systemctl restart gunicorn
Not: Üretim modunda Rosetta'nın locale/ klasöründe bulunan .po
dosyasına okuma ve yazma yetkisi verilmelidir.
Rosetta'ya ulaşabilmek için tarayıcınızın adres çubuğuna http://127.0.0.1:8000/rosetta/ url'ini yazmanız yeterli.
Açılan sayfada genel istatistikleri görebilir, listedeki UYGULAMA alanından proje adına tıkladığımızda çevirileri yapabileceğiniz ekrana ulaşabilirsiniz.
Çevirileri yaptıktan sonra "Kaydet ve Sonraki Bloğu Çevir
" butonuna basarak çevirileri kaydedebilirsiniz. Bu işlemden sonra Rosetta çeviri dosyasını otomatik olarak derleyecektir, dolayısıyla django-admin compilemessages --ignore=env
komutunu manuel olarak çalıştırmanıza gerek yoktur. Çeviriler sitenizde gözükmüyorsa yukarıda anlattığım şekilde gunicorn'u yeniden başlatabilirsiniz.
django-rosetta
kütüphanesinin kendi dökümentasyonu için buraya tıklayarak tüm bilgilere ulaşabilirsiniz.
Django Parler İle Modelleri Çevirin
Django modeller için hazırda tam bir çeviri altyapısı sunmamaktadır. Bunun için üçüncü taraf kütüphanelere ihtiyacımız olup, bu kütüphaneler arasında da en iyisi olan django-parler
kullanımı size anlatacağım. Tam olarak Parler'in ne işe yaradığını aşağıdaki resime bakarak kafanızda canlandırabilirsiniz.
Gördüğünüz gibi, örnekte kullanılan blog modeli için iki farklı model oluşturmak yerine, sadece django-parler
kütüphanesini kullanarak aynı modeli istediğimiz dillerde doğrudan Django admin paneli üzerinden düzenleyerek çevirebiliyoruz. Bu bize olduça fazla konfor sağlayacaktır.
Django Parler Kurulumu
django-parler
kütüphanesini projemize kurmak için komut satırında aşağıdaki kodu çalıştırabilirsiniz:
pip install django-parler
Ardından settings.py
dosyamızdaki INSTALLED_APPS
değişkenine parler uygulamasını eklemeniz gerekmektedir.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'mainsite.apps.MainsiteConfig',
# third party
'rosetta',
'parler', # parler uygulaması
]
Zorunlu olmayan ama eklenmesini tavsite ettiğim dir diğer ayar da şöyle:
PARLER_LANGUAGES = {
None: (
{'code': 'tr', }, # Türkçe
{'code': 'en', }, # İngilizce
),
'default': {
'fallbacks': ['tr'],
'hide_untranslated': False,
}
}
PARLER_DEFAULT_LANGUAGE_CODE = 'tr'
Burada None
yazan alanda, eğer ayarlarınızda çoklu siteli proje (multi-site) veya başka bir nedenle SITE_ID
kullanıyorsanız, SITE_ID
için tanımladığınız rakamı yazabilirsiniz. Örneğin SITE_ID = 1
ise None yerine de 1 ve 2 şeklinde yazabilirsiniz.
Dil kodlarında ilk sırada varsayılan dilin önce yazılması gerekmektedir. default olarak tanımlanan fallbacks
anahtarı PARLER_DEFAULT_LANGUAGE_CODE
için tanımlanmış varsayılan dil kodununun değerini alır ama yazmaktan zarar gelmez. hide_untranslated
anahtarı ise çevirisi eklenmemiş dillerin görüntülenip görüntülenmeyeceğini belirler. Genelde örnek olarak bir blog yazısı yazarken, diğer dilleri de hemen ardından eklemek en doğru seçenek olduğu için, bunu False
olarak bırakmanız mantıklı olacaktır. Eğer diğer dil seçeneğinde bir ekleme yapmadıysanız, fallbacks
anahtarının değerindeki dil kodunda yer alan içerik gözükecektir.
Django Parler Model İçerisinde Kullanımı
django-parler
, model alanlarını çevirmek için bir TranslatableModel model sınıfı ile bir TranslatedFields sarmalayıcı sınıf (wrapper class) sağlar ve çevrilebilir her model için veritabanında başka bir model oluşturarak çevirileri yönetir. Gelin anlatmaktansa aşağıdaki örnekle bunu anlamaya çalışalım.
from django.db import models
from ckeditor_uploader.fields import RichTextUploadingField
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from parler.models import TranslatableModel, TranslatedFields
class Blog(TranslatableModel):
status = models.BooleanField('Aktif/Pasif', default=False)
translations = TranslatedFields(
slug=models.SlugField("Slug", max_length=60, unique=True),
title=models.CharField('Sayfa Başlığı', max_length=150, unique=True),
short_description=models.TextField('Kısa Açıklama', max_length=300),
content=RichTextUploadingField('İçerik Yazısı'),
)
published_date = models.DateTimeField(_('Yayınlanma Tarihi'), default=timezone.now)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.seo_title)
super(Blog, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('mainsite:blog-details', args=[self.slug])
class Meta:
verbose_name_plural = "Blog Yazıları"
verbose_name = "Blog Yazısı"
ordering = ['-published_date']
Yukarıdaki örneği tek tek inceleyelim:
Normal şartlarda Django ile model sınıfı tasarlarken models.Model
sınıfını kullanırken, django-parler ile TranslatableModel
sınıfını kullanıyoruz. Modelin içerisinde çevirisinin olmasını istediğimiz alanları ise translations
değişkeni içerisinde TranslatedFields
sarmalayıcı sınıfını kullanarak tanımlıyoruz.
Burada slug
alanı ile alakalı bazı önemli bilgileri size birazdan vereceğim. Şimdilik buna kafa yormanıza gerek yok. Ayrıca farkettiyseniz yine "_
" alt çizgi ile çevirisini işaretlediğimiz bazı metinlerimiz (strings) bulunuyor.
Model içerisinde yapmamız gereken ayarlamalar bu kadar. Şimdi aşağıdaki komutlarla veritabanını güncelleyebiliriz.
(env)$ python manage.py makemigrations
(env)$ python manage.py migrate
Ayrıca üretim modundaysanız gunicorn
'u da yeniden başlatmanız faydalı olacaktır.
Django Parler Views (Görünümler) İçinde Kullanımı
django-parler
'i görünümler (views) içinde normal durumlarda kullanmanız gerekmez. Ancak bazı durumlarda, örneğin yukarıdaki slug
kullanmak isteyeceğiniz durumlarda görünümlerde de bazı değişiklikler yapmanız gerekecektir. Bu ve bunlar gibi durumlar için parler bize ViewUrlMixin
, TranslatableSlugMixin
, LanguageChoiceMixin
, TranslatableModelFormMixin
, TranslatableCreateView
, TranslatableUpdateView
gibi hazır sınıflar sunuyor. Aşağıda slug
kullanımına yönelik görünümler üzerinden bir örnek verelim.
from django.views.generic import DetailView
from parler.views import TranslatableSlugMixin
class BlogDetailView(TranslatableSlugMixin, DetailView):
template_name = "mainsite/blog-details.html"
queryset = Blog.objects.filter(status=True)
context_object_name = "blog_post"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['blog'] = self.get_object()
return context
Görüldüğü üzere projenizdeki çevirilebilir her slug
içeren modelin DetailView
görünümünde ek olarak TranslatableSlugMixin
sınıfını çağırmamız yeterli oluyor. Ayrıca aşağıda göreceğiniz admin.py
dosyasında da bazı değişiklikler gerekecek. Bu sayede slug
alanını her dil için kolayca çevirebilir ve html kodumuzda kolayca ilgili dile ait slug
url sini çağırabiliriz. Bunu da mesela yukarıda örneğini verdiğimiz kullanıcı dil seçimi aracında {% get_translated_url 'en' %}
etiketini kullanarak kolayca yapabilirsiniz. Bu etiket, mevcut modelin İngilizce dilinceki url adresini otomatik olarak alabilmemizi sağlıyor. Tabi bu etiketi kullanabilmek için öncelikle html kodunuzun en üstünde daha önce eklediğiniz i18n
etiketinin yanına parler_tags
etiketini de eklemeniz gerekiyor. Yani şu şekilde olacak: {% load i18n parler_tags %}
.
Django Parler Admin Dosyası İçinde Kullanımı
Parler ile modelimizi düzenledikten sonra elbette django yönetici paneli içinde de bunun çalışabilmesi için bazı basit ayarlamalar yapmak gerekiyor. Normal durumlarda admin.py
dosyasında bir modeli kayıt edebilmek için admin.ModelAdmin
sınıfını çağırıyorduk. Parler ile bunu yapmak için sadece bu sınıfı değiştirmeniz yeterli. Aşağıdaki örneği inceleyelim.
@admin.register(Blog)
class BlogAdmin(TranslatableAdmin):
list_display = ["title", "published_date", "status"]
list_editable = ["status"]
readonly_fields = ["published_date"]
fieldsets = (
("İÇERİK", {
"fields": ("status", "title", "short_description", "content", "published_date")
}),
)
def get_prepopulated_fields(self, request, obj=None):
return {
'slug': ('title',)
}
Gördüğünüz gibi yukarıda Blog modelini admin paneline kayıt ederken TranslatableAdmin
sınıfını çağırıyoruz. Slug alanı için ise get_prepopulated_fields
fonksiyonu ile slug
adresinin Blog modelindeki title
alanından otomatik olarak üretilmesini sağlıyoruz. Bunu normal şartlarda doğrudan BlogAdmin
sınıfı içinde prepopulated_fields
değişkeni ile tanımlıyorken, django-parler
ile ayrı bir fonksiyon içersinde yapmamız gerekiyor.
Parler hakkında detaylı bilgiye sahip olmak için django-parler
resmi dökümantasyonuna buraya tıklayarak ulaşabilirsiniz.
Son Söz
Django, çoklu dil desteğini kolayca eklemenize olanak tanır. Bu, uygulamanızın daha geniş bir kitleye ulaşmasına yardımcı olur.
Bu blog yazısında, Django için çoklu dil ekleme hakkında detaylı bilgi paylaştım. Bu bilgilere dayanarak, kendi uygulamanızda çoklu dil desteğini ekleyebilirsiniz.