Rapor
Transkript
Rapor
KARADENİZ TEKNİK ÜNİVERSİTESİ MÜHENDİSLİK FAKÜLTESİ BİLGİSAYAR MÜHENDİSLİĞİ BÖLÜMÜ GÖKTÜRKÇE YAZI ÇEVİRİCİ TASARIM PROJESİ Muhammed Mehdi USLU Salih TOPÇU 2015-2016 GÜZ DÖNEMİ KARADENİZ TEKNİK ÜNİVERSİTESİ MÜHENDİSLİK FAKÜLTESİ BİLGİSAYAR MÜHENDİSLİĞİ BÖLÜMÜ GÖKTÜRKÇE YAZI ÇEVİRİCİ TASARIM PROJESİ Muhammed Mehdi USLU Salih TOPÇU Bu projenin teslim edilmesi ve sunulması tarafımca uygundur. Danışman : Yrd. Doç. Tuğrul ÇAVDAR 2015-2016 GÜZ DÖNEMİ ......................... IEEE Etik Kuralları IEEE Code of Ethics Mesleğime karşı şahsi sorumluluğumu kabul ederek, hizmet ettiğim toplumlara ve üyelerine en yüksek etik ve mesleki davranışta bulunmaya söz verdiğimi ve aşağıdaki etik kurallarını kabul ettiğimi ifade ederim: 1. Kamu güvenliği, sağlığı ve refahı ile uyumlu kararlar vermenin sorumluluğunu kabul etmek ve kamu veya çevreyi tehdit edebilecek faktörleri derhal açıklamak; 2. Mümkün olabilecek çıkar çatışması, ister gerçekten var olması isterse sadece algı olması, durumlarından kaçınmak. Çıkar çatışması olması durumunda, etkilenen taraflara durumu bildirmek; 3. Mevcut verilere dayalı tahminlerde ve fikir beyan etmelerde gerçekçi ve dürüst olmak; 4. Her türlü rüşveti reddetmek; 5. Mütenasip uygulamalarını ve muhtemel sonuçlarını gözeterek teknoloji anlayışını geliştirmek; 6. Teknik yeterliliklerimizi sürdürmek ve geliştirmek, yeterli eğitim veya tecrübe olması veya işin zorluk sınırları ifade edilmesi durumunda ancak başkaları için teknolojik sorumlulukları üstlenmek; 7. Teknik bir çalışma hakkında yansız bir eleştiri için uğraşmak, eleştiriyi kabul etmek ve eleştiriyi yapmak; hatları kabul etmek ve düzeltmek; diğer katkı sunanların emeklerini ifade etmek; 8. Bütün kişilere adilane davranmak; ırk, din, cinsiyet, yaş, milliyet, cinsi tercih, cinsiyet kimliği, veya cinsiyet ifadesi üzerinden ayırımcılık yapma durumuna girişmemek; 9. Yanlış veya kötü amaçlı eylemler sonucu kimsenin yaralanması, mülklerinin zarar görmesi, itibarlarının veya istihdamlarının zedelenmesi durumlarının oluşmasından kaçınmak; 10. Meslektaşlara ve yardımcı personele mesleki gelişimlerinde yardımcı olmak ve onları desteklemek. IEEE Yönetim Kurulu tarafından Ağustos 1990’da onaylanmıştır. II ÖNSÖZ Bu projedeki amacımız eski Türkçemizi yaşatan, seven, ilgi duyan kişilerin böyle bir uygulamaya duydukları ihtiyacı gidermekti. İlk sürümü çıkardığımızda da gerçekten böyle olduğunu gördük ve onlardan aldığımız geri dönüş ile birlikte uygulamamıza yeni özellik ekleyerek ikinci sürümünü yaparak eski Türkçe metinlerini paylaşabilmelerini sağladık. Böyle bir projede yer almamızı, binlerce insana ulaşmamızı ve eski Türkçemizi yaşatabilme imkanı veren Tuğrul ÇAVDAR hocamıza teşekkürlerimiz sunuyoruz. Muhammed Mehdi USLU Salih TOPÇU Trabzon 2015 III İÇİNDEKİLER IEEE ETİK KURALLARI ÖNSÖZ İÇİNDEKİLER ÖZET 1. GENEL BİLGİLER 1.1. Giriş 1.2. Göktürkçe Harflerin Latin Karşılıkları 1.3. Latin Kelimelerin Göktürkçeye Çevrilirken Kullanılan Kurallar 2. YAPILAN ÇALIŞMALAR 2.1. Kullanılan Materyaller 2.2. Font Seçimi 2.3. Android’te Unicode Karakterlerin Yazımı 2.4. Java Kodları 2.4.1. Intro Sınıfı 2.4.2. About Sınıfı 2.4.3. MainActivity Sınıfı 2.4.4. Preprocess Sınıfı 2.4.5. Rules Sınıfı 2.4.6. DBHelper Sınıfı 2.4.7. Save Sınıfı 2.5. Tasarım 2.5.1. Intro Ekranının Tasarımı 2.5.2. Hakkında Ekranının Tasarımı 2.5.3. Ana Ekran Tasarımı 2.5.4. Kaydetme ve Paylaş Ekranının Tasarımı 3. SONUÇLAR 4. ÖNERİLER 5. KAYNAKLAR STANDARTLAR ve KISITLAR FORMU IV Sayfa No II III IV V 1 1 2 2 4 4 4 4 5 5 8 9 16 23 27 30 35 35 41 41 45 51 52 53 54 ÖZET Projenin amacı günümüz Latin harflerini kullanarak yazdığımız metinleri eski Türkçemiz olan Göktürkçe metine çevrilip istenildiğinde görüntü dosyası olarak kaydetmek veya herhangi bir yerde paylaşılabilmesi sağlamaktır. Uygulama istenilen düzeye getirildi ve binlerce kullanıcıya ulaştı. V 1 1. GENEL BİLGİLER 1.1. Giriş Uygulamada kullanıcıdan alınan Latin harflerle yazılmış Türkçe metin Göktürkçeye dönüştürülerek tekrar kullanıcıya sunulmaktadır. Bu çeviri işlem Göktürkçe kuralları uygulanarak yapılmaktadır. Çeviride kullanılan kurallar kok-turk.blogspot.com [2] sitesinden alınmıştır. Android işletim sistemli cihazlarda Göktürkçe karakter içiren bir font olmadığı için uygulama içine bir font gömüldü. Böylece uygulama içinde Göktürkçe karakterlerin sorunsuz bir şekilde gösterilmesi sağlandı. Göktürkçede bazı kelimeler özel bir yazıma sahip olmaktadır. Dolayısıyla diğer kelimelerin çevirisinde kullanılan kurallar bu kelimeleri doğru bir biçimde çevirememektedir. Bu yüzden program ilk çalıştırıldığında bu özel kelimeler cihazın veri tabanına kaydedilir. Kullanıcı bu kelimeleri girdiği zaman kelimenin mevcudiyeti veri tabanında kontrol edilir. Eğer kelime mevcut ise gerekli değişiklikler yapılarak çevirme işlemi başlatılır. Bu farklılık genellikle dilimizde eskiden var olup günümüz alfabesinde kullanılmayan Nazal n ve Kapalı e harflerin eksikliğinden kaynaklanmaktadır. Bu harflerin kullanıldığı kelimeleri veri tabanına ekleyerek bu eksikliği ortadan kaldırmaya çalışılmıştır. Ayrıca yine bazı kelimeler Göktürkçede günümüz Türkçesinde yazıldığı gibi yazılmaz. Örneğin komşu kelimesi Göktürkçede konşu olarak yazılmaktadır. Aynı şekilde omurga kelimesi de onurga olarak yazılmaktadır. Yine bu gibi kelimeler çevrilmeden önce bir ön işleme tabi tutulması gerekmektedir. Çeviri işlemi yapılmadan önce bu kelimeler tespit edilir ve gerekli değişiklikler yapılarak çeviri işlemi yapılmaktadır. Son olarak Göktürkçede bazı iki sesli harfler bulunmaktadır. Örneğin ng, nc, nt gibi. Çeviri işlemi yapılmadan önce kelimede bu harfler aranır ve Türkçede bulunmayan X, x, W, w gibi harflere dönüştürülür. Daha sonra çeviri işlemi sırasında bu harflere karşılık düşen gibi 2 harflere dönüştürülür. Çeviri işlemi sırasında bu harflere karşılık düşen Göktürkçe karakterler yazılır. 1.2. Göktürkçe Harflerin Latin Karşılıkları Göktürkçede harfler kalın ve ince olarak ayrılmaktadır. Harflerin kalın veya ince olduğu sessiz harfin yanındaki sesli harfe bakılarak anlaşılmaktadır. 1.3. Latin Kelimelerin Göktürkçeye Çevrilirken Kullanılan Kurallar 1. Yazı sağdan sola yazılır ve kelimeler : ile ayrılır. 2. Kalın harflerden önce a, ince harflerden önce e yazılmaz. 3. Kelime başında ve ortasında a/e yazılmaz ama sonunda yazılır. 4. Kelime başında ı/i/o/ö/u/ü her zaman yazılır. Sadece ık = iç = , ok/uk = , ök/ük = , ile bitiyorsa istisna olarak bu özel harfler kullanılmıştır. 5. İlk hecedeki sesliye bağlı olarak sonraki hecelerde genellikle küçük ünlü uyumuna 3 uyan sesliler (a/e/ı/i a/e/ı/i, o/ö/u/ü a/e/u/ü) yazılmaz. Yani: • İlk hecede a/e varsa sonraki hecelerde ı/i yazılmaz; ama yuvarlak sesli yazılır. • İlk hecede olan seslinin aynısı sonraki hecelerde varsa yazılmaz. Yani: İlk hecede ı/i varsa sonraki hecelerde ı/i yazılmaz. İlk hecede o/u varsa sonraki hecelerde o/u yazılmaz. İlk hecede ö/ü varsa sonraki hecelerde ö/ü yazılmaz. • İlk hecede yuvarlak sesli varsa sonraki hecelerde ı/i yazılır. • İlk hecede düz sesli varsa sonraki hecelerde yuvarlak sesli yazılır. 6. Kelime sonunda tüm sesliler yazılır. 7. Günümüz Türkçesinde F, C/J, H, V yerine sırasıyla P, Ç, K, B kullanılabilir. 8. k harfinin özel hallerinden sonra gelen bazı sesliler için aşağıdaki kullanımlar mevcuttur. • : ok/uk iken, : ko/ku (sıklıkla) • : ök/ük iken, : kö/kü (nadiren) • : ık iken, : kı (sıklıkla) 4 2. YAPILAN ÇALIŞMALAR 2.1. Kullanılan Materyaller Projede IDE olarak Android Studio, emülatör olarak Genymotion, test yapılan mobil cihazlar olarak Sony Xperia Z3 Compact, Samsung Galaxy Note 2, General Mobile Discovery 2, Asus Transformer Pad kullanıldı. 2.2. Font Seçimi Göktürkçe harfleri mobil cihaz ekranında görebilmek için Göktürkçe Unicode aralığını destekleyen bir font kullanıldı. Font olarak Windows 10 ile birlikte gelen Segoe UI Historic tercih edildi. Çoğu sistem fontu Göktürkçe Unicode aralığını desteklemediği ve sistem fontunu mobil cihazlarda değiştirmek zor ve tehlikeli olduğundan dolayı seçilen font uygulamaya gömülmüştür. Bu işlem için assets klasörünün içine fonts adında bir klasör oluşturulup istenilen font bu klasörün içine koyulur. Tablo 2.1’ de fontun TextView’e uygulanmasını gösteren kod parçası verilmiştir. Tablo 2.1. Fontun TextView’e uygulanmasını gösteren kod parçası. Typeface font = Typeface.createFromAsset(getAssets(),"fonts/seguihis.ttf"); Latin_Turk_TextView.setTypeface(font, Typeface.BOLD); Typeface setlemesi bu fontun kullanılacağı her araçta yapılmalıdır. 2.3. Android’te Unicode Karakterlerin Yazımı Göktürkçe harfler için ayrılan Unicode aralığı beş karakterden oluşmaktadır. Ancak Android’te beş karakterli Unicode karakter desteklenmemektedir. Beş karakterli Unicode karakterler için bir ayırma işlemi yapılmaktadır. Örneğin 10C00 için D803 ve DC00 olmaktadır. Bu ayırma işlemi bir internet sitesi yardımı ile yapılabilmektedir [1]. Bir 5 TextView’ de bu işlemin nasıl gerçekleştirildiği Tablo 2.2.’ de gösterilmiştir. Tablo 2.2. Beş karakterli Unicode karakterin TextView’ e aktarılması. GokTurk_Text = "\uD803\uDC00"; 2.4. Java Kodları Yapılan uygulamada hem kodun açık ve anlaşılır olması hem de modüler olmasını sağlayabilmek için Java sınıflarına (Class) ayrılmıştır. Her bir sınıf genellikle bir görevi yerine getirmesi için kullanılmıştır. 2.4.1. Intro Sınıfı Bu sınıf uygulama başlatıldığında yapılacak ilk işlemleri içerir ve giriş ekranın java sınıfıdır. Bu sınıf bir ekrana karşılık düştüğünden dolayı Activity sınıfından miras alır. Giriş ekranında önemli bir bilgi verildiği için kullanıcının okumayı bitirdikten sonra bu ekranı geçmesi için bir buton tanımlanmıştır. Bu butonda Geç yazısının yanında Göktürkçe Geç kelimesinin karşılığı yazıldığından font setlemesi yapılmıştır. Tablo 2.3. Buton tanımlanması, font setlemesi ve buton yazısının yerleştirilmesi. final Button Skip_Button = (Button) findViewById(R.id.Skip_Button); final Typeface font = Typeface.createFromAsset(getAssets(), "fonts/seguihis.ttf"); Skip_Button.setTypeface(font); Skip_Button.setText("Geç / \uD803\uDC0F\uD803\uDC32"); Intro sınıfında bir veri tabanı oluşturulması ve veri tabanına verilerin girilmesi işlemi yapıldığı için bu işlemin bitmeden geç butonuna basılmasını engellemek için bu işlemler önce butonu pasif yapacak bir işlem gerçekleştirilmiştir. 6 Tablo 2.4. Butonu pasif hale geçirme. Skip_Button.setClickable(false); Her uygulama başlatıldığında tekrardan veri tabanını oluşturup verileri tekrar girmeyi engellemek için uygulama eğer önceden başlatılmış ise bunu algılayıp bu kısmı atlayacak kod parçası eklenmiştir. Tablo 2.5. Uygulamanın daha önce başlatıldığını algılayan kod parçası. SharedPreferences settings = getSharedPreferences("SQL", 0); boolean firstTime = settings.getBoolean("firstTime", true); Veri tabanı oluşturmak için DBHelper sınıfından yararlanılmıştır. 2.4.6 DBHelper başlığında veri tabanı oluşturma işleminden bahsedilmiştir. dbHelper değişkeni DBHelper sınıfından oluşturulmuş global nesnedir. Tablo 2.6. Veri tabanının oluşturulması. dbHelper = new DBHelper(this); Eğer uygulama önceden başlatılmış ise verileri tekrar girmesini engellemek için if koşulu kullanılmıştır. Göktürkçede kapalı n ve kapalı e kullanılması gereken bazı kelimler olduğu için bu kelimler iki ayrı diziye atanmıştır ve iki for döngüsüyle veri tabanına eklenmesi sağlanmıştır. Tablo 2.7. Kelimelerin diziye atanması ve veri tabanına eklenmesi. 7 if (firstTime) { String[] Nazal_N_Word = new String[]{ "anla", "and", . . "yön", "yün"}; String [] Kapali_E_Word = new String[] { "beş", "beşik", . . "yegirmi", "yenlik"}; for (int i=0 ; i < Nazal_N_Word.length ;i++) { dbHelper.insert_Nazal_N_Word(Nazal_N_Word[i]); } for (int i=0 ; i < Kapali_E_Word.length ;i++) { dbHelper.insert_Kapali_E_Word(Kapali_E_Word[i]); } SharedPreferences.Editor editor = settings.edit(); editor.putBoolean("firstTime", false); editor.commit();} Veri tabanı işlemleri bu aşamada bittiği için Geç butonu aktif hale getirilir. 8 Tablo 2.8. Geç butonunun aktif hale getirilmesi. Skip_Button.setClickable(true); Son olarak Geç butonun’ a basıldığında ana ekrana geçilmesinin sağlayacak fonksiyon tanımlanmıştır. Bu fonksiyon bir buton fonksiyonu olduğu için View tipinde bir argüman almak zorundadır. Tablo 2.9. Geç Butonu fonksiyonu. public void Skip_Button_Fonk(View v) { Intent main_intent=new Intent(getApplicationContext(),MainActivity.class); startActivity(main_intent); this.finish(); } 2.4.2. About Sınıfı About sınıfı Intro sınıfının görüntü olarak aynısıdır. Herhangi bir veri tabanı işlemi yapılmamıştır. Ana ekran ve kaydetme ekranlarında Hakkında sekmesine basıldığında yönlendirilen ekrandır. Sadece bir buton bulunduğu için font setlemesi ve text setlemesi yapılmıştır. Tablo 2.10. Font setlemesi ve text setlemesi. skip_button = (Button) findViewById(R.id.About_Skip_Button); final Typeface font = Typeface.createFromAsset(getAssets(),"fonts/seguihis.ttf"); skip_button.setTypeface(font); skip_button.setText("Geç / \uD803\uDC0F\uD803\uDC32"); 9 Butona basıldığında yapılacak işlemleri Skip_Button_Fonk yapmaktadır. Bu fonksiyonun içinde mobil cihazlardaki geri tuşunun yaptığı görevi yapan fonksiyon bulunmaktadır. Bunu yapılması amaç ise bir önceki sayfaya dönüldüğünde ordaki bilgilerin kaybedilmemesidir. Tablo 2.11. Skip_Button_Fonk fonksiyonu. public void Skip_Button_Fonk(View v) { onBackPressed(); } 2.4.3. MainActivity Sınıfı Intro sayfasındaki işlemler bittikten sonra uygulamada MainActivity sınıfı çalışmaya başlamaktadır. Bu bölümde öncelikle Intro ara yüzünden sonra gelen ara yüzdeki görsel nesneler tanımlanmıştır. Latin metnini yazıldığı ve karşılığında Göktürkçe metnini gösterildiği birer adet EditText eklenmiştir. Çevirme ve Paylaşma işlemleri için birer buton eklenmiştir.. Ve son olarak EditText’lerin içerikleri hakkında bilgi bulunduran ikisi Türkçe ikisi Göktürkçe olmak üzere 4 adet Label eklenmiştir.. Bu nesnelerin ekran düzenleri Tasarım başlığı altında detaylı olarak anlatılmıştır. Ardından bu nesnelerin fontları yine dinamik olarak bu bölümde setlenmiştir. Bu nesnelere ait kodlar Tablo 2.12. gösterilmiştir. Tablo 2.12. Global değişkenlerin tanımlanması. EditText Latin_Text; EditText Gokturk_Text; TextView Latin_Turk_TextView; 10 TextView Turk_Turk_TextView; Button Translate_Button; Button Save_Button; LinearLayout mainLayout; public Typeface font; Tablo 2.13. Nesnelerin id’lerle ilişkilendirilmesi ve Temel özelliklerin belirlenmesi. mainLayout = (LinearLayout) findViewById(R.id.myLayout); font = Typeface.createFromAsset(getAssets(),"fonts/seguihis.ttf"); Latin_Turk_TextView = (TextView) findViewById(R.id.Latin_Turk_TextView); Latin_Turk_TextView.setTypeface(font, Typeface.BOLD); Latin_Turk_TextView.setText("\uD803\uDC1E\uD803\uDC43\uD803\uDC24:"); Latin_Turk_TextView.setGravity(Gravity.BOTTOM | Gravity.RIGHT); Turk_Turk_TextView = (TextView) findViewById(R.id.Turk_Turk_TextView); Turk_Turk_TextView.setTypeface(font); Turk_Turk_TextView.setTypeface(font, Typeface.BOLD); Turk_Turk_TextView.setText("\uD803\uDC45\uD803\uDC35\uD803\uDC3C\uD803\uDC1C: "); Turk_Turk_TextView.setGravity(Gravity.BOTTOM | Gravity.RIGHT); Latin_Text = (EditText) findViewById(R.id.Latin_Text); Latin_Text.setTypeface(font); Latin_Text.setHint("Latin Metin"); Gokturk_Text = (EditText) findViewById(R.id.Gokturk_Text); Gokturk_Text.setTypeface(font); Gokturk_Text.setHint("Göktürk Metin"); Gokturk_Text.setTextIsSelectable(true); Translate_Button = (Button) findViewById(R.id.Translate_Button); Translate_Button.setTypeface(font); 11 Translate_Button.setText("Çevir / \uD803\uDC32\uD803\uDC0B\uD803\uDC3C"); Save_Button = (Button) findViewById(R.id.Save_Button); Save_Button.setTypeface(font); Save_Button.setText(" Kaydét / Paylaş"+"\n\uD803\uDC2F\uD803\uDC16\uD803\uDC1E\uD803\uDC41 / \uD803\uDC34\uD803\uDC16\uD803\uDC11:\uD803\uDC03\uD803\uDC45"); Save_Button.setEnabled(false); Save_Button.setClickable(false); Uygulamada Gokturk_Text içinde herhangi bir metin olmadan Kaydet/Paylaş ara yüzüne geçişi engellemek için Gokturk_Text boş olduğu durumda Kaydet/Paylaş butonu deaktif yapılmaktadır. Bu işlem tablodaki son iki satırla yapılmaktadır. Çevir ve Kaydet/Paylaş butonları için birer adet fonksiyon tanımlanmıştır. “Çevir” için tanımlanan Translate fonksiyonu Latin metni Göktürkçe metne dönüştüren asıl fonksiyondur. Buton nesnesi için kullanıldığı için bir adet View parametresi almıştır. Bu fonksiyonda öncelikle Göktürkçenin kurallarını içeren Rules sınıfından bir nesne türetilir. Sonra kullanıcının girmiş olduğu Latin metni bir değişkene aktarır. Buradan itibaren çeviri işlemi bu değişken referans alınarak yapılmaktadır. Göktürkçede büyük küçük harf olmadığı için değişken içindeki tüm harfler küçük yapılır. Ardından kelimelerin kökünü bulup veri tabanında sorgulatmak için DB_control adında geçici olarak kelimenin kökünü tutan bir string değişkeni tanımlandı. Bu değişken veri tabanında aranır. Eğer aranan kelime Kapalı e tablosunda mevcut ise flag_kapalı_e adındaki boolean tipindeki değişkeni TRUE yapar. Nazal_n tablosunda mevcut ise bu kez flag_nazlan_n adındaki boolean değişkeni TRUE yapılmaktadır. Bu değişkenler referans alınarak kelimedeki e veya n, nazal n veya kapalı e olarak değiştirilir. Tablo 2.14. Çeviri öncesi gerekli değişkenlerin setlenmesi. 12 Rules rules = new Rules(); String GokTurk_Text = ""; String Get_Latin_Text = Latin_Text.getText().toString(); Get_Latin_Text = Get_Latin_Text.toLowerCase(); String DB_control = null; Boolean flag_nazal_n = false; Boolean flag_kapali_e = false; Translate fonksiyonu öncelikle Latin metni Preprocess sınıfına aktararak buradan kelimelere parçalanmış bir string dizisi elde etmektir. Tablo 2.15. Metnin kelimelere parçalana işlemi. Preprocess preprocess = new Preprocess(); String[] word = preprocess.Preprocess(Get_Latin_Text); Bu işlemden sonra her kelime için çevirme işlemi yapılacağı için bir for döngüsü oluşturulmuştur. Bu döngünün döngü sayısı word.lengt yani metin içindeki kelime sayısı olarak belirlendi. Döngüde ilk olarak girilen kelimenin veri tabanında mevcut olup olmadığı kontrol edilir. Veri tabanındaki en kısa kelime 2 harfli olduğundan öncelikle kelimenin ilk iki harfi veri tabanında sorgulanır. Mevcut değilse bir harf daha eklenir ve tekrar aranır. Bu işlem kelime veri tabanında bulunana kadar veya eğer veri tabanında yoksa kelimenin tamamı deneninceye kadar devam edilir. Bu işlem hem Nazal n hem de Kapalı e için ayrı ayrı döngüler içinde yapılmaktadır. Eğer kelime veri tabanında mevcut ise ilgili bayrak setlenir ve ilerleyen adımlarda Rules sınıfına gönderilerek kelime çevirisi yapılırken değerlendirilir. Tablo 2.16. Nazal n / Kapalı e kontrolü. if (word[i].length() >= 2) { for (int j = 2; j <= word[i].length(); j++) { 13 if (word[i].length() >= j) { DB_control = word[i].substring(0, j); flag_nazal_n = DB_Search_Nazal_n(DB_control); if (flag_nazal_n) { } } } break; for (int j = 3; j <= word[i].length(); j++) { if (word[i].length() >= j) { DB_control = word[i].substring(0, j); flag_kapali_e = DB_Search_Kapali_e(DB_control); if (flag_kapali_e) { } } } break; Sonraki adımda kelimeler Rules sınıfına gönderilerek çevirme işlemi yapılır. Rulse sınıfında iki adet fonksiyon bulunmaktadır. Bu fonksiyonlardan biri sadece 1 harf uzunluğundaki kelimelerin çevirisini yaparken kullanılmaktadır (Keyboard_Alphabet). Bu fonksiyon kullanıcılara harflerin karşılıklarını öğrenme imkanı sunmak için yazılmıştır. Diğer fonksiyon ise birden çok harf bulunduran kelimelerin çevirisi için kullanılmaktadır (Text_Size_Length_Bigger_One). Bu fonksiyonların içeriği Rules başlığı altında detaylı olarak anlatılacaktır. Bu adımda hangi fonksiyonun çağrılacağını belirlemek için bir switch kullanıldı. Bu switch kelimenin uzunluğuna göre seçim yapacak şekilde programlandı. Eğer kelime tek harfli ise Keyboard_Alphabet fonksiyonu çağrılarak geri dönen değer Gokturk_Text değişkenine eklenir. Kelime uzunluğu 1’den daha büyük ise Text_Size_Length_Bigger_One fonksiyonu çağrılır ve geri dönen değer GokTurk_Text değişkenine eklenir. 14 Tablo 2.17. Kelimelerin Rules sınıfına gönderilmesi. switch (word[i].length()) { case 0: Toast.makeText(getApplicationContext(), "Metin Giriniz !...", Toast.LENGTH_LONG).show(); break; case 1: if (isNumeric(word[i])) { GokTurk_Text += word[i]; } else GokTurk_Text += rules.Keyboard_Alphabet(word[i]); Gokturk_Text.setText(GokTurk_Text); break; default: if (isNumeric(word[i])) GokTurk_Text += word[i]; else GokTurk_Text += rules.Text_Size_Length_Bigger_One(word[i], flag_nazal_n, flag_kapali_e); Gokturk_Text.setText(GokTurk_Text); break; } Bu adımdan sonra tüm kelimeler Göktürkçeye çevrilerek GokTurk_Text değişkeni içine yazılır. Son olarak Çevrilen metin EditText’e yazılır ve çeviri tamamlanmış olur. Artık Göktürkçe metin kısmı boş olmadığına göre Kaydet/Paylaş butonunun da aktifleşmesi gerekir. Bunu için Translate fonksiyonunun sonuna ‘Kaydet/Paylaş’ butonunu aktifleştiren 15 aşağıdaki kodlar eklendi. Tablo 2.18. Kaydet/Paylaş butonunun aktifleştirilmesi. Save_Button.setEnabled(true); Save_Button.setClickable(true); Kaydet/Paylaş butonuna basıldığında uygulama başka bir ara yüze geçmektedir. Bu ara yüzde Göktürkçe metin bir resim dosyasına dönüştürülür ve isteğe göre kaydedilir ya da paylaşılır. Bu işlemin yapılabilmesi için bazı bilgilerin bu ara yüze aktarılması gerekmektedir. Bilgilerin aktarılması işlemini Kaydet/Paylaş butonuna basılmasıyla çalışan ConvertToBitmap fonksiyonu sağlamaktadır. Öncelikle uygulamalar arsında veri aktarmamızı sağlayan bir Bundle nesnesi oluşturuldu ve bu nesneye Göktürkçe metin, Göktürk EditText’inin genişliği ve yazının boyut bilgileri kaydedildi. Sonra Bundle nesnesi bir sonraki ara yüz ile ilişkilendirildi ve startActivitiy ile yeni ara yüze geçildi. Tablo 2.19. Kaydet/Paylaş butonunun işlevi. public void ConvertToBitmap(View v){ Bundle bundle = new Bundle(); bundle.putString("Gokturk_Text", Gokturk_Text.getText().toString()); bundle.putInt("Gokturk_Text_Width", Gokturk_Text.getWidth()); bundle.putInt("Gokturk_Text_Size",(int)Gokturk_Text.getTextSize()); Intent save_activity = new Intent(getApplicationContext(),Save.class); save_activity.putExtras(bundle); startActivity(save_activity); } 2.4.4. Preprocess Sınıfı 16 Bu sınıfta Göktürkçe çeviri yapılmadan önce Latin metin üzerinde bir takım ön işlemler yapılmaktadır. İlk işlem Göktürkçede olmayan ancak Latin harf olan harflerin değiştirilmesidir. h, j, f, v harfleri sırasıyla k, c, p, b harfleriyle yer değiştirilir. é harfinin karşılığı olarak i harfi kullanılmıştır. â, î, û harflerinin yerine şapkasız olan harflerle, a, ı, u, değiştirilmiştir. Yeni satıra geçiş yapıldığını anlayabilmek içinde \n yerine başında ve sonunda boşluk olacak şekilde değiştirilmiştir. Böylece metini parçalarken yeni satır karakterini de ayrılmış olacaktır. Tablo 2.20. Metindeki harflerin değiştirilmesi. word = word.replace("h","k"); word = word.replace("j","c"); word = word.replace("f","p"); word = word.replace("v","b"); word = word.replace("é","i"); word = word.replace("â","a"); word = word.replace("î","i"); word = word.replace("û","u"); word = word.replace("\n"," \n "); Klavyedeki harfler dışında kalan tüm karakterlerde metini kelimelere ayırırken ayrılması için başında ve sonunda boşluklar olacak şekilde yer değiştirilmesi yapılmıştır. Tablo 2.21. Metindeki karakterlerin değiştirilmesi. word = word.replace("!"," ! "); word = word.replace("'"," ' "); word = word.replace("£"," £ "); ... 17 ... word = word.replace("|"," | "); Aynı replace fonksiyonu kullanılarak Latin Türkçesindeki bazı kelimelerin eski Türkçe halleri ile değiştirilmiştir. Bu işlemlerden sonra metin split fonksiyonuna verilerek boşluklara göre ayırarak yani metni kelimelerine ayırarak bir diziye kaydeder. Tablo 2.22. Metinin kelimelere ayrılması. word_first = word.split(" "); Kelimelere ayırdıktan sonra dot_parse isimli fonksiyona gönderilerek tırnak işareti kelimeye birleşikse bunu ayırma işlemi yapılır. Tablo 2.23. Metinin kelimelere ayrılması. public String[] dot_parse(String [] first_word) { ArrayList<String> word = new ArrayList<String>() ; for(int i = 0 ; i < first_word.length ; i++) { if (!first_word[i].equals("'")) { word.add(first_word[i]); } else { word.set(i-1,first_word[i - 1] + first_word[i + 1] ); i++; } } for (int i = 0 ; i < word.size() ; i++) { if (word.get(i).equals("")) word.remove(i); } first_word = new String [word.size()]; word.toArray(first_word); 18 size = word.size(); } return first_word; Tırnak işaretinde olduğu gibi sayılarda kelimelere ya da harflere bitişik bir şekilde olabilir bunun içinde bir takım işlemler yapılmaktadır. Sayılar kelimlerin ya da harflerin başında, sonunda olabilir. Bunun için indexOf fonksiyonu ile her kelimeye bakılarak sayının ayrıma işlemi yapılır ve kelime ya da harf Göktürkçeye çevrilir. Çevirme işleminde böyle bir kelime denk geldiğinde çevirme işlemi yapılmayıp direk yazılır. Tablo 2.24. Sayıların kelimeden ayrılması. for (int i = 0; i < word2.length; i++) { if (!isNumeric(word2[i])) { if ((word2[i].indexOf("0") != -1 || word2[i].indexOf("7") != -1|| word2[i].indexOf("2") != -1 || word2[i].indexOf("8") != -1|| word2[i].indexOf("6") != -1|| word2[i].indexOf("3") != -1 || word2[i].indexOf("9") != -1|| word2[i].indexOf("5") != -1|| word2[i].indexOf("4") != -1 || word2[i].indexOf("1") != -1)) { word2[i] = word2[i].replace("0"," 0 "); word2[i] = word2[i].replace("1"," 1 "); word2[i] = word2[i].replace("2"," 2 "); word2[i] = word2[i].replace("3"," 3 "); word2[i] = word2[i].replace("4"," 4 "); word2[i] = word2[i].replace("5"," 5 "); word2[i] = word2[i].replace("6"," 6 "); 19 word2[i] = word2[i].replace("7"," 7 "); word2[i] = word2[i].replace("8"," 8 "); word2[i] = word2[i].replace("9"," 9 "); temp_word = word2[i].split(" "); ArrayList<String> word_list = new ArrayList<String>() ; for (int m = 0 ; m < temp_word.length ; m++) { word_list.add(temp_word[m]); } for (int n = 0 ; n < word_list.size() ; n++) { if (word_list.get(n).equals("")) word_list.remove(n); } temp_word = new String[word_list.size()]; word_list.toArray(temp_word); if (!isNumeric(temp_word[0])) { temp_word2 = ""; if (temp_word[0].length() > 1) { temp_word2 += rules.Text_Size_Length_Bigger_One(temp_word[0], false, false); for (int p = 1; p < temp_word.length; p++) { temp_word2 += temp_word[p]; } word2[i] = temp_word2; break; 20 } else { temp_word2 += rules.Keyboard_Alphabet(temp_word[0]); for (int p = 1; p < temp_word.length; p++) { temp_word2 += temp_word[p]; } word2[i] = temp_word2; break; } } else { temp_word2 = ""; temp_word2 += temp_word[0]; for (int k = 1; k < temp_word.length; k++) { if (isNumeric(temp_word[k])) { temp_word2 += temp_word[k]; } else { if (temp_word[k].length() > 1) { temp_word2 += rules.Text_Size_Length_Bigger_One(temp_word[k], false, false); word2[i] = temp_word2; break; 21 } else { temp_word2 += rules.Keyboard_Alphabet(temp_word[k]); word2[i] = temp_word2; break; }}}}}}} for (int i = 0; i < word2.length; i++) { int count = 0; int temp_index = i; if (isNumeric(word2[temp_index])) { while (temp_index+1 < word2.length && isNumeric(word2[temp_index+1])) { count++; temp_index++; } if (count != 0) { int last_index = i + count; int temp_last_index = last_index; int uzunluk = (last_index - i ) + 1; String temp; if (uzunluk % 2 != 0) { int ort = (last_index + i) / 2; while (last_index != ort) 22 { temp = word2[i]; word2[i] = word2[last_index]; word2[last_index] = temp; last_index += -1; i += 1; } i = temp_last_index + 1; }else { while (i < last_index) { temp = word2[i]; word2[i] = word2[last_index]; word2[last_index] = temp; last_index += -1; i += 1; } i = temp_last_index + 1; }}}} isNumeric fonksiyonu ise kelimenin sayılardan oluşup oluşmadığının kontrol eder. Tablo 2.25. isNumeric Fonksiyonu. public static boolean isNumeric(String word) { try { double d = Double.parseDouble(word); } catch(NumberFormatException nfe) { 23 return false; } return true;} 2.4.5. Rules Sınıfı Bu sınıf Göktürkçe harflerin karşılıklarının bulunduğu ve dil kurallarının uygulandığı kısımdır. Bu sınıfa sürekli olarak MainActivity sınıfından kelime gönderilir. Gelen kelime burada dönüştürülür ve tekrar MainActivity sınıfına gönderilir. Rules sınıfında kelime çevirisi yapan üç fonksiyon bulunmaktadır. Bunlardan ilki kelime tek harfli olduğu durumlarda çalışan Keyboard_Alphabet fonksiyonudur. Bu fonksiyonda Latin harflere karşılık gelen harfler bir switch içinde listelenmiştir. Gelen her harf için Göktürkçe karşılığı bulunur ve bu Göktürkçe karakter geriye döndürülür. Tablo 2.26. Keyboard_Alphabet fonksiyonu. public String Keyboard_Alphabet(String Latin_Text) { String GokTurk_Text = null; switch (Latin_Text) { case "a": GokTurk_Text = "\uD803\uDC00"; break; case "A": GokTurk_Text = "\uD803\uDC00"; break; case "b": GokTurk_Text = "\uD803\uDC0B"; break; case "B": GokTurk_Text = "\uD803\uDC09"; break; 24 . . . case "\"": GokTurk_Text = "\""; break; case "\n": GokTurk_Text = "\n"; break; default: GokTurk_Text = " "; break; } return GokTurk_Text; } Rules sınıfındaki bir diğer fonksiyon ise Original_Alphabet fonksiyonudur. Bu fonksiyonun genel yapısı Keyboard_Alphabet fonksiyonun yapısına benzerdir. Farklı olarak switchteki caseler içinde 1 karakterin yanı sıra 2 karakter de bulunabilmektedir. Bunun sebebi yazılacak olan harfin duruma göre kalın mı yoksa incemi olacağını anlayabilmektir. Örnek olarak Tez kelimesini ele alacak olursak; ilk harf T’dir. Ancak Göktürkçede biri kalın diğeri ince olmak üzere iki adet T bulunmaktadır. Bunu anlamak için T harfinin yanındaki diğer karaktere yani e’ye bakılarak yazılacak olan T’nin ince olacağına karar verilir ve bu iki harf et olarak Original_Alphabet fonksiyonuna gönderilir. te yerine et gönderilmektedir çünkü Göktürkçe karakterler okunurken sesli harf önce söylenmektedir. Yani Türkçede örneğin K harfini Ke olarak okumaktayız. Göktürkçede ise bu durumun tersi söz konusu olmaktadır. Tablo 2.27. Original_Alphabet fonksiyonu. 25 public String Original_Alphabet(String Latin_Text) { String GokTurk_Text = null; switch (Latin_Text) { case "a": GokTurk_Text break; case "A": GokTurk_Text break; case "eb": //b GokTurk_Text break; case "ab": //B GokTurk_Text break; = "\uD803\uDC00"; = "\uD803\uDC00"; = "\uD803\uDC0B"; = "\uD803\uDC09"; . . . . } } case "eŋ": GokTurk_Text break; case "añ": GokTurk_Text break; case "eñ": GokTurk_Text break; case "é": GokTurk_Text break; default: GokTurk_Text break; = "\uD803\uDC2D"; = "\uD803\uDC2D"; = "\uD803\uDC2D"; = "\uD803\uDC03"; = " "; return GokTurk_Text; Original_Alphabet fonksiyonu sadece Rules sınıfındaki üçüncü fonksiyon olan Text_Size_Length_Bigger_One fonksiyonu tarafından çağrılmaktadır. Bu fonksiyon Asıl çeviri işlemini yapan kodları içermektedir. Çeviri yapılırken metindeki kelimeler sırayla bu fonksiyona verilir. Her kelime için bu fonksiyon içindeki dil kuralları uygulanır. Öncelikle kelimenin ilk iki harfi kontrol edilir. Eğer ilk iki harf sessiz harf ise 26 Head_Of_Word fonksiyonu çağrılır. Bu fonksiyon kelimenin üçüncü harfine bakarak ilk iki harfin kalın mı yoksa incemi olacağına karar verir, harfleri çevirir ve kelimeyi tekrar Text_Size_Length_Bigger_One fonksiyonuna gönderir. Ardından sıradaki karakter kontrol edilir. Göktürkçede a ve e harfleri kelime içinde yazılmaz. Diğer sesli harfler ise kelime içinde bir kez yazıldıktan sonra aynı harf kelimenin devamında yazılmaz. Bu kuralları uygulamak için her sesli harf için birer if koşulu tanımlandı. Ayrıca (a,e), (ı,i), (o,u) ve (ö,ü) harf grupları için birer tane boolean değişkeni setlendi. Bu değişkenler bayrak olarak kullanıldı. Yani bu harflerden biri yazıldığı takdirde kelimenin devamında bu tekrar yazmayı engellemek için bu bayraklar setlenir. Bu bayrakların setlenme işlemi her sesli harf için tanımlanan if koşulları içerisinde yapılmaktadır. Sessiz harf geldiğinde ise bir sonraki harf kontrol edilerek ona göre ince veya kalın olacağına karar verilir. Son olarak kelimenin sonuna gelindiğinde, eğer kelimenin sonunda sesli harf varsa bu harf ne olursa olsun yazılması gerekmektedir. Bu işlem de Text_Size_Length_Bigger_One fonksiyonunun son kısmında yapılmaktadır. 2.4.6. DBHelper Sınıfı Bu sınıf SQLite sorgularının yapıldığı fonksiyonları ve veri tabanın oluşturulması için kullanıldı. Veri tabanı işlemleri yapabilmek için SQLiteOpenHelper’ı miras alır. Veri tabanı versiyonu, tablo isimleri bir değişkene atanmıştır ve bir fonksiyon yardımıyla veri tabanının oluşturulması sağlanmıştır. Tablo 2.28. Veri Tabanı oluşturma. private static final int DATABASE_VERSION = 1; private static final String DATABASE_NAME = "kokturukDB"; private static final String TABLE_N = "Nazaln"; 27 private static final String TABLE_E = "Kapalie"; public DBHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } Bu işlemden sonra tabloların oluşturulması sağlanmıştır. Tablo 2.29. Tabloların oluşturulması. public void onCreate(SQLiteDatabase db) { String create_table_nazaln = "CREATE TABLE IF NOT EXISTS " + TABLE_N + "(Latin_Word TEXT" + ")"; String create_table_kapalie = "CREATE TABLE IF NOT EXISTS " + TABLE_E + "(Latin_Word TEXT" + ")"; db.execSQL(create_table_nazaln); db.execSQL(create_table_kapalie);} Veri tabanının güncellenmesi halinde tabloları silecek fonksiyon tanımlanmıştır. Tablo 2.30. Veri tabanının güncellenmesi. @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_N); db.execSQL("DROP TABLE IF EXISTS " + TABLE_E); onCreate(db); } Tablolara verilerin girilmesini sağlayan fonksiyonlar tanımlandı. 28 Tablo 2.31. Veri girişlerini gerçekleştiren fonksiyonlar. public void insert_Nazal_N_Word(String Latin_Word) { SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("Latin_Word", Latin_Word); db.insert(TABLE_N, null, values); db.close(); } public void insert_Kapali_E_Word(String Latin_Word) { SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("Latin_Word", Latin_Word); db.insert(TABLE_E, null, values); db.close();} Veri tabanında sorgu yapılacak fonksiyonlar tanımlanmıştır. Bu fonksiyonlar sadece değerin olup olmadığını kontrol ettikleri true ya da false olarak geri dönüş yapmaktadırlar. Tablo 2.32. Veri tabanı sorgusu yapan fonksiyonlar. public boolean DB_Search_Nazal_n(String Latin_Word) { int count = -1; SQLiteDatabase db = this.getReadableDatabase(); String query = "SELECT COUNT(*) FROM " + TABLE_N + " WHERE Latin_Word = '" 29 + Latin_Word + "'" ; Cursor cursor = db.rawQuery(query, null); cursor.moveToNext(); count = cursor.getInt(0); db.close(); return count > 0; } public boolean DB_Search_Kapali_e(String Latin_Word) { int count = -1; SQLiteDatabase db = this.getReadableDatabase(); String query = "SELECT COUNT(*) FROM " + TABLE_E + " WHERE Latin_Word = '" + Latin_Word + "'" ; count = cursor.getInt(0); db.close(); return count > 0;} 2.4.7. Save Sınıfı Save sınıfı, çevirisi yapılan metnin Göktürkçe karşılığını bir resim dosyasına dönüştürerek kaydetme veya paylaşma imkanı vermektedir. Bu işlemin yapılabilmesi için MainActivity sınıfında çevirisi yapılan metnin ve metinle ilgili bazı bilgilerin Save sınıfına aktarılması gerekmektedir. Bu işlem MainActivity sınıfında ConvertToBitmap fonksiyonunu ile yapılır. Veriler bu fonksiyon tarafından Save sınıfına aktarılır. Save sınıfın da Tablo 2.33’deki kodlar ile bu verileri almaktadır. Tablo 2.33. Metin ile ilgili verilerin Save sınıfına aktarılması. Bundle data = getIntent().getExtras(); Gokturk_Text = data.getString("Gokturk_Text"); Gokturk_Text_Width = data.getInt("Gokturk_Text_Width"); 30 Gokturk_Text_Size = data.getInt("Gokturk_Text_Size"); Resim oluşturulurken kullanıcıya font rengi seçimi imkanı da sunulmaktadır. 6 adet font rengi kullandığımız için 6 adet ImageButton tanımlandı. Her butonun tıklandığında çalıştıracağı fonksiyonu clickImageButtons fonksiyonu olarak belirlendi. Bu fonksiyon butonların tıklanması olayında çağrıldığı için bir adet View parametresi geçirildi. Ayrıca font rengini tutan bir adet Color değişkeni tanımlandı. Bu değişken kullanıcı hiçbir seçim yapmadığı için font renginin siyah olmasının sağlanması için siyah değeri verildi. Yani kullanıcı font rengi seçimi yapmadıysa default olarak font rengi siyah yapılacaktır. clickImageButtons fonksiyonunda öncelikle fonksiyonun hangi buton tarafından çağrıldığı kontrol edilir. Hangi buton tarafından çağrıldıysa color değişkeni ilgili butonun rengine dönüştürülür. Daha sonra drawText fonksiyonu çağrılarak resim oluşturulur ve ImageView’e aktarılır. Tablo 2.34. clickImageButtons fonksiyonu. public void clickImageButtons(View v){ if(v == red) color = Color.RED; else if(v == green) color = Color.argb(255,0,156,0);//0x009c00; else if(v == blue) color = Color.argb(255,0,0,156);//0x00009c; else if(v == white) color = Color.WHITE; else if(v == kahve) color = Color.argb(255,148,74,0);//0x944a00; else if(v == black) { 31 color = Color.BLACK; } img = drawText(Gokturk_Text,2*Gokturk_Text_Width, 2*Gokturk_Text_Size, font, color); GokturkImg.setImageBitmap(img); } Save sınıfında resmi kaydetme veya paylaşma olmak üzere iki seçenek vardır. Kaydetme için kullanıcıya arka plan rengini beyaz veya şeffaf yapma seçimi sunulur. Beyaz seçilirse resim JPEG formatında kaydedilir. Transparan seçilirse PNG formatında kaydedilir. Paylaşma seçeneğinde ise resim JPEG formatında oluşturulur ve arka plan beyaz yapılır. Çizim işlemini drawText fonksiyonu yapmaktadır. Bu fonksiyon çizilecek metni, metin kutusunun genişlik değerini, metnin boyutunu, font tipini ve renk değerini parametre olarak alır. Öncelikle bir TextPaint nesnesi oluşturulur ve metin bu nesneye çizilir. Ardından genişlik ve yükseklik değerleri uygun olacak şekilde ayarlanmış bir Bitmap nesnesi oluşturulur. Ardından bir Canvas nesnesi oluşturulur ve bu nesne bitmap üzerine yerleştirilir. Değişiklikler artık Canvas nesnesi üzerinde yapılır. Canvas üzerine TextPaint nesnesi ile oluşturulan metin çizimi yerleştirilir ve işlem tamamlanmış olur. Bu fonksiyon geriye Bitmap nesnesini döndürür. Tablo 2.35. drawText fonksiyonu. public static Bitmap drawText(String text, int textWidth, int textSize, Typeface font, int textColor) { TextPaint textPaint; textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG); textPaint.setTypeface(font); textPaint.setStyle(Paint.Style.FILL); 32 textPaint.setColor(textColor); textPaint.setTextSize(textSize); StaticLayout mTextLayout = new StaticLayout(text, textPaint, textWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); // Create bitmap and canvas to draw to Bitmap b = Bitmap.createBitmap(textWidth, mTextLayout.getHeight(), Bitmap.Config.RGB_565); Canvas c = new Canvas(b); // Draw background Paint paint = new Paint(); paint.setStyle(Paint.Style.FILL); paint.setColor(Color.WHITE); c.drawPaint(paint); // Draw text c.save(); c.translate(0, 0); mTextLayout.draw(c); c.restore(); } return b; Kaydet butonuna basıldığında Image_Save fonksiyonu çağrılır. Bu fonksiyon ekranda bir AlertBox penceresi oluşturur ve kullanıcıya arkaplan seçimini sunar. Eğer Transparan seçilirse Create_Image fonksiyonu çağrılır. Beyaz seçildiğinde ise Create_Image_Jpeg fonksiyonu çağrılır. Create_Image fonksiyonu öncelikle resmi drawText fonksiyonu ile arka plan şeffaf olacak şekilde çizdirir. Ardından string tipinde resmin adını alacak bir değişken oluşturulur ve DataFormat sınıfı ile o anki tarih bu değişkenin içine yazılır. Bu tarih oluşturulan dosyanın 33 ismi olacaktır. Böylece hiçbir zaman bu isim tekrarlanmayacak dolayısıyla aynı isimde birden çok resim olma durumu ortadan kaldırılacaktır. Ardından cihazın ana dizinini alan bir değişken tanımlanır. Böylece ana dizinden başlayarak resim dosyasını nereye kaydedeceğimizi belirleyebilecektik. Daha sonra bir File nesnesi oluşturulup dosyanın tam yolu verilerek bu nesne çıkışa gönderilir. Sonraki adımda resim PNG formatına dönüştürülerek %85 oranında sıkıştırılır ve çıkışa gönderilir. Son olarak medya içeriği yenilenir ve kaydetme işlemi tamamlanmış olur. Tablo 2.36. Create_Image fonksiyonu. public void Create_Image(Bitmap img) { img = drawTextTransparan(Gokturk_Text,2*Gokturk_Text_Width, 2*Gokturk_Text_Size, font, color); String filename; filename = DateFormat.getDateTimeInstance().format(new Date()); try{ String path = Environment.getExternalStorageDirectory().toString(); OutputStream fOut = null; file = new File(path, "/Download/"+filename+".png"); fOut = new FileOutputStream(file); img.compress(Bitmap.CompressFormat.PNG, 85, fOut); fOut.flush(); fOut.close(); MediaStore.Images.Media.insertImage(getContentResolver() , file.getAbsolutePath(), file.getName(), file.getName()); Toast.makeText(getApplicationContext(), "Metin arkaplanı saydam olacak şekilde Download dizinine kaydedilmiştir.", Toast.LENGTH_LONG).show(); return; }catch (Exception e) { e.printStackTrace(); 34 } } Eğer arkaplan beyaz seçilirse bu kez Create_Image_Jpeg fonksiyonu çağrılır. Bu fonksiyon Create_Image fonksiyonu ile tek farkı resmi PNG formatında kaydetmek yerine JPEG formatında kaydetmesidir. Son olarak Paylaş butonuna basıldığında shareFunction fonksiyonu çağrılmaktadır. Bu fonksiyon önce Create_Image_Jpeg fonksiyonunu çağırarak resim dosyasını oluşturur. Daha sonra resmin kaydedildiği dizini bir değişkene kaydeder ve bu değişken ile dosyayı bulup paylaşıma açar. Tablo 2.37. shareFunction fonksiyonu public void shareFunction(View v){ Create_Image_Jpeg(img); String agendaFilename = file.getAbsolutePath(); ContentValues values = new ContentValues(2); values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); values.put(MediaStore.Images.Media.DATA, agendaFilename); Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,valu es); Intent shareIntent = new Intent(Intent.ACTION_SEND); shareIntent.setType("image/jpeg"); shareIntent.putExtra(Intent.EXTRA_STREAM, uri); startActivity(Intent.createChooser(shareIntent, "Paylaş")); } 2.5. Tasarım 35 Uygulamada ekran tasarımlarının adaptif olmasına özen gösterilmiştir. Her ne kadar adaptif olarak tasarlansa da metnin uzunluğundan ya da size boyutundan kaynaklanan kaymalar oluşmaktadır. Bunun için yatay, dikeyde ve tablet ekranları olarak üç kısma ayırılarak tasarım yapılmıştır. Uygulama kodlanmaya başladığında sadece ana ekran için kabaca bir tasarım yapılmıştır. Bu kaba tasarım bir buton ve 2 tane editText’ten oluşmaktadır. Bir editText’ten Latin metin girdisi alınmakta ve diğer editText’e Göktürkçe karşılığı yazdırılmaktaydı. Kodlama bittikten sonra asıl tasarıma geçilmiştir. 2.5.1. Intro Ekranının Tasarımı Intro ekranı kullanıcı uygulamayı ilk açtığında çıkan ekrandır. Bir Activityt oluşturulduğunda otomatik olarak activity_ActivityName.xml bir layout yani ekran tasarımı için xml dosyası oluşturulur. Tasarımda LinearLayout(vertical) tasarımın iskeletini oluşturmaktadır. Bu layouta ne araç eklenirse eklensin alt alta yerleştirmektedir. LinerLayout’un içine üç tane FrameLayout yerleştirilmiştir. FrameLayout ise içine yerleştirilen araçları ortaya, sağa, sola yaslama gibi işlemleri yapmamızı sağlamıştır. Bu üç FrameLayot’un içerikleri aşağıdaki gibidir: 1. FrameLayot: KTU’nun logosunu içeren bir ımageView içerir. Bu logo drawable klasörünün içinden alınmaktadır. FrameLayoutun genişliği mobil cihazın genişliği kadar seçilmiştir. Bu da match_parent’a karşılık gelmektedir. Yüksekliği layotun içindeki aracın içeriği kadar ayarlanması sağlanmıştır. Bu ise wrap_content’e denk gelmektedir. Tablo 2.38. 1. FrameLayot xml kodları. <FrameLayout 36 android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0.009"> <ImageView android:layout_width="107dp" android:layout_height="107dp" android:id="@+id/imageView" android:layout_gravity="center" android:background="@drawable/ktulogo" /> </FrameLayout> 2. FrameLayout: Bu layout bu projeyle ilgilenenlerin adlarının ve önemli bir notun yer aldığı layouttur. Bu yazılar alt alta olduğu için bu layoutun içine vertical LinearLayout yerleştirilmiştir ve LinearLayout’un içine ise üç tane textView yerleştirilmiştir. Tablo 2.39. 2. FrameLayot xml kodları. <FrameLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" 37 android:textAppearance="?android:attr/textAppearanceLarge" android:text="@string/IntroHead" android:id="@+id/names_intro" android:layout_weight="0.53" android:gravity="center" android:autoText="false" android:textSize="15dp" android:textStyle="bold" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="@string/version" android:id="@+id/textView2" android:textSize="15dp" android:gravity="center" android:textStyle="bold" android:textColor="@android:color/black" android:layout_gravity="center_horizontal" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="@string/Intro" android:id="@+id/intro_intro" android:layout_weight="0.53" android:gravity="center" android:autoText="false" android:textSize="14dp" /> 38 <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="@string/Copyright" android:id="@+id/info_intro" android:layout_weight="0.53" android:gravity="center" android:autoText="false" android:textSize="15dp" android:textStyle="bold" /> </LinearLayout> </FrameLayout> 3. FrameLayout: Bu layoutta ise buton vardır. Tablo 2.40. 2. FrameLayot xml kodları. <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_weight="0.009"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" 39 android:id="@+id/Skip_Button" android:layout_gravity="center" android:onClick="Skip_Button_Fonk" android:visibility="visible" /> </FrameLayout> Yukarıda yapılan işlemlerin hepsi dikey ekran görüntüsü içindir. Şekil 2.1. Intro ekranının dikey görüntüsü. Yatay ekran görüntüsü için ise layout klasörünün altına layout-land adında bir klasör oluşturulur ve layout klasörünün içindeki tüm xml dosyaları aynen bunun içerisine kopyalanır. Tasarımdaki bozulmaların önüne geçmek için logonun boyu ve metnin büyüklüğü değiştirilmiştir. 40 Şekil 2.2. Intro ekranının yatay görüntüsü. Tablet ekranlar için ise layout-large klasörü oluşturulur. Daha geniş bir ekran olduğu için layout_weight değerleri değeri artılarak daha geniş alanlara yayılması sağlanmıştır. Yatay ekranda yapıldığı gibi metnin büyüklüğü ve logonun büyüklüğü ayarlanmıştır. 2.5.2. Hakkında Ekranının Tasarımı Hakkında ekranı About ekranının tamamen aynısıdır. 2.5.3. Ana Ekran Tasarımı Ana ekran tasarımında yatay ve tablet ekranları için ayrı bir değer değiştirme yapılmamıştır çünkü herhangi bir boyut ve metin boyutu sorunu olmadığı ve dikeyde adaptif olarak tasarlandığı için mobil cihazlar kendileri ayarlayabilmektedirler. Bu tasarımda da en dışta bir Vertical LinearLayout kullanılmıştır. Böylece araçların alt alta sıralanması sağlanmıştır. LinearLayout’a dört tane FrameLayout yerleştirlmiştir. Birinci FrameLayout’ta iki tane buton vardır ve butonlar biri sola diğer sağa dayalı olarak yerleştirlmiştir. 41 Tablo 2.41. Birinci FrameLayout xml kodları. <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <GridLayout android:layout_width="match_parent" android:layout_height="59dp"> <Button android:layout_width="160dp" android:layout_height="match_parent" android:id="@+id/Translate_Button" android:onClick="Translate" android:gravity="center" android:layout_gravity="top|center_vertical" android:width="173dp" /> <Button android:layout_width="160dp" android:layout_height="match_parent" android:id="@+id/Save_Button" android:layout_gravity="center_vertical|right" android:onClick="ConvertToBitmap" android:enabled="false" android:textSize="15dp" android:gravity="center|top" android:paddingTop="3dp" /> 42 </GridLayout> </FrameLayout> İkinci layoutta ise Latin editText’in etiketi olan iki tane textView yer almaktadır. Sola dayalı olarak Latin sağa dayalı olarak Latin’in karşılığı olan Göktürkçe kelime yazmaktadır. Tablo 2.42. Birinci FrameLayout xml kodları. <FrameLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="0.001" android:id="@+id/Latin_Layout_Id" android:layout_gravity="bottom" android:foregroundGravity="bottom"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="Latin:" android:id="@+id/Latin_Latin_TextView" android:layout_gravity="left|center_vertical" android:textStyle="bold" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" 43 android:id="@+id/Latin_Turk_TextView" android:gravity="bottom|right" android:layout_gravity="right|center_vertical" android:textStyle="bold" /> </FrameLayout> Üçüncü layoutta Latin metinin girildiği editText bulunmaktadır. Tablo 2.43. Birinci FrameLayout xml kodları. <FrameLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="0.48"> <EditText android:layout_width="fill_parent" android:layout_height="fill_parent" android:inputType="textMultiLine" android:ems="10" android:id="@+id/Latin_Text" android:clickable="false" android:background="#ffffff" android:gravity="top" /> </FrameLayout> editText’in içeriği ile boyutu değiştirdiği için bu değişikliğin olmaması için layout_height 0(sıfır) olarak setlenmiştir. Dördüncü ve beşinci layoutlar üçüncü ve ikinci olarak aynıdır. Üçüncü layoutta Türk 44 kelimesi ve Göktürkçe karşılığı vardır. Şekil 2.2. Ana ekranının görüntüsü. 2.5.4. Kaydetme ve Paylaş Ekranının Tasarımı Bu ekranda Intro ekranına oldukça benzemektedir. Yine bir Vertical LinearLayout kullanılmıştır. Bu layoutun içerisinde de 3 tane FrameLayout bulunmaktadır. Birinci FrameLayout’ta iki tane buton bulunmaktadır ve bunlardan biri sola diğeri ise sağa dayalı olarak konumlandırılmıştır. 45 Tablo 2.44. Birinci FrameLayout xml kodları. <GridLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <Button android:layout_width="160dp" android:layout_height="wrap_content" android:id="@+id/saveButton" android:onClick="Image_Save" android:gravity="center" android:layout_gravity="top|center_vertical" android:width="173dp" /> <Button android:layout_width="160dp" android:layout_height="wrap_content" android:id="@+id/shareButton" android:gravity="center" android:layout_gravity="right|center_vertical" android:onClick="shareFunction" /> </GridLayout> İkinci FrameLayout’ta imageView konumlandırılmıştır. Bu imageView yüksekliği içeriği ile aynı olması istendiği için layout_height="wrap_content" olacak şekilde seçilmiştir. Tablo 2.45. İkinci FrameLayout xml kodları. <FrameLayout android:layout_width="match_parent" 46 android:layout_height="wrap_content" android:layout_above="@+id/linearLayout" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_weight="6"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/Gokturk_Img" android:layout_gravity="center" /> </FrameLayout> Üçüncü FrameLayout ise metin renginin seçilmesi sağlayan renkler vardır. Bu renkler resim olarak drawable klasörüne yerleştirilmiştir. ImageButton kullanılarak bunlara butonluk özelliği verilmiştir. Ayrıca bu FrameLayout’un içerisinde Horizontal LinearLayout kullanılarak bu resimlerin yan yana konumlandırılması sağlanmıştır. Tablo 2.46. İkinci FrameLayout xml kodları. </FrameLayout> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal"> 47 <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/black" android:background="@drawable/dark_button" android:layout_marginRight="@dimen/abc_action_bar_content_inset_material" android:onClick="clickImageButtons" /> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/white" android:background="@drawable/white_button" android:onClick="clickImageButtons" /> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/red" android:background="@drawable/red_button" android:layout_marginRight="@dimen/abc_action_bar_content_inset_material" android:layout_marginLeft="@dimen/abc_action_bar_content_inset_material" android:onClick="clickImageButtons" /> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/green" android:background="@drawable/dark_green_button" android:layout_marginRight="@dimen/abc_action_bar_content_inset_material" android:onClick="clickImageButtons" /> 48 <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/blue" android:background="@drawable/dark_blue_button" android:onClick="clickImageButtons" /> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/kahve" android:layout_marginLeft="@dimen/abc_action_bar_content_inset_material" android:background="@drawable/kahve_button" android:onClick="clickImageButtons" /> </LinearLayout> 49 Şekil 2.3. Kaydet ve paylaş ekranının görüntüsü. 50 3. SONUÇLAR Kodlama bittikten sonra projenin test aşamasına geçtik ve uygulamanın ne kadar doğru çalıştığını sınamaya başladık. Uygulama %99 oranında doğru çalışmaktadır. Kalan %1’lik kısımda ise doğal dil işleme yapılamadığından hatalı sonuç üretebilmektedir. Ancak kullanıcı Göktürkçe dil kurallarını bilirse ve çevrilecek metinde doğru karakterleri kullanırsa bu %1’lik hata payını da ortadan kaldırabilmektedir. Metin çevirisi yapıldığında kullanıcıların oluşturulan Göktürkçe metni kaydetmeleri yada sosyal paylaşım ortamlarında paylaşmak istemeleri durumunda çoğu platform Göktürkçe karakterleri desteklemediğinden kopyala/yapıştır tekniğiyle metni paylaşamayacaklardı. Bu sorunu çevrilen metni bir resim dosyasına dönüştürerek ortadan kaldırdık. Metni paylaşmak isteyen kullanıcılar Kaydet/Paylaş butonu aracılığıyla istediği font rengini seçtikten sonra metnin görüntü dosyasına çevrilmiş halini telefon hafızasına kaydedebilmekte yada istediği sosyal paylaşım ortamında doğrudan paylaşabilmektedir. 51 4. ÖNERİLER Göktürkçe alfabesi ve dil kurallarının günümüz Türkçesine uygulanması oldukça kolaydır. Ancak Türkçeye sonradan giren yabancı kökenli kelimeler Türkçenin dil kurallarına uymadığından dolayı Göktürkçe dil kurallara bu kelimelere uygulanamamaktadır. Bunu yerine bu projede yabancı kökenli kelimeler için alternatif çeviriler uygulanmaktadır. Projede bu alternatifler uygulanırken Tuğrul ÇAVDAR hocamızın bloğundaki bilgiler referans alınmıştır. Göktürk alfabesi günümüzde kullanılan Latin alfabesine göre daha çok karakter içermektedir. Ayrıca Türkçede ihtiyaç duyulan bazı sesler Latin alfabesinde olmamasına karşın Göktürkçede bu ihtiyaçların tamamı karşılanabilmektedir. Bu yüzden de Göktürkçeye karşı ilgi gün geçtikçe daha da artmaktadır. 52 5. KAYNAKLAR 1. http://www.russellcottrell.com/greek/utilities/SurrogatePairCalculator.htm The Surrogate Pair Calculator etc. 1 Ekim 2015. 2. http://kok-turk.blogspot.com.tr Nasıl Yazılır. 1 Ekim 2015. 53 STANDARTLAR ve KISITLAR FORMU Projenin hazırlanmasında uyulan standart ve kısıtlarla ilgili olarak, aşağıdaki soruları cevaplayınız. 1. Projenizin tasarım boyutu nedir? (Yeni bir proje midir? Var olan bir projenin tekrarı mıdır? Bir projenin parçası mıdır? Sizin tasarımınız proje toplamının yüzde olarak ne kadarını oluşturmaktadır?) Yeni bir projedir. %100 bizim tasarımımızdır. 2. Projenizde bir mühendislik problemini kendiniz formüle edip, çözdünüz mü? Açıklayınız. Hayır. 3. Önceki derslerde edindiğiniz hangi bilgi ve becerileri kullandınız? Algoritma ve programlama becerilerimizi kullandık. 4. Kullandığınız veya dikkate aldığınız mühendislik standartları nelerdir? (Proje konunuzla ilgili olarak kullandığınız ve kullanılması gereken standartları burada kod ve isimleri ile sıralayınız). Genel kod yazım kuralları ve yazılımın modüler olması dikkate alındı. 5. Kullandığınız veya dikkate aldığınız gerçekçi kısıtlar nelerdir? Lütfen boşlukları uygun yanıtlarla doldurunuz. a) Ekonomi Tamamen ücretsizdir. b) Çevre sorunları: Herhangi bir çevre sorunu vermemektedir. 54 c) Sürdürülebilirlik: Projeye doğal dil işleme eklenene kadar sürdürülebilir. d) Üretilebilirlik: Tamamen ücretsiz olduğu için dağıtımı sınırsızdır. e) Etik: Herhangi bir etik kuralı ihlal etmemektedir. f) Sağlık: Telefonun SAR değeri ile sınırlıdır. g) Güvenlik: Güvenlik zafiyeti çıkaracak herhangi bir unsuru yoktur. h) Sosyal ve politik sorunlar: Böyle sorunlarla karşılaşılmamıştır.
Benzer belgeler
1. GÜN Staj boyunca android programlama
Verileri çekme ve işleme konusuna bu şekilde bir çözüm bulduktan sonra projenin tasarımı için
algoritmaları üzerine düşünmeye başladım. En az iki farklı ekran olması gerektiği, ilk ekranda
illerin ...