master
cpp 120 lines 2.91 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 Localization.cpp
8
9 Abstract:
10
11 This file contains the class to format localized strings.
12
13 --*/
14
15 #include "precomp.h"
16 #include "Localization.h"
17
18 extern bool g_runningInService;
19
20 namespace {
21
22 std::vector<std::wstring> GetUserLanguagesImpl()
23 {
24 DWORD count{};
25 DWORD bufferSize{};
26 GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &count, nullptr, &bufferSize);
27
28 std::vector<wchar_t> buffer(bufferSize, '\0');
29 if (!GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &count, buffer.data(), &bufferSize))
30 {
31 LOG_LAST_ERROR_MSG("GetUserDefaultLocaleName failed");
32 return {L""};
33 }
34
35 std::vector<std::wstring> languages;
36 for (size_t i = 0; buffer[i] != '\0'; i += wcslen(&buffer[i]) + 1)
37 {
38 languages.emplace_back(&buffer[i]);
39 }
40
41 return languages;
42 }
43
44 std::vector<std::wstring> GetUserLanguages(bool impersonate)
45 {
46 if (g_runningInService)
47 {
48 // N.B. If we're in the service, the locale needs to be queried every time since different users
49 // can have different language configurations.
50 std::optional<wil::unique_coreverttoself_call> revert;
51 if (impersonate)
52 {
53 // If we're running in wslservice.exe, impersonation is needed to get the correct locale
54 try
55 {
56 revert = wil::CoImpersonateClient();
57 }
58 catch (...)
59 {
60 // Continue if this failed so we fall back to the machine's locale
61 LOG_CAUGHT_EXCEPTION();
62 }
63 }
64
65 return GetUserLanguagesImpl();
66 }
67 else
68 {
69 static std::vector<std::wstring> languages;
70 static std::once_flag flag;
71 std::call_once(flag, [&]() { languages = GetUserLanguagesImpl(); });
72
73 return languages;
74 }
75 }
76 } // namespace
77
78 LPCWSTR wsl::shared::Localization::LookupString(const std::vector<std::pair<std::wstring, LPCWSTR>>& strings, Options options)
79 {
80 WI_ASSERT(!strings.empty());
81
82 try
83 {
84 for (const auto& language : GetUserLanguages(options != Options::DontImpersonate && g_runningInService))
85 {
86 for (const auto& e : strings)
87 {
88 if (e.first == language)
89 {
90 return e.second;
91 }
92 }
93 }
94 }
95 catch (...)
96 {
97 LOG_CAUGHT_EXCEPTION();
98 }
99
100 // Default to English is string is not found (English is always the first entry)
101 return strings[0].second;
102 }
103
104 bool wsl::shared::Localization::IsCurrentLanguageEnglish(Options options)
105 {
106 try
107 {
108 const auto languages = GetUserLanguages(options != Options::DontImpersonate && g_runningInService);
109 if (!languages.empty())
110 {
111 return languages[0] == L"en" || languages[0].starts_with(L"en-");
112 }
113 }
114 catch (...)
115 {
116 LOG_CAUGHT_EXCEPTION();
117 }
118
119 return true;
120 }