LoadString работает, только если у меня нет таблицы строк на английском языке - PullRequest
7 голосов
/ 31 июля 2009

Я хочу иметь возможность программно изменять язык приложения или, по крайней мере, использовать язык, указанный в Панели управления -> Региональные и языковые параметры -> Форматы.

Если я добавлю таблицу английских строк, сделаю ее копию на французском и немецком языках и удаляю английскую, я могу программно переключаться между загрузкой строк на французском и немецком языках. Если я сохраняю английскую копию, английские строки загружаются, несмотря ни на что, когда я пытаюсь загрузить немецкую или французскую.

Я думаю, что это ошибка загрузчика ресурсов, и что загрузчик ресурсов игнорирует SetThreadLocale, если он находит таблицу строк на том же языке, что и язык пользовательского интерфейса Windows (например, язык меню Windows Explorer).

Я пытался изменить Панель управления -> Региональные и языковые параметры -> Форматы на французский, но это не имеет никакого эффекта. Редактор ресурсов показывает таблицу французских строк без добавленного языка, но моя программа по-прежнему всегда загружает английские строки. Копирование этого изменения в системную учетную запись также не имеет никакого эффекта.

Вот код, с которым я пытался это сделать:

#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;
}

Здесь - наполовину неверное, неполное объяснение (во второй половине метода 2). Второй предложенный здесь обходной путь, использующий только строково-нейтральные строковые таблицы, бесполезен, потому что у меня есть отдельные строковые таблицы Португалия-Португалия и Португалия-Бразилия.

Первый предложенный обходной путь не работает. С кодом ниже я получаю ошибку 1814.

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

Итак, что мне делать? Чем объясняется эта странная «ошибка»?

ПОСЛЕДНЕЕ РЕДАКТИРОВАНИЕ:

После еще нескольких тестов я узнал, что:

  1. GetThreadLocale () возвращает то, что установить в панели управления -> Региональный и Параметры языка -> Форматы.
  2. Ошибка загрузчика ресурсов заключается в том, что если в моей программе есть ресурсы на английском языке США, эти ресурсы будут загружаться независимо от того, что установлено в форматах. Если он не имеет ресурсов английского языка США, будет использоваться язык, установленный в форматах.
  3. Если у меня есть таблица строк на французском (Neutral) и немецком (Neutral), и я установил форматы на French (Франция), немецкие строки загружаются. Если я добавлю английскую (нейтральную) таблицу строк, английские строки будут загружены. Таким образом, нейтральный запасной вариант культуры не работает для форматов.
  4. Если я добавлю таблицу нейтральных строк, она будет использоваться, даже если у меня есть другая таблица строк на английском (нейтральном) или английском языке (США).

Ответы [ 3 ]

6 голосов
/ 21 декабря 2011

Подробное описание выбора локализованных ресурсов (включая порядок поиска FindResource) прямо из MSDN: Многоязычные ресурсы

Редактировать: Однако, исходя из моего опыта (по крайней мере, в Windows XP), порядок поиска, подробно описанный для FindResource на этой странице, не описывает фактическое поведение. Фактическое поведение выглядит так:

  1. LANG_NEUTRAL ресурс
  2. ресурс, где Lang и SubLang соответствуют языку пользовательского интерфейса Lang и SubLang
  3. ресурс, где Lang соответствует языку пользовательского интерфейса Lang, а ресурс Sublang нейтрален
  4. ресурс, где Lang и SubLang соответствуют языку локали Lang и SubLang
  5. ресурс, где Lang соответствует языку локали Lang, а ресурс Sublang нейтрален
  6. ресурс с наименьшим числовым LANGID

Примечание. У меня нет источников для проверки этого списка, поэтому, если кто-то может что-то обновить или исправить, сделайте это.

Редактировать: Чтобы понять это поведение, важно распознать разницу между 'locale' и 'UIlanguage', как объяснено здесь: NLS Terminology . Выбор языка функции FindResource основан, главным образом, на языке пользовательского интерфейса, который НЕ является настройкой «Региональные параметры» в «Региональных и языковых настройках» (то есть настройкой «locale», которая аналогична вызову SetThreadLocale ()).

Насколько я могу судить, причина, по которой параметр языкового стандарта или SetThreadLocale () влияет на FindResource (), вызван исключительной ситуацией, описанной @Kirill V. Lyadvinsky в одном из ответов, который более подробно объясняется на Блог Майкла Каплана .

Установка языка для FindResource в коде чисто и детерминистически стала возможной только с новой функцией SetThreadUILanguage в Vista и далее. Каждое место, которое вы видите, вместо этого использует SetThreadLocale, будет иметь хаки, чтобы заставить его работать и / или иметь проблемы при изменении языка пользовательского интерфейса (например, установка иностранных языков Windows).

5 голосов
/ 31 июля 2009

Вы используете Vista или Windows 7? Если это так, то SetThreadLocale не работает (даже если он возвращает TRUE, вздох), и вы должны использовать SetThreadUILanguage.

Я только что заполнил приложение WTL, переведенное на 7 разных языков, и пользователь может переключать языки без проблем, которые вы описываете. Я использую SetThreadLocale на XP и SetThreadUILanguage на Vista / 7.

Подробнее:

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/

4 голосов
/ 31 июля 2009

Подвох здесь в том, что если языковой стандарт потока совпадает с текущим выбранным языковым стандартом пользователя, системный загрузчик ресурсов по умолчанию будет использовать языковой идентификатор 0 (нейтральный). Если требуемый ресурс определен как нейтральный язык, то это значение будет возвращено. В противном случае будут перечислены все языковые ресурсы (в порядке идентификатора языка) и будет возвращен первый соответствующий идентификатор ресурса - независимо от его языка.

Единственный способ контролировать ресурсы - использовать отдельные библиотеки ресурсов для каждого языка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...