Получение COleDateTime::Format для возврата "stycznia" вместо "styczeń" для польского месяца "январь"

У меня есть этот метод, чтобы установить язык на польский:

void CMeetingScheduleAssistantApp::SetLocale()
{
    // https://www.microsoft.com/resources/msdn/goglobal/default.mspx#ISO2
    CString strLang[NUM_LANGUAGES] =
    {
        _T("plk")
        // Add more languages here
    };

    _tsetlocale(LC_ALL, strLang[m_eLanguage - LANGUAGE_ENGLISH]);
}

Я вырезал другие языки для краткости. Теперь, когда я форматирую COleDateTime Объект и отобразить месяц, скажем, январь, он показывает как:

styczeń

Но я хочу показать это как:

Stycznia

Существует ли настройка языка для настройки значений месяца, возвращаемых COleDateTime::Format метод или локаль?

В противном случае мне придется добавить что-то ручное, чтобы переопределить.

Месяцы, которые я хотел бы вернуть:

  1. Stycznia
  2. Lutego
  3. Marca
  4. kwietnia
  5. Maja
  6. czerwca
  7. Lipca
  8. Sierpnia
  9. Września
  10. października
  11. Listopada
  12. grudnia

Обновить

Согласно здесь говорится:

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

Теперь, вот как я на самом деле форматирую свои строки дат (поскольку я поддерживаю более 40 языков, это немного сложно. Итак, (для английского) я начну с этой строки формата:

%1 %2!d!-%3!d!
  1. %1 это месяц.
  2. %2!d! значение первого дня.
  3. %3!d! значение второго дня.

Если мое свидание нужно для пересечения через два месяца, у меня есть:

%1 %2!d!–%3 %4!d!
  1. %1 значение месяца
  2. %2!d! значение первого дня.
  3. %3 значение второго месяца.
  4. %3!d! значение второго дня.

Вышеуказанное используется так:

if (datThisMonday.GetMonth() == datEndOfWeek.GetMonth())
{
    strDate.FormatMessage(IDS_STR_TPL_OCLM_WEEK,
            datThisMonday.Format(_T("%B")), datThisMonday.GetDay(), datEndOfWeek.GetDay());
}
else
{
    strDate.FormatMessage(IDS_STR_TPL_OCLM_WEEK2,
            datThisMonday.Format(_T("%B")), datThisMonday.GetDay(),
            datEndOfWeek.Format(_T("%B")), datEndOfWeek.GetDay());
}

Для польского, мои соответствующие строки формата:

%2!d!-%3!d! %1
%2!d! %1–%4!d! %3

Итак, я вижу это, потому что я форматирую строку даты, используя FormatMessage и только используя COleDateTime::Format метод, чтобы разобрать только месяц, который потенциально является причиной проблемы.

Поскольку в строке даты у меня две даты, я не могу просто использовать один вызов API форматирования даты (поскольку моя строка даты представляет интервал недели).

Итак, я проверил:

strDate = datThisMonday.Format(_T("%d %B"));

И это не имело никакого значения. Поэтому я попробовал это вместо:

SYSTEMTIME sTime;
datThisMonday.GetAsSystemTime(sTime);
GetDateFormat(GetThreadLocale(), 
              DATE_LONGDATE, 
              &sTime, _T("d MMMM"), 
              strDate.GetBuffer(_MAX_PATH), _MAX_PATH);

Это не имело никакого значения. Он по-прежнему показывает дату так же, как и раньше. Даже если он отображал дату правильно, он не учитывает диапазон дат из двух объектов COleDateTime.

Смущенный.

Обновление 2:

Также попробовал:

TCHAR szDate[100] = _T("");
GetDateFormatEx(_T("pl"), NULL, &sTime, _T("ddd MMMM"), szDate, 100, NULL);
AfxMessageBox(szDate);

Просто не покажу свой вариант.

Обновление 3

Единственный способ показать правильную дату - вот так:

GetDateFormatEx(_T("pl"), DATE_LONGDATE, &sTime, NULL, szDate, 100, NULL);

Тогда месяц правильный. Теперь в статье, на которую я ссылался, говорится:

Windows возвращает обе формы в одной строке, разделенной нулевым значением.

Я даже не могу понять, как получить к этому доступ.

2 ответа

Решение

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

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

Поскольку я хочу отобразить диапазон дат, я начну с этого:

польский

Шаблон: %1-%2Дата 1: dДата 2: d MMMM

Затем я форматирую дату:

SYSTEMTIME sysTime;
ENSURE(rDate.GetAsSystemTime(sysTime));
GetDateFormatEx(_T("pl"),
    NULL,
    &sysTime, 
    strDateFormat, 
    strDate.GetBuffer(_MAX_PATH), _MAX_PATH, nullptr);

Это показывает это правильно. И если диапазон дат охватывает два месяца, у меня есть:

Шаблон: %1-%2Дата 1: d MMMMДата 2: d MMMM

Это работает хорошо.

Начиная с Windows 7, вы также можете использовать LOCALE_RETURN_GENITIVE_NAMESвернуть родительное название месяца. Запуск этого:

      const wchar_t localeName[] = L"pl-PL";
for (LCTYPE m = LOCALE_SMONTHNAME1; m <= LOCALE_SMONTHNAME12; ++m) {
  wchar_t buf[1024];
  GetLocaleInfoEx(localeName, m | LOCALE_RETURN_GENITIVE_NAMES, buf, sizeof(buf) / sizeof(*buf));
  std::cout << to_utf8(buf) << '\n';
}

Дает следующий результат:

      stycznia
lutego
marca
kwietnia
maja
czerwca
lipca
sierpnia
września
października
listopada
grudnia

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

Другие вопросы по тегам