2009-07-31 12 views
7

Quiero poder modificar el idioma de la aplicación mediante programación, o al menos usar el idioma especificado en el Panel de control -> Opciones regionales y de idioma -> Formatos.LoadString funciona solo si no tengo una tabla de cadenas en inglés

Si agrego una tabla de cadenas en inglés, hago una copia en francés y en alemán, y elimino la en inglés, puedo cambiar programáticamente entre cargar las cadenas en francés y en alemán. Si guardo la copia en inglés, las cadenas en inglés se cargan, pase lo que pase, cuando intento cargar el alemán o el francés.

Creo que este es un error del cargador de recursos, y que el cargador de recursos ignora SetThreadLocale, si encuentra una tabla de cadenas en el mismo idioma que el de Windows UI (el idioma de los menús de Windows Explorer, por ejemplo).

Traté de cambiar el Panel de control -> Configuración regional y de idioma -> Formatos al francés, pero eso no tiene ningún efecto. El editor de recursos muestra la tabla de cadenas en francés sin el idioma adjunto, pero mi programa todavía carga las cadenas en inglés. Copiar este cambio en la cuenta del sistema tampoco tiene ningún efecto.

Este es el código He intentado esto con:

#include "stdafx.h" 
#include <iostream> 
#include "windows.h" // this should go to stdafx.h 
#include "resource.h" // this should not go to stdafx.h 
using namespace std; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    // 1036 = french, 1031 = german 
    SetThreadLocale(MAKELCID(1036, SORT_DEFAULT)); 
    const int maxSize = 100; 
    wchar_t c[maxSize]; 
    LoadString(GetModuleHandle(NULL), IDS_STRING101, c, maxSize); 
    std::cout << c; 
    return 0; 
} 

Here es una mitad incorrecta, incompleta explicación (en la segunda mitad del método 2). La segunda solución propuesta allí, que utiliza solo tablas de cadenas neutrales de coutry es inútil, porque tengo tablas de cadenas portugués-portugués y portugués-brasileño separadas.

La primera solución propuesta allí no funciona. Con el siguiente código, obtengo el error 1814.

HRSRC r = FindResource(
    GetModuleHandle(NULL), 
    MAKEINTRESOURCE(IDS_STRING101), 
    RT_STRING); 
DWORD e = GetLastError(); 

Entonces, ¿qué debo hacer? ¿Cuál es la explicación de este extraño "error"?

de editar posteriormente:

Después de algunas pruebas más descubrí que:

  1. GetThreadLocale() devuelve lo que es conjunto del Panel de control -> Opciones regionales y de idioma -> Formatos.
  2. La falla del cargador de recursos es esencialmente que si mi programa también tiene recursos de inglés de EE. UU., Esos recursos se cargarán, sin importar lo que esté configurado en Formats. Si no tiene recursos de inglés de EE. UU., Se usará el idioma establecido en Formats.
  3. Si tengo una tabla de cadenas francesa (neutral) y alemana (neutral), y configuré formatos en francés (Francia), se cargan las cadenas alemanas. Si agrego una tabla de cadenas en inglés (Neutral), las cadenas en inglés están cargadas. Entonces, la recuperación de la cultura neutral no funciona para lo que se establece en Formats.
  4. Si agrego una tabla de cadenas neutrales, esa será utilizada, incluso si tengo otra tabla de cadenas en inglés (neutral) o en inglés (Estados Unidos).

Respuesta

4

El truco aquí es que si la configuración regional de subproceso es la misma que la configuración regional del usuario seleccionado en ese momento, cargador de recursos del sistema por defecto usará el identificador de idioma 0 (neutro). Si el recurso deseado se define como un idioma neutral, se devolverá este valor. De lo contrario, se enumerarán todos los recursos del idioma (en el orden de ID de idioma) y se devolverá la primera ID de recurso coincidente, independientemente de su idioma.

La única manera de controlar los recursos es usar DLL de recursos separados para cada idioma.

+0

¿Cuál es la configuración regional de usuario seleccionada actualmente? Es el idioma de los menús en el Explorador de Windows e inmutable. La ubicación del subproceso está marcada antes de que tenga la oportunidad de modificarlo? ¿Cómo puedo configurar la configuración regional predeterminada con el editor de recursos? –

+0

Es la configuración regional que se seleccionó en Configuración regional en el Panel de control. –

+0

Eso no está relacionado con la pestaña Formato. Es la pestaña Avanzado. –

5

¿Está ejecutando Vista o Windows 7? Si es así, entonces SetThreadLocale no funciona (aunque devuelve TRUE, suspiro) y debe usar SetThreadUILanguage.

Acabo de completar una aplicación WTL que se ha traducido a 7 idiomas diferentes y el usuario puede cambiar de idioma sin los problemas que está describiendo. Estoy usando SetThreadLocale en XP y SetThreadUILanguage en Vista/7.

Más información:

http://social.msdn.microsoft.com/forums/en-US/windowscompatibility/thread/d3a44b1c-900c-4c64-bdf8-fe94e46722e2/

http://www.curlybrace.com/words/2008/06/10/setthreadlocale-and-setthreaduilanguage-for-localization-on-windows-xp-and-vista/

6

Descripción detallada de cómo los recursos localizados son seleccionados (incluyendo el orden de búsqueda de FindResource) directamente desde MSDN: Multiple-Language Resources

Editar: Sin embargo, según mi experiencia (al menos en Windows XP), el orden de búsqueda detallado para FindResource en esa página no describe el comportamiento real. El comportamiento real parece ser:

  1. recursos LANG_NEUTRAL
  2. recurso donde Lang y SubLang lenguaje partido de la interfaz de usuario Lang y SubLang
  3. recurso donde Lang coincide con el lenguaje de interfaz de usuario Lang y recursos Sublang es neutral
  4. recurso donde Lang y SubLang coinciden con el idioma local Lang y SubLang
  5. recurso donde Lang coincide con el idioma local Lang y el recurso Sublang es neutral
  6. recurso con el valor numérico más bajo LANGID

Nota: No tengo ninguna fuente para validar esa lista, por lo que si alguien puede actualizar o corregir algo, hágalo.

Editar: Para comprender este comportamiento, es importante reconocer la diferencia entre la 'configuración regional' y 'UIdioma' como se explica aquí: NLS Terminology. La selección del idioma de la función FindResource se basa principalmente en el idioma de la IU que NO es la configuración de 'Opciones regionales' en 'Configuración regional y de idioma' (que es la configuración 'locale', que es lo mismo que llamar a SetThreadLocale()).

Hasta donde puedo decir, la razón por la que la configuración regional o 'SetThreadLocale()' afecta a FindResource() se debe al caso de excepción descrito por @Kirill V. Lyadvinsky en una de las respuestas aquí, explicado con más detalle en Michael Kaplan's blog.

Configurar el lenguaje para FindResource en el código de forma limpia y determinista solo fue posible con la nueva función 'SetThreadUILanguage' en Vista en adelante. Cada lugar que vea que en su lugar use SetThreadLocale tendrá ataques de intrusión para que funcione y/o problemas cuando cambie el idioma de la interfaz de usuario (es decir: se instalará Windows en un idioma extranjero).

+0

El enlace [Recursos de varios idiomas] (https://msdn.microsoft.com/en-us/library/cc194810.aspx) es de un libro escrito en 1995 (menciona Windows 95 y Visual C++ 2.0). Parece que alguna funcionalidad/comportamiento ha cambiado desde entonces, por lo que la información en el enlace debe tomarse con un grano de sal. – Val

+0

Sí, el enlace de MLR es antiguo; consulte mi nota al final de la respuesta sobre las versiones que comienzan con Vista y en adelante donde siempre debe usar SetThreadUILanguage – Sogger

Cuestiones relacionadas