2009-07-31 9 views
7

Desidero essere in grado di modificare la lingua dell'applicazione in modo programmatico o almeno utilizzare la lingua specificata in Pannello di controllo -> Opzioni internazionali e della lingua -> Formati.LoadString funziona solo se non si dispone di una tabella di stringhe inglese

Se aggiungo una tabella di stringhe inglese, ne creo una copia francese e una tedesca, ed elimina quella inglese, posso passare in modo programmatico tra il caricamento delle stringhe francese e quella tedesca. Se tengo la copia inglese, le stringhe inglesi vengono caricate, non importa cosa, quando provo a caricare quelle tedesche o francesi.

Penso che questo sia un bug del caricatore di risorse e che il caricatore di risorse ignori SetThreadLocale, se trova una tabella di stringhe nella stessa lingua della lingua dell'interfaccia utente di Windows (ad esempio, la lingua dei menu di Windows Explorer).

Ho provato a cambiare Pannello di controllo -> Opzioni internazionali e della lingua -> Formati al francese, ma ciò non ha alcun effetto. L'editor delle risorse mostra la tabella delle stringhe francese senza la lingua aggiunta, ma il mio programma carica sempre le stringhe inglesi. La copia di questa modifica sull'account di sistema non ha alcun effetto.

Ecco il codice che ho provato 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 è un mezzo mal spiegazione incompleta (nella seconda metà del metodo 2). La seconda soluzione proposta qui, utilizzando solo tabelle di stringa neutrali in stile coutry è inutile, perché ho separato le tabelle di stringhe portoghese-portoghese e portoghese-brasiliano.

La prima soluzione proposta qui non funziona. Con il codice qui sotto, ottengo l'errore 1814.

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

Quindi, cosa dovrei fare? Qual è la spiegazione di questo strano "bug"?

DOPO EDIT:

Dopo qualche test ho scoperto che:

  1. GetThreadLocale() restituisce ciò che è insieme nel Pannello di controllo -> Opzioni internazionali e della lingua -> Formati.
  2. Il bug del caricatore di risorse è essenzialmente che se il mio programma ha anche risorse in inglese americano, tali risorse verranno caricate, indipendentemente da ciò che è impostato nei formati. Se non dispone di risorse in inglese americano, verrà utilizzata la lingua impostata in Formats.
  3. Se si dispone di una tabella di stringhe francese (neutro) e tedesco (neutro) e si impostano i formati in francese (Francia), vengono caricate le stringhe tedesche. Se aggiungo una tabella di stringhe in inglese (neutro), vengono caricate le stringhe in inglese. Quindi, il fallback della cultura neutrale non funziona per ciò che è impostato su Formats.
  4. Se aggiungo una tabella di stringhe neutre, quella verrà utilizzata anche se si dispone di un'altra tabella di stringhe inglese (neutro) o inglese (Stati Uniti).

risposta

4

La cattura è che se l'impostazione del filo è uguale locali dell'utente attualmente selezionato, Caricatore di risorse di sistema per default utilizza l'ID lingua 0 (neutro). Se la risorsa desiderata è definita come lingua neutra, verrà restituito questo valore. Altrimenti, verranno enumerate tutte le risorse linguistiche (nell'ordine ID lingua) e verrà restituito il primo ID risorsa corrispondente, indipendentemente dalla lingua utilizzata.

L'unico modo per controllare le risorse consiste nell'utilizzare DLL di risorse separate per ogni lingua.

+0

Qual è il locale dell'utente attualmente selezionato? È la lingua dei menu in Esplora risorse di Windows e non è modificabile. Le impostazioni locali del thread vengono controllate prima che abbia la possibilità di modificarlo? Come posso impostare la locale predefinita con l'editor di risorse? –

+0

È la locale selezionata in Impostazioni internazionali nel Pannello di controllo. –

+0

Questo non è correlato alla scheda Formato. È la scheda Avanzate. –

5

Stai utilizzando Vista o Windows 7? Se è così allora SetThreadLocale non funziona (anche se restituisce VERO, sospiro) e devi usare SetThreadUILanguage.

Ho appena completato un'app WTL che è stata tradotta in 7 lingue diverse e l'utente può cambiare lingua senza i problemi che si stanno descrivendo. Sto usando SetThreadLocale su XP e SetThreadUILanguage su Vista/7.

Maggiori informazioni:

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

descrizione dettagliata di come le risorse localizzate sono selezionati (tra cui l'ordine di ricerca di FindResource) direttamente da MSDN: Multiple-Language Resources

Edit: Tuttavia, dalla mia esperienza (almeno su Windows XP) l'ordine di ricerca dettagliato per FindResource in quella pagina non descrive il comportamento effettivo. Il comportamento effettivo sembra essere:

  1. risorsa LANG_NEUTRAL
  2. risorse in cui Lang e SubLang lingua partita UI Lang e SubLang
  3. risorse in cui Lang corrisponde lingua dell'interfaccia utente Lang e delle risorse Sublang è neutrale
  4. risorse in cui Lang e SubLang lingua partita locale Lang e SubLang
  5. risorse in cui Lang corrisponde la lingua locale Lang e delle risorse Sublang è neutrale
  6. delle risorse con più basso LANGID numerico

Nota: non ho alcuna fonte per convalidare tale elenco, quindi se qualcuno può aggiornare o correggere qualcosa, si prega di farlo.

Modifica: per comprendere questo comportamento, è importante riconoscere la differenza tra "locale" e "UIlanguage" come spiegato qui: NLS Terminology. La selezione della lingua della funzione FindResource si basa principalmente sulla lingua dell'interfaccia utente che NON è l'impostazione "Opzioni internazionali" nelle "Opzioni internazionali e della lingua" (ovvero l'impostazione "locale", che equivale a chiamare SetThreadLocale()).

Per quanto posso dire, il motivo per cui l'impostazione locale o "SetThreadLocale()" influenza FindResource() è a causa del caso di eccezione descritto da @Kirill V. Lyadvinsky in una delle risposte qui, spiegato in modo più dettagliato su Michael Kaplan's blog.

L'impostazione della lingua per FindResource nel codice in modo pulito e deterministico è stata resa possibile solo con la nuova funzione 'SetThreadUILanguage' in Vista in poi. Ogni luogo che vedi che utilizza SetThreadLocale avrà degli hack per farlo funzionare e/o avere problemi quando la lingua dell'interfaccia utente cambia (es: installazione di Windows in lingua straniera).

+0

Il collegamento [Multiple Language Resources] (https://msdn.microsoft.com/en-us/library/cc194810.aspx) proviene da un libro scritto intorno al 1995 (menzioni Windows 95 e Visual C++ 2.0). Sembra che alcune funzionalità/comportamenti siano cambiati da allora, quindi le informazioni nel link devono essere prese con un pizzico di sale. – Val

+0

Sì, il collegamento MLR è obsoleto - vedere la mia nota alla fine della risposta sulle versioni che iniziano con Vista e in poi dove si dovrebbe sempre usare SetThreadUILanguage – Sogger

Problemi correlati