2012-09-21 9 views
10

Okazuje się, że umieszczenie znaku jest skomplikowaną sprawą. Jeśli wydostaniesz się z podstawowego zestawu znaków ASCII, zasady dotyczące umieszczania znaku na dużej wysokości i zmniejszania znaku są w rzeczywistości zależne od ustawień narodowych, w których aplikacja jest uruchomiona.W haskell w jaki sposób można wpisać wielką literę znaku Unicode w odniesieniu do bieżących ustawień narodowych

Jako aplikacja demonstracyjna próbuję wpisać wielką literę "i" (kropką) oraz literę "i" (bez kropki). Teraz, w en_US, "i" (z kropką) przechodzi do "I", a "i" (bez kropki) nie istnieje (ale nadal jest w przypadku wielkich liter "I").

Ale jeśli przejdę na turecki (tr_TR.UTF-8), "i" (z kropką) musi być wielkimi literami na "İ" (również kropką), a "ı" (bez kropki) musi być wielkimi literami do "ja" (również bez kropki). Małe litery powinny odwrócić te operacje.

iİıI --> İİII (tr_TR.UTF-8) 
iİıI --> IİII (en_US.UTF-8) 

Teraz mogę zrobić to doskonale w C. Jak mogę to zrobić w Haskell? Wszystkie wyszukiwania, które wykonuję, kierują mnie bezpośrednio do Data.Char.toUpper, który nie jest locale-aware. Nie znalazłem żadnych funkcji, które są w żaden sposób zorientowane lokalnie.


Oto przykład kodu z C. Uruchomiłem go na moim komputerze z systemem Linux.

#include <stdio.h> 
#include <stdlib.h> 
#include <locale.h> 
#include <wctype.h> 
#include <string.h> 
#include <errno.h> 

wchar_t latin_small_sharp_s[5] = {0x00df, 0x00df, 0x0053, 0x0053, 0}; 
wchar_t turkish_is[5] = {0x0069, 0x0130, 0x0131, 0x0049, 0}; 

char multibyte_turkish_is[7] = {0x69, 0x01, 0x30, 0x01, 0x31, 0x49, 0}; 

void print_in_locale (const char *locale, const wchar_t *str, const size_t len) { 
    wchar_t *dest = calloc(len * 2, sizeof(wchar_t)); 
    int i; 

    if (!setlocale(LC_CTYPE, locale)) { 
    fprintf(stderr, "Locale %s failed with error: %s", locale, strerror(errno)); 
    exit(1); 
    } 

    for (i = 0; i < len; i++) { 
    dest[i] = towupper(str[i]); 
    } 
    printf("%ls, %ls\n", str, dest); 
    free(dest); 
} 

int main() { 
    print_in_locale("de_DE.utf8", latin_small_sharp_s, 5); 
    print_in_locale("tr_TR.utf8", turkish_is, 5); 
    print_in_locale("de_DE.utf8", turkish_is, 5); 
} 

Jeśli zapisałeś go do „locale_test.c”, można go uruchomić z linii poleceń z ...

gcc -o locale_test locale_test.c && ./locale_test 
+0

Czy wykorzystałeś tylko język turecki lub czy tworzysz oprogramowanie ukierunkowane na Turcję? –

+1

Przykład. Pracuję nad oprogramowaniem, które zamierzamy wydać w sposób wielowymiarowy, kiedy zacząłem go wykorzystywać, a następnie rozmawiając o nim w G +, mam wielu przyjaciół, w tym tych, którzy nie są technikami, którzy interesują się problemem. Myślałem, że przez weekend opracuję oprogramowanie, które zademonstrowało wiele z tego, ale nigdy nie miałem okazji. –

Odpowiedz

13

Użyj funkcji Data.Text.ICU.toUpper z pakietu text-icu.

toUpper :: LocaleName -> Text -> Text

wielkimi literami znaki w ciąg.

Obudowa jest zależna od regionu i jest zależna od kontekstu. Wynik może być dłuższy lub krótszy od oryginału o .

+0

To było dokładnie to! Wygląda na to, że dla większości wsparcia Unicode, nie potrzebuję niczego poza Prelude putStrLn, Data.Text.ICU (dla zależnych od ustawień lokalnych i małych liter) i Data.Text (dla budowania ciągów unicode). Prawdopodobnie również funkcje kodeków Unicode przełączają się między UTF-8 a wewnętrzną reprezentacją. –

Powiązane problemy