Нейтральная локаль, как и все остальные, определяется в ресурсах EXE или DLL и имеет код 0x000. Я думаю, что зачастую имеет смысл определять более обобщённые варианты ресурсов, дабы не дублировать их для каждой конкретной локали, например:
- ru вместо ru-RU
- en вместо en-US, en-GB и т.п.
Если специфичная локаль (en-US или en-GB) не будет найдена в ресурсах модуля, то будет выполнена дополнительная попытка найти более обобщённый вариант локали: en. Однако обратное не верно: если задан поиск локали en, а в ресурсах вместо неё присутствуют более конкретные локали (en-US или en-GB), то они будут проигнорированы.
В качестве примера в файле resources.txt определим текстовые ресурсы с таким набором локализаций:
- нейтральная
- ru
- en-US
; // ***** resources.txt *****
; // This is the header section.
MessageIdTypedef=DWORD
SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS
Informational=0x1:STATUS_SEVERITY_INFORMATIONAL
Warning=0x2:STATUS_SEVERITY_WARNING
Error=0x3:STATUS_SEVERITY_ERROR
)
FacilityNames=(System=0x0:FACILITY_SYSTEM
Runtime=0x2:FACILITY_RUNTIME
Stubs=0x3:FACILITY_STUBS
Io=0x4:FACILITY_IO_ERROR_CODE
)
; // The neutral locale.
LanguageNames=(Neutral=0x000:MSG00000)
; // This locale will be used for any RU-based locale.
LanguageNames=(ru=0x019:MSG00019)
; // This locale will be used only for en-US locale, instead
; // of any EN-based locale.
LanguageNames=(en_US=0x409:MSG00409)
; // The following are message definitions.
MessageId=0x1
Severity=Success
Facility=System
SymbolicName=MSG_HELLO
Language=en_US
USA locale only (en-US).
.
Language=ru
Любая RU-основанная локаль (RU).
.
Language=Neutral
Neutral locale.
.
Далее разными способами программно пытаемся получить локализованный вариант нашего текста:
#include <Windows.h>
#include <tchar.h>
#include <iostream>
#include <exception>
#include «resources.h»
using namespace std;
/*
MSDN resources:
FormatMessage function:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351%28v=vs.85%29.aspx
Message Text Files:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd996906%28v=vs.85%29.aspx
Sample Message Text File:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd996907%28v=vs.85%29.aspx
Message Compiler (MC.exe):
https://msdn.microsoft.com/en-us/library/windows/desktop/aa385638%28v=vs.85%29.aspx
*/
// Our function uses the WinAPI mechanism for notifying of error
void PrintMessage(DWORD);
int wmain(int argc, LPTSTR argv[])
try {
// For right displaying of Cyrillic chars in the console window
setlocale(LC_ALL, «Russian»);
wcout << L»For neutral locale:» << endl;
DWORD nl = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
PrintMessage(nl);
TCHAR x[LOCALE_NAME_MAX_LENGTH];
DWORD du = GetUserDefaultLCID();
int n = GetUserDefaultLocaleName(x, LOCALE_NAME_MAX_LENGTH);
if (0 != n) {
wcout << L»For user default locale <» << x << L»>:» << endl;
PrintMessage(du);
}
DWORD ds = GetSystemDefaultLCID();
n = GetSystemDefaultLocaleName(x, LOCALE_NAME_MAX_LENGTH);
if (0 != n) {
wcout << L»For system default locale <» << x << L»>:» << endl;
PrintMessage(ds);
}
// Any RU-based locale (defined in the resources)
wcout << L»For RU locale:» << endl;
DWORD ru = MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL);
PrintMessage(ru);
// Specific locale (NOT defined in the resources)
// At this case will be used more common locale: RU
wcout << L»For ru-RU locale:» << endl;
DWORD ru_ru = MAKELANGID(LANG_RUSSIAN, SUBLANG_RUSSIAN_RUSSIA);
PrintMessage(ru_ru);
// Any EN-based locale (defined in the resources)
wcout << L»For EN locale:» << endl;
DWORD en = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL);
PrintMessage(en);
// Specific locale (defined in the resources)
wcout << L»For en-US locale:» << endl;
DWORD en_us = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
PrintMessage(en_us);
wcout << L»Press any char for exit…» << endl;
wchar_t c;
wcin >> c;
}
catch (…) {
wcerr << L»Unknown exception.» << endl;
return 1;
}
void PrintMessage(DWORD localeId) {
DWORD msgId = MSG_HELLO;
LPTSTR buffer = NULL;
HMODULE hModule = GetModuleHandle(NULL);
DWORD result = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
hModule, msgId, localeId, (LPTSTR)&buffer, 0, NULL);
if (0 == result) {
msgId = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, msgId, 0, (LPTSTR)&buffer, 0, NULL);
}
wcout << buffer << endl;
HeapFree(GetProcessHeap(), 0, buffer);
}
Результат работы кода выглядит следующим образом: