Unicode, UTF-8, UTF-16 nedir?


395

Unicode'un temeli nedir ve neden UTF-8 veya UTF-16'ya ihtiyaç var? Bunu Google'da araştırdım ve burada da aradım, ancak benim için net değil.

VSS'de bir dosya karşılaştırması yaparken, bazen iki dosyanın farklı UTF'lerine sahip olduğunu belirten bir mesaj vardır. Neden böyle olsun?

Lütfen basit terimlerle açıklayınız.


123

5
Resmi Unicode web sitesinden gelen bu SSS'nin sizin için bazı cevapları var.
Nemanja Trifunovic

4
@John: bu çok güzel bir giriş, ama nihai kaynak değil: Ayrıntılardan birkaçını atlıyor (genel bakış / tanıtım için iyi!)
Joachim Sauer

5
Makale harika, ancak birkaç hatası var ve biraz muhafazakar bir ışıkla UTF-8'i temsil ediyor. Ek olarak utf8everywhere.org yazmanızı öneririm.
Pavel Radzivilovsky

2
Bu web sitesine bir göz atın: utf8everywhere.org
Vertexwahn

Yanıtlar:


550

Neden Unicode'a ihtiyacımız var?

(Çok da değil) ilk günlerde var olan tek şey ASCII idi. İhtiyacınız olan tek şey birkaç cümle karakteri, noktalama işaretleri, rakamlar ve bu cümledeki gibi harflerdi. Ne yazık ki, günümüzün küresel iletişim ve sosyal medya garip dünyası öngörülmedi ve aynı belgede İngilizce, العربية, 汉语, עִבְרִית, ελληνικά ve ភាសាខ្មែរ görmek çok sıra dışı değil (umarım eski tarayıcılar).

Ancak argüman uğruna, Joe Average'un bir yazılım geliştiricisi olduğunu varsayalım. Sadece İngilizce'ye ihtiyaç duyacağı konusunda ısrar ediyor ve bu yüzden sadece ASCII kullanmak istiyor. Bu Joe kullanıcı için iyi olabilir , ama bu yazılım geliştirici Joe için iyi değil . Dünyanın yaklaşık yarısı Latin olmayan karakterler kullanıyor ve ASCII kullanmak bu insanlar için tartışmasız bir şekilde düşünüyor ve bunun üzerine yazılımını büyük ve büyüyen bir ekonomiye kapatıyor.

Bu nedenle, tüm dilleri içeren bir karakter setine ihtiyaç vardır. Böylece Unicode geldi. Her karaktere kod noktası adı verilen benzersiz bir sayı atar . Unicode'un diğer olası setlere göre bir avantajı, ilk 256 kod noktasının ISO-8859-1 ve dolayısıyla ASCII ile aynı olmasıdır. Ek olarak, yaygın olarak kullanılan karakterlerin büyük çoğunluğu, Temel Çok Dilli Düzlem (BMP) adı verilen bir bölgede sadece iki bayt ile temsil edilebilir . Şimdi bu karakter setine erişmek için bir karakter kodlaması gerekiyor ve sorunun da sorduğu gibi UTF-8 ve UTF-16'ya odaklanacağım.

Bellek hususları

Peki kaç bayt bu kodlamalarda hangi karakterlere erişim sağlıyor?

  • UTF-8:
    • 1 bayt: Standart ASCII
    • 2 bayt: Arapça, İbranice, çoğu Avrupa alfabesi (en önemlisi Gürcüce hariç )
    • 3 bayt: BMP
    • 4 bayt: Tüm Unicode karakterler
  • UTF-16:
    • 2 bayt: BMP
    • 4 bayt: Tüm Unicode karakterler

BMP'de olmayan karakterlerin eski senaryolar, matematiksel semboller, müzikal semboller ve daha nadir Çince / Japonca / Korece (CJK) karakterleri içerdiğini belirtmek gerekir .

Çoğunlukla ASCII karakterleriyle çalışacaksanız, UTF-8 kesinlikle daha fazla bellek verimlidir. Ancak, çoğunlukla Avrupa dışındaki komut dosyalarıyla çalışıyorsanız, UTF-8 kullanmak, UTF-16'dan 1,5 kat daha az bellek verimliliği sağlayabilir. Büyük web sayfaları veya uzun sözcük belgeleri gibi büyük miktarlarda metinle uğraşırken, bu durum performansı etkileyebilir.

Kodlama ile ilgili temel bilgiler

Not: UTF-8 ve UTF-16'nın nasıl kodlandığını biliyorsanız, pratik uygulamalar için bir sonraki bölüme geçin.

  • UTF-8: Standart ASCII (0-127) karakterleri için UTF-8 kodları aynıdır. Bu, mevcut ASCII metni ile geriye dönük uyumluluk gerektiğinde UTF-8'i ideal hale getirir. Diğer karakterler 2-4 bayt arasında bir yere ihtiyaç duyar. Bu, çok baytlık bir karakterin parçası olduğunu belirtmek için bu baytların her birinde bazı bitler ayırarak yapılır. Özellikle, her baytın ilk biti 1ASCII karakterleri ile çakışmadan kaçınmaktır.
  • UTF-16: Geçerli BMP karakterleri için UTF-16 temsili basitçe kod noktasıdır. Bununla birlikte, BMP dışı karakterler için UTF-16 vekil çiftler sunar . Bu durumda, iki baytlık iki bölümün birleşimi BMP olmayan bir karakterle eşleşir. Bu iki baytlık kısımlar BMP sayısal aralığından gelir, ancak Unicode standardı tarafından BMP karakterleri olarak geçersiz olmaları garanti edilir. Ek olarak, UTF-16 temel birimi olarak iki bayta sahip olduğundan endianizmden etkilenir . Telafi etmek için, bir bayt sırası işareti , endianizmi gösteren bir veri akışının başına yerleştirilebilir. Bu nedenle, UTF-16 girdisini okuyorsanız ve endianness belirtilmemişse, bunu kontrol etmelisiniz.

Görülebileceği gibi, UTF-8 ve UTF-16 birbirleriyle hiçbir yere yakın değildir. G / Ç yapıyorsanız, hangi kodlamayı kullandığınızı bildiğinizden emin olun! Bu kodlamalar hakkında daha fazla bilgi için lütfen UTF SSS bölümüne bakın .

Pratik programlama hususları

Karakter ve Dize veri türleri: Programlama dilinde nasıl kodlanırlar? Ham baytlarsa, ASCII olmayan karakterler çıkarmaya çalıştığınız anda, birkaç sorunla karşılaşabilirsiniz. Ayrıca, karakter tipi bir UTF'yi temel alsa bile, bu, dizelerin uygun UTF olduğu anlamına gelmez. Yasadışı olan bayt dizilerine izin verebilirler. Genellikle, C, C ++ ve Java için ICU gibi UTF'yi destekleyen bir kütüphane kullanmanız gerekir . Her durumda, varsayılan kodlama dışında bir şey girmek / çıktısını almak istiyorsanız, önce onu dönüştürmeniz gerekir.

Önerilen / varsayılan / baskın kodlamalar: Hangi UTF'nin kullanılacağına dair bir seçenek verildiğinde, genellikle çalıştığınız ortam için önerilen standartları izlemek en iyisidir. Örneğin, UTF-8 web'de baskındır ve HTML5'ten beri olmuştur önerilen kodlama . Tersine, hem .NET hem de Java ortamları UTF-16 karakter türünde kurulmuştur. Kafa karıştırıcı (ve yanlış) olarak, genellikle belirli bir ortamda baskın UTF kodlaması anlamına gelen "Unicode kodlaması" na başvurulur.

Kütüphane desteği: Kullandığınız kütüphaneler bir tür kodlamayı destekler. Hangisi? Köşe kasalarını destekliyorlar mı? Zorunluluk buluşun anası olduğundan, UTF-8 kütüphaneleri genellikle 4 baytlık karakterleri düzgün bir şekilde destekleyecektir, çünkü 1, 2 ve hatta 3 baytlık karakterler sık ​​sık ortaya çıkabilir. Bununla birlikte, iddia edilen UTF-16 kütüphanelerinin tümü, çok nadiren ortaya çıktıkları için vekil çiftleri düzgün bir şekilde desteklemez.

Karakterleri Sayma: Orada bulunmamakta birleştirerek Unicode karakterleri. Örneğin, kod noktası U + 006E (n) ve U + 0303 (bir birleştirici tilde) ñ oluşturur, ancak kod noktası U + 00F1 ñ oluşturur. Aynı görünmelidir, ancak basit bir sayma algoritması ilk örnek için 2, ikinci örnek için 1 döndürür. Bu mutlaka yanlış değildir, ancak istenen sonuç da olmayabilir.

Eşitlik için karşılaştırma: A, А ve Α aynı görünüyor, ancak sırasıyla Latin, Kiril ve Yunan. Ayrıca C ve Ⅽ gibi vakalarınız da var, biri harf, diğeri Romen rakamı. Ayrıca, dikkate alınması gereken birleştirici karakterlere sahibiz. Daha fazla bilgi için bkz . Unicode'da karakterleri çoğaltma .

Yedek çiftler: Bunlar SO'da yeterince sık görülür, bu yüzden sadece bazı örnek bağlantılar sağlayacağım:

Diğerleri ?:


11
Mükemmel cevap, lütuf için büyük şanslar ;-) Şahsen bazılarının evrensel karakter kodlaması olarak UTF-8 için tartıştığını ekleyeceğim , ancak bunun herkes tarafından paylaşılmayan bir görüş olduğunu biliyorum.
Joachim Sauer

3
Bu aşamada hala benim için çok teknik. Merhaba kelimesi bir bilgisayarda UTF-8 ve UTF-16'da nasıl saklanır?
Adı Soyadı

1
Örneğin BMP'nin UTF-8'de neden 3 bayt aldığı konusunda daha fazla bilgi verebilir misiniz? Maksimum değeri 0xFFFF (16 bit) olduğu için erişmek için sadece 2 bayt olacağını düşünürdüm.
mark

2
@mark Bazı bitler kodlama amacıyla ayrılmıştır. UTF-8'de 2 bayt alan bir kod noktası için, bir kod noktası seçmek üzere yalnızca 11 bit bırakarak 5 ayrılmış bit vardır. U + 07FF, 2 baytta temsil edilebilen en yüksek kod noktası olur.
DPenner1

1
BTW - ASCII, temsil için yalnızca 7 bit kullanarak yalnızca 128 kod noktasını tanımlar. 256 kod noktasını tanımlayan ve gösterim için 8 bit kullanan ISO-8859-1 / ISO-8859-15'dir. Tüm bu 3 kodun ilk 128 kod noktası aynıdır.
Tuxdude

67
  • Unicode
    • dünyada kullanılan bir dizi karakterdir
  • UTF-8
    • Unicode'da olası tüm karakterleri (kod noktaları denir) kodlayabilen bir karakter kodlaması.
    • kod birimi 8 bit
    • Unicode'u kodlamak için bir ila dört kod birimi kullanın
    • " $ " İçin 00100100 (bir 8 bit); " ¢ " için 11000010 10100010 (iki 8 bit); 11100010 10000010 10101100 " " için (üç 8 bit)
  • UTF-16
    • başka bir karakter kodlaması
    • kod birimi 16 bit
    • Unicode'u kodlamak için bir ila iki kod birimi kullanın
    • " $ " İçin 00000000 00100100 (bir adet 16 bit); 11011000 01010010 11011111 " 𤭢 " için 01100010 (iki 16 bit)

1
Kısa ve hassas
Aritra Chatterjee

30

Unicode oldukça karmaşık bir standarttır. Çok korkma, ama biraz çalışmaya hazır ol! [2]

Güvenilir bir kaynağa her zaman ihtiyaç duyulduğu için, ancak resmi rapor muazzam olduğundan, aşağıdakileri okumanızı öneririm:

  1. Mutlak Minimum Her Yazılım Geliştiricisi Unicode ve Karakter Kümelerini Kesinlikle, Olumlu Olarak Bilmeli (Bahane Yok!) Stack Exchange CEO'su Joel Spolsky'nin tanıtımı.
  2. BMP ve ötesine! Daha sonra Teknik Direktör, daha sonra Başkan Yardımcısı, Unicode Konsorsiyumu'nda Eric Muller tarafından verilen bir eğitim. (ilk 20 slayt ve işiniz bitti)

Kısa bir açıklama:

Bilgisayarlar baytları ve insanlar karakterleri okur, bu nedenle karakterleri baytlarla eşleştirmek için kodlama standartlarını kullanırız. ASCII ilk yaygın olarak kullanılan standarttır, ancak yalnızca Latin alfabesini kapsar (7 bit / karakter 128 farklı karakteri temsil edebilir). Unicode, dünyadaki tüm olası karakterleri kapsamayı amaçlayan bir standarttır (1,114,112 karaktere kadar, en fazla 21 bit / karakter anlamına gelir. Geçerli Unicode 8.0 toplamda 120,737 karakter belirtir ve hepsi budur).

Temel fark, bir ASCII karakterinin bir bayta (8 bit) sığabilmesi, ancak çoğu Unicode karakterinin sığmamasıdır. Dolayısıyla kodlama formları / şemaları (UTF-8 ve UTF-16 gibi) kullanılır ve karakter modeli şu şekilde gider:

Her karakter kod noktası olarak adlandırılan 0 ile 1,114,111 (hex: 0-10FFFF) arasında numaralandırılmış bir konuma sahiptir .
Bir kodlama formu bir kod noktasını bir kod birimi dizisiyle eşler. Bir kod birimi karakterlerin hafıza, 8-bitlik birimler, 16 bit birimlerinde düzenlenen ve benzeri olmak istiyorum yoludur. UTF-8, 1 bitlik 4 bitlik 8 bit kullanır ve UTF-16, maksimum 21 bitlik Unicode'un tamamını kapsamak için 16 bitlik 1 veya 2 birim kullanır. Birimler, karakter sınırlarının tespit edilebilmesi için önek kullanır ve daha fazla birim, bitleri kaplayan daha fazla önek anlamına gelir. UTF-8, Latin komut dosyası için 1 bayt kullanıyor olsa da, Temel Çok Dilde Düzlem içindeki sonraki komut dosyaları için 3 bayta ihtiyaç duyarken, UTF-16 tüm bunlar için 2 bayt kullanır. Ve bu onların temel farkı.
Son olarak, bir kodlama şeması (UTF-16BE veya UTF-16LE gibi) bir kod birimi dizisini bir bayt dizisiyle eşler (serileştirir).

karakter: π
kod noktası: U + 03C0
kodlama formları (kod birimleri):
      UTF-8: CF 80
      UTF-16: 03C0
kodlama şemaları (bayt):
      UTF-8: CF 80
      UTF-16BE: 03 C0
      UTF-16LE: C0 03

İpucu: Onaltılık basamak 4 biti temsil eder, bu nedenle iki basamaklı onaltılık sayı baytı temsil eder
Ayrıca karakter kümesi düzenini hissetmek için Wikipedia'daki Düzlem haritalarına da göz atın


19

Başlangıçta, Unicode sabit genişlikli 16 bit kodlamaya (UCS-2) sahipti. Java ve Windows NT gibi Unicode'un ilk kullanıcıları, kitaplıklarını 16 bitlik dizeler etrafında oluşturdular.

Daha sonra, Unicode'un kapsamı, 16 bit kodlamanın destekleyeceği 65.536 kod noktasından fazlasını gerektiren tarihi karakterleri içerecek şekilde genişletildi. Ek karakterlerin UCS-2 kullanan platformlarda gösterilmesine izin vermek için UTF-16 kodlaması tanıtıldı. Ek düzlemlerdeki karakterleri temsil etmek için "vekil çiftler" kullanır.

Bu arada, birçok eski yazılım ve ağ protokolü 8 bit dizeler kullanıyordu. UTF-8, bu sistemlerin geniş karakterler kullanmak zorunda kalmadan Unicode'u destekleyebilmesi için yapılmıştır. 7 bit ASCII ile geriye dönük uyumludur.


3
Microsoft'un hala UTF-16'yı Unicode olarak adlandırdığını ve karışıklığa katkıda bulunduğunu belirtmek gerekir. İkisi aynı değil .
Mark Ransom

15

Bu makalede tüm ayrıntılar açıklanmaktadır http://kunststube.net/encoding/

TAMPON YAZMA

UTF8 kodlamalı bir 4 bayt ara belleğe yazarsanız , ikili kodunuz şöyle görünür:

00000000 11100011 10000001 10000010

UTF16 kodlamalı bir 4 bayt ara belleğe yazarsanız , ikili kodunuz şöyle görünür:

00000000 00000000 00110000 01000010

Gördüğünüz gibi, içeriğinizde hangi dili kullanacağınıza bağlı olarak bu, belleğinizi buna göre etkileyecektir.

Örneğin, bu sembol için: UTF16 kodlaması, bir sonraki sembol için 2 yedek baytımız olduğundan daha verimlidir. Ancak bu, Japonya alfabesi için UTF16 kullanmanız gerektiği anlamına gelmez.

TAMPONDAN OKUMA

Şimdi yukarıdaki baytları okumak istiyorsanız, hangi kodlamaya yazıldığını bilmeniz ve doğru bir şekilde kodunu çözmeniz gerekir.

Bu deşifre olursa örneğin: 00000000 11100011 10000001 10000010 UTF16 kodlama içine, sen ile sona erecek değil

Not: Kodlama ve Unicode iki farklı şeydir. Unicode, her sembolün benzersiz bir kod noktasına eşlendiği büyük (tablo) . örneğin sembol (harf) bir (kod noktasına) sahiptir : 30 42 (altıgen). Diğer yandan kodlama, donanıma depolarken sembolleri daha uygun bir biçime dönüştüren bir algoritmadır.

30 42 (hex) - > UTF8 encoding - > E3 81 82 (hex), which is above result in binary.

30 42 (hex) - > UTF16 encoding - > 30 42 (hex), which is above result in binary.

resim açıklamasını buraya girin


11

Unicode , tüm dillerdeki karakterleri Kod Noktaları adı verilen belirli bir sayısal değere eşleyen bir standarttır . Bunu yapmasının nedeni, aynı kod noktaları kümesini kullanarak farklı kodlamaların mümkün olmasına izin vermesidir.

UTF-8 ve UTF-16 bu tür iki kodlamadır. Kod noktalarını girdi olarak alırlar ve kodlanmış dizeyi üretmek için iyi tanımlanmış bir formül kullanarak kodlarlar.

Belirli bir kodlamanın seçilmesi gereksinimlerinize bağlıdır. Farklı kodlamaların farklı bellek gereksinimleri vardır ve ilgileneceğiniz karakterlere bağlı olarak, bu karakterleri kodlamak için en az bayt dizisini kullanan kodlamayı seçmelisiniz.

Unicode, UTF-8 ve UTF-16 hakkında daha ayrıntılı bilgi için bu makaleye göz atabilirsiniz,

Her programcının Unicode hakkında bilmesi gerekenler


9

Neden unicode? Çünkü ASCII'nin sadece 127 karakteri var. 128 ila 255 arasındakiler farklı ülkelerde farklı, bu yüzden kod sayfaları var. Böylece 1114111 karaktere kadar izin verdiklerini söylediler. Peki en yüksek kod noktasını nasıl saklarsınız? 21 bit kullanarak saklamanız gerekecek, bu nedenle 11 bitlik 32 bitli bir DWORD kullanacaksınız. Unicode bir karakteri saklamak için bir DWORD kullanırsanız, DWORD'nuzdaki değer tam olarak kod noktasıyla eşleştiği için en kolay yol budur. Ancak DWORD dizileri elbette WORD dizilerinden daha büyüktür ve elbette BYTE dizilerinden bile daha büyüktür. Bu yüzden sadece utf-32 değil, aynı zamanda utf-16 da var. Ancak utf-16 bir WORD akışı anlamına gelir ve bir WORD'ün 16 biti vardır, bu nedenle en yüksek kod noktası 1114111 bir WORD'ye nasıl sığabilir? Olamaz! Böylece her şeyi 65535'ten daha yüksek bir vekil çifti olarak adlandırdıkları bir DWORD'ye koydular. Bu vekil çift iki WORD'dür ve ilk 6 bite bakarak tespit edilebilir. Peki ya utf-8? Bir bayt dizisi veya bayt akışıdır, ancak en yüksek kod noktası 1114111 bir bayta nasıl sığar? Olamaz! Tamam, bir DWORD da koydular değil mi? Veya muhtemelen bir KELİME, değil mi? Neredeyse doğru! Utf-8 dizilerini icat ettiler, yani 127'den yüksek olan her kod noktası 2 bayt, 3 bayt veya 4 bayt diziye kodlanmalıdır. Vaov! Fakat bu tür dizileri nasıl tespit edebiliriz? 127'ye kadar olan her şey ASCII ve tek bir bayttır. 110 ile başlayan iki baytlık bir dizidir, 1110 ile başlayan üç baytlık bir dizidir ve 11110 ile başlayan dört baytlık bir dizidir. "Başlangıç ​​baytları" olarak adlandırılan bunlardan geriye kalan bitler kod noktasına aittir. Şimdi diziye bağlı olarak, aşağıdaki baytların izlenmesi gerekir. Aşağıdaki bayt 10 ile başlar, geri kalan bitler 6 bit yük bitidir ve kod noktasına aittir. Başlangıç ​​baytının ve sonraki bayt / s'ların taşıma yükü bitlerini birleştirin ve kod noktasına sahip olun. Bütün bu utf-8'in büyüsü.


3
utf-8 utf-8 3 baytlık sırayla kodu çözülmüş € (Euro) işareti örneği: E2 = 11100010 82 = 10000010 AC = 10101100 Gördüğünüz gibi, E2 1110 ile başlıyor, bu gördüğünüz gibi üç baytlık bir sıra , 82 ve AC 10 ile başlıyor, bu yüzden bunlar baytları takip ediyor Şimdi "faydalı yük bitleri" ni birleştiriyoruz: 0010 + 000010 + 101100 = 10000010101100 ondalık sayı 8364 Yani 8364 € (Euro) işareti için kod noktası olmalı.
aydınlık

5

ASCII - Yazılım belirli bir karakter için belleğe yalnızca 8 bit bayt ayırır. İlgili ondalık değerleri ondalık değerde 128'in altına düştüğü için İngilizce ve kabul edilen (cephe gibi kredi kelimeleri) karakterler için iyi çalışır. Örnek C programı.

UTF-8 - Yazılım belirli bir karakter için 1 ila 4 değişken 8 bit bayt ayırır. Buradaki değişken ile ne anlama geliyor? Tarayıcıdaki HTML sayfalarınız üzerinden 'A' karakterini gönderdiğinizi varsayalım (HTML UTF-8'dir), A'nın karşılık gelen ondalık değeri 65'tir, ondalık sayıya dönüştürdüğünüzde 01000010 olur. Bu sadece 1 bayt gerektirir , Bir kelime cephesinde 'ç' gibi benimsenen özel İngilizce karakterler için bile 1 bayt bellek ayrılmıştır. Bununla birlikte, Avrupa karakterlerini saklamak istediğinizde 2 bayt gerektirir, bu nedenle UTF-8'e ihtiyacınız vardır. Ancak, Asya dillerindeki karakterleri tercih ettiğinizde, en az 2 bayt ve en fazla 4 bayt gerekir. Benzer şekilde, Emoji 3 ila 4 bayt gerektirir. UTF-8 tüm ihtiyaçlarınızı çözecektir.

UTF-16 karakter başına minimum 2 bayt ve maksimum 4 bayt tahsis eder, 1 veya 3 bayt tahsis etmez. Her karakter 16 bit veya 32 bit olarak temsil edilir.

O zaman neden UTF-16 var? Başlangıçta, Unicode 16 bit 8 bit değildi. Java, UTF-16'nın orijinal sürümünü benimsedi.

Özetle, üzerinde çalıştığınız dil veya platform tarafından kabul edilmedikçe hiçbir yerde UTF-16'ya ihtiyacınız yoktur.

Web tarayıcıları tarafından çağrılan Java programı UTF-16 kullanır, ancak web tarayıcısı UTF-8 kullanarak karakter gönderir.


"Dil veya platform tarafından kabul edilmedikçe hiçbir yerde UTF-16'ya ihtiyacınız yoktur": Bu iyi bir nokta, ancak kapsayıcı olmayan bir liste: JavaScript, Java, .NET, SQL NCHAR, SQL NVARCHAR , VB4, VB5, VB6, VBA, VBScript, NTFS, Windows API….
Tom Blodget

2

UTF, Unicode Dönüşüm Biçimi anlamına gelmektedir. Günümüz dünyasında temel olarak, daha önce kullanılan temel ASCII tarafından kapsanmayan yüzlerce başka dilde yazılmış komut dosyaları vardır. Böylece UTF ortaya çıktı.

UTF-8 karakter kodlama özelliklerine sahiptir ve kod birimi 8 bit iken UTF-16 için 16 bittir.

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.