21
21
#include < fstream>
22
22
#include < regex>
23
23
#include < sstream>
24
+ #include < unordered_map>
24
25
#include < windows.h>
25
- #include < map>
26
26
27
27
namespace {
28
-
29
- // Build a cache key from id + placeholders.
30
- static std::wstring makeKey (const std::wstring& id,
28
+ // --- Local helpers ----------------------------------------------------
29
+ std::wstring makeKey (const std::wstring& id,
31
30
const std::vector<std::wstring>& repl)
32
31
{
33
- // Use a rarely used unit separator as delimiter.
34
32
std::wstring key = id;
35
33
key.push_back (L' \x1F ' );
36
- for (const auto & r : repl) {
37
- key += r;
38
- key.push_back (L' \x1F ' );
39
- }
34
+ for (const auto & r : repl) { key += r; key.push_back (L' \x1F ' ); }
40
35
return key;
41
36
}
42
37
43
- // Global cache holder for getLPCW(); single instance per process.
44
- static std::unordered_map<std::wstring, std::wstring>& lpcwCache ()
38
+ std::unordered_map<std::wstring, std::wstring>& lpcwCache ()
45
39
{
46
40
static std::unordered_map<std::wstring, std::wstring> cache;
47
41
return cache;
48
42
}
49
-
50
43
}
51
44
52
- // -----------------------------------------------------------------
53
- // Singleton
54
- // -----------------------------------------------------------------
45
+ // --- Singleton ------------------------------------------------------------
55
46
LanguageManager& LanguageManager::instance ()
56
47
{
57
48
static LanguageManager mgr;
58
49
return mgr;
59
50
}
60
51
61
- // -----------------------------------------------------------------
62
- // Public loading helpers
63
- // -----------------------------------------------------------------
52
+ // --- Loading --------------------------------------------------------------
64
53
bool LanguageManager::load (const std::wstring& pluginDir,
65
54
const std::wstring& nativeLangXmlPath)
66
55
{
@@ -77,8 +66,7 @@ bool LanguageManager::load(const std::wstring& pluginDir,
77
66
bool LanguageManager::loadFromIni (const std::wstring& iniFile,
78
67
const std::wstring& languageCode)
79
68
{
80
- // 1) fallback = English
81
- _table = languageMap;
69
+ _table = languageMap; // fallback: English
82
70
83
71
if (!_cache.load (iniFile))
84
72
return false ;
@@ -88,7 +76,7 @@ bool LanguageManager::loadFromIni(const std::wstring& iniFile,
88
76
for (const auto & kv : it->second )
89
77
_table[kv.first ] = kv.second ;
90
78
91
- invalidateCaches (); // Clear derived caches after language change
79
+ invalidateCaches ();
92
80
return true ;
93
81
}
94
82
@@ -97,65 +85,61 @@ void LanguageManager::invalidateCaches()
97
85
lpcwCache ().clear ();
98
86
}
99
87
100
- // -----------------------------------------------------------------
101
- // String getters
102
- // -----------------------------------------------------------------
103
- // Replace <br/>, then $REPLACE_n (descending), then $REPLACE.
88
+ // --- Strings --------------------------------------------------------------
89
+ // <br/> -> CRLF, then $REPLACE_STRINGn (high->low), then $REPLACE_STRING.
104
90
std::wstring LanguageManager::get (const std::wstring& id,
105
91
const std::vector<std::wstring>& repl) const
106
92
{
107
93
auto it = _table.find (id);
108
94
if (it == _table.end ())
109
- return id; // developer-friendly fallback: show missing key
95
+ return id;
110
96
111
97
std::wstring result = it->second ;
112
98
const std::wstring base = L" $REPLACE_STRING" ;
113
99
114
- // 1) Replace <br/> with CRLF (all occurrences)
100
+ // <br/> -> CRLF
115
101
for (size_t p = result.find (L" <br/>" );
116
102
p != std::wstring::npos;
117
103
p = result.find (L" <br/>" , p))
118
104
{
119
105
result.replace (p, 5 , L" \r\n " );
120
- p += 2 ; // advance beyond inserted CRLF to avoid re-scan at same spot
106
+ p += 2 ;
121
107
}
122
108
123
- // 2) Numbered placeholders: $REPLACE_STRING1, $REPLACE_STRING2, ... (highest index first)
109
+ // $REPLACE_STRINGn
124
110
for (size_t i = repl.size (); i > 0 ; --i)
125
111
{
126
112
const std::wstring ph = base + std::to_wstring (i);
127
- const std::wstring& val = repl[i - 1 ];
113
+ const std::wstring& vv = repl[i - 1 ];
128
114
129
115
for (size_t p = result.find (ph);
130
116
p != std::wstring::npos;
131
117
p = result.find (ph, p))
132
118
{
133
- result.replace (p, ph.size (), val );
134
- p += val .size (); // skip over inserted text
119
+ result.replace (p, ph.size (), vv );
120
+ p += vv .size ();
135
121
}
136
122
}
137
123
138
- // 3) Plain $REPLACE_STRING -> repl[0] (empty if not provided)
124
+ // $REPLACE_STRING
139
125
{
140
- const std::wstring& val = repl.empty () ? std::wstring () : repl[0 ];
126
+ const std::wstring& vv = repl.empty () ? std::wstring () : repl[0 ];
141
127
142
128
for (size_t p = result.find (base);
143
129
p != std::wstring::npos;
144
130
p = result.find (base, p))
145
131
{
146
- result.replace (p, base.size (), val );
147
- p += val .size (); // skip over inserted text
132
+ result.replace (p, base.size (), vv );
133
+ p += vv .size ();
148
134
}
149
135
}
150
136
151
137
return result;
152
138
}
153
139
154
-
155
140
LPCWSTR LanguageManager::getLPCW (const std::wstring& id,
156
141
const std::vector<std::wstring>& repl) const
157
142
{
158
- // Cache per (id + repl) to avoid wrong reuse for different placeholders.
159
143
auto & cache = lpcwCache ();
160
144
const std::wstring key = makeKey (id, repl);
161
145
@@ -166,24 +150,20 @@ LPCWSTR LanguageManager::getLPCW(const std::wstring& id,
166
150
return it->second .c_str ();
167
151
}
168
152
169
-
170
153
LPWSTR LanguageManager::getLPW (const std::wstring& id,
171
154
const std::vector<std::wstring>& repl) const
172
155
{
173
- // Use a thread-local buffer to avoid data races and overwrite issues.
174
156
thread_local std::wstring buf;
175
157
buf = get (id, repl);
176
- return buf.empty () ? nullptr : & buf[ 0 ] ;
158
+ return buf.empty () ? nullptr : buf. data () ;
177
159
}
178
160
179
-
180
- // -----------------------------------------------------------------
181
- // Detect active language from Notepad++ nativeLang.xml
182
- // -----------------------------------------------------------------
161
+ // --- nativeLang.xml detection --------------------------------------------
183
162
std::wstring LanguageManager::detectLanguage (const std::wstring& xmlPath)
184
163
{
185
164
std::wifstream file (xmlPath);
186
- if (!file.is_open ()) return L" english" ;
165
+ if (!file.is_open ())
166
+ return L" english" ;
187
167
188
168
std::wregex rx (L" <Native-Langue .*? filename=\" (.*?)\\ .xml\" " );
189
169
std::wsmatch m;
@@ -196,8 +176,7 @@ std::wstring LanguageManager::detectLanguage(const std::wstring& xmlPath)
196
176
break ;
197
177
}
198
178
}
199
- catch (...) {
200
- // keep fallback
201
- }
179
+ catch (...) { /* keep fallback */ }
180
+
202
181
return lang;
203
182
}
0 commit comments