Idiomas bidireccionales… no todo en localización son recursos

Esta semana arreglé un defecto de localización en uno de los componentes en los que trabajo.  Por el tipo de error y la relación que tiene con este blog me parece un perfecto tópico para ilustrar el siguiente punto: “Escribir código para múltiples idiomas está lleno de sutilezas.”

Analicemos primero el escenario en qué aparece este defecto.  El componente en cuestión sólo está soportado en los idiomas más populares (el código requiere conocimiento del idioma), si un usuario intenta lanzar este componente en un idioma no soportado recibe un mensafe de alerta indicando el error:

image

Este mensaje se genera utilizando la función MessageBox.

    1: ::MessageBox(NULL, message, caption, MB_OK);

(Asumiendo que message y caption se obtuvieron de los recursos localizables)

Esto funciona bien para casi todos los idiomas, pero qué sucede en idiomas que se escriben de derecha a izquierda como hebreo y árabe.  En el caso de cuadros de diálogo cuando se traducen estos recursos se activan los bits correctos, pero la función MessageBox sólo recibe texto, así que es necesario indicarle que estamos en un idioma de derecha a izquierda mediante las banderas MB_RIGHT (alinear texto a la derecha) y MB_RTLREADING (desplegar los controles alineados a la derecha).  Utilizando estas banderas el cuadro de diálogo se despliega así:

image

Antes de utilizar estas banderas, tenemos que determinar si nuestra aplicación se está utilizando en un idioma de derecha izquierda.  En este caso específico es fácil, ya que la aplicación tiene una ventana principal que tiene el estilo extendido WS_EX_LAYOUTRTL.

El siguiente código crea el mensaje de alerta con los parámetros correctos.

    1: UINT mirroredFlag(0);
    2: LONG style = ::GetWindowLong(hwndMain, GWL_EXSTYLE);
    3: if ((style & WS_EX_LAYOUTRTL) != 0)
    4: {
    5:     mirroredFlag = MB_RTLREADING | MB_RIGHT;
    6: }
    7: MessageBox(hwndMain, message, caption, MB_OK | mirroredFlag);

No siempre es necesario realizar todos estos pasos (en una aplicación para uso interno en general no hay que considerar detalles de localización), pero si estamos escribiendo software para un mercado global, estas sutilezas son el pan de todos los días.

P.S. – Mi primera corrección de este defecto sólo cambiaba los controles del cuadro de diálogo, pero no alineaba el texto correctamente.  Un recordatorio de que es necesario leer la documentación a fondo antes de hacer correcciones “sencillas”.