Beta utf 8 windows 10

Время на прочтение
2 мин

Количество просмотров 28K

Квалификацию надо иногда повышать, и вообще учиться для мозгов полезно. А потому пошел я недавно на курсы — поизучать Python и всякие его фреймворки. На днях вот до Django добрался. И тут мы в ходе обучения коллективно выловили не то чтобы баг, но дивный эффект на стыке Python 3, Sqlite 3, JSON и Win 10. Причем эффект был настолько дивен, что гугль нам не помог — пришлось собираться всей заинтересованной группой вместе с преподавателем и коллективным разумом его решать.

А дело вот в чем: изучали мы базу данных (а у Django предустановлена Sqlite 3) и, чтоб каждый раз заново руками данные не вбивать, прикрутили загрузку скриптом из json-файлов. А в файлы данные из базы штатно дампили питоновскими же методами:

python manage.py dumpdata -e contenttypes -o db.json

Внезапно те, кто работал под виндой (за все версии не поручусь, у нас подобрались только обитатели Win 10), обнаружили, что дамп у них производится в кодировке windows-1251. Более того, джейсоны в этой кодировке отлично скармливаются базе. Но стоило только переформатировать их в штатную по документам для Sqlite 3, Python 3 и особенно для JSON кодировку UTF-8, как в лучшем случае кириллица в базе превращалась в тыкву, а в худшем ломался вообще весь процесс загрузки данных.

Ничего подобного найти не удалось ни в документации, ни во всем остальном гугле, считая и англоязычный. Что самое загадочное, ручная загрузка тех же самых данных через консоль или админку проекта работала как часы, хотя уж там-то кодировка была точно UTF-8. Более того, принудительное прописывание кодировки базе никакого эффекта не дало.

Мы предположили, что причиной эффекта было взаимодействие джейсона с операционной системой — каким-то образом при записи и чтении именно джейсонов система навязывала свою родную кодировку вместо нормальной. И действительно, когда при открытии файла принудительно устанавливалась кодировка UTF-8:

open(os.path.join(JSON_PATH, file_name + '.json'), 'r', encoding="utf-8")

в базу попадали не кракозябры, а нормальные русские буквы. Но проблему с созданием дампа таким способом не решишь, а переделывать кодировку потом руками тоже как-то не по-нашему.

И тогда мы решили поискать способ укротить винду.

И такой способ нашелся. Вот он:

  • открываем панель управления, но не новую красивую, а старую добрую:

  • открываем (по стрелке) окошко региона:

  • по стрелкам переключаем вкладку «Дополнительно» и открываем окошко «Изменить язык системы»:

  • и в нем ставим галку по стрелке в чекбоксе «Бета-версия: Использовать Юникод (UTF-8) для поддержки языка во всем мире.

Система потребует перезагрузки, после чего проблема будет решена.

Не могу сказать, чтобы этот мелкий странный баг был так уж важен или интересен (питоновские проекты обычно живут под линуксами, где такого не бывает), но мозги он нам поломал изрядно — вследствие чего я и решил написать эту заметку. Мало ли кто еще из новичков как раз во время учебы попадется.

In some Windows 10 builds (insiders starting April 2018 and also «normal» 1903) there is a new option called «Beta: Use Unicode UTF-8 for worldwide language support».

You can see this option by going to Settings and then:
All Settings -> Time & Language -> Language -> «Administrative Language Settings»

This is what it looks like:

enter image description here

When this checkbox is checked I observe some irregularities (below) and I would like to know what exactly this checkbox does and why the below happens.

Create a brand new Windows Forms application in your Visual Studio 2019. On the main form specify the Paint even handler as follows:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    Font buttonFont = new Font("Webdings", 9.25f);
    TextRenderer.DrawText(e.Graphics, "0r", buttonFont, new Point(), Color.Black);
}

Run the program, here is what you will see if the checkbox is NOT checked:

enter image description here

However, if you check the checkbox (and reboot as asked) this changes to:

enter image description here

You can look up Webdings font on Wikipedia. According to character table given, the codes for these two characters are "\U0001F5D5\U0001F5D9". If I use them instead of "0r" it works with the checkbox checked but without the checkbox checked it now looks like this:

enter image description here

I would like to find a solution that always works that is regardless whether the box checked or unchecked.

Can this be done?

Solution 1:[1]

You can see it in ProcMon.
It seems to set the REG_SZ values ACP, MACCP, and OEMCP in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage
to 65001.

I’m not entirely sure but it might be related to the variable gAnsiCodePage in KernelBase.dll, which GetACP reads. If you really want to, you might be able to change it dynamically for your program regardless of the system setting by dynamically disassembling GetACP to find the instruction sequence that reads gAnsiCodePage and obtaining a pointer to it, then updating the variable directly.

(Actually, I see references to an undocumented function named SetCPGlobal that would’ve done the job, but I can’t find that function on my system. Not sure if it still exists.)

Solution 2:[2]

Most Windows C APIs come in two different variants:

  • «A» variant that uses 8-bit strings with whatever the systems configured encoding is. This varies depending on the configured country/language.
    (Microsoft calls the configured encoding the «ANSI Code Page», but it’s not really anything to do with ANSI).
  • «W» variant that uses 16-bit strings in a fixed almost-UTF-16 encoding. (The «almost» is because «unpaired surrogates» are allowed; if you don’t know what those are then don’t worry about them).

The official Microsoft advice is not to use the «A» versions, but to ensure your code always use uses the «W» variants. That way you’re supposed to get consistent behaviour no matter what the user’s country/language is configured as.

However, it looks like that checkbox is doing more than one thing. It’s clear it’s supposed to change the «ANSI Code Page» to 65001, which means UTF-8. It looks like it’s also changing font rendering to be more Unicody.

I suggest you detect if GetACP() == 65001, then draw the Unicode version of your strings, otherwise draw the old «0r» version. I’m not sure how you do that from .NET…

Solution 3:[3]

Please look at this question to see what it solves when it is enabled: How to save to file non-ascii output of program in Powershell?

Also I found explanation written by Ghisler helpful (source):

If you check this option, Windows will use codepage 65001 (Unicode
UTF-8) instead of the local codepage like 1252 (Western Latin1) for
all plain text files. The advantage is that text files created in e.g.
Russian locale can also be read in other locale like Western or
Central Europe. The downside is that ANSI-Only programs (most older
programs) will show garbage instead of accented characters.


I leave here two ways to enable it, I think they will be helpful for many users:

  1. Win+R -> intl.cpl
  2. Administrative tab
  3. Click the Change system locale button.
  4. Enable Beta: Use Unicode UTF-8 for worldwide language support
  5. Reboot

or alternatively via reg file:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage]
"ACP"="65001"
"OEMCP"="65001"
"MACCP"="65001"

Solution 4:[4]

On my windows, When I checked the Beta: Use Unicode UTF-8 for worldwide language support.
The following regedit values in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage changed.

ACP: 936 -> 65001
MACCP: 10008 -> 65001
OEMCP : 936 -> 65001

If I do not checked, then the visual studio compilation failed with Exception: Bad UTF-8 encoding (U+FFFD; REPLACEMENT CHARACTER) found while decoding string: ..., If I checked, then the compilation successed, but the os is full with unreadable code.

В некоторых сборках Windows 10 (инсайдеры, начиная с апреля 2018 года, а также в «обычном» 1903 году) есть новая опция под названием «Бета: использование Unicode UTF-8 для всемирной языковой поддержки».

Вы можете увидеть эту опцию, перейдя в Настройки, а затем: Все настройки -> Время и язык -> Язык -> «Настройки административного языка»

Вот как это выглядит:

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

Создайте новое приложение Windows Froms в Visual Studio 2019. В главной форме укажите Paint даже обработчик следующим образом:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    Font buttonFont = new Font("Webdings", 9.25f);
    TextRenderer.DrawText(e.Graphics, "0r", buttonFont, new Point(), Color.Black);
}

Запустите программу, вот что вы увидите, если флажок НЕ установлен:

Однако, если вы установите флажок (и перезагрузите компьютер в соответствии с запросом), это изменится на:

Вы можете посмотреть шрифт Webdings в Википедии. Согласно приведенной таблице символов коды для этих двух символов "\U0001F5D5\U0001F5D9", Если я использую их вместо "0r" он работает с установленным флажком, но без установленного флажка теперь выглядит так:

Я хотел бы найти решение, которое всегда работает и не подвержено никаким изменениям, независимо от того, установлен флажок или нет.

Можно ли это сделать?

2019-06-03 02:11

4
ответа

Вы можете увидеть это в ProcMon. Кажется, чтобы установить REG_SZ ценности ACP, MACCP, а также OEMCP в HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage в 65001,

Я не совсем уверен, но это может быть связано с переменной gAnsiCodePage в KernelBase.dll, который GetACP читает. Если вы действительно хотите, вы можете изменить его динамически для вашей программы независимо от настроек системы путем динамической разборки GetACP найти последовательность команд, которая читает gAnsiCodePage и получить указатель на него, затем обновить переменную напрямую.

(На самом деле, я вижу ссылки на недокументированную функцию с именемSetCPGlobal это сделало бы эту работу, но я не могу найти эту функцию в моей системе. Не уверен, что он все еще существует.)

2019-08-03 23:27

Большинство API-интерфейсов Windows C представлены в двух вариантах:

  • Вариант «A», использующий 8-битные строки с любой кодировкой, сконфигурированной системой. Это зависит от настроенной страны / языка.
    (Microsoft называет настроенную кодировку «Кодовой страницей ANSI», но на самом деле это не имеет ничего общего с ANSI).
  • Вариант «W», использующий 16-битные строки в фиксированной кодировке почти UTF-16. («Почти» означает, что «непарные суррогаты» разрешены; если вы не знаете, что это такое, не беспокойтесь о них).

Официальный совет Microsoft — не использовать версии «A», но чтобы ваш код всегда использовал варианты «W». Таким образом, вы должны добиться согласованного поведения независимо от страны / языка пользователя.

Однако похоже, что этот флажок выполняет несколько функций. Понятно, что предполагается изменить «Кодовую страницу ANSI» на 65001, что означает UTF-8. Похоже, он также меняет рендеринг шрифтов, чтобы он стал более Unicody.

Я предлагаю вам определить, если GetACP() == 65001, затем нарисовать версию Unicode ваших строк, в противном случае нарисуйте старую версию «0r». Я не уверен, как это сделать из.NET…


user37386

08 апр ’20 в 21:29
2020-04-08 21:29

2020-04-08 21:29

Посмотрите на этот вопрос, чтобы узнать, что он решает, когда он включен: Как сохранить в Powershell вывод программы в формате, отличном от ascii?

Также я нашел полезным объяснение, написанное Гислером (источник):

Если вы отметите этот параметр, Windows будет использовать кодовую страницу 65001 (UnicodeUTF-8) вместо локальной кодовой страницы, такой как 1252 (Western Latin1), для всех текстовых файлов. Преимущество состоит в том, что текстовые файлы, созданные, например, в русской локали, также могут быть прочитаны в другой локали, например, в Западной или Центральной Европе. Обратной стороной является то, что программы только для ANSI (большинство старых программ) будут отображать мусор вместо символов с диакритическими знаками.


Я оставляю здесь два способа включить его, я думаю, они будут полезны многим пользователям:

  1. Win+R ->
    intl.cpl
  2. Administrative вкладка
  3. Щелкните значок
    Change system locale кнопка.
  4. Давать возможность
    Beta: Use Unicode UTF-8 for worldwide language support

или, альтернативно, через
reg файл:

      Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage]
"ACP"="65001"
"OEMCP"="65001"
"MACCP"="65001"

2021-06-21 13:08

На моих окнах, когда я проверил
Beta: Use Unicode UTF-8 for worldwide language support. Следующие значения regedit в
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePageизмененный.

      ACP: 936 -> 65001
MACCP: 10008 -> 65001
OEMCP : 936 -> 65001

Если я не проверил, то компиляция визуальной студии не удалась с
Exception: Bad UTF-8 encoding (U+FFFD; REPLACEMENT CHARACTER) found while decoding string: ..., если я проверял, то компиляция прошла успешно, но ос заполнена нечитаемым кодом.

2022-06-01 01:54

We know there is an application called AppLocale, which can change the code page of non-Unicode applications, to solve text display problems.

But there is a program whose right display code page is UTF-8, which means its text should be shown as UTF-8, but instead Windows displays it as the native code page and makes the text unreadable. It seems funny, because there are almost all countries and regions, but without UTF-8. I think it is a bug, because the programmers may use English and ignore testing non-English text display issues. I don’t think the producer will fix it and I wanna fix it myself.

Is it possible to set non-Unicode output as UTF-8 by using software like AppLocale? Default non-Unicode output is native code page? How can I set the native code page to UTF-8?

phuclv's user avatar

phuclv

26.7k15 gold badges115 silver badges235 bronze badges

asked Jan 29, 2016 at 15:23

Komeiji Kuroko's user avatar

1

Previously it was not possible because

Microsoft claimed a UTF-8 locale might break some functions (a possible example is _mbsrev) as they were written to assume multibyte encodings used no more than 2 bytes per character, thus until now code pages with more bytes such as GB 18030 (cp54936) and UTF-8 could not be set as the locale.

https://en.wikipedia.org/wiki/Unicode_in_Microsoft_Windows#UTF-8

However there’s a «Beta: Use Unicode UTF-8 for worldwide language support» checkbox since Windows 10 insider build 17035 for setting the locale code page to UTF-8

Beta: Use Unicode UTF-8 for worldwide language support

See also

  • Changing ansi and OEM code page in Windows
  • Windows 10 Insider Preview Build 17035 Supports UTF-8 as ANSI

That said, the support is still buggy at this point

  • Freeze issue in Windows 10 1803 when use UTF-8 as default code page
  • when unicode beta support in windows 10 is turned on, add-ons fail to install
  • UTF-8 support for single byte character sets is beta in Windows and likely breaks a lot of applications not expecting this
  • Build fail with internal error in MSVC

Update:

Microsoft has also added the ability for programs to use the UTF-8 locale without even setting the UTF-8 beta flag above. You can use the /execution-charset:utf-8 or /utf-8 options when compiling with MSVC or set the ActiveCodePage property in appxmanifest

You can also use UTF-8 locale in older Windows versions by linking with the appropriate C runtime

Starting in Windows 10 build 17134 (April 2018 Update), the Universal C Runtime supports using a UTF-8 code page. This means that char strings passed to C runtime functions will expect strings in the UTF-8 encoding. To enable UTF-8 mode, use «UTF-8» as the code page when using setlocale. For example, setlocale(LC_ALL, ".utf8") will use the current default Windows ANSI code page (ACP) for the locale and UTF-8 for the code page.

To use this feature on an OS prior to Windows 10, such as Windows 7, you must use app-local deployment or link statically using version 17134 of the Windows SDK or later. For Windows 10 operating systems prior to 17134, only static linking is supported.

UTF-8 Support

answered Jun 22, 2019 at 10:42

phuclv's user avatar

phuclvphuclv

26.7k15 gold badges115 silver badges235 bronze badges

From what I read about Microsoft AppLocale tool on Wikipedia, the tool can NOT change your code page to UTF-8. It only works with Non-Unicode applications, but UTF-8 is part of Unicode standard.

Under the hood, Unicode processing of non-ASCII characters greatly differs from non-Unicode one, so while it is possible to change between non-Unicode code pages (this is what AppLocale does) it is NOT possible to change between Unicode and non-Unicode without modification of the application made by its producer.

answered Jan 29, 2016 at 15:40

miroxlav's user avatar

miroxlavmiroxlav

13k6 gold badges65 silver badges103 bronze badges

2

Just to mention it here:
In Windows 10 17133 there is now a beta option to use UTF-8 for worldwide support. But it does not help with non-Unicode programs for me as of now, but it is placed on the pop-up where I can change the locale for non-Unicode programs.

So, maybe they are working on something to end the necessity of having to change the locale for non-Unicode programs.

hippietrail's user avatar

hippietrail

4,50515 gold badges53 silver badges86 bronze badges

answered Apr 11, 2018 at 13:54

anthropos's user avatar

3

You must log in to answer this question.

Not the answer you’re looking for? Browse other questions tagged

.

  • Best windows player for windows 8
  • Best music players for windows
  • Best windows emulator for android
  • Best music player for windows 10
  • Best windows apps windows 10