"Birbirine benzeyen" Unicode karakterleri nasıl karşılaştırılır?


94

Şaşırtıcı bir konuya düşüyorum.

Uygulamama bir metin dosyası yükledim ve µ değerine sahip olan değeri karşılaştıran bazı mantığım var.

Metinler aynı olsa bile karşılaştırma değerinin yanlış olduğunu fark ettim.

 Console.WriteLine("μ".Equals("µ")); // returns false
 Console.WriteLine("µ".Equals("µ")); // return true

Daha sonraki satırda µ karakteri kopyalanarak yapıştırılır.

Ancak, bunun gibi olan tek karakterler bunlar olmayabilir.

C # 'da aynı görünen ama aslında farklı olan karakterleri karşılaştırmanın bir yolu var mı?


159
Görünüşe göre Schrödinger'in mu'sunu bulmuşsunuz.
BoltClock

19
Farklı karakterlerdir - aynı görünseler bile farklı karakter kodlarına sahiptirler.
user2864740

94
Unicode'a hoş geldiniz.
ta.speot.is

11
ne elde etmek istiyorsun Bu ikisinin eşit olması gerektiğini, o zaman karakter kodları bile farklı ama aynı yüz?
Yeşim

28
"Benzer görünmek" ve "aynı görünmek" belirsiz kavramlardır. Gliflerin kimliği mi yoksa sadece yakın benzerlik mi? Ne kadar yakın? İki karakterin bazı yazı tiplerinde aynı gliflere sahip olabileceğini, diğerlerinde çok benzer ve başka bir yazı tipinde oldukça farklı olabileceğini unutmayın. Önemli olan, neden böyle bir karşılaştırma yapacağınız ve hangi bağlamda (ve yanlış pozitiflerin ve yanlış negatiflerin kabul edilebilirliğidir).
Jukka K. Korpela

Yanıtlar:


125

Birçok durumda, şunları yapabilirsiniz normalleştirmek karşılaştırarak önce belirli bir normalleşme forma Unicode karakterleri hem ve onlar maç için mümkün olmalıdır. Elbette hangi normalleştirme biçimini kullanmanız gerektiği, karakterlerin kendilerine bağlıdır; Sadece onlar çünkü bakmak mutlaka aynı karakteri temsil anlamına gelmez hem. Ayrıca kullanım durumunuza uygun olup olmadığını da düşünmelisiniz - Jukka K. Korpela'nın yorumuna bakın.

Bu özel durum için, Tony'nin cevabındaki bağlantılara bakarsanız , U + 00B5 tablosunun şunu söylediğini göreceksiniz :

Ayrıştırma <uyumluluk> YUNAN KÜÇÜK MEKTUP MU (U + 03BC)

Bu, orijinal karşılaştırmanızdaki ikinci karakter olan U + 00B5'in ilk karakter olan U + 03BC'ye ayrıştırılabileceği anlamına gelir.

Böylece karakterleri, KC veya KD normalleştirme formlarıyla tam uyumluluk ayrıştırmasını kullanarak normalleştireceksiniz. Göstermek için yazdığım hızlı bir örnek:

using System;
using System.Text;

class Program
{
    static void Main(string[] args)
    {
        char first = 'μ';
        char second = 'µ';

        // Technically you only need to normalize U+00B5 to obtain U+03BC, but
        // if you're unsure which character is which, you can safely normalize both
        string firstNormalized = first.ToString().Normalize(NormalizationForm.FormKD);
        string secondNormalized = second.ToString().Normalize(NormalizationForm.FormKD);

        Console.WriteLine(first.Equals(second));                     // False
        Console.WriteLine(firstNormalized.Equals(secondNormalized)); // True
    }
}

Unicode normalleşme ve farklı normalleştirme formları hakkında ayrıntılı bilgi için bakınız System.Text.NormalizationFormve Unicode Spec .


26
Unicode özellik bağlantısı için teşekkürler. İlk defa onu okudum. Ondan küçük bir not: "Normalleştirme Formları KC ve KD, rastgele metne körü körüne uygulanmamalıdır. Bu Normalleştirme Formlarını büyük harf veya küçük harf eşlemeleri gibi düşünmek en iyisidir: belirli bağlamlarda temel anlamları tanımlamak için yararlı, ancak aynı zamanda metinde her zaman uygun olmayabilecek değişiklikler. "
user2864740

149

Çünkü aynı görünseler bile gerçekten farklı semboller, ilki gerçek harf ve karaktere sahip code = 956 (0x3BC), ikincisi mikro işaret ve sahip 181 (0xB5).

Referanslar:

Dolayısıyla, onları karşılaştırmak istiyorsanız ve eşit olmalarına ihtiyacınız varsa, bunu manuel olarak halletmeniz veya karşılaştırmadan önce bir karakteri başka bir karakterle değiştirmeniz gerekir. Veya aşağıdaki kodu kullanın:

public void Main()
{
    var s1 = "μ";
    var s2 = "µ";

    Console.WriteLine(s1.Equals(s2));  // false
    Console.WriteLine(RemoveDiacritics(s1).Equals(RemoveDiacritics(s2))); // true 
}

static string RemoveDiacritics(string text) 
{
    var normalizedString = text.Normalize(NormalizationForm.FormKC);
    var stringBuilder = new StringBuilder();

    foreach (var c in normalizedString)
    {
        var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
        if (unicodeCategory != UnicodeCategory.NonSpacingMark)
        {
            stringBuilder.Append(c);
        }
    }

    return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
}

Ve Demo


11
Merak ettiğimden, iki µ sembolüne sahip olmanın nedeni nedir? "Kilo işareti" adında özel bir K görmüyorsunuz (veya siz?)
MartinHaTh

12
@MartinHaTh: Wikipedia'ya göre "tarihsel nedenlerden dolayı" .
BoltClock

12
Unicode, bu karakter kümelerinden dönüştürmeyi kolaylaştırmak için eski karakter kümelerinden ( ISO 8859-1 gibi ) getirilen birçok uyumluluk karakterine sahiptir . Karakter kümeleri 8 bit ile sınırlandırıldığında, en yaygın matematik ve bilimsel kullanımlar için birkaç glif (bazı Yunan harfleri gibi) içerirlerdi. Görünüme dayalı glif yeniden kullanımı yaygındı, bu nedenle özel "K" eklenmedi. Ancak bu her zaman bir çözümdü; "mikro" için doğru sembol, gerçek Yunanca küçük harf mu, Ohm için doğru sembol, gerçek büyük omega, vb.
VGR

8
Histerik kuru üzümler için yapılan bir şeyden daha iyi bir şey yok
paulm

11
Tahıl için özel bir K var mı?

86

Her ikisinin de farklı karakter kodları vardır: Daha fazla ayrıntı için buna bakın

Console.WriteLine((int)'μ');  //956
Console.WriteLine((int)'µ');  //181

Birincisi nerede:

Display     Friendly Code   Decimal Code    Hex Code    Description
====================================================================
μ           &mu;            &#956;          &#x3BC;     Lowercase Mu
µ           &micro;         &#181;          &#xB5;      micro sign Mu

Resim


39

Belirli bir μ(mu) ve µ(mikro işaret) örneği için , ikincisinin öncekine uyumluluk ayrışması vardır , böylece mikro işaretleri muşa dönüştürebilir veya sicimi normalleştirebilirsiniz .FormKCFormKD

Bununla birlikte, birbirine benzeyen ancak herhangi bir Unicode normalleştirme formu altında eşdeğer olmayan birçok karakter kümesi vardır. Örneğin, A(Latin), Α(Yunanca) ve А(Kiril). Unicode web sitesinde, geliştiricilerin homograph saldırılarına karşı korunmalarına yardımcı olmayı amaçlayan, bunların listesini içeren bir confusables.txt dosyası vardır . Gerekirse, bu dosyayı ayrıştırabilir ve dizelerin "görsel olarak normalleştirilmesi" için bir tablo oluşturabilirsiniz.


Normalize kullanırken kesinlikle bilmek güzel. Farklı kalmaları şaşırtıcı görünüyor.
user2864740

4
@ user2864740: Büyük Yunan tau, Roma harfinden T'den farklı kalmasaydı, Yunanca ve Romence metnin alfabetik sıraya göre mantıklı bir şekilde sıralanması çok zor olurdu. Dahası, bir yazı tipi Yunan ve Roma harfleri için farklı bir görsel stil kullanacak olsaydı, şekilleri Roma harflerine benzeyen Yunan harflerinin, kullanılmayanlardan farklı şekilde yorumlanması çok dikkat dağıtıcı olurdu.
supercat

7
Daha da önemlisi, Avrupa alfabelerinin birleştirilmesi, uygulamayı zorlaştırır ToUpper/ ToLowerzorlaştırır. Sen sahip olmak gerekiyordu "B".ToLower()olmak bİngilizce ama βYunanca ve вRusça olarak. Olduğu gibi, sadece Türkçe (noktasız i) ve diğer birkaç dil varsayılandan farklı büyük / küçük harf kurallarına ihtiyaç duyar.
dan04

@ dan04: Acaba hiç kimse Türkçe "i" ve "I" nin dört varyasyonuna da benzersiz kod noktaları atamayı düşündü mü? Bu, toUpper / toLower davranışındaki herhangi bir belirsizliği ortadan kaldırırdı.
supercat

34

Unicode veritabanındaki her iki karakteri de arayın ve farkı görün .

Biri küçük Yunan Harfi µ ve diğeri Mikro İşarettir µ .

Name            : MICRO SIGN
Block           : Latin-1 Supplement
Category        : Letter, Lowercase [Ll]
Combine         : 0
BIDI            : Left-to-Right [L]
Decomposition   : <compat> GREEK SMALL LETTER MU (U+03BC)
Mirror          : N
Index entries   : MICRO SIGN
Upper case      : U+039C
Title case      : U+039C
Version         : Unicode 1.1.0 (June, 1993)

Name            : GREEK SMALL LETTER MU
Block           : Greek and Coptic
Category        : Letter, Lowercase [Ll]
Combine         : 0
BIDI            : Left-to-Right [L]
Mirror          : N
Upper case      : U+039C
Title case      : U+039C
See Also        : micro sign U+00B5
Version         : Unicode 1.1.0 (June, 1993)

4
Bu nasıl 37 olumlu oy aldı? Soruyu yanıtlamaz ("Unicode karakterleri nasıl karşılaştırılır"), sadece bu belirli örneğin neden eşit olmadığı hakkında yorum yapar. En iyi ihtimalle, soruya bir yorum yapılmalıdır. Yorum biçimlendirme seçeneklerinin, yanıt biçimlendirme seçeneklerinin yaptığı kadar güzel bir şekilde gönderilmesine izin vermediğini anlıyorum, ancak bu bir yanıt olarak göndermek için geçerli bir neden olmamalıdır.
Konerak

5
Aslında soru farklı bir soruydu ve μ ve μ eşitlik kontrolünün neden yanlış döndürdüğünü soruyordu. Bu Cevap yanıtlıyor. Daha sonra OP başka bir soru (bu soru) birbirine benzeyen iki karakterin nasıl karşılaştırılacağını sordu. Her iki sorunun da en iyi yanıtları vardı ve daha sonra moderatörden biri her iki soruyu birleştirerek ikincisinin en iyi yanıtını en iyi olarak seçti. Birisi bu soruyu özetleyecek şekilde düzenledi
Subin Jacob

Aslında, birleştirmeden sonra herhangi bir içerik eklemedim
Subin Jacob

24

DÜZENLE Bu sorunun C # 'da' μ 've' µ ' ile nasıl karşılaştırılacağı ile birleştirildikten sonra
Orijinal yanıt yayınlandı:

 "μ".ToUpper().Equals("µ".ToUpper()); //This always return true.

DÜZENLEME yorumları okuduktan sonra evet bu bizim kullanmalıdır için, girdilerin diğer bazı türü için yanlış sonuçlar verebilir çünkü yukarıdaki yöntemi kullanmak iyi değil normalleştirmek belirtildiği gibi tam uyumluluk oluşumuna kullanarak wiki . ( BoltClock tarafından gönderilen cevap sayesinde )

    static string GREEK_SMALL_LETTER_MU = new String(new char[] { '\u03BC' });
    static string MICRO_SIGN = new String(new char[] { '\u00B5' });

    public static void Main()
    {
        string Mus = "µμ";
        string NormalizedString = null;
        int i = 0;
        do
        {
            string OriginalUnicodeString = Mus[i].ToString();
            if (OriginalUnicodeString.Equals(GREEK_SMALL_LETTER_MU))
                Console.WriteLine(" INFORMATIO ABOUT GREEK_SMALL_LETTER_MU");
            else if (OriginalUnicodeString.Equals(MICRO_SIGN))
                Console.WriteLine(" INFORMATIO ABOUT MICRO_SIGN");

            Console.WriteLine();
            ShowHexaDecimal(OriginalUnicodeString);                
            Console.WriteLine("Unicode character category " + CharUnicodeInfo.GetUnicodeCategory(Mus[i]));

            NormalizedString = OriginalUnicodeString.Normalize(NormalizationForm.FormC);
            Console.Write("Form C Normalized: ");
            ShowHexaDecimal(NormalizedString);               

            NormalizedString = OriginalUnicodeString.Normalize(NormalizationForm.FormD);
            Console.Write("Form D Normalized: ");
            ShowHexaDecimal(NormalizedString);               

            NormalizedString = OriginalUnicodeString.Normalize(NormalizationForm.FormKC);
            Console.Write("Form KC Normalized: ");
            ShowHexaDecimal(NormalizedString);                

            NormalizedString = OriginalUnicodeString.Normalize(NormalizationForm.FormKD);
            Console.Write("Form KD Normalized: ");
            ShowHexaDecimal(NormalizedString);                
            Console.WriteLine("_______________________________________________________________");
            i++;
        } while (i < 2);
        Console.ReadLine();
    }

    private static void ShowHexaDecimal(string UnicodeString)
    {
        Console.Write("Hexa-Decimal Characters of " + UnicodeString + "  are ");
        foreach (short x in UnicodeString.ToCharArray())
        {
            Console.Write("{0:X4} ", x);
        }
        Console.WriteLine();
    }

Çıktı

INFORMATIO ABOUT MICRO_SIGN    
Hexa-Decimal Characters of µ  are 00B5
Unicode character category LowercaseLetter
Form C Normalized: Hexa-Decimal Characters of µ  are 00B5
Form D Normalized: Hexa-Decimal Characters of µ  are 00B5
Form KC Normalized: Hexa-Decimal Characters of µ  are 03BC
Form KD Normalized: Hexa-Decimal Characters of µ  are 03BC
 ________________________________________________________________
 INFORMATIO ABOUT GREEK_SMALL_LETTER_MU    
Hexa-Decimal Characters of µ  are 03BC
Unicode character category LowercaseLetter
Form C Normalized: Hexa-Decimal Characters of µ  are 03BC
Form D Normalized: Hexa-Decimal Characters of µ  are 03BC
Form KC Normalized: Hexa-Decimal Characters of µ  are 03BC
Form KD Normalized: Hexa-Decimal Characters of µ  are 03BC
 ________________________________________________________________

Unicode_equivalence içindeki bilgileri okurken buldum

Eşdeğerlik kriterlerinin seçimi arama sonuçlarını etkileyebilir. Örneğin, U + FB03 (ffi) gibi bazı tipografik bitişik harfler ..... bu nedenle alt dizge olarak U + 0066 (f) araması , U + FB03'ün NFKC normalizasyonunda başarılı olur , ancak U + FB03'ün NFC normalizasyonunda başarılı olmaz .

Dolayısıyla eşdeğerliği karşılaştırmak için normalde FormKCyani NFKC normalizasyonu veya FormKDyani NFKD normalizasyonu kullanmalıyız.
Tüm Unicode karakterleri hakkında daha fazla bilgi sahibi olmayı biraz merak ediyordum, bu yüzden içindeki tüm Unicode karakterini yineleyecek bir örnek yaptım UTF-16ve tartışmak istediğim bazı sonuçlar aldım

  • Karakterler hakkında bilgi FormCve FormDnormalize değerler eşdeğer değildi
    Total: 12,118
    Character (int value): 192-197, 199-207, 209-214, 217-221, 224-253, ..... 44032-55203
  • Karakterler hakkında bilgi FormKCve FormKDnormalize değerler eşdeğer değildi
    Total: 12,245
    Character (int value): 192-197, 199-207, 209-214, 217-221, 224-228, ..... 44032-55203, 64420-64421, 64432-64433, 64490-64507, 64512-64516, 64612-64617, 64663-64667, 64735-64736, 65153-65164, 65269-65274
  • Tüm karakter olan FormCve FormDnormalleştirilmiş değeri eşdeğer değildi, orada FormKCve FormKDnormalize değerler de bu karakterler haricinde denk değildi
    Karakterler:901 '΅', 8129 '῁', 8141 '῍', 8142 '῎', 8143 '῏', 8157 '῝', 8158 '῞'
    , 8159 '῟', 8173 '῭', 8174 '΅'
  • Ekstra bir karakter olan FormKCve FormKDnormalleştirilmiş değeri eşdeğer değildi, ama orada FormCve FormDnormalize değerler eşdeğer olduğunu
    Total: 119
    Karakterler:452 'DŽ' 453 'Dž' 454 'dž' 12814 '㈎' 12815 '㈏' 12816 '㈐' 12817 '㈑' 12818 '㈒' 12819 '㈓' 12820 '㈔' 12821 '㈕', 12822 '㈖' 12823 '㈗' 12824 '㈘' 12825 '㈙' 12826 '㈚' 12827 '㈛' 12828 '㈜' 12829 '㈝' 12830 '㈞' 12910 '㉮' 12911 '㉯' 12912 '㉰' 12913 '㉱' 12914 '㉲' 12915 '㉳' 12916 '㉴' 12917 '㉵' 12918 '㉶' 12919 '㉷' 12920 '㉸' 12921 '㉹' 12922 '㉺' 12923 '㉻' 12924 '㉼' 12925 '㉽' 12926 '㉾' 13056 '㌀' 13058 '㌂' 13060 '㌄' 13063 '㌇' 13070 '㌎' 13071 '㌏' 13072 '㌐' 13073 '㌑' 13075 '㌓' 13077 '㌕' 13080 '㌘' 13081 '㌙' 13082 '㌚' 13086 '㌞' 13089 '㌡' 13092 '㌤' 13093 '㌥' 13094 '㌦' 13099 '㌫' 13100 '㌬' 13101 '㌭' 13102 '㌮' 13103 '㌯' 13104 '㌰' 13105 '㌱' 13106 '㌲' 13108 '㌴' 13111 '㌷' 13112 '㌸' 13114 '㌺' 13115 '㌻' 13116 '㌼' 13117 '㌽' 13118 '㌾' 13120 '㍀' 13130 '㍊' 13131 '㍋' 13132 '㍌' 13134 '㍎' 13139 '㍓' 13140 '㍔' 13142 '㍖' .......... ﺋ' 65164 'ﺌ' 65269 'ﻵ' 65270 'ﻶ' 65271 'ﻷ' 65272 'ﻸ' 65273 'ﻹ' 65274'
  • Normalize edilemeyen bazı karakterler var ,ArgumentException denendiğinde atıyorlar
    Total:2081 Characters(int value): 55296-57343, 64976-65007, 65534

Bu bağlantılar, Unicode eşdeğerliği için hangi kuralların geçerli olduğunu anlamak için gerçekten yardımcı olabilir

  1. Unicode_equivalence
  2. Unicode_compatibility_characters

4
Garip ama işe yarıyor ... Demek istediğim onlar farklı anlamlara sahip iki farklı karakter ve onları yukarıya dönüştürmek onları eşit mi yapıyor? Mantık ama güzel bir çözüm
görmüyorum

45
Bu çözüm sorunu maskeler ve genel bir durumda sorunlara neden olabilir. Bu tür bir test bunu bulur "m".ToUpper().Equals("µ".ToUpper());ve "M".ToUpper().Equals("µ".ToUpper());aynı zamanda doğrudur. Bu arzu edilmeyebilir.
Andrew Leach

6
-1 - bu berbat bir fikir. Unicode ile bu şekilde çalışmayın.
Konrad Rudolph

1
ToUpper () tabanlı hileler yerine, neden String.Equals ("μ", "μ", StringComparison.CurrentCultureIgnoreCase) kullanılmasın?
svenv

6
"MİKRO İŞARETİ" ile "YUNAN KÜÇÜK MEKTUBU MU" arasında ayrım yapmak için iyi bir neden var - mikro işaretin "büyük harfinin" hala mikro işaret olduğunu söylemek. Ancak büyük harf kullanımı mikrodan mega'ya, mutlu mühendislik.
Greg

9

Büyük olasılıkla, aynı karakteri (görünür şekilde) yapan iki farklı karakter kodu vardır. Teknik olarak eşit olmasalar da, eşit görünüyorlar. Karakter tablosuna bir göz atın ve bu karakterin birden fazla örneği olup olmadığına bakın. Veya kodunuzdaki iki karakterin karakter kodunu yazdırın.


6

"Nasıl karşılaştırılır" diye soruyorsunuz ama bize ne yapmak istediğinizi söylemiyorsunuz.

Bunları karşılaştırmanın en az iki ana yolu vardır:

Ya onları doğrudan olduğunuz gibi karşılaştırırsınız ve onlar farklıdır

Veya ihtiyaç duyduğunuzda, bunları eşleşecek şekilde bulan bir karşılaştırma için Unicode Uyumluluk Normalleştirmesini kullanırsınız.

Unicode uyumluluk normalizasyonu diğer birçok karakterin karşılaştırmasını eşit yapacağından bir sorun olabilir. Yalnızca bu iki karakterin aynı şekilde değerlendirilmesini istiyorsanız, kendi normalleştirme veya karşılaştırma işlevlerinizi döndürmelisiniz.

Daha spesifik bir çözüm için özel probleminizi bilmemiz gerekir. Bu problemle karşılaştığınız bağlam nedir?


1
"Mikro işaret" ve küçük mu karakteri kanonik olarak eşdeğer midir? Kanonik normalleştirme kullanmak size daha katı bir karşılaştırma sağlayacaktır.
Tanner Swett

@ TannerL.Swett: Aslında bunu kafamın üstünden nasıl kontrol edeceğimi bile bilmiyorum ...
hippietrail

1
Aslında fizik formülü içeren bir dosya ithal ediyordum. Normalleşme konusunda haklısın. Daha derinlemesine geçmeliyim ..
DJ

Ne tür bir dosya? Bir kişi tarafından düz Unicode metninde el yapımı bir şey mi? Veya bir uygulamanın belirli bir formatta çıktısı olan bir şey?
hippietrail

5

Bilgiçlik taslamak istersem, sorunuzun bir anlamı olmadığını söyleyebilirim ama biz Noel'e yaklaştığımız ve kuşlar şarkı söylediği için buna devam edeceğim.

Öncelikle, karşılaştırmak çalıştığınız 2 varlıklardır glyphler bir kabartma genellikle "yazı" olarak bildiğimiz şey tarafından sağlanan glif kümesi, genellikle gelir şeyin bir parçası, ttf, otfne olursa olsun dosya biçimi veya kullanarak.

Glifler, belirli bir sembolün temsilidir ve belirli bir kümeye bağlı bir temsil olduklarından, sadece 2 benzer veya hatta "daha iyi" aynı sembole sahip olmayı bekleyemezsiniz, bu anlamsız bir cümle bağlamı göz önünde bulundurursanız, böyle bir soruyu formüle ederken en azından hangi yazı tipini veya glif kümesini düşündüğünüzü belirtmelisiniz.

Genellikle karşılaştığınıza benzer bir sorunu çözmek için kullanılan şey, bir OCR'dir, esasen glifleri tanıyan ve karşılaştıran bir yazılımdır, C # varsayılan olarak bir OCR sağlıyorsa , bunu bilmiyorum, ancak genellikle çok kötü Gerçekten bir OCR'ye ihtiyacınız yoksa ve onunla ne yapacağınızı biliyorsanız, fikir edin.

OCR'nin genellikle kaynaklar açısından pahalı olduğu gerçeğinden bahsetmeden bir fizik kitabını eski bir yunan kitabı olarak yorumlayabilirsiniz.

Bu karakterlerin yerelleştirildikleri şekilde yerelleştirilmesinin bir nedeni var, bunu yapmayın.


1

DrawStringYöntemle her iki karakteri aynı yazı tipi stili ve boyutu ile çizmek mümkündür . Semboller içeren iki bitmap oluşturulduktan sonra, bunları piksel piksel karşılaştırmak mümkündür.

Bu yöntemin avantajı, yalnızca mutlak eşit karakterleri değil, aynı zamanda benzerleri (kesin toleransla) karşılaştırabilmenizdir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.