返回提交历史
Modified
package.json
+2
-1
Added
scripts/update-translations.js
+46
-0
Modified
src/routes/webui.ts
+5
-0
Modified
static/webui/index.html
+91
-111
Modified
static/webui/script.js
+81
-64
Modified
static/webui/style.css
+1
-3
Added
static/webui/translations/en.js
+111
-0
Added
static/webui/translations/ru.js
+112
-0
XFEstudio/XFESpaceNinjaServer
feat(webui): translations (#909)
Closes #900 Supersedes #903 Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/909
78032f19
代码差异
8 个文件
+449
-179
@@ -9,7 +9,8 @@
9
9
"build": "tsc && copyfiles static/webui/** build",
10
10
"lint": "eslint --ext .ts .",
11
11
"lint:fix": "eslint --fix --ext .ts .",
12
"prettier": "prettier --write ."
12
"prettier": "prettier --write .",
13
"update-translations": "cd scripts && node update-translations.js"
13
14
},
14
15
"license": "GNU",
15
16
"dependencies": {
@@ -0,0 +1,46 @@
1
// Based on http://209.141.38.3/OpenWF/Translations/src/branch/main/update.php
2
// Converted via ChatGPT-4o
3
4
const fs = require('fs');
5
6
function extractStrings(content) {
7
const regex = /([a-zA-Z_]+): `([^`]*)`,/g;
8
let matches;
9
const strings = {};
10
while ((matches = regex.exec(content)) !== null) {
11
strings[matches[1]] = matches[2];
12
}
13
return strings;
14
}
15
16
const source = fs.readFileSync("../static/webui/translations/en.js", "utf8");
17
const sourceStrings = extractStrings(source);
18
const sourceLines = source.split("\n");
19
20
fs.readdirSync("../static/webui/translations").forEach(file => {
21
if (fs.lstatSync(`../static/webui/translations/${file}`).isFile() && file !== "en.js") {
22
const content = fs.readFileSync(`../static/webui/translations/${file}`, "utf8");
23
const targetStrings = extractStrings(content);
24
const contentLines = content.split("\n");
25
26
const fileHandle = fs.openSync(`../static/webui/translations/${file}`, "w");
27
fs.writeSync(fileHandle, contentLines[0] + "\n");
28
29
sourceLines.forEach(line => {
30
const strings = extractStrings(line);
31
if (Object.keys(strings).length > 0) {
32
Object.entries(strings).forEach(([key, value]) => {
33
if (targetStrings.hasOwnProperty(key)) {
34
fs.writeSync(fileHandle, `\t${key}: \`${targetStrings[key]}\`,\n`);
35
} else {
36
fs.writeSync(fileHandle, `\t${key}: \`[UNTRANSLATED] ${value}\`,\n`);
37
}
38
});
39
} else {
40
fs.writeSync(fileHandle, line + "\n");
41
}
42
});
43
44
fs.closeSync(fileHandle);
45
}
46
});
@@ -54,4 +54,9 @@ webuiRouter.get("/webui/riven-tool/RivenParser.js", (_req, res) => {
54
54
res.sendFile(path.join(repoDir, "node_modules/warframe-riven-info/RivenParser.js"));
55
55
});
56
56
57
// Serve translations
58
webuiRouter.get("/translations/:file", (req, res) => {
59
res.sendFile(path.join(rootDir, `static/webui/translations/${req.params.file}`));
60
});
61
57
62
export { webuiRouter };
@@ -34,13 +34,13 @@
34
34
<li><a class="dropdown-item" href="#" data-lang="th" onclick="event.preventDefault();setLanguage('th');">แบบไทย</a></li>
35
35
</ul>
36
36
</li>
37
<li class="nav-item dropdown">
37
<li class="nav-item dropdown user-dropdown">
38
38
<button class="nav-link dropdown-toggle displayname" data-bs-toggle="dropdown" aria-expanded="false"></button>
39
39
<ul class="dropdown-menu dropdown-menu-end">
40
<li><a class="dropdown-item" href="/webui/" onclick="logout();">Logout</a></li>
40
<li><a class="dropdown-item" href="/webui/" onclick="logout();" data-loc="navbar_logout"></a></li>
41
41
<li><hr class="dropdown-divider"></li>
42
<li><a class="dropdown-item" href="#" onclick="event.preventDefault();renameAccount();">Rename Account</a></li>
43
<li><a class="dropdown-item" href="#" onclick="event.preventDefault();deleteAccount();">Delete Account</a></li>
42
<li><a class="dropdown-item" href="#" onclick="event.preventDefault();renameAccount();" data-loc="navbar_renameAccount"></a></li>
43
<li><a class="dropdown-item" href="#" onclick="event.preventDefault();deleteAccount();" data-loc="navbar_deleteAccount"></a></li>
44
44
</ul>
45
45
</li>
46
46
</ul>
@@ -56,16 +56,16 @@
56
56
<div class="navbar p-0">
57
57
<ul class="navbar-nav justify-content-end">
58
58
<li class="nav-item">
59
<a class="nav-link" href="/webui/inventory" data-bs-dismiss="offcanvas" data-bs-target="#sidebar">Inventory</a>
59
<a class="nav-link" href="/webui/inventory" data-bs-dismiss="offcanvas" data-bs-target="#sidebar" data-loc="navbar_inventory"></a>
60
60
</li>
61
61
<li class="nav-item">
62
<a class="nav-link" href="/webui/mods" data-bs-dismiss="offcanvas" data-bs-target="#sidebar">Mods</a>
62
<a class="nav-link" href="/webui/mods" data-bs-dismiss="offcanvas" data-bs-target="#sidebar" data-loc="navbar_mods"></a>
63
63
</li>
64
64
<li class="nav-item">
65
<a class="nav-link" href="/webui/cheats" data-bs-dismiss="offcanvas" data-bs-target="#sidebar">Cheats</a>
65
<a class="nav-link" href="/webui/cheats" data-bs-dismiss="offcanvas" data-bs-target="#sidebar" data-loc="navbar_cheats"></a>
66
66
</li>
67
67
<li class="nav-item">
68
<a class="nav-link" href="/webui/import" data-bs-dismiss="offcanvas" data-bs-target="#sidebar">Import</a>
68
<a class="nav-link" href="/webui/import" data-bs-dismiss="offcanvas" data-bs-target="#sidebar" data-loc="navbar_import"></a>
69
69
</li>
70
70
</ul>
71
71
</div>
@@ -73,38 +73,35 @@
73
73
</div>
74
74
<div class="w-100">
75
75
<div data-route="/webui/" data-title="Login | OpenWF WebUI">
76
<p>Login using your OpenWF account credentials (same as in-game when connecting to this server).</p>
76
<p data-loc="login_description"></p>
77
77
<form onsubmit="doLogin();return false;">
78
<label for="email">Email address</label>
78
<label for="email" data-loc="login_emailLabel"></label>
79
79
<input class="form-control" type="email" id="email" required />
80
80
<br />
81
<label for="password">Password</label>
81
<label for="password" data-loc="login_passwordLabel"></label>
82
82
<input class="form-control" type="password" id="password" required />
83
83
<br />
84
<button class="btn btn-primary" type="submit">Login</button>
84
<button class="btn btn-primary" type="submit" data-loc="login_loginButton"></button>
85
85
</form>
86
86
</div>
87
87
<div data-route="/webui/inventory" data-title="Inventory | OpenWF WebUI">
88
<p class="mb-3">
89
Note: Changes made here will only be reflected in-game when the game re-downloads your
90
inventory. Visiting the navigation should be the easiest way to trigger that.
91
</p>
88
<p class="mb-3" data-loc="general_inventoryUpdateNote"></p>
92
89
<div class="card mb-3">
93
<h5 class="card-header">Add Items</h5>
90
<h5 class="card-header" data-loc="inventory_addItems"></h5>
94
91
<form class="card-body input-group" onsubmit="doAcquireMiscItems();return false;">
95
92
<input class="form-control" id="miscitem-count" type="number" min="1" value="1" />
96
93
<input class="form-control w-50" id="miscitem-type" list="datalist-miscitems" />
97
<button class="btn btn-primary" type="submit">Add</button>
94
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
98
95
</form>
99
96
</div>
100
97
<div class="row g-3">
101
98
<div class="col-lg-6">
102
99
<div class="card mb-3" style="height: 400px;">
103
<h5 class="card-header">Warframes</h5>
100
<h5 class="card-header" data-loc="inventory_suits"></h5>
104
101
<div class="card-body overflow-auto">
105
102
<form class="input-group mb-3" onsubmit="doAcquireEquipment('Suits');return false;">
106
103
<input class="form-control" id="acquire-type-Suits" list="datalist-Suits" />
107
<button class="btn btn-primary" type="submit">Add</button>
104
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
108
105
</form>
109
106
<table class="table table-hover w-100">
110
107
<tbody id="Suits-list"></tbody>
@@ -114,11 +111,11 @@
114
111
</div>
115
112
<div class="col-lg-6">
116
113
<div class="card mb-3" style="height: 400px;">
117
<h5 class="card-header">Primary Weapons</h5>
114
<h5 class="card-header" data-loc="inventory_longGuns"></h5>
118
115
<div class="card-body overflow-auto">
119
116
<form class="input-group mb-3" onsubmit="doAcquireEquipment('LongGuns');return false;">
120
117
<input class="form-control" id="acquire-type-LongGuns" list="datalist-LongGuns" />
121
<button class="btn btn-primary" type="submit">Add</button>
118
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
122
119
</form>
123
120
<table class="table table-hover w-100">
124
121
<tbody id="LongGuns-list"></tbody>
@@ -130,11 +127,11 @@
130
127
<div class="row g-3">
131
128
<div class="col-lg-6">
132
129
<div class="card mb-3" style="height: 400px;">
133
<h5 class="card-header">Secondary Weapons</h5>
130
<h5 class="card-header" data-loc="inventory_pistols"></h5>
134
131
<div class="card-body overflow-auto">
135
132
<form class="input-group mb-3" onsubmit="doAcquireEquipment('Pistols');return false;">
136
133
<input class="form-control" id="acquire-type-Pistols" list="datalist-Pistols" />
137
<button class="btn btn-primary" type="submit">Add</button>
134
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
138
135
</form>
139
136
<table class="table table-hover w-100">
140
137
<tbody id="Pistols-list"></tbody>
@@ -144,11 +141,11 @@
144
141
</div>
145
142
<div class="col-lg-6">
146
143
<div class="card mb-3" style="height: 400px;">
147
<h5 class="card-header">Melee Weapons</h5>
144
<h5 class="card-header" data-loc="inventory_melee"></h5>
148
145
<div class="card-body overflow-auto">
149
146
<form class="input-group mb-3" onsubmit="doAcquireEquipment('Melee');return false;">
150
147
<input class="form-control" id="acquire-type-Melee" list="datalist-Melee" />
151
<button class="btn btn-primary" type="submit">Add</button>
148
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
152
149
</form>
153
150
<table class="table table-hover w-100">
154
151
<tbody id="Melee-list"></tbody>
@@ -160,11 +157,11 @@
160
157
<div class="row g-3">
161
158
<div class="col-lg-6">
162
159
<div class="card mb-3" style="height: 400px;">
163
<h5 class="card-header">Archwing</h5>
160
<h5 class="card-header" data-loc="inventory_spaceSuits"></h5>
164
161
<div class="card-body overflow-auto">
165
162
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceSuits');return false;">
166
163
<input class="form-control" id="acquire-type-SpaceSuits" list="datalist-SpaceSuits" />
167
<button class="btn btn-primary" type="submit">Add</button>
164
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
168
165
</form>
169
166
<table class="table table-hover w-100">
170
167
<tbody id="SpaceSuits-list"></tbody>
@@ -174,11 +171,11 @@
174
171
</div>
175
172
<div class="col-lg-6">
176
173
<div class="card mb-3" style="height: 400px;">
177
<h5 class="card-header">Archwing Primary Weapons</h5>
174
<h5 class="card-header" data-loc="inventory_spaceGuns"></h5>
178
175
<div class="card-body overflow-auto">
179
176
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceGuns');return false;">
180
177
<input class="form-control" id="acquire-type-SpaceGuns" list="datalist-SpaceGuns" />
181
<button class="btn btn-primary" type="submit">Add</button>
178
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
182
179
</form>
183
180
<table class="table table-hover w-100">
184
181
<tbody id="SpaceGuns-list"></tbody>
@@ -190,11 +187,11 @@
190
187
<div class="row g-3">
191
188
<div class="col-lg-6">
192
189
<div class="card mb-3" style="height: 400px;">
193
<h5 class="card-header">Archwing Melee Weapons</h5>
190
<h5 class="card-header" data-loc="inventory_spaceMelee"></h5>
194
191
<div class="card-body overflow-auto">
195
192
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceMelee');return false;">
196
193
<input class="form-control" id="acquire-type-SpaceMelee" list="datalist-SpaceMelee" />
197
<button class="btn btn-primary" type="submit">Add</button>
194
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
198
195
</form>
199
196
<table class="table table-hover w-100">
200
197
<tbody id="SpaceMelee-list"></tbody>
@@ -204,11 +201,11 @@
204
201
</div>
205
202
<div class="col-lg-6">
206
203
<div class="card mb-3" style="height: 400px;">
207
<h5 class="card-header">Necramechs</h5>
204
<h5 class="card-header" data-loc="inventory_mechSuits"></h5>
208
205
<div class="card-body overflow-auto">
209
206
<form class="input-group mb-3" onsubmit="doAcquireEquipment('MechSuits');return false;">
210
207
<input class="form-control" id="acquire-type-MechSuits" list="datalist-MechSuits" />
211
<button class="btn btn-primary" type="submit">Add</button>
208
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
212
209
</form>
213
210
<table class="table table-hover w-100">
214
211
<tbody id="MechSuits-list"></tbody>
@@ -220,11 +217,11 @@
220
217
<div class="row g-3">
221
218
<div class="col-lg-6">
222
219
<div class="card mb-3" style="height: 400px;">
223
<h5 class="card-header">Sentinels</h5>
220
<h5 class="card-header" data-loc="inventory_sentinels"></h5>
224
221
<div class="card-body overflow-auto">
225
222
<form class="input-group mb-3" onsubmit="doAcquireEquipment('Sentinels');return false;">
226
223
<input class="form-control" id="acquire-type-Sentinels" list="datalist-Sentinels" />
227
<button class="btn btn-primary" type="submit">Add</button>
224
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
228
225
</form>
229
226
<table class="table table-hover w-100">
230
227
<tbody id="Sentinels-list"></tbody>
@@ -234,11 +231,11 @@
234
231
</div>
235
232
<div class="col-lg-6">
236
233
<div class="card mb-3" style="height: 400px;">
237
<h5 class="card-header">Sentinel Weapons</h5>
234
<h5 class="card-header" data-loc="inventory_sentinelWeapons"></h5>
238
235
<div class="card-body overflow-auto">
239
236
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SentinelWeapons');return false;">
240
237
<input class="form-control" id="acquire-type-SentinelWeapons" list="datalist-SentinelWeapons" />
241
<button class="btn btn-primary" type="submit">Add</button>
238
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
242
239
</form>
243
240
<table class="table table-hover w-100">
244
241
<tbody id="SentinelWeapons-list"></tbody>
@@ -250,7 +247,7 @@
250
247
<div class="row g-3">
251
248
<div class="col-lg-6">
252
249
<div class="card mb-3" style="height: 400px;">
253
<h5 class="card-header">Amps</h5>
250
<h5 class="card-header" data-loc="inventory_operatorAmps"></h5>
254
251
<div class="card-body overflow-auto">
255
252
<table class="table table-hover w-100">
256
253
<tbody id="OperatorAmps-list"></tbody>
@@ -260,7 +257,7 @@
260
257
</div>
261
258
<div class="col-lg-6">
262
259
<div class="card mb-3" style="height: 400px;">
263
<h5 class="card-header">K-Drives</h5>
260
<h5 class="card-header" data-loc="inventory_hoverboards"></h5>
264
261
<div class="card-body overflow-auto">
265
262
<table class="table table-hover w-100">
266
263
<tbody id="Hoverboards-list"></tbody>
@@ -270,23 +267,23 @@
270
267
</div>
271
268
</div>
272
269
<div class="card mb-3">
273
<h5 class="card-header">Bulk Actions</h5>
270
<h5 class="card-header" data-loc="general_bulkActions"></h5>
274
271
<div class="card-body">
275
272
<div class="mb-2 d-flex flex-wrap gap-2">
276
<button class="btn btn-primary" onclick="addMissingEquipment(['Suits']);">Add Missing Warframes</button>
277
<button class="btn btn-primary" onclick="addMissingEquipment(['Melee', 'LongGuns', 'Pistols']);">Add Missing Weapons</button>
278
<button class="btn btn-primary" onclick="addMissingEquipment(['SpaceSuits']);">Add Missing Archwings</button>
279
<button class="btn btn-primary" onclick="addMissingEquipment(['SpaceGuns', 'SpaceMelee']);">Add Missing Archwing Weapons</button>
280
<button class="btn btn-primary" onclick="addMissingEquipment(['Sentinels']);">Add Missing Sentinels</button>
281
<button class="btn btn-primary" onclick="addMissingEquipment(['SentinelWeapons']);">Add Missing Sentinel Weapons</button>
273
<button class="btn btn-primary" onclick="addMissingEquipment(['Suits']);" data-loc="inventory_bulkAddSuits"></button>
274
<button class="btn btn-primary" onclick="addMissingEquipment(['Melee', 'LongGuns', 'Pistols']);" data-loc="inventory_bulkAddWeapons"></button>
275
<button class="btn btn-primary" onclick="addMissingEquipment(['SpaceSuits']);" data-loc="inventory_bulkAddSpaceSuits"></button>
276
<button class="btn btn-primary" onclick="addMissingEquipment(['SpaceGuns', 'SpaceMelee']);" data-loc="inventory_bulkAddSpaceWeapons"></button>
277
<button class="btn btn-primary" onclick="addMissingEquipment(['Sentinels']);" data-loc="inventory_bulkAddSentinels"></button>
278
<button class="btn btn-primary" onclick="addMissingEquipment(['SentinelWeapons']);" data-loc="inventory_bulkAddSentinelWeapons"></button>
282
279
</div>
283
280
<div class="mb-2 d-flex flex-wrap gap-2">
284
<button class="btn btn-success" onclick="maxRankAllEquipment(['Suits']);">Max Rank All Warframes</button>
285
<button class="btn btn-success" onclick="maxRankAllEquipment(['Melee', 'LongGuns', 'Pistols']);">Max Rank All Weapons</button>
286
<button class="btn btn-success" onclick="maxRankAllEquipment(['SpaceSuits']);">Max Rank All Archwings</button>
287
<button class="btn btn-success" onclick="maxRankAllEquipment(['SpaceGuns', 'SpaceMelee']);">Max Rank All Archwing Weapons</button>
288
<button class="btn btn-success" onclick="maxRankAllEquipment(['Sentinels']);">Max Rank All Sentinels</button>
289
<button class="btn btn-success" onclick="maxRankAllEquipment(['SentinelWeapons']);">Max Rank All Sentinel Weapons</button>
281
<button class="btn btn-success" onclick="maxRankAllEquipment(['Suits']);" data-loc="inventory_bulkRankUpSuits"></button>
282
<button class="btn btn-success" onclick="maxRankAllEquipment(['Melee', 'LongGuns', 'Pistols']);" data-loc="inventory_bulkRankUpWeapons"></button>
283
<button class="btn btn-success" onclick="maxRankAllEquipment(['SpaceSuits']);" data-loc="inventory_bulkRankUpSpaceSuits"></button>
284
<button class="btn btn-success" onclick="maxRankAllEquipment(['SpaceGuns', 'SpaceMelee']);" data-loc="inventory_bulkRankUpSpaceWeapons"></button>
285
<button class="btn btn-success" onclick="maxRankAllEquipment(['Sentinels']);" data-loc="inventory_bulkRankUpSentinels"></button>
286
<button class="btn btn-success" onclick="maxRankAllEquipment(['SentinelWeapons']);" data-loc="inventory_bulkRankUpSentinelWeapons"></button>
290
287
</div>
291
288
</div>
292
289
</div>
@@ -295,14 +292,14 @@
295
292
<h3 class="mb-0"></h3>
296
293
<p class="text-body-secondary"></p>
297
294
<div class="card mb-3">
298
<h5 class="card-header">Archon Shard Slots</h5>
295
<h5 class="card-header" data-loc="powersuit_archonShardsLabel"></h5>
299
296
<div class="card-body">
300
<p>You can use these unlimited slots to apply a wide range of upgrades.</p>
297
<p data-loc="powersuit_archonShardsDescription"></p>
301
298
<form class="input-group mb-3" onsubmit="doPushArchonCrystalUpgrade();return false;">
302
299
<input type="number" id="archon-crystal-add-count" min="1" max="10000" value="1" class="form-control" style="max-width:100px" />
303
300
<span class="input-group-text">x</span>
304
301
<input class="form-control" list="datalist-archonCrystalUpgrades" />
305
<button class="btn btn-primary" type="submit">Add</button>
302
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
306
303
</form>
307
304
<table class="table table-hover w-100">
308
305
<tbody id="crystals-list"></tbody>
@@ -311,14 +308,11 @@
311
308
</div>
312
309
</div>
313
310
<div data-route="/webui/mods" data-title="Mods | OpenWF WebUI">
314
<p class="mb-3">
315
Note: Changes made here will only be reflected in-game when the game re-downloads your
316
inventory. Visiting the navigation should be the easiest way to trigger that.
317
</p>
311
<p class="mb-3" data-loc="general_inventoryUpdateNote"></p>
318
312
<div class="row g-3">
319
313
<div class="col-xxl-6">
320
314
<div class="card mb-3">
321
<h5 class="card-header">Add Riven</h5>
315
<h5 class="card-header" data-loc="mods_addRiven"></h5>
322
316
<form class="card-body" onsubmit="doAcquireRiven();return false;">
323
317
<select class="form-control mb-3" id="addriven-type">
324
318
<option value="LotusArchgunRandomModRare">LotusArchgunRandomModRare</option>
@@ -329,13 +323,13 @@
329
323
<option value="LotusShotgunRandomModRare">LotusShotgunRandomModRare</option>
330
324
<option value="PlayerMeleeWeaponRandomModRare">PlayerMeleeWeaponRandomModRare</option>
331
325
</select>
332
<textarea id="addriven-fingerprint" class="form-control mb-3" placeholder="Fingerprint"></textarea>
333
<button class="btn btn-primary" style="margin-right: 5px" type="submit">Add</button>
334
<a href="riven-tool/" target="_blank">Need help with the fingerprint?</a>
326
<textarea id="addriven-fingerprint" class="form-control mb-3" data-loc-placeholder_"mods.fingerprint"></textarea>
327
<button class="btn btn-primary" style="margin-right: 5px" type="submit" data-loc="general_addButton"></button>
328
<a href="riven-tool/" target="_blank" data-loc="mods_fingerprintHelp"></a>
335
329
</form>
336
330
</div>
337
331
<div class="card mb-3">
338
<h5 class="card-header">Rivens</h5>
332
<h5 class="card-header" data-loc="mods_rivens"></h5>
339
333
<div class="card-body">
340
334
<table class="table table-hover w-100">
341
335
<tbody id="riven-list"></tbody>
@@ -345,12 +339,12 @@
345
339
</div>
346
340
<div class="col-xxl-6">
347
341
<div class="card mb-3">
348
<h5 class="card-header">Mods</h5>
342
<h5 class="card-header" data-loc="mods_mods"></h5>
349
343
<div class="card-body">
350
344
<form class="input-group mb-3" onsubmit="doAcquireMod();return false;">
351
345
<input class="form-control" id="mod-count" type="number" min="1" value="1"/>
352
346
<input class="form-control w-50" id="mod-to-acquire" list="datalist-mods" />
353
<button class="btn btn-primary" type="submit">Add</button>
347
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
354
348
</form>
355
349
<table class="table table-hover w-100">
356
350
<tbody id="mods-list"></tbody>
@@ -358,9 +352,9 @@
358
352
</div>
359
353
</div>
360
354
<div class="card mb-3">
361
<h5 class="card-header">Bulk Actions</h5>
355
<h5 class="card-header" data-loc="general_bulkActions"></h5>
362
356
<div class="card-body">
363
<button class="btn btn-primary" onclick="doAddAllMods();">Add Missing Mods</button>
357
<button class="btn btn-primary" onclick="doAddAllMods();" data-loc="mods_bulkAddMods"></button>
364
358
</div>
365
359
</div>
366
360
</div>
@@ -373,127 +367,113 @@
373
367
<h5 class="card-header">Server</h5>
374
368
<div class="card-body">
375
369
<div id="server-settings-no-perms" class="d-none">
376
<p class="card-text">You must be an administrator to use this feature. To become an administrator, add <code>"<span class="displayname"></span>"</code> to <code>administratorNames</code> in the config.json.</p>
370
<p class="card-text" data-loc="cheats_administratorRequirement"></p>
377
371
</div>
378
372
<form id="server-settings" class="d-none" onsubmit="doChangeSettings();return false;">
379
373
<div class="form-check">
380
374
<input class="form-check-input" type="checkbox" id="skipTutorial" />
381
<label class="form-check-label" for="skipTutorial">Skip Tutorial</label>
375
<label class="form-check-label" for="skipTutorial" data-loc="cheats_skipTutorial"></label>
382
376
</div>
383
377
<div class="form-check">
384
378
<input class="form-check-input" type="checkbox" id="skipAllDialogue" />
385
<label class="form-check-label" for="skipAllDialogue">Skip All Dialogue</label>
379
<label class="form-check-label" for="skipAllDialogue" data-loc="cheats_skipAllDialogue"></label>
386
380
</div>
387
381
<div class="form-check">
388
382
<input class="form-check-input" type="checkbox" id="unlockAllScans" />
389
<label class="form-check-label" for="unlockAllScans">Unlock All Scans</label>
383
<label class="form-check-label" for="unlockAllScans" data-loc="cheats_unlockAllScans"></label>
390
384
</div>
391
385
<div class="form-check">
392
386
<input class="form-check-input" type="checkbox" id="unlockAllMissions" />
393
<label class="form-check-label" for="unlockAllMissions">Unlock All Missions</label>
387
<label class="form-check-label" for="unlockAllMissions" data-loc="cheats_unlockAllMissions"></label>
394
388
</div>
395
389
<div class="form-check">
396
390
<input class="form-check-input" type="checkbox" id="unlockAllQuests" />
397
<label class="form-check-label" for="unlockAllQuests">Unlock All Quests</label>
391
<label class="form-check-label" for="unlockAllQuests" data-loc="cheats_unlockAllQuests"></label>
398
392
</div>
399
393
<div class="form-check">
400
394
<input class="form-check-input" type="checkbox" id="completeAllQuests" />
401
<label class="form-check-label" for="completeAllQuests">Complete All Quests</label>
395
<label class="form-check-label" for="completeAllQuests" data-loc="cheats_completeAllQuests"></label>
402
396
</div>
403
397
<div class="form-check">
404
398
<input class="form-check-input" type="checkbox" id="infiniteCredits" />
405
<label class="form-check-label" for="infiniteCredits">Infinite Credits</label>
399
<label class="form-check-label" for="infiniteCredits" data-loc="cheats_infiniteCredits"></label>
406
400
</div>
407
401
<div class="form-check">
408
402
<input class="form-check-input" type="checkbox" id="infinitePlatinum" />
409
<label class="form-check-label" for="infinitePlatinum">Infinite Platinum</label>
403
<label class="form-check-label" for="infinitePlatinum" data-loc="cheats_infinitePlatinum"></label>
410
404
</div>
411
405
<div class="form-check">
412
406
<input class="form-check-input" type="checkbox" id="infiniteEndo" />
413
<label class="form-check-label" for="infiniteEndo">Infinite Endo</label>
407
<label class="form-check-label" for="infiniteEndo" data-loc="cheats_infiniteEndo"></label>
414
408
</div>
415
409
<div class="form-check">
416
410
<input class="form-check-input" type="checkbox" id="infiniteRegalAya" />
417
<label class="form-check-label" for="infiniteRegalAya">Infinite Regal Aya</label>
411
<label class="form-check-label" for="infiniteRegalAya" data-loc="cheats_infiniteRegalAya"></label>
418
412
</div>
419
413
<div class="form-check">
420
414
<input class="form-check-input" type="checkbox" id="unlockAllShipFeatures" />
421
<label class="form-check-label" for="unlockAllShipFeatures">Unlock All Ship Features</label>
415
<label class="form-check-label" for="unlockAllShipFeatures" data-loc="cheats_unlockAllShipFeatures"></label>
422
416
</div>
423
417
<div class="form-check">
424
418
<input class="form-check-input" type="checkbox" id="unlockAllShipDecorations" />
425
<label class="form-check-label" for="unlockAllShipDecorations">Unlock All Ship Decorations</label>
419
<label class="form-check-label" for="unlockAllShipDecorations" data-loc="cheats_unlockAllShipDecorations"></label>
426
420
</div>
427
421
<div class="form-check">
428
422
<input class="form-check-input" type="checkbox" id="unlockAllFlavourItems" />
429
<label class="form-check-label" for="unlockAllFlavourItems">
430
Unlock All <abbr title="Animation Sets, Glyphs, Plattes, etc.">Flavor Items</abbr>
431
</label>
423
<label class="form-check-label" for="unlockAllFlavourItems" data-loc="cheats_unlockAllFlavourItems"></label>
432
424
</div>
433
425
<div class="form-check">
434
426
<input class="form-check-input" type="checkbox" id="unlockAllSkins" />
435
<label class="form-check-label" for="unlockAllSkins">Unlock All Skins</label>
427
<label class="form-check-label" for="unlockAllSkins" data-loc="cheats_unlockAllSkins"></label>
436
428
</div>
437
429
<div class="form-check">
438
430
<input class="form-check-input" type="checkbox" id="unlockAllCapturaScenes" />
439
<label class="form-check-label" for="unlockAllCapturaScenes">Unlock All Captura Scenes</label>
431
<label class="form-check-label" for="unlockAllCapturaScenes" data-loc="cheats_unlockAllCapturaScenes"></label>
440
432
</div>
441
433
<div class="form-check">
442
434
<input class="form-check-input" type="checkbox" id="universalPolarityEverywhere" />
443
<label class="form-check-label" for="universalPolarityEverywhere">
444
Universal Polarity Everywhere
445
</label>
435
<label class="form-check-label" for="universalPolarityEverywhere" data-loc="cheats_universalPolarityEverywhere"></label>
446
436
</div>
447
437
<div class="form-check">
448
438
<input class="form-check-input" type="checkbox" id="unlockDoubleCapacityPotatoesEverywhere" />
449
<label class="form-check-label" for="unlockDoubleCapacityPotatoesEverywhere">
450
Potatoes Everywhere
451
</label>
439
<label class="form-check-label" for="unlockDoubleCapacityPotatoesEverywhere" data-loc="cheats_unlockDoubleCapacityPotatoesEverywhere"></label>
452
440
</div>
453
441
<div class="form-check">
454
442
<input class="form-check-input" type="checkbox" id="unlockExilusEverywhere" />
455
<label class="form-check-label" for="unlockExilusEverywhere">
456
Exilus Adapters Everywhere
457
</label>
443
<label class="form-check-label" for="unlockExilusEverywhere" data-loc="cheats_unlockExilusEverywhere"></label>
458
444
</div>
459
445
<div class="form-check">
460
446
<input class="form-check-input" type="checkbox" id="unlockArcanesEverywhere" />
461
<label class="form-check-label" for="unlockArcanesEverywhere">
462
Arcane Adapters Everywhere
463
</label>
447
<label class="form-check-label" for="unlockArcanesEverywhere" data-loc="cheats_unlockArcanesEverywhere"></label>
464
448
</div>
465
449
<div class="form-check">
466
450
<input class="form-check-input" type="checkbox" id="noDailyStandingLimits" />
467
<label class="form-check-label" for="noDailyStandingLimits">
468
No Daily Standing Limits
469
</label>
451
<label class="form-check-label" for="noDailyStandingLimits" data-loc="cheats_noDailyStandingLimits"></label>
470
452
</div>
471
453
<div class="form-group mt-2">
472
<label class="form-label" for="spoofMasteryRank">
473
Spoofed Mastery Rank (-1 to disable)
474
</label>
454
<label class="form-label" for="spoofMasteryRank" data-loc="cheats_spoofMasteryRank"></label>
475
455
<input class="form-control" id="spoofMasteryRank" type="number" min="-1" max="65535" />
476
456
</div>
477
<button class="btn btn-primary mt-3" type="submit">Save Settings</button>
457
<button class="btn btn-primary mt-3" type="submit" data-loc="cheats_saveSettings"></button>
478
458
</form>
479
459
</div>
480
460
</div>
481
461
</div>
482
462
<div class="col-md-6">
483
463
<div class="card mb-3">
484
<h5 class="card-header">Account</h5>
464
<h5 class="card-header" data-loc="cheats_account"></h5>
485
465
<div class="card-body">
486
<p><button class="btn btn-primary" onclick="doUnlockAllFocusSchools();">Unlock All Focus Schools</button></p>
487
<button class="btn btn-primary" onclick="doHelminthUnlockAll();">Fully Level Up Helminth</button>
466
<p><button class="btn btn-primary" onclick="doUnlockAllFocusSchools();" data-loc="cheats_unlockAllFocusSchools"></button></p>
467
<button class="btn btn-primary" onclick="doHelminthUnlockAll();" data-loc="cheats_helminthUnlockAll"></button>
488
468
</div>
489
469
</div>
490
470
</div>
491
471
</div>
492
472
</div>
493
473
<div data-route="/webui/import" data-title="Import | OpenWF WebUI">
494
<p>You can provide a full or partial inventory response (client respresentation) here. All fields that are supported by the importer <b>will be overwritten</b> in your account.</p>
474
<p data-loc="import_importNote"></p>
495
475
<textarea class="form-control" id="import-inventory"></textarea>
496
<button class="btn btn-primary mt-3" onclick="doImport();">Submit</button>
476
<button class="btn btn-primary mt-3" onclick="doImport();" data-loc="import_submit"></button>
497
477
</div>
498
478
</div>
499
479
</div>
@@ -14,6 +14,9 @@ function loginFromLocalStorage() {
14
14
$(".displayname").text(data.DisplayName);
15
15
window.accountId = data.id;
16
16
window.authz = "accountId=" + data.id + "&nonce=" + data.Nonce;
17
if (window.dict) {
18
updateLocElements();
19
}
17
20
updateInventory();
18
21
},
19
22
() => {
@@ -50,7 +53,7 @@ function revalidateAuthz(succ_cb) {
50
53
},
51
54
() => {
52
55
logout();
53
alert("Your credentials are no longer valid.");
56
alert(loc("code_nonValidAuthz"));
54
57
single.loadRoute("/webui/"); // Show login screen
55
58
}
56
59
);
@@ -62,24 +65,17 @@ function logout() {
62
65
}
63
66
64
67
function renameAccount() {
65
const newname = window.prompt("What would you like to change your account name to?");
68
const newname = window.prompt(loc("code_changeNameConfirm"));
66
69
if (newname) {
67
70
fetch("/custom/renameAccount?" + window.authz + "&newname=" + newname).then(() => {
68
71
$(".displayname").text(newname);
72
updateLocElements();
69
73
});
70
74
}
71
75
}
72
76
73
77
function deleteAccount() {
74
if (
75
window.confirm(
76
"Are you sure you want to delete your account " +
77
document.querySelector(".displayname").textContent +
78
" (" +
79
localStorage.getItem("email") +
80
")? This action cannot be undone."
81
)
82
) {
78
if (window.confirm(loc("code_deleteAccountConfirm"))) {
83
79
fetch("/custom/deleteAccount?" + window.authz).then(() => {
84
80
logout();
85
81
single.loadRoute("/webui/"); // Show login screen
@@ -110,55 +106,80 @@ single.on("route_load", function (event) {
110
106
}
111
107
});
112
108
109
function loc(tag) {
110
return ((window.dict ?? {})[tag] ?? tag)
111
.split("|DISPLAYNAME|").join(document.querySelector(".displayname").textContent)
112
.split("|EMAIL|").join(localStorage.getItem("email"));
113
}
114
115
function updateLocElements() {
116
document.querySelectorAll("[data-loc]").forEach(elm => {
117
elm.innerHTML = loc(elm.getAttribute("data-loc"));
118
});
119
}
120
113
121
function setActiveLanguage(lang) {
114
122
window.lang = lang;
115
123
const lang_name = document.querySelector("[data-lang=" + lang + "]").textContent;
116
124
document.getElementById("active-lang-name").textContent = lang_name;
117
125
document.querySelector("[data-lang].active").classList.remove("active");
118
126
document.querySelector("[data-lang=" + lang + "]").classList.add("active");
127
128
window.dictPromise = new Promise(resolve => {
129
const webui_lang = ["en", "ru"].indexOf(lang) == -1 ? "en" : lang;
130
const script = document.createElement("script");
131
script.src = "/translations/" + webui_lang + ".js";
132
script.onload = function() {
133
updateLocElements();
134
resolve(window.dict);
135
};
136
document.documentElement.appendChild(script);
137
});
119
138
}
120
139
setActiveLanguage(localStorage.getItem("lang") ?? "en");
121
140
122
141
function setLanguage(lang) {
123
142
setActiveLanguage(lang);
124
143
localStorage.setItem("lang", lang);
125
fetchItemList();
126
updateInventory();
144
if (window.authz) { // Not in prelogin state?
145
fetchItemList();
146
updateInventory();
147
}
127
148
}
128
149
129
150
let uniqueLevelCaps = {};
130
151
function fetchItemList() {
131
152
window.itemListPromise = new Promise(resolve => {
132
153
const req = $.get("/custom/getItemLists?lang=" + window.lang);
133
req.done(data => {
154
req.done(async (data) => {
155
await dictPromise;
156
134
157
window.archonCrystalUpgrades = data.archonCrystalUpgrades;
135
158
136
159
const itemMap = {
137
160
// Generics for rivens
138
"/Lotus/Weapons/Tenno/Archwing/Primary/ArchGun": { name: "Archgun" },
139
"/Lotus/Weapons/Tenno/Melee/PlayerMeleeWeapon": { name: "Melee" },
140
"/Lotus/Weapons/Tenno/Pistol/LotusPistol": { name: "Pistol" },
141
"/Lotus/Weapons/Tenno/Rifle/LotusRifle": { name: "Rifle" },
142
"/Lotus/Weapons/Tenno/Shotgun/LotusShotgun": { name: "Shotgun" },
161
"/Lotus/Weapons/Tenno/Archwing/Primary/ArchGun": { name: loc("code_archgun") },
162
"/Lotus/Weapons/Tenno/Melee/PlayerMeleeWeapon": { name: loc("code_melee") },
163
"/Lotus/Weapons/Tenno/Pistol/LotusPistol": { name: loc("code_pistol") },
164
"/Lotus/Weapons/Tenno/Rifle/LotusRifle": { name: loc("code_rifle") },
165
"/Lotus/Weapons/Tenno/Shotgun/LotusShotgun": { name: loc("code_shotgun") },
143
166
// Modular weapons
144
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimary": { name: "Kitgun" },
145
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryBeam": { name: "Kitgun" },
146
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryLauncher": { name: "Kitgun" },
147
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryShotgun": { name: "Kitgun" },
148
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimarySniper": { name: "Kitgun" },
149
"/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondary": { name: "Kitgun" },
150
"/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryBeam": { name: "Kitgun" },
151
"/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryShotgun": { name: "Kitgun" },
152
"/Lotus/Weapons/Ostron/Melee/LotusModularWeapon": { name: "Zaw" },
153
"/Lotus/Weapons/Sentients/OperatorAmplifiers/SentTrainingAmplifier/OperatorTrainingAmpWeapon": {
154
name: "Mote Amp"
155
},
156
"/Lotus/Weapons/Sentients/OperatorAmplifiers/OperatorAmpWeapon": { name: "Amp" },
157
"/Lotus/Weapons/Operator/Pistols/DrifterPistol/DrifterPistolPlayerWeapon": { name: "Sirocco" },
158
"/Lotus/Types/Vehicles/Hoverboard/HoverboardSuit": { name: "K-Drive" },
167
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimary": { name: loc("code_kitgun") },
168
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryBeam": { name: loc("code_kitgun") },
169
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryLauncher": { name: loc("code_kitgun") },
170
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryShotgun": { name: loc("code_kitgun") },
171
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimarySniper": { name: loc("code_kitgun") },
172
"/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondary": { name: loc("code_kitgun") },
173
"/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryBeam": { name: loc("code_kitgun") },
174
"/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryShotgun": { name: loc("code_kitgun") },
175
"/Lotus/Weapons/Ostron/Melee/LotusModularWeapon": { name: loc("code_zaw") },
176
"/Lotus/Weapons/Sentients/OperatorAmplifiers/SentTrainingAmplifier/OperatorTrainingAmpWeapon": { name: loc("code_moteAmp") },
177
"/Lotus/Weapons/Sentients/OperatorAmplifiers/OperatorAmpWeapon": { name: loc("code_amp") },
178
"/Lotus/Weapons/Operator/Pistols/DrifterPistol/DrifterPistolPlayerWeapon": { name: loc("code_sirocco") },
179
"/Lotus/Types/Vehicles/Hoverboard/HoverboardSuit": { name: loc("code_kdrive") },
159
180
// Missing in data sources
160
"/Lotus/Upgrades/Mods/Fusers/LegendaryModFuser": { name: "Legendary Core" },
161
"/Lotus/Upgrades/CosmeticEnhancers/Peculiars/CyoteMod": { name: "Traumatic Peculiar" }
181
"/Lotus/Upgrades/Mods/Fusers/LegendaryModFuser": { name: loc("code_legendaryCore") },
182
"/Lotus/Upgrades/CosmeticEnhancers/Peculiars/CyoteMod": { name: loc("code_traumaticPeculiar") }
162
183
};
163
184
for (const [type, items] of Object.entries(data)) {
164
185
if (type == "archonCrystalUpgrades") {
@@ -173,7 +194,7 @@ function fetchItemList() {
173
194
} else if (type != "badItems") {
174
195
items.forEach(item => {
175
196
if (item.uniqueName in data.badItems) {
176
item.name += " (Imposter)";
197
item.name += " " + loc("code_badItem");
177
198
} else if (item.uniqueName.substr(0, 18) != "/Lotus/Types/Game/") {
178
199
const option = document.createElement("option");
179
200
option.setAttribute("data-key", item.uniqueName);
@@ -272,7 +293,7 @@ function updateInventory() {
272
293
}
273
294
}
274
295
};
275
a.title = "Max Rank";
296
a.title = loc("code_maxRank");
276
297
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M214.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-160 160c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 141.2V448c0 17.7 14.3 32 32 32s32-14.3 32-32V141.2L329.4 246.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z"/></svg>`;
277
298
td.appendChild(a);
278
299
}
@@ -287,12 +308,12 @@ function updateInventory() {
287
308
a.href = "#";
288
309
a.onclick = function (event) {
289
310
event.preventDefault();
290
const name = prompt("Enter new custom name:");
311
const name = prompt(loc("code_renamePrompt"));
291
312
if (name !== null) {
292
313
renameGear(category, item.ItemId.$oid, name);
293
314
}
294
315
};
295
a.title = "Rename";
316
a.title = loc("code_rename");
296
317
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M0 80V229.5c0 17 6.7 33.3 18.7 45.3l176 176c25 25 65.5 25 90.5 0L418.7 317.3c25-25 25-65.5 0-90.5l-176-176c-12-12-28.3-18.7-45.3-18.7H48C21.5 32 0 53.5 0 80zm112 32a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg>`;
297
318
td.appendChild(a);
298
319
}
@@ -303,7 +324,7 @@ function updateInventory() {
303
324
event.preventDefault();
304
325
disposeOfGear(category, item.ItemId.$oid);
305
326
};
306
a.title = "Remove";
327
a.title = loc("code_remove");
307
328
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M135.2 17.7L128 32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H320l-7.2-14.3C307.4 6.8 296.3 0 284.2 0H163.8c-12.1 0-23.2 6.8-28.6 17.7zM416 128H32L53.2 467c1.6 25.3 22.6 45 47.9 45H346.9c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>`;
308
329
td.appendChild(a);
309
330
}
@@ -327,11 +348,11 @@ function updateInventory() {
327
348
const td = document.createElement("td");
328
349
td.textContent = itemMap[fingerprint.compat]?.name ?? fingerprint.compat;
329
350
td.textContent += " " + RivenParser.parseRiven(rivenType, fingerprint, 1).name;
330
td.innerHTML += " <span title='Number of buffs'>▲ " + fingerprint.buffs.length + "</span>";
351
td.innerHTML += " <span title='" + loc("code_buffsNumber") + "'>▲ " + fingerprint.buffs.length + "</span>";
331
352
td.innerHTML +=
332
" <span title='Number of curses'>▼ " + fingerprint.curses.length + "</span>";
353
" <span title='" + loc("code_cursesNumber") + "'>▼ " + fingerprint.curses.length + "</span>";
333
354
td.innerHTML +=
334
" <span title='Number of rerolls'>⟳ " + parseInt(fingerprint.rerolls) + "</span>";
355
" <span title='" + loc("code_rerollsNumber") + "'>⟳ " + parseInt(fingerprint.rerolls) + "</span>";
335
356
tr.appendChild(td);
336
357
}
337
358
{
@@ -349,7 +370,7 @@ function updateInventory() {
349
370
})
350
371
);
351
372
a.target = "_blank";
352
a.title = "View Stats";
373
a.title = loc("code_viewStats");
353
374
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M160 80c0-26.5 21.5-48 48-48h32c26.5 0 48 21.5 48 48V432c0 26.5-21.5 48-48 48H208c-26.5 0-48-21.5-48-48V80zM0 272c0-26.5 21.5-48 48-48H80c26.5 0 48 21.5 48 48V432c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V272zM368 96h32c26.5 0 48 21.5 48 48V432c0 26.5-21.5 48-48 48H368c-26.5 0-48-21.5-48-48V144c0-26.5 21.5-48 48-48z"/></svg>`;
354
375
td.appendChild(a);
355
376
}
@@ -360,7 +381,7 @@ function updateInventory() {
360
381
event.preventDefault();
361
382
disposeOfGear("Upgrades", item.ItemId.$oid);
362
383
};
363
a.title = "Remove";
384
a.title = loc("code_remove");
364
385
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M135.2 17.7L128 32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H320l-7.2-14.3C307.4 6.8 296.3 0 284.2 0H163.8c-12.1 0-23.2 6.8-28.6 17.7zM416 128H32L53.2 467c1.6 25.3 22.6 45 47.9 45H346.9c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>`;
365
386
td.appendChild(a);
366
387
}
@@ -376,7 +397,7 @@ function updateInventory() {
376
397
{
377
398
const td = document.createElement("td");
378
399
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
379
td.innerHTML += " <span title='Rank'>★ " + rank + "/" + maxRank + "</span>";
400
td.innerHTML += " <span title='" + loc("code_rank") + "'>★ " + rank + "/" + maxRank + "</span>";
380
401
tr.appendChild(td);
381
402
}
382
403
{
@@ -389,7 +410,7 @@ function updateInventory() {
389
410
event.preventDefault();
390
411
setFingerprint(item.ItemType, item.ItemId, { lvl: maxRank });
391
412
};
392
a.title = "Max Rank";
413
a.title = loc("code_maxRank");
393
414
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M214.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-160 160c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 141.2V448c0 17.7 14.3 32 32 32s32-14.3 32-32V141.2L329.4 246.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z"/></svg>`;
394
415
td.appendChild(a);
395
416
}
@@ -400,7 +421,7 @@ function updateInventory() {
400
421
event.preventDefault();
401
422
disposeOfGear("Upgrades", item.ItemId.$oid);
402
423
};
403
a.title = "Remove";
424
a.title = loc("code_remove");
404
425
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M135.2 17.7L128 32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H320l-7.2-14.3C307.4 6.8 296.3 0 284.2 0H163.8c-12.1 0-23.2 6.8-28.6 17.7zM416 128H32L53.2 467c1.6 25.3 22.6 45 47.9 45H346.9c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>`;
405
426
td.appendChild(a);
406
427
}
@@ -415,7 +436,7 @@ function updateInventory() {
415
436
{
416
437
const td = document.createElement("td");
417
438
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
418
td.innerHTML += " <span title='Rank'>★ 0/" + maxRank + "</span>";
439
td.innerHTML += " <span title='" + loc("code_rank") + "'>★ 0/" + maxRank + "</span>";
419
440
if (item.ItemCount > 1) {
420
441
td.innerHTML += " <span title='Count'>🗍 " + parseInt(item.ItemCount) + "</span>";
421
442
}
@@ -431,7 +452,7 @@ function updateInventory() {
431
452
event.preventDefault();
432
453
setFingerprint(item.ItemType, item.LastAdded, { lvl: maxRank });
433
454
};
434
a.title = "Max Rank";
455
a.title = loc("code_maxRank");
435
456
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M214.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-160 160c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 141.2V448c0 17.7 14.3 32 32 32s32-14.3 32-32V141.2L329.4 246.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z"/></svg>`;
436
457
td.appendChild(a);
437
458
}
@@ -442,7 +463,7 @@ function updateInventory() {
442
463
event.preventDefault();
443
464
disposeOfItems("Upgrades", item.ItemType, item.ItemCount);
444
465
};
445
a.title = "Remove";
466
a.title = loc("code_remove");
446
467
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M135.2 17.7L128 32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H320l-7.2-14.3C307.4 6.8 296.3 0 284.2 0H163.8c-12.1 0-23.2 6.8-28.6 17.7zM416 128H32L53.2 467c1.6 25.3 22.6 45 47.9 45H346.9c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>`;
447
468
td.appendChild(a);
448
469
}
@@ -491,7 +512,7 @@ function updateInventory() {
491
512
event.preventDefault();
492
513
doPopArchonCrystalUpgrade(upgradeType);
493
514
};
494
a.title = "Remove";
515
a.title = loc("code_remove");
495
516
a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M135.2 17.7L128 32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H320l-7.2-14.3C307.4 6.8 296.3 0 284.2 0H163.8c-12.1 0-23.2 6.8-28.6 17.7zM416 128H32L53.2 467c1.6 25.3 22.6 45 47.9 45H346.9c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>`;
496
517
td.appendChild(a);
497
518
}
@@ -572,7 +593,7 @@ function addMissingEquipment(categories) {
572
593
});
573
594
if (
574
595
requests.length != 0 &&
575
window.confirm("Are you sure you want to add " + requests.length + " items to your account?")
596
window.confirm(loc("code_addItemsConfirm").split("|COUNT|").join(requests.length))
576
597
) {
577
598
dispatchAddItemsRequestsBatch(requests);
578
599
}
@@ -627,7 +648,7 @@ function maxRankAllEquipment(categories) {
627
648
return sendBatchGearExp(batchData);
628
649
}
629
650
630
alert("No equipment to rank up.");
651
alert(loc("code_noEquipmentToRankUp"));
631
652
});
632
653
});
633
654
}
@@ -743,7 +764,7 @@ function doAcquireMiscItems() {
743
764
}
744
765
])
745
766
}).done(function () {
746
alert("Successfully added.");
767
alert(loc("code_succAdded"));
747
768
});
748
769
});
749
770
}
@@ -938,13 +959,9 @@ function doUnlockAllFocusSchools() {
938
959
await unlockFocusSchool(upgradeType);
939
960
}
940
961
if (Object.keys(missingFocusUpgrades).length == 0) {
941
alert("All focus schools are already unlocked.");
962
alert(loc("code_focusAllUnlocked"));
942
963
} else {
943
alert(
944
"Unlocked " +
945
Object.keys(missingFocusUpgrades).length +
946
" new focus schools! An inventory update will be needed for the changes to be reflected in-game. Visiting the navigation should be the easiest way to trigger that."
947
);
964
alert(loc("code_focusUnlocked").split("|COUNT|").join(Object.keys(missingFocusUpgrades).length));
948
965
}
949
966
});
950
967
});
@@ -996,7 +1013,7 @@ function doAddAllMods() {
996
1013
modsAll = Array.from(modsAll);
997
1014
if (
998
1015
modsAll.length != 0 &&
999
window.confirm("Are you sure you want to add " + modsAll.length + " mods to your account?")
1016
window.confirm(loc("code_addModsConfirm").split("|COUNT|").join(modsAll.length))
1000
1017
) {
1001
1018
$.post({
1002
1019
url: "/custom/addItems?" + window.authz,
@@ -1071,7 +1088,7 @@ function doImport() {
1071
1088
inventory: JSON.parse($("#import-inventory").val())
1072
1089
})
1073
1090
}).then(function () {
1074
alert("Successfully imported.");
1091
alert(loc("code_succImport"));
1075
1092
updateInventory();
1076
1093
});
1077
1094
});
@@ -14,9 +14,7 @@
14
14
}
15
15
}
16
16
17
body:not(.logged-in) .navbar-toggler,
18
body:not(.logged-in) .nav-item.dropdown,
19
body:not(.logged-in) #refresh-note {
17
body:not(.logged-in) .user-dropdown {
20
18
display: none;
21
19
}
22
20
@@ -0,0 +1,111 @@
1
dict = {
2
general_inventoryUpdateNote: `Note: Changes made here will only be reflected in-game when the game re-downloads your inventory. Visiting the navigation should be the easiest way to trigger that.`,
3
general_addButton: `Add`,
4
general_bulkActions: `Bulk Actions`,
5
code_nonValidAuthz: `Your credentials are no longer valid.`,
6
code_changeNameConfirm: `What would you like to change your account name to?`,
7
code_deleteAccountConfirm: `Are you sure you want to delete your account |DISPLAYNAME| (|EMAIL|)? This action cannot be undone.`,
8
code_archgun: `Archgun`,
9
code_melee: `Melee`,
10
code_pistol: `Pistol`,
11
code_rifle: `Rifle`,
12
code_shotgun: `Shotgun`,
13
code_kitgun: `Kitgun`,
14
code_zaw: `Zaw`,
15
code_moteAmp: `Mote Amp`,
16
code_amp: `Amp`,
17
code_sirocco: `Sirocco`,
18
code_kDrive: `K-Drive`,
19
code_legendaryCore: `Legendary Core`,
20
code_traumaticPeculiar: `Traumatic Peculiar`,
21
code_badItem: `(Imposter)`,
22
code_maxRank: `Max Rank`,
23
code_rename: `Rename`,
24
code_renamePrompt: `Enter new custom name:`,
25
code_remove: `Remove`,
26
code_addItemsConfirm: `Are you sure you want to add |COUNT| items to your account?`,
27
code_noEquipmentToRankUp: `No equipment to rank up.`,
28
code_succAdded: `Successfully added.`,
29
code_buffsNumber: `Number of buffs`,
30
code_cursesNumber: `Number of curses`,
31
code_rerollsNumber: `Number of rerolls`,
32
code_viewStats: `View Stats`,
33
code_rank: `Rank`,
34
code_count: `Count`,
35
code_focusAllUnlocked: `All focus schools are already unlocked.`,
36
code_focusUnlocked: `Unlocked |COUNT| new focus schools! An inventory update will be needed for the changes to be reflected in-game. Visiting the navigation should be the easiest way to trigger that.`,
37
code_addModsConfirm: `Are you sure you want to add |COUNT| mods to your account?`,
38
code_succImport: `Successfully imported.`,
39
login_description: `Login using your OpenWF account credentials (same as in-game when connecting to this server).`,
40
login_emailLabel: `Email address`,
41
login_passwordLabel: `Password`,
42
login_loginButton: `Login`,
43
navbar_logout: `Logout`,
44
navbar_renameAccount: `Rename Account`,
45
navbar_deleteAccount: `Delete Account`,
46
navbar_inventory: `Inventory`,
47
navbar_mods: `Mods`,
48
navbar_cheats: `Cheats`,
49
navbar_import: `Import`,
50
inventory_addItems: `Add Items`,
51
inventory_suits: `Warframes`,
52
inventory_longGuns: `Primary Weapons`,
53
inventory_pistols: `Secondary Weapons`,
54
inventory_melee: `Melee Weapons`,
55
inventory_spaceSuits: `Archwings`,
56
inventory_spaceGuns: `Archwing Primary Weapons`,
57
inventory_spaceMelee: `Archwing Melee Weapons`,
58
inventory_mechSuits: `Necramechs`,
59
inventory_sentinels: `Sentinels`,
60
inventory_sentinelWeapons: `Sentinel Weapons`,
61
inventory_operatorAmps: `Amps`,
62
inventory_hoverboards: `K-Drives`,
63
inventory_bulkAddSuits: `Add Missing Warframes`,
64
inventory_bulkAddWeapons: `Add Missing Weapons`,
65
inventory_bulkAddSpaceSuits: `Add Missing Archwings`,
66
inventory_bulkAddSpaceWeapons: `Add Missing Archwing Weapons`,
67
inventory_bulkAddSentinels: `Add Missing Sentinels`,
68
inventory_bulkAddSentinelWeapons: `Add Missing Sentinel Weapons`,
69
inventory_bulkRankUpSuits: `Max Rank All Warframes`,
70
inventory_bulkRankUpWeapons: `Max Rank All Weapons`,
71
inventory_bulkRankUpSpaceSuits: `Max Rank All Archwings`,
72
inventory_bulkRankUpSpaceWeapons: `Max Rank All Archwing Weapons`,
73
inventory_bulkRankUpSentinels: `Max Rank All Sentinels`,
74
inventory_bulkRankUpSentinelWeapons: `Max Rank All Sentinel Weapons`,
75
powersuit_archonShardsLabel: `Archon Shard Slots`,
76
powersuit_archonShardsDescription: `You can use these unlimited slots to apply a wide range of upgrades`,
77
mods_addRiven: `Add Riven`,
78
mods_fingerprint: `Fingerprint`,
79
mods_fingerprintHelp: `Need help with the fingerprint?`,
80
mods_rivens: `Rivens`,
81
mods_mods: `Mods`,
82
mods_bulkAddMods: `Add Missing Mods`,
83
cheats_administratorRequirement: `You must be an administrator to use this feature. To become an administrator, add <code>|DISPLAYNAME|</code> to <code>administratorNames</code> in the config.json.`,
84
cheats_skipTutorial: `Skip Tutorial`,
85
cheats_skipAllDialogue: `Skip All Dialogue`,
86
cheats_unlockAllScans: `Unlock All Scans`,
87
cheats_unlockAllMissions: `Unlock All Missions`,
88
cheats_unlockAllQuests: `Unlock All Quests`,
89
cheats_completeAllQuests: `Complete All Quests`,
90
cheats_infiniteCredits: `Infinite Credits`,
91
cheats_infinitePlatinum: `Infinite Platinum`,
92
cheats_infiniteEndo: `Infinite Endo`,
93
cheats_infiniteRegalAya: `Infinite Regal Aya`,
94
cheats_unlockAllShipFeatures: `Unlock All Ship Features`,
95
cheats_unlockAllShipDecorations: `Unlock All Ship Decorations`,
96
cheats_unlockAllFlavourItems: `Unlock All <abbr title=\"Animation Sets, Glyphs, Plattes, etc.\">Flavor Items</abbr>`,
97
cheats_unlockAllSkins: `Unlock All Skins`,
98
cheats_unlockAllCapturaScenes: `Unlock All Captura Scenes`,
99
cheats_universalPolarityEverywhere: `Universal Polarity Everywhere`,
100
cheats_unlockDoubleCapacityPotatoesEverywhere: `Potatoes Everywhere`,
101
cheats_unlockExilusEverywhere: `Exilus Adapters Everywhere`,
102
cheats_unlockArcanesEverywhere: `Arcane Adapters Everywhere`,
103
cheats_noDailyStandingLimits: `No Daily Standing Limits`,
104
cheats_spoofMasteryRank: `Spoofed Mastery Rank (-1 to disable)`,
105
cheats_saveSettings: `Save Settings`,
106
cheats_account: `Account`,
107
cheats_unlockAllFocusSchools: `Unlock All Focus Schools`,
108
cheats_helminthUnlockAll: `Fully Level Up Helminth`,
109
import_importNote: `You can provide a full or partial inventory response (client respresentation) here. All fields that are supported by the importer <b>will be overwritten</b> in your account.`,
110
import_submit: `Submit`,
111
}
@@ -0,0 +1,112 @@
1
// Russian translation by AMelonInsideLemon
2
dict = {
3
general_inventoryUpdateNote: `Примечание: изменения, внесенные здесь, отобразятся в игре только после повторной загрузки вашего инвентаря. Посещение навигации — самый простой способ этого добиться.`,
4
general_addButton: `Добавить`,
5
general_bulkActions: `Массовые действия`,
6
code_nonValidAuthz: `Ваши данные больше не действительны.`,
7
code_changeNameConfirm: `Какое имя вы хотите установить для своей учетной записи?`,
8
code_deleteAccountConfirm: `Вы уверены, что хотите удалить аккаунт |DISPLAYNAME| (|EMAIL|)? Это действие нельзя отменить.`,
9
code_archgun: `Арч-Пушка`,
10
code_melee: `Ближний бой`,
11
code_pistol: `Пистолет`,
12
code_rifle: `Винтовка`,
13
code_shotgun: `Дробовик`,
14
code_kitgun: `Китган`,
15
code_zaw: `Зо`,
16
code_moteAmp: `Пылинка`,
17
code_amp: `Усилитель`,
18
code_sirocco: `Сирокко`,
19
code_kDrive: `К-Драйв`,
20
code_legendaryCore: `Легендарное ядро`,
21
code_traumaticPeculiar: `Травмирующая Странность`,
22
code_badItem: `(Самозванец)`,
23
code_maxRank: `Максимальный ранг`,
24
code_rename: `Переименовать`,
25
code_renamePrompt: `Введите новое имя:`,
26
code_remove: `Удалить`,
27
code_addItemsConfirm: `Вы уверены, что хотите добавить |COUNT| предметов на ваш аккаунт?`,
28
code_noEquipmentToRankUp: `Нет снаряжения для повышения ранга.`,
29
code_succAdded: `Успешно добавлено.`,
30
code_buffsNumber: `Количество усилений`,
31
code_cursesNumber: `Количество проклятий`,
32
code_rerollsNumber: `Количество циклов`,
33
code_viewStats: `Просмотр характеристики`,
34
code_rank: `Ранг`,
35
code_count: `Количество`,
36
code_focusAllUnlocked: `Все школы фокуса уже разблокированы.`,
37
code_focusUnlocked: `Разблокировано |COUNT| новых школ фокуса! Для отображения изменений в игре потребуется обновление инвентаря. Посещение навигации — самый простой способ этого добиться.`,
38
code_addModsConfirm: `Вы уверены, что хотите добавить |COUNT| модов на ваш аккаунт?`,
39
code_succImport: `Успешно импортировано.`,
40
login_description: `Войдите, используя учетные данные OpenWF (те же, что и в игре при подключении к этому серверу).`,
41
login_emailLabel: `Адрес электронной почты`,
42
login_passwordLabel: `Пароль`,
43
login_loginButton: `Войти`,
44
navbar_logout: `Выйти`,
45
navbar_renameAccount: `Переименовать аккаунт`,
46
navbar_deleteAccount: `Удалить аккаунт`,
47
navbar_inventory: `Инвентарь`,
48
navbar_mods: `Моды`,
49
navbar_cheats: `Читы`,
50
navbar_import: `Импорт`,
51
inventory_addItems: `Добавить предметы`,
52
inventory_suits: `Варфреймы`,
53
inventory_longGuns: `Основное оружие`,
54
inventory_pistols: `Вторичное оружие`,
55
inventory_melee: `Оружие ближнего боя`,
56
inventory_spaceSuits: `Арчвинги`,
57
inventory_spaceGuns: `Оружие арчвинга`,
58
inventory_spaceMelee: `Оружие ближнего боя арчвинга`,
59
inventory_mechSuits: `Некрамехи`,
60
inventory_sentinels: `Стражи`,
61
inventory_sentinelWeapons: `Оружие стражей`,
62
inventory_operatorAmps: `Усилители`,
63
inventory_hoverboards: `К-Драйвы`,
64
inventory_bulkAddSuits: `Добавить отсутствующие варфреймы`,
65
inventory_bulkAddWeapons: `Добавить отсутствующее оружие`,
66
inventory_bulkAddSpaceSuits: `Добавить отсутствующие арчвинги`,
67
inventory_bulkAddSpaceWeapons: `Добавить отсутствующее оружие арчвингов`,
68
inventory_bulkAddSentinels: `Добавить отсутствующих стражей`,
69
inventory_bulkAddSentinelWeapons: `Добавить отсутствующее оружие стражей`,
70
inventory_bulkRankUpSuits: `Максимальный ранг всех варфреймов`,
71
inventory_bulkRankUpWeapons: `Максимальный ранг всего оружия`,
72
inventory_bulkRankUpSpaceSuits: `Максимальный ранг всех арчвингов`,
73
inventory_bulkRankUpSpaceWeapons: `Максимальный ранг всего оружия арчвингов`,
74
inventory_bulkRankUpSentinels: `Максимальный ранг всех стражей`,
75
inventory_bulkRankUpSentinelWeapons: `Максимальный ранг всего оружия стражей`,
76
powersuit_archonShardsLabel: `Ячейки осколков архонта`,
77
powersuit_archonShardsDescription: `Вы можете использовать эти неограниченные ячейки для установки множества улучшений.`,
78
mods_addRiven: `Добавить Мод Разлома`,
79
mods_fingerprint: `Отпечаток`,
80
mods_fingerprintHelp: `Нужна помощь с отпечатком?`,
81
mods_rivens: `Моды Разлома`,
82
mods_mods: `Моды`,
83
mods_bulkAddMods: `Добавить отсутствующие моды`,
84
cheats_administratorRequirement: `Вы должны быть администратором для использования этой функции. Чтобы стать администратором, добавьте <code>\"|DISPLAYNAME|\"</code> в <code>administratorNames</code> в config.json.`,
85
cheats_skipTutorial: `Пропустить обучение`,
86
cheats_skipAllDialogue: `Пропустить все диалоги`,
87
cheats_unlockAllScans: `Разблокировать все сканирования`,
88
cheats_unlockAllMissions: `Разблокировать все миссии`,
89
cheats_unlockAllQuests: `Разблокировать все квесты`,
90
cheats_completeAllQuests: `Завершить все квесты`,
91
cheats_infiniteCredits: `Бесконечные кредиты`,
92
cheats_infinitePlatinum: `Бесконечная платина`,
93
cheats_infiniteEndo: `Бесконечное эндо`,
94
cheats_infiniteRegalAya: `Бесконечная Королевская Айя`,
95
cheats_unlockAllShipFeatures: `Разблокировать все функции корабля`,
96
cheats_unlockAllShipDecorations: `Разблокировать все украшения корабля`,
97
cheats_unlockAllFlavourItems: `Разблокировать все <abbr title=\"Наборы анимаций, глифы, палитры и т. д.\">уникальные предметы</abbr>`,
98
cheats_unlockAllSkins: `Разблокировать все скины`,
99
cheats_unlockAllCapturaScenes: `Разблокировать все сцены Каптуры`,
100
cheats_universalPolarityEverywhere: `Универсальная полярность везде`,
101
cheats_unlockDoubleCapacityPotatoesEverywhere: `Катализаторы везде`,
102
cheats_unlockExilusEverywhere: `Адаптеры Эксилус везде`,
103
cheats_unlockArcanesEverywhere: `Адаптеры для мистификаторов везде`,
104
cheats_noDailyStandingLimits: `Без ежедневных ограничений репутации`,
105
cheats_spoofMasteryRank: `Подделанный ранг мастерства (-1 для отключения)`,
106
cheats_saveSettings: `Сохранить настройки`,
107
cheats_account: `Аккаунт`,
108
cheats_unlockAllFocusSchools: `Разблокировать все школы фокуса`,
109
cheats_helminthUnlockAll: `Полностью улучшить Гельминта`,
110
import_importNote: `Вы можете загрузить полный или частичный ответ инвентаря (клиентское представление) здесь. Все поддерживаемые поля <b>будут перезаписаны</b> в вашем аккаунте.`,
111
import_submit: `Отправить`,
112
}