Преобразование трехбуквенного кода языка в идентификатор языка (LANGID)

Есть ли способ в Win32 API преобразовать трехбуквенный код языка, возвращаемый GetLocaleInfo() с указанным LOCALE_SABBREVLANGNAME, в соответствующий LANGID или LCID? То есть идти «наоборот» к тому, что обычно делает GetLocaleInfo()?

Что я пытаюсь сделать, так это проанализировать, какой язык использует ресурсная DLL, и до сих пор, ничего не касаясь DLL, переходя по имени dll в формате nameLNG.dll, где LNG — трехбуквенный код языка, кажется самым простым методом, если такая функция существует.

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


person Jonas    schedule 13.10.2009    source источник


Ответы (3)


К сожалению, нет прямого Win32 API, который дает вам LANGID, учитывая трехбуквенную аббревиатуру.

Похоже, CLanguageSupport — ваш друг сегодня :-) Он уже реализует ваш план Б по поиску LANGID на основе содержимого информационного ресурса версии.

Фрагмент кода, который вы ищете, находится внутри функции

LANGID CLanguageSupport::GetLangIdFromFile(LPCTSTR pszFilename)

Конечно, недостатком является то, что у вас может быть несоответствие между информацией о версии и именем DLL. Но вы бы очень быстро поймали это во время тестов. И если вы позволите такому инструменту, как appTranslator, создать для вас библиотеки DLL, вы точно обезопасите себя. сторона.

person Serge Wautier    schedule 13.10.2009
comment
Да, я думаю, что тогда я в конечном итоге буду использовать этот класс, поскольку вы, по-видимому, уже обошли не одну, а две проблемы, с которыми мы сейчас сталкиваемся. Мы можем даже повторно реализовать языковое подменю, которое я удалил несколько дней назад, думая, что наш переход на механизм MFC будет окончательным. Ну что ж... - person Jonas; 14.10.2009

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

В этом случае я бы рекомендовал использовать Plan B. Обычно я избегаю кодирования в имени файла. Если ни по какой другой причине, использование 3-символьного варианта ISO-639 не является идеальным, если вы строго указываете, какой вариант вы используете - ISO-639-2/B, ISO-639-2 /T или ISO-639-3.

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

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

person D.Shawley    schedule 13.10.2009
comment
EnumSystemLocales дает мне только список трехбуквенных аббревиатур, верно? Я не уверен, как построить карту, используя только эту информацию и не имея LCID или LANGID для перевода? Это решение было бы идеальным, если бы функция обратного вызова для EnumSystemLocales возвращала пару строк LCID и ISO. - person Jonas; 14.10.2009
comment
Аргумент для EnumLocalesProc на самом деле является LCID, отформатированным как шестнадцатеричное число в строку. Документация не совсем ясна по этому поводу - Указатель на буфер, содержащий строку идентификатора локали, заканчивающуюся нулем. Что они не упоминают, так это то, что вам нужно вызвать что-то вроде _tcstoul(lpLocaleString, NULL, 16), чтобы получить идентификатор локали в пригодной для использования форме. Получив LCID, вы можете получить то, что вам нужно, от GetLocaleInfo(), используя LOCALE_SISO639LANGNAME и LOCALE_SISO3166CTRYNAME. - person D.Shawley; 14.10.2009

Вы можете получить LangID, вызвав GetLocaleInfo() с LOCAL_RETURN_NUMBER|LOCALE_ILANGUAGE для параметра LCType, точно так же, как вы передали LOCALE_SABBREVLANGNAME для получения трехбуквенного кода ISO. Передав в эту функцию тот же lcid, вы можете сохранить соответствующий LangID с кодом ISO.

Обратите внимание, что MSDN говорит, что LOCALE_ILANGUAGE не следует использовать вместо LOCALE_SLANG в Vista и выше, но я считаю, что комментарий не относится к использованию LOCALE_ILANGUAGE с LOCALE_RETURN_NUMBER.

По мере развития вашего проекта вы можете создать несколько локализованных файлов для каждого языка. По этой причине я бы посоветовал вам хранить локализованные файлы в подкаталогах, названных в честь языка. Microsoft использовала каталоги, названные в честь LangID, например «1033», в качестве каталога ресурсов на английском языке. Я думаю, было бы удобнее использовать трехбуквенный код, например "ENU\name.dll". В любом случае, подкаталоги — это простое решение, и мы надеемся, что они не усложнят процесс сборки так сильно, как изменение имени целевого файла.

person Heath Hunnicutt    schedule 13.10.2009
comment
К сожалению, у меня нет доступа к LCID, но мне нужен LANGID из трехбуквенной аббревиатуры языкового кода (фальшивый код ISO). - person Jonas; 14.10.2009
comment
FWIW, MS хочет, чтобы мы отошли от LOCALE_ILANGUAGE, потому что они хотят перейти к идентификаторам языков, состоящим только из строк, а-ля идентификаторы культур .NET. сейчас они пытаются убедить нас, что LANGID может когда-нибудь умереть, по крайней мере, для недавно поддерживаемых языков в Win8+ - person Serge Wautier; 14.10.2009