2012-09-21 24 views
10

Resulta que aplicar un carácter a mayúsculas es una tarea complicada. Si sale del juego de caracteres ASCII básico, las reglas para aplicar mayúscula a un carácter y minicar un carácter dependen realmente de la configuración regional en la que se ejecuta la aplicación.En haskell, ¿cómo puedo mayúsculo un carácter Unicode con respecto a la configuración regional actual

Como una aplicación de demostración, estoy tratando de mayúscula la letra 'i' (con un punto) y la letra 'i' (sin un punto). Ahora, en en_US, 'i' (con un punto) en mayúsculas en 'I', e 'i' (sin un punto) no existe (pero sigue siendo mayúscula en 'I').

Pero, si cambio a turco (tr_TR.UTF-8), 'i' (con un punto) debe mayúscula a 'İ' (también con un punto) y 'ı' (sin un punto) debe mayúscula a 'I' (también sin un punto). Las minúsculas deben invertir estas operaciones.

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

Ahora, puedo hacer esto perfectamente en C. ¿Cómo puedo hacerlo en Haskell? Todas las búsquedas que hago me dirigen directamente a Data.Char.toUpper, que no tiene en cuenta la configuración regional. No he encontrado ninguna función que tenga en cuenta la configuración regional de ninguna manera.


Aquí hay un ejemplo de código de C. Lo ejecuto en mi máquina 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); 
} 

Si lo guardó para "locale_test.c", se puede ejecutar en la línea de comandos con ...

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

¿Usaste el turco solo como ejemplo o desarrollas un software para Turquía? –

+1

Ejemplo. Estoy trabajando en un software que vamos a lanzar multinacionalmente cuando comencé a toparme con esto, y luego al hablar sobre él en G + tengo muchos amigos, incluidos aquellos que no son expertos en tecnología, interesados ​​en el problema. Pensé que durante el fin de semana desarrollaría un programa que demostraba mucho de esto, pero nunca tuve la oportunidad. –

Respuesta

13

Utilice la función Data.Text.ICU.toUpper del paquete text-icu.

toUpper :: LocaleName -> Text -> Text

mayúsculas los caracteres de una cadena.

La carcasa depende de la configuración regional y del contexto. El resultado puede ser más largo o más corto que el original.

+0

¡Eso fue exactamente! Parece que para la mayor parte del soporte Unicode, no necesito nada más allá de Prelude putStrLn, Data.Text.ICU (para mayúsculas y minúsculas dependiente de la configuración regional) y Data.Text (para crear cadenas de Unicode). Posiblemente también el códec Unicode funcione para cambiar entre UTF-8 y representación interna. –

Cuestiones relacionadas