В дополнение к предыдущей заметке...
Нейтральная локаль, как и все остальные, определяется в ресурсах EXE или DLL и имеет код 0x000. Я думаю, что зачастую имеет смысл определять более обобщённые варианты ресурсов, дабы не дублировать их для каждой конкретной локали, например:
В качестве примера в файле resources.txt определим текстовые ресурсы с таким набором локализаций:
; // ***** 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);
}
Результат работы кода выглядит следующим образом:
Нейтральная локаль, как и все остальные, определяется в ресурсах EXE или DLL и имеет код 0x000. Я думаю, что зачастую имеет смысл определять более обобщённые варианты ресурсов, дабы не дублировать их для каждой конкретной локали, например:
- ru вместо ru-RU
- 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);
}
Результат работы кода выглядит следующим образом:
Комментариев нет:
Отправить комментарий