-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathwriting-plugins.html
More file actions
559 lines (511 loc) · 52.1 KB
/
writing-plugins.html
File metadata and controls
559 lines (511 loc) · 52.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
<!DOCTYPE html>
<html class="writer-html5" lang="en" data-content_root="./">
<head>
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Writing Plugins — MO2 Python Plugin API documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=b86133f3" />
<link rel="stylesheet" type="text/css" href="_static/css/theme.css?v=e59714d7" />
<link rel="stylesheet" type="text/css" href="_static/graphviz.css?v=4ae1632d" />
<link rel="shortcut icon" href="_static/mo2.ico"/>
<script src="_static/jquery.js?v=5d32c60e"></script>
<script src="_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
<script src="_static/documentation_options.js?v=5929fcd5"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/js/theme.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="FAQ" href="faq.html" />
<link rel="prev" title="Type of Plugins" href="plugin-types.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="index.html" class="icon icon-home">
MO2 Python Plugin API
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="setup-tools.html">Setting up the environment</a><ul>
<li class="toctree-l2"><a class="reference internal" href="setup-tools.html#required-tools">Required tools</a></li>
<li class="toctree-l2"><a class="reference internal" href="setup-tools.html#preparation">Preparation</a><ul>
<li class="toctree-l3"><a class="reference internal" href="setup-tools.html#get-the-mobase-stubs">1. Get the <code class="docutils literal notranslate"><span class="pre">mobase</span></code> stubs</a></li>
<li class="toctree-l3"><a class="reference internal" href="setup-tools.html#configure-visual-studio-code-for-mobase">2. Configure Visual Studio Code for <code class="docutils literal notranslate"><span class="pre">mobase</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="setup-tools.html#optional-configure-black-to-auto-format-your-source-files">3. [Optional] Configure <code class="docutils literal notranslate"><span class="pre">black</span></code> to auto-format your source files</a></li>
<li class="toctree-l3"><a class="reference internal" href="setup-tools.html#optional-automatically-reload-plugins-during-development">4. [Optional] Automatically reload plugins during development</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="setup-tools.html#testing-the-setup">Testing the setup</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="plugin-types.html">Type of Plugins</a><ul>
<li class="toctree-l2"><a class="reference internal" href="plugin-types.html#installers">Installers</a></li>
<li class="toctree-l2"><a class="reference internal" href="plugin-types.html#previewers">Previewers</a></li>
<li class="toctree-l2"><a class="reference internal" href="plugin-types.html#mod-page">Mod Page</a></li>
<li class="toctree-l2"><a class="reference internal" href="plugin-types.html#game">Game</a></li>
<li class="toctree-l2"><a class="reference internal" href="plugin-types.html#tool">Tool</a></li>
<li class="toctree-l2"><a class="reference internal" href="plugin-types.html#proxies">Proxies</a></li>
<li class="toctree-l2"><a class="reference internal" href="plugin-types.html#free-plugins"><em>Free Plugins</em></a></li>
<li class="toctree-l2"><a class="reference internal" href="plugin-types.html#extension-interfaces">Extension Interfaces</a><ul>
<li class="toctree-l3"><a class="reference internal" href="plugin-types.html#diagnose">Diagnose</a></li>
<li class="toctree-l3"><a class="reference internal" href="plugin-types.html#file-mappings">File Mappings</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Writing Plugins</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#getting-started">Getting started</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#single-file-plugins">Single file plugins</a></li>
<li class="toctree-l3"><a class="reference internal" href="#module-plugins">Module Plugins</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#writing-the-plugin">Writing the plugin</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#iplugin-interface"><code class="docutils literal notranslate"><span class="pre">IPlugin</span></code> interface</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#examples">Examples</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#tutorial-plugins">Tutorial Plugins</a></li>
<li class="toctree-l3"><a class="reference internal" href="#official-plugins">Official Plugins</a></li>
<li class="toctree-l3"><a class="reference internal" href="#unofficial-plugins">Unofficial Plugins</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#internationalization">Internationalization</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#adding-translation-code">Adding translation code</a></li>
<li class="toctree-l3"><a class="reference internal" href="#generating-qt-translation-files">Generating Qt translation files</a></li>
<li class="toctree-l3"><a class="reference internal" href="#translating">Translating</a></li>
<li class="toctree-l3"><a class="reference internal" href="#distributing-translations">Distributing translations</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="faq.html">FAQ</a><ul>
<li class="toctree-l2"><a class="reference internal" href="faq.html#why-is-mo2-throwing-an-exception-when-i-try-to-create-a-type-inheriting-one-of-mo2-class">1. Why is MO2 throwing an exception when I try to create a type inheriting one of MO2 class?</a></li>
<li class="toctree-l2"><a class="reference internal" href="faq.html#how-can-i-be-sure-to-implement-all-the-required-methods-when-creating-a-plugin">2. How can I be sure to implement all the required methods when creating a plugin?</a></li>
<li class="toctree-l2"><a class="reference internal" href="faq.html#why-are-my-isinstance-x-qobject-and-isinstance-y-qwidget-not-working">3. Why are my <code class="docutils literal notranslate"><span class="pre">isinstance(x,</span> <span class="pre">QObject)</span></code> and <code class="docutils literal notranslate"><span class="pre">isinstance(y,</span> <span class="pre">QWidget)</span></code> not working?</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="autoapi/index.html">API Reference</a><ul>
<li class="toctree-l2"><a class="reference internal" href="autoapi/mobase/index.html">mobase</a><ul>
<li class="toctree-l3"><a class="reference internal" href="autoapi/mobase/index.html#submodules">Submodules</a><ul>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/widgets/index.html">mobase.widgets</a></li>
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="autoapi/mobase/index.html#attributes">Attributes</a></li>
<li class="toctree-l3"><a class="reference internal" href="autoapi/mobase/index.html#classes">Classes</a></li>
<li class="toctree-l3"><a class="reference internal" href="autoapi/mobase/index.html#functions">Functions</a></li>
<li class="toctree-l3"><a class="reference internal" href="autoapi/mobase/index.html#package-contents">Package Contents</a><ul>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.BSAInvalidation"><code class="docutils literal notranslate"><span class="pre">BSAInvalidation</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.DataArchives"><code class="docutils literal notranslate"><span class="pre">DataArchives</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.EndorsedState"><code class="docutils literal notranslate"><span class="pre">EndorsedState</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.ExecutableForcedLoadSetting"><code class="docutils literal notranslate"><span class="pre">ExecutableForcedLoadSetting</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.ExecutableInfo"><code class="docutils literal notranslate"><span class="pre">ExecutableInfo</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.FileInfo"><code class="docutils literal notranslate"><span class="pre">FileInfo</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.FileTreeEntry"><code class="docutils literal notranslate"><span class="pre">FileTreeEntry</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.GameFeature"><code class="docutils literal notranslate"><span class="pre">GameFeature</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.GamePlugins"><code class="docutils literal notranslate"><span class="pre">GamePlugins</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.GuessQuality"><code class="docutils literal notranslate"><span class="pre">GuessQuality</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.GuessedString"><code class="docutils literal notranslate"><span class="pre">GuessedString</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IDownloadManager"><code class="docutils literal notranslate"><span class="pre">IDownloadManager</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IFileTree"><code class="docutils literal notranslate"><span class="pre">IFileTree</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IGameFeatures"><code class="docutils literal notranslate"><span class="pre">IGameFeatures</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IInstallationManager"><code class="docutils literal notranslate"><span class="pre">IInstallationManager</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IModInterface"><code class="docutils literal notranslate"><span class="pre">IModInterface</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IModList"><code class="docutils literal notranslate"><span class="pre">IModList</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IModRepositoryBridge"><code class="docutils literal notranslate"><span class="pre">IModRepositoryBridge</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IOrganizer"><code class="docutils literal notranslate"><span class="pre">IOrganizer</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IPlugin"><code class="docutils literal notranslate"><span class="pre">IPlugin</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IPluginDiagnose"><code class="docutils literal notranslate"><span class="pre">IPluginDiagnose</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IPluginFileMapper"><code class="docutils literal notranslate"><span class="pre">IPluginFileMapper</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IPluginGame"><code class="docutils literal notranslate"><span class="pre">IPluginGame</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IPluginInstaller"><code class="docutils literal notranslate"><span class="pre">IPluginInstaller</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IPluginInstallerCustom"><code class="docutils literal notranslate"><span class="pre">IPluginInstallerCustom</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IPluginInstallerSimple"><code class="docutils literal notranslate"><span class="pre">IPluginInstallerSimple</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IPluginList"><code class="docutils literal notranslate"><span class="pre">IPluginList</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IPluginModPage"><code class="docutils literal notranslate"><span class="pre">IPluginModPage</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IPluginPreview"><code class="docutils literal notranslate"><span class="pre">IPluginPreview</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IPluginRequirement"><code class="docutils literal notranslate"><span class="pre">IPluginRequirement</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IPluginTool"><code class="docutils literal notranslate"><span class="pre">IPluginTool</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.IProfile"><code class="docutils literal notranslate"><span class="pre">IProfile</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.ISaveGame"><code class="docutils literal notranslate"><span class="pre">ISaveGame</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.ISaveGameInfoWidget"><code class="docutils literal notranslate"><span class="pre">ISaveGameInfoWidget</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.InstallResult"><code class="docutils literal notranslate"><span class="pre">InstallResult</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.LoadOrderMechanism"><code class="docutils literal notranslate"><span class="pre">LoadOrderMechanism</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.LocalSavegames"><code class="docutils literal notranslate"><span class="pre">LocalSavegames</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.Mapping"><code class="docutils literal notranslate"><span class="pre">Mapping</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.ModDataChecker"><code class="docutils literal notranslate"><span class="pre">ModDataChecker</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.ModDataContent"><code class="docutils literal notranslate"><span class="pre">ModDataContent</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.ModRepositoryFileInfo"><code class="docutils literal notranslate"><span class="pre">ModRepositoryFileInfo</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.ModState"><code class="docutils literal notranslate"><span class="pre">ModState</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.PluginRequirementFactory"><code class="docutils literal notranslate"><span class="pre">PluginRequirementFactory</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.PluginSetting"><code class="docutils literal notranslate"><span class="pre">PluginSetting</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.PluginState"><code class="docutils literal notranslate"><span class="pre">PluginState</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.ProfileSetting"><code class="docutils literal notranslate"><span class="pre">ProfileSetting</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.ReleaseType"><code class="docutils literal notranslate"><span class="pre">ReleaseType</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.SaveGameInfo"><code class="docutils literal notranslate"><span class="pre">SaveGameInfo</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.ScriptExtender"><code class="docutils literal notranslate"><span class="pre">ScriptExtender</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.SortMechanism"><code class="docutils literal notranslate"><span class="pre">SortMechanism</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.TrackedState"><code class="docutils literal notranslate"><span class="pre">TrackedState</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.UnmanagedMods"><code class="docutils literal notranslate"><span class="pre">UnmanagedMods</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.VersionInfo"><code class="docutils literal notranslate"><span class="pre">VersionInfo</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.VersionScheme"><code class="docutils literal notranslate"><span class="pre">VersionScheme</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.getFileVersion"><code class="docutils literal notranslate"><span class="pre">getFileVersion()</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.getIconForExecutable"><code class="docutils literal notranslate"><span class="pre">getIconForExecutable()</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.getProductVersion"><code class="docutils literal notranslate"><span class="pre">getProductVersion()</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.GameFeatureType"><code class="docutils literal notranslate"><span class="pre">GameFeatureType</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.INVALID_HANDLE_VALUE"><code class="docutils literal notranslate"><span class="pre">INVALID_HANDLE_VALUE</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.MoVariant"><code class="docutils literal notranslate"><span class="pre">MoVariant</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="autoapi/mobase/index.html#mobase.__version__"><code class="docutils literal notranslate"><span class="pre">__version__</span></code></a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="index.html">MO2 Python Plugin API</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item active">Writing Plugins</li>
<li class="wy-breadcrumbs-aside">
<a href="_sources/writing-plugins.rst.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="writing-plugins">
<h1>Writing Plugins<a class="headerlink" href="#writing-plugins" title="Link to this heading"></a></h1>
<section id="getting-started">
<h2>Getting started<a class="headerlink" href="#getting-started" title="Link to this heading"></a></h2>
<p>Now that you know which type of plugin you need, you can start writing your own plugin.
There is two way to write a Python plugin:</p>
<ul class="simple">
<li><p><a class="reference internal" href="#single-file-plugin"><span class="std std-ref">Single file plugins</span></a>: You use a single <code class="docutils literal notranslate"><span class="pre">.py</span></code> file that you put directly in the <code class="docutils literal notranslate"><span class="pre">plugins</span></code>
folder of the MO2 installation.</p></li>
<li><p><a class="reference internal" href="#module-plugin"><span class="std std-ref">Module Plugins</span></a>: You create a Python package (folder) with a <code class="docutils literal notranslate"><span class="pre">__init__.py</span></code> file that you
put in the <code class="docutils literal notranslate"><span class="pre">plugins</span></code> folder of the MO2 installation.</p></li>
</ul>
<p>Most examples of plugins will be module plugins.</p>
<section id="single-file-plugins">
<span id="single-file-plugin"></span><h3>Single file plugins<a class="headerlink" href="#single-file-plugins" title="Link to this heading"></a></h3>
<p>Prior to version 2.3, this was the only way of creating a Python plugin. You simply need
to create a <code class="docutils literal notranslate"><span class="pre">myplugin.py</span></code> file in the <code class="docutils literal notranslate"><span class="pre">plugins</span></code> folder of Mod Organizer 2 with a content
similar to:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">mobase</span>
<span class="k">class</span><span class="w"> </span><span class="nc">MyPlugin</span><span class="p">(</span><span class="o">...</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">def</span><span class="w"> </span><span class="nf">createPlugin</span><span class="p">()</span> <span class="o">-></span> <span class="n">mobase</span><span class="o">.</span><span class="n">IPlugin</span><span class="p">:</span>
<span class="k">return</span> <span class="n">MyPlugin</span><span class="p">()</span>
</pre></div>
</div>
<p>We will see later on how to create the actual <code class="docutils literal notranslate"><span class="pre">MyPlugin</span></code> class.
The <code class="docutils literal notranslate"><span class="pre">createPlugin</span></code> function is the function that is called by Mod Organizer 2 to instantiate
the plugin.</p>
<p>You can also provide multiple plugins by using <code class="docutils literal notranslate"><span class="pre">createPlugins</span></code> instead of <code class="docutils literal notranslate"><span class="pre">createPlugin</span></code>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">List</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">mobase</span>
<span class="k">class</span><span class="w"> </span><span class="nc">MyPlugin1</span><span class="p">(</span><span class="o">...</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">class</span><span class="w"> </span><span class="nc">MyPlugin2</span><span class="p">(</span><span class="o">...</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">def</span><span class="w"> </span><span class="nf">createPlugins</span><span class="p">()</span> <span class="o">-></span> <span class="n">List</span><span class="p">[</span><span class="n">mobase</span><span class="o">.</span><span class="n">IPlugin</span><span class="p">]:</span>
<span class="k">return</span> <span class="p">[</span><span class="n">MyPlugin1</span><span class="p">(),</span> <span class="n">MyPlugin2</span><span class="p">()]</span>
</pre></div>
</div>
<p><strong>Note:</strong> If you provide neither <code class="docutils literal notranslate"><span class="pre">createPlugin()</span></code> nor <code class="docutils literal notranslate"><span class="pre">createPlugins</span></code>, MO2 will display
an error message in the logs.</p>
<p><strong>Note:</strong> If you add a return type-hint to <code class="docutils literal notranslate"><span class="pre">createPlugin()</span></code> or <code class="docutils literal notranslate"><span class="pre">createPlugins</span></code> (<code class="docutils literal notranslate"><span class="pre">-></span></code>), <code class="docutils literal notranslate"><span class="pre">mypy</span></code>
will type-check the function and warn you if one of your plugins is invalid, e.g. if you
forgot to implement a required method.</p>
<p>If you need to provide other files with your <code class="docutils literal notranslate"><span class="pre">.py</span></code> (assets or other Python files), you can
put them in the <code class="docutils literal notranslate"><span class="pre">plugins/data</span></code>, but this is deprecated since MO2 2.3, and you should instead
create a Python module plugin.</p>
</section>
<section id="module-plugins">
<span id="module-plugin"></span><h3>Module Plugins<a class="headerlink" href="#module-plugins" title="Link to this heading"></a></h3>
<p>Module plugins were introduced in MO2 2.3 and are shipped as whole folder containg a python module.
The minimum content of the folder is a <code class="docutils literal notranslate"><span class="pre">__init__.py</span></code> file with <code class="docutils literal notranslate"><span class="pre">createPlugin</span></code> or <code class="docutils literal notranslate"><span class="pre">createPlugins</span></code>
function.</p>
<p>A minimal module plugin could be as follows:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>plugins/<span class="w"> </span><span class="c1"># MO2 plugins folder</span>
<span class="w"> </span>myplugin/
<span class="w"> </span>__init__.py
<span class="w"> </span>plugin.py
</pre></div>
</div>
<p>In <code class="docutils literal notranslate"><span class="pre">plugin.py</span></code>, you could define your plugin:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># plugin.py</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">mobase</span>
<span class="k">class</span><span class="w"> </span><span class="nc">MyPlugin</span><span class="p">(</span><span class="o">...</span><span class="p">):</span>
<span class="o">...</span>
</pre></div>
</div>
<p>And in <code class="docutils literal notranslate"><span class="pre">__init__.py</span></code>, you should write <code class="docutils literal notranslate"><span class="pre">createPlugin</span></code>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># __init__.py</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">mobase</span> <span class="c1"># For type-checking createPlugin().</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">.plugin</span><span class="w"> </span><span class="kn">import</span> <span class="n">MyPlugin</span> <span class="c1"># Always use relative import:</span>
<span class="k">def</span><span class="w"> </span><span class="nf">createPlugin</span><span class="p">()</span> <span class="o">-></span> <span class="n">mobase</span><span class="o">.</span><span class="n">IPlugin</span><span class="p">:</span>
<span class="k">return</span> <span class="n">MyPlugin</span><span class="p">()</span>
</pre></div>
</div>
<p>Similar to single-file plugins, you can expose <code class="docutils literal notranslate"><span class="pre">createPlugins</span></code> instead of <code class="docutils literal notranslate"><span class="pre">createPlugin</span></code>
to instantiate multiple plugins.</p>
<p><strong>Note:</strong> The name of the folder does not have to be a valid python package, and you should
always use relative imports within the module (<code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">.xxx</span></code>) instead of absolute ones.</p>
</section>
</section>
<section id="writing-the-plugin">
<h2>Writing the plugin<a class="headerlink" href="#writing-the-plugin" title="Link to this heading"></a></h2>
<section id="iplugin-interface">
<h3><code class="docutils literal notranslate"><span class="pre">IPlugin</span></code> interface<a class="headerlink" href="#iplugin-interface" title="Link to this heading"></a></h3>
<p>In the code snippets above, the <code class="docutils literal notranslate"><span class="pre">MyPlugin</span></code> class was not implemented.
Depending on the <a class="reference internal" href="plugin-types.html#type-of-plugins"><span class="std std-ref">type of plugins</span></a> that you want to create, you will
need to extend a different class.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">MyTool</span><span class="p">(</span><span class="n">mobase</span><span class="o">.</span><span class="n">IPluginTool</span><span class="p">):</span> <span class="c1"># Create a Tool plugin</span>
<span class="o">...</span>
<span class="k">class</span><span class="w"> </span><span class="nc">MyPreview</span><span class="p">(</span><span class="n">mobase</span><span class="o">.</span><span class="n">IPluginPreview</span><span class="p">):</span> <span class="c1"># Create a preview plugin</span>
<span class="o">...</span>
</pre></div>
</div>
<p>Each plugin class has its own abstract methods that you need to implement but all the classes
also extend <code class="docutils literal notranslate"><span class="pre">IPlugin</span></code>, so you need to implement the methods from <a class="reference internal" href="autoapi/mobase/index.html#mobase.IPlugin" title="mobase.IPlugin"><code class="xref py py-class docutils literal notranslate"><span class="pre">IPlugin</span></code></a>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">List</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">mobase</span>
<span class="k">class</span><span class="w"> </span><span class="nc">MyPlugin</span><span class="p">(</span><span class="o">...</span><span class="p">):</span> <span class="c1"># The base class depends on the actual type of plugin</span>
<span class="n">_organizer</span><span class="p">:</span> <span class="n">mobase</span><span class="o">.</span><span class="n">IOrganizer</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">()</span> <span class="c1"># You need to call this manually.</span>
<span class="k">def</span><span class="w"> </span><span class="nf">init</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">organizer</span><span class="p">:</span> <span class="n">mobase</span><span class="o">.</span><span class="n">IOrganizer</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_organizer</span> <span class="o">=</span> <span class="n">organizer</span>
<span class="k">return</span> <span class="kc">True</span>
<span class="k">def</span><span class="w"> </span><span class="nf">name</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
<span class="k">return</span> <span class="s2">""</span>
<span class="k">def</span><span class="w"> </span><span class="nf">author</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
<span class="k">return</span> <span class="s2">"Tannin"</span>
<span class="k">def</span><span class="w"> </span><span class="nf">description</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_tr</span><span class="p">(</span><span class="s2">"Gives a friendly greeting"</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">version</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">mobase</span><span class="o">.</span><span class="n">VersionInfo</span><span class="p">:</span>
<span class="k">return</span> <span class="n">mobase</span><span class="o">.</span><span class="n">VersionInfo</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">mobase</span><span class="o">.</span><span class="n">ReleaseType</span><span class="o">.</span><span class="n">FINAL</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">isActive</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="nb">bool</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_organizer</span><span class="o">.</span><span class="n">pluginSetting</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">(),</span> <span class="s2">"enabled"</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">settings</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">List</span><span class="p">[</span><span class="n">mobase</span><span class="o">.</span><span class="n">PluginSetting</span><span class="p">]:</span>
<span class="k">return</span> <span class="p">[</span>
<span class="n">mobase</span><span class="o">.</span><span class="n">PluginSetting</span><span class="p">(</span><span class="s2">"enabled"</span><span class="p">,</span> <span class="s2">"enable this plugin"</span><span class="p">,</span> <span class="kc">True</span><span class="p">)</span>
<span class="p">]</span>
</pre></div>
</div>
<p>Most of these are pretty simple to understand:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">name</span></code>: Returns the name of the plugin. The name of the plugin is used to
fetch settings, and in many places, so this should not change between versions.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">author</span></code>: Returns the name of the plugin author (you!).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">description</span></code>: Returns the description of the plugin.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">version</span></code>: Returns the version of the plugin. See <a class="reference internal" href="autoapi/mobase/index.html#mobase.VersionInfo" title="mobase.VersionInfo"><code class="xref py py-class docutils literal notranslate"><span class="pre">VersionInfo</span></code></a> for
more details.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">isActive</span></code>: Returns <code class="docutils literal notranslate"><span class="pre">True</span></code> if the plugin is active, <code class="docutils literal notranslate"><span class="pre">False</span></code> otherwise. This
usually returns <code class="docutils literal notranslate"><span class="pre">True</span></code>, unless you want to check for something to dynamically
enable the plugin. You can also use a plugin setting to allow users to disable
your plugins.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">settings</span></code>: Returns the list of settings (that user can modify) for this plugin.
Settings can be <code class="docutils literal notranslate"><span class="pre">int</span></code>, <code class="docutils literal notranslate"><span class="pre">bool</span></code>, <code class="docutils literal notranslate"><span class="pre">str</span></code> or list of <code class="docutils literal notranslate"><span class="pre">str</span></code>. Here we indicate
that we have a “enabled” setting that user could use to disable the plugin (and
we use it in <code class="docutils literal notranslate"><span class="pre">isActive</span></code>).</p></li>
</ul>
<p>The <code class="docutils literal notranslate"><span class="pre">__init__</span></code> method is the normal Python constructor for our plugin, called when doing
<code class="docutils literal notranslate"><span class="pre">MyPlugin()</span></code>.
You should always call <code class="docutils literal notranslate"><span class="pre">super().__init__()</span></code> explicitly when extending MO2 classes (due to
a “bug” in <code class="docutils literal notranslate"><span class="pre">boost.python</span></code>).</p>
<p>The <code class="docutils literal notranslate"><span class="pre">init</span></code> method is called by MO2 to initialize the plugin. The given argument, <code class="docutils literal notranslate"><span class="pre">organizer</span></code>,
is an instance of <a class="reference internal" href="autoapi/mobase/index.html#mobase.IOrganizer" title="mobase.IOrganizer"><code class="xref py py-class docutils literal notranslate"><span class="pre">IOrganizer</span></code></a> which is the class used to interface with MO2.
Here, we use it in the <code class="docutils literal notranslate"><span class="pre">isActive()</span></code> method to retrieve the “enabled” setting for our plugin.
See <a class="reference internal" href="autoapi/mobase/index.html#mobase.IOrganizer" title="mobase.IOrganizer"><code class="xref py py-class docutils literal notranslate"><span class="pre">IOrganizer</span></code></a> for more details.</p>
</section>
</section>
<section id="examples">
<h2>Examples<a class="headerlink" href="#examples" title="Link to this heading"></a></h2>
<p>This section contains (links to) examples of MO2 Python plugins.
Some of these plugins have been created for educational purpose and are thus very detailed and
easy to understand or get started from.</p>
<section id="tutorial-plugins">
<h3>Tutorial Plugins<a class="headerlink" href="#tutorial-plugins" title="Link to this heading"></a></h3>
<p><a class="reference external" href="https://github.com/Holt59/modorganizer-python_plugins">This repository</a> contains examples of Python
plugins that were written only to help users write their own plugins.
If you want to start somewhere, this is the place to go.</p>
</section>
<section id="official-plugins">
<h3>Official Plugins<a class="headerlink" href="#official-plugins" title="Link to this heading"></a></h3>
<p>These plugins are (or will be) included in MO2 releases and are usually maintain by some members of
the MO2 development teams.
These plugins are not as well documented as the ones in the repository above.</p>
<ul class="simple">
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/ModOrganizer2/modorganizer-basic_games">Basic Games</a> [<code class="docutils literal notranslate"><span class="pre">IPluginGame</span></code>]</dt><dd><p>This is the meta-plugin for “basic” games. It is a complex
plugins and should mostly be investigated if you want to add a game to it.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/ModOrganizer2/modorganizer-fnistool">FNIS Tool</a> [<code class="docutils literal notranslate"><span class="pre">IPluginTool</span></code>]:</dt><dd><p>Plugin to integrate FNIS into MO2.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/ModOrganizer2/modorganizer-installer_wizard">Installer Wizard</a> [<code class="docutils literal notranslate"><span class="pre">IPluginInstaller</span></code>]:</dt><dd><p>Installer for BAIN archives containing wizard scripts.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/ModOrganizer2/modorganizer-preview_dds">Preview DDS</a> [<code class="docutils literal notranslate"><span class="pre">IPluginPreview</span></code>]:</dt><dd><p>Plugin to preview DDS files. Quite complex due to the use
of OpenGL for display.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/ModOrganizer2/modorganizer-form43_checker">Form 43 Checker</a> [<code class="docutils literal notranslate"><span class="pre">IPluginDiagnose</span></code>]:</dt><dd><p>Plugin that warn users if there are form 43 ESPs (Skyrim ESPs)
enabled when managing a Skyrim SE instance.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/ModOrganizer2/modorganizer-tool_configurator">Tool Configurator</a> [<code class="docutils literal notranslate"><span class="pre">IPluginTool</span></code>]:</dt><dd><p>Plugin that allows easier modifications of game settings.
Mostly contains a complex GUI for managing INI files.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/ModOrganizer2/modorganizer-script_extender_plugin_checker">Script Extender Plugin Checker</a> [<code class="docutils literal notranslate"><span class="pre">IPluginDiagnose</span></code>]:</dt><dd><p>Plugin that checks Script Extender logs to see
if some plugins have failed to load and display information to the user if possible.</p>
</dd>
</dl>
</li>
</ul>
</section>
<section id="unofficial-plugins">
<h3>Unofficial Plugins<a class="headerlink" href="#unofficial-plugins" title="Link to this heading"></a></h3>
<p>These plugins have been created by developers for MO2 and are usually distributed on Nexus.</p>
<ul class="simple">
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/deorder/mo2-plugins">Merge Plugins Hide</a> [<code class="docutils literal notranslate"><span class="pre">IPluginTool</span></code>]:</dt><dd><p>Hide / unhide plugins that were merged using <code class="docutils literal notranslate"><span class="pre">Merge</span> <span class="pre">Plugins</span></code> or <code class="docutils literal notranslate"><span class="pre">zMerge</span></code>.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/AnyOldName3/ModOrganizer-to-OpenMW">OpenMW Exporter</a> [<code class="docutils literal notranslate"><span class="pre">IPluginTool</span></code>]:</dt><dd><p>A Mod Organizer plugin to export your VFS, plugin selection and load order to OpenMW.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/AnyOldName3/modorganizer-orphaned_script_extender_save_deleter">Orphaned Script Extender Save Deleter</a> [<code class="docutils literal notranslate"><span class="pre">IPluginTool</span></code>]:</dt><dd><p>Mod Organizer plugin to delete orphaned script extender co-saves.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/deorder/mo2-plugins">Sync Mod Order</a> [<code class="docutils literal notranslate"><span class="pre">IPluginTool</span></code>]:</dt><dd><p>Synchronize mod order from current profile to another while keeping the (enabled/disabled) state intact.</p>
</dd>
</dl>
</li>
</ul>
<p><em>Feel free to open an issue or a pull-request if you want to add your own plugin to the list.</em></p>
</section>
</section>
<section id="internationalization">
<h2>Internationalization<a class="headerlink" href="#internationalization" title="Link to this heading"></a></h2>
<p>If you plan to distribute your plugin, it is often a good idea to provide translations for it.</p>
<section id="adding-translation-code">
<h3>Adding translation code<a class="headerlink" href="#adding-translation-code" title="Link to this heading"></a></h3>
<p>Mod Organizer uses Qt translation system, so you need to adapt your plugin code to provide
translation strings.
To do this, you need two things:</p>
<ol class="arabic simple">
<li><p>In every class containing strings you need to translate, you must add a <code class="docutils literal notranslate"><span class="pre">__tr</span></code> function
that takes a <code class="docutils literal notranslate"><span class="pre">str</span></code> input and call <cite>QApplication.translate</cite> on it (see example below).</p></li>
<li><p>You need to wrap all translatable strings in a call to <code class="docutils literal notranslate"><span class="pre">self.__str("My</span> <span class="pre">String")</span></code> (see
example below).</p></li>
</ol>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">PyQt5.QtWidgets</span><span class="w"> </span><span class="kn">import</span> <span class="n">QApplication</span>
<span class="k">class</span><span class="w"> </span><span class="nc">MyPlugin</span><span class="p">(</span><span class="o">...</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="nf">localizedName</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
<span class="c1"># Use self.__tr to wrap string you want translatable.</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__tr</span><span class="p">(</span><span class="s2">"My Plugin Name"</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">__tr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">txt</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
<span class="c1"># The first argument must EXACTLY match the class name:</span>
<span class="k">return</span> <span class="n">QApplication</span><span class="o">.</span><span class="n">translate</span><span class="p">(</span><span class="s2">"MyPlugin"</span><span class="p">,</span> <span class="n">txt</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="generating-qt-translation-files">
<h3>Generating Qt translation files<a class="headerlink" href="#generating-qt-translation-files" title="Link to this heading"></a></h3>
<p>Once your code is updated, you need to generate the Qt translation file <code class="docutils literal notranslate"><span class="pre">.ts</span></code>.
You can use <code class="docutils literal notranslate"><span class="pre">PyQt5.lupdate_main</span></code> for this:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>PyQt5.lupdate_main<span class="w"> </span>mysourcefile.py<span class="w"> </span>-ts<span class="w"> </span>mysourcefile.ts
</pre></div>
</div>
<p>You should generate a single translation file for your whole plugin even if it contains
multiple files by passing all Python file and Qt UI (<code class="docutils literal notranslate"><span class="pre">.ui</span></code>) file to the command above.</p>
</section>
<section id="translating">
<h3>Translating<a class="headerlink" href="#translating" title="Link to this heading"></a></h3>
<p>Now that you have the original <code class="docutils literal notranslate"><span class="pre">.ts</span></code> file, you need to translate it in order to obtain
translation files for other languages.
To do so, you can use online services such as <a class="reference external" href="https://www.transifex.com">Transifex</a> or
simply Qt Linguistic tools.</p>
</section>
<section id="distributing-translations">
<h3>Distributing translations<a class="headerlink" href="#distributing-translations" title="Link to this heading"></a></h3>
<p>Once you have obtained translation files for another language, e.g. French, you need to
compile it into a <code class="docutils literal notranslate"><span class="pre">.qm</span></code> file and then ship it.</p>
<ul class="simple">
<li><p>If you are using a single Python file plugin <code class="docutils literal notranslate"><span class="pre">myplugin.py</span></code>, the name of the compiled
translation must be <code class="docutils literal notranslate"><span class="pre">myplugin_fr.qm</span></code>.</p></li>
<li><p>If you are shipping a module <code class="docutils literal notranslate"><span class="pre">mymoduleplugin</span></code>, the name of the compiled translation
must be <code class="docutils literal notranslate"><span class="pre">mymoduleplugin</span></code>.</p></li>
</ul>
</section>
</section>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="plugin-types.html" class="btn btn-neutral float-left" title="Type of Plugins" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="faq.html" class="btn btn-neutral float-right" title="FAQ" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>© Copyright 2023, Holt59.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>