Çok Dilli Projelerde Veri Tabanı Tasarımı #1 — Kolon Yaklaşımı

Mustafa Zahid Efe
4 min readMar 11, 2018

--

Merhabalar efenim.

Yakın zamanda bir müşterimiz web sitesini çok dilli bir siteye çevirmek istediğini söyledi. Ben de bunun üzerine biraz araştırma yapıp en uygun veri tabanı modelini bulmaya çalıştım bu proje için. Araştırırken genel olarak kullanılan 4 farklı yaklaşımla karşılaştım. Bunları ayrı ayrı videolarda kısaca anlatmaya çalışacağım. Bu ilk videom. Bu videoda “Kolon Yaklaşımı”ndan bahsettim. Videoyu izlemek istemeyenler olursa eğer biraz daha kaydırarak yazılı anlatımı da inceleyebilir.

Basit bir örnekle başlayalım. Bir adet posts (gönderiler) tablomuz olsun veri tabanımızda ve yapımızın şöyle olduğunu varsayalım.

Görsele aşina olmayanlar olabilir. Kısaca bahsedeyim. Field kısmında veri tabanındaki alanımızın ismi bulunuyor. Type kısmında alanımızın tipi (örneğin: integer, varchar, blob, text, longtext vb) bulunuyor. Null yazan kısım, alanımızın boş bırakılabilirliğini gösteriyor. Null olabilen alanlar YES, olamayan alanlar NO olarak belirtiliyor. Key kısmı o alana ait herhangi bir key varsa onu gösteriyor. Gördüğünüz gibi id kısmı PRIMARY KEY olarak belirtilmiş. Default kısmı, alanımızın varsayılan değerinin gösterildiği kısım. Herhangi bir varsayılan değer ataması yapmazsanız varsayılan değeriniz NULL oluyor. Extra kısmında da ekstra bilgiler yer alıyor. Gördüğünüz gibi id kısmı auto_increment. Bunların açıklamasını yaptığımıza göre devam edebiliriz.

Yapımızın ilk başta böyle olduğunu düşünelim. Burada çevirisi yapılabilecek olan alanlarımız title (başlık) ve content (içerik). Bu yaklaşıma göre her çevrilebilir alanımız için yabancı dil sayısı kadar yeni alan oluşturuyoruz. Örneğin projemizin Türkçe ve İngilizce dillerini desteklediğini varsayalım. Bu durumda title kolonu yerine title_tr ve title_en adında iki tane kolon oluşturmamız gerekiyor. Aynı işlemi content için de yapıyoruz. Content alanımız yerine content_tr ve content_en adında iki tane alan oluşturuyoruz. Veri tabanımızın son halinin şöyle olması gerekiyor.

Bundan sonra her dildeki içeriği kendi alanına gireceğiz. Her yaklaşımın kendince artıları ve eksileri var. Genel olarak bu yaklaşımın çok mantıklı olduğunu söyleyemeyiz. Sonraki yazılarda bundan çok daha iyilerini göreceksin. Bu yaklaşımın artılarına ve eksilerine bir bakalım şimdi.

Artıları

  • Aşırı derecede basit.
  • SQL sorgularında zorluk çıkartmaz.

Eksileri

  • Yeni dil eklemek çok uğraştırır. Her seferinde veri tabanınızı açıp yeniden kolonlar eklemeniz gerekir.
  • Bakım yapması zordur. 10 dili olan bir sistem yazdığınızı varsayalım. Sadece başlık ve içerik alanı için bile toplamda 20 adet kolonunuz olacaktır ve bu kolonlar arasında kaybolma ihtimaliniz çok yüksek.
  • Gereksiz boş alanlar depolarsınız. Çevirisi yapılmayan veya yapılmayacak olan alanlar gereksiz boşluk oluştururlar.
  • Veri çekmek için sorgu yazarken özellikle çekmek istediğiniz alanları belirtmediğinizde (SELECT * FROM tablo gibi bir sorgu yaptığınızda) bir sürü gereksiz veri döndürecek ve gereksiz kaynak tüketecektir.

Sonradan Ekleme

Videoda bahsettiğim ama yazıda atladığım bir kısım var. Slug meselesi. @yakuter abimin uyarısı üzerine bu bölümü ekliyorum. Kendisine teşekkür ediyorum.

Sistemlerinizde gönderiler için slug da kullanmak istiyor olabilirsiniz. Bu durumda her bir slug için yeni bir kolon oluşturmanız gerekiyor. Örneğin slug_tr, slug_en vs.

Burada da sluga göre bir arama yapmanız gerektiğinde şu şekilde bir sorgu yapıyorsunuz.

SELECT * FROM posts WHERE slug_tr = 'post_slug' || slug_en = 'post_slug'

Bu şekilde bütün dillerdeki slug için aynı değeri aratıyoruz ve bulduğumuz değeri çekiyoruz. Bu durum bize iki adet daha eksi getiriyor.

Bu eksilerden birincisi şu: slug_tr alanımız, başka bir gönderinin slug_en alanıyla aynı değere sahip olabilir ve maalesef alanları unique olarak belirleyerek de bu sorunu çözemezsiniz. Çünkü slug_tr alanları kendi içerisinde ve slug_en alanları da kendi içerisinde benzersiz olacaktır ama bir gönderinin slug_tr değeri ile başka bir gönderinin slug_en değeri aynı olursa ciddi sorunlar yaşayabilirsiniz.

Bir diğer eksimiz de şu: Kullanıcı siteye girdi ve sluga bakarak hangi yazıyı okumak istediğinizi anladınız ama kullanıcının bu yazıyı hangi dilde okumak istediğini anlayamazsınız. Bunun için tekrar kontrol yapmanız gerekir. Öncelikle slug değerini alacaksınız ve slug_tr alanı ile karşılaştıracaksınız. Eğer slug_tr alanı ile slug birbirine eşitse bu durumda kullanıcı Türkçe olan içeriği istemiş demektir. Tam tersi durumda da İngilizce içeriği istemiş demektir. Bu da böyle garip bir sorun.

Şimdi ben de size bir soru yönelteyim. Sluglarımızın başlıklara göre otomatik oluşturulduğunu düşünelim ve Türkçe başlığımızla İngilizce başlığımız aynı olsun. Bu durumda ne olacak ?

Bu durumda sluglarımız da aynı olacaktır ve yukarıdaki yöntem bir işe yaramayacaktır. Bu tarz durumlarda da bir şekilde kullanıcıdan dili istemeniz gerekecektir. Kısacası bu yapıyla birlikte slug da kullanmak isterseniz çok başınız ağrıyabilir.

İnşallah anlaşılabilir bir yazı olmuştur. Videoda veya yazıda gördüğünüz eksikleri veya hataları özel veya genel kanallar aracılığıyla bana bildirirseniz çok sevinirim.

Herkese iyi çalışmalar ve iyi günler dilerim.

--

--

Mustafa Zahid Efe

Web Developer @ Megafonn Creative Digital Agency. Blogger, Youtuber. (More information: zahidefe.net)