Pregunta Ordenando matriz con intercalación


Tengo una matriz con palabras en francés: ['États-Unis', 'Espagne', etc.] que me gustaría haber ordenado alfabéticamente según su configuración regional (fr_FR)

Estoy usando el siguiente código:

$collator = new Collator('fr-FR');
echo $collator->getErrorMessage();
$collator->asort($array);

pero recibo el error U_USING_DEFAULT_WARNING donde supongo que se está utilizando el inglés o alguna otra configuración regional. Lo que es más importante, la matriz no está ordenada correctamente (EE. UU. Aparece antes de España, esperaba que sucediera lo contrario)

Tengo el paquete intl instalado y mi sistema tiene las configuraciones regionales correspondientes (Ubuntu)

$locale -a
C
C.UTF-8
en_US.utf8
es_ES.utf8
fr_FR
fr_FR.iso88591
fr_FR.utf8
POSIX

Intenté diferentes combinaciones al construir el objeto Collation, sin ningún resultado bueno: "fr-FR", "fr-FR.UTF8", etc.

¿Hay algo más que me pierdo?


8
2017-11-26 18:55


origen


Respuestas:


De acuerdo a esta publicación en el blog, para las palabras redil, redil, redil y redil (ya ordenado en inglés), el orden de clasificación en francés es: redil, redil, redil y redil. El código siguiente ordena las palabras en la intercalación francesa:

$words = array('cote', 'coté', 'côte',  'côté');
print_r($words);

$collator = new Collator('fr_FR');

// print info about locale
echo 'French Collation ' . (($collator->getAttribute(Collator::FRENCH_COLLATION) ==    Collator::ON) ? 'On' : 'Off') . "\n";
echo $collator->getLocale(Locale::VALID_LOCALE) . "\n";
echo $collator->getLocale(Locale::ACTUAL_LOCALE) . "\n";

$collator->asort($words);

print_r($words);

Y el resultado impreso es el siguiente:

Array
(
    [0] => cote
    [1] => coté
    [2] => côte
    [3] => côté
)
French Collation On
fr_FR
fr
Array
(
    [0] => cote
    [2] => côte
    [1] => coté
    [3] => côté
)

En la misma publicación del blog, el autor dice:

[...] los diacríticos se evalúan de derecha a izquierda en vez de izquierda a derecha. Así redil viene antes redil, en lugar de hacerlo después como lo hace en idiomas como el inglés, que los evalúa de izquierda a derecha. Porque la palabra redil no tiene AGUDO en la "e" al final de la palabra mientras redil hace. En inglés y en la mayoría de los otros idiomas, la evaluación comienza a la izquierda y, por lo tanto, el CIRCUMFLEX o la falta del mismo en la "o" es el factor de control en el pedido.

Entonces, si tienes una matriz con las palabras España y NOS, tendrán el mismo orden en inglés y francés.

También debe tener en cuenta que asort método mantener la asociación de índice de la matriz. Ver la diferencia:

asort:
Array
(
    [0] => cote
    [2] => côte
    [1] => coté
    [3] => côté
)

sort:
Array
(
    [0] => cote
    [1] => côte
    [2] => coté
    [3] => côté
)

Acerca de U_USING_DEFAULT_WARNING

De acuerdo a esto Documentación de API:

U_USING_DEFAULT_WARNING indica que se usaron los datos de configuración regional predeterminados; no se pudo encontrar la configuración regional solicitada ni ninguno de sus entornos alternativos.

Cuando uso el fr_FR configuración regional, por ejemplo, obtengo un U_USING_FALLBACK_WARNING, que indica que se utilizó una configuración regional de recuperación, en este caso, la configuración regional fr.

Lugar

Como parece, su computadora no tiene soporte para el idioma francés (o lo hace, pero de alguna manera PHP no puede usarlo y luego recurrir al idioma predeterminado), aunque el comando locale -a muestra los paquetes franceses. Tengo algunas sugerencias que puedes probar.

Primero, enumere todas las configuraciones regionales compatibles:

cat /usr/share/i18n/SUPPORTED 

Ahora, genere los idiomas que necesita:

sudo locale-gen fr_FR.UTF-8
sudo locale-gen fr_FR.ISO-8859-1
sudo dpkg-reconfigure locales

Si no funciona, intente instalar los paquetes language-pack-fr y language-support-fr y generar los idiomas de nuevo.

Este problema es extraño. Tengo una máquina virtual con Ubuntu 11.04 y PHP 5.3.8 y funciona muy bien, en mi Debian 6 también, y no he instalado ningún paquete ni configurado nada.


5
2017-11-30 14:05



Estoy usando cygwin:

$ locale -a | grep fr_FR
fr_FR
fr_FR.utf8
[email protected]

(nota que no tengo fr_FR.iso88591 en la salida)

Código (la codificación del archivo es UTF-8):

$collator = new Collator('fr_FR');
var_dump($collator->getErrorMessage());

// FRENCH_COLLATION is OFF

$arr = array('États-Unis', 'Espagne');

var_dump($collator->getAttribute(Collator::FRENCH_COLLATION) == Collator::ON);
var_dump($collator->getLocale(Locale::VALID_LOCALE));
var_dump($collator->getLocale(Locale::ACTUAL_LOCALE));
$collator->asort($arr);
var_dump($arr);

// FRENCH_COLLATION is ON

$collator->setAttribute(Collator::FRENCH_COLLATION, Collator::ON);

$arr = array('États-Unis', 'Espagne');

var_dump($collator->getAttribute(Collator::FRENCH_COLLATION) == Collator::ON);
var_dump($collator->getLocale(Locale::VALID_LOCALE));
var_dump($collator->getLocale(Locale::ACTUAL_LOCALE));
$collator->asort($arr);
var_dump($arr);

Salida:

string(23) "U_USING_DEFAULT_WARNING"
bool(false)
string(5) "fr_FR"
string(4) "root"
array(2) {
  [1]=>
  string(7) "Espagne"
  [0]=>
  string(11) "États-Unis"
}
bool(true)
string(5) "fr_FR"
string(4) "root"
array(2) {
  [1]=>
  string(7) "Espagne"
  [0]=>
  string(11) "États-Unis"
}

Y aquí está el truco: Convierto la codificación de archivos a ISO 8859-1 (en vim, lo hago :set fileencoding=iso-8859-1) e intenta de nuevo:

string(23) "U_USING_DEFAULT_WARNING"
bool(false)
string(5) "fr_FR"
string(4) "root"
array(2) {
  [0]=>
  string(10) "▒tats-Unis"
  [1]=>
  string(7) "Espagne"
}
bool(true)
string(5) "fr_FR"
string(4) "root"
array(2) {
  [0]=>
  string(10) "▒tats-Unis"
  [1]=>
  string(7) "Espagne"
}

Algunos símbolos están rotos, pero creo que es porque mi terminal no es compatible con la página de códigos dada. Lo principal es que el orden de las cadenas ahora es exactamente lo que has descrito: "Espagne" viene después de "États-Unis".

Entonces, creo que es una codificación de archivo.


0
2017-12-01 14:20



Prueba solo 'FR', debería funcionar para tu sistema, supongo:

$collator = new Collator('FR');

0
2017-12-06 17:40