Files

559 lines
52 KiB
HTML
Raw Permalink Normal View History

<!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 &mdash; 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">-&gt;</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">-&gt;</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">-&gt;</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">-&gt;</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">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
<span class="k">return</span> <span class="s2">&quot;&quot;</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">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
<span class="k">return</span> <span class="s2">&quot;Tannin&quot;</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">-&gt;</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">&quot;Gives a friendly greeting&quot;</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">-&gt;</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">-&gt;</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">&quot;enabled&quot;</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">-&gt;</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">&quot;enabled&quot;</span><span class="p">,</span> <span class="s2">&quot;enable this plugin&quot;</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(&quot;My</span> <span class="pre">String&quot;)</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">-&gt;</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">&quot;My Plugin Name&quot;</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">-&gt;</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">&quot;MyPlugin&quot;</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>&#169; 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>