Category: Tutorials

Translating a ClassicPress plugin by azurecurve

Internationalization, or i18n as it’s often abbreviated, is an important part of many projects. That is why we want to highlight a course made by Ian Grieve of azurecurve. In this course Ian will take you through the process of translating plugins (and themes) step by step.

Ian introduces his new series as follows:

“I started using WordPress when I launched this blog back in 2011 and a couple of years later started writing plugins to add missing functionality. At the end of last year I switched over to ClassicPress, a hard-fork of WordPress.

As part of my transition to ClassicPress I created new versions of my plugins which added new functionality and improved security. I had already done some work to internationalize my plugins, but took the opportunity to improve this aspect as well.

Having done so, I thought that a series on how to internationalize and localize plugins might be a useful thing to write; while the series is targeted at plugins, as I am a plugin author, the principles are the same for themes.”

Where do I start?

If you want to get serious about creating plugins or themes for ClassicPress, i18n is not an afterthought, but should be regarded as a requirement. In this context, azurecurve’s new course should be an invaluable resource.

Excited to get started? You can find the series index here.

Resolve Plugin Conflicts without Deactivating All ClassicPress Plugins

A common recommendation in the WordPress world when you’re having issues with a plugin is to disable all plugins. Don’t do it!

While we can employ best practices in our own code, we have no control over what other developers are doing. As a result, plugin conflicts will sometimes happen. What’s more, another developer’s plugin might be causing the issue, while it is my plugin that actually exhibits the symptoms.

When these types of issues arise, the most common thing a developer will recommend is to deactivate all your plugins, set your theme to TwentyWhatever, then try their plugin again. While this has been the standard advice for a decade, this is often a waste of time. There’s a better way.

About Deactivating Plugins

Consider what happens when you deactivate a plugin. Do you actually know? Yeah, me neither. Other than the plugin no longer working, it may not be clear what has changed. Were options deleted? Were settings lost? Is the site still working? The answer is: it’s up to each and every plugin developer, so, who knows.

Unless you dig into the code of each plugin, you never really know what may happen when you deactivate them. You just might get stuck having to reconfigure a bunch of plugins. This is why it is preferable to not deactivate all plugins as a first course of action – you just don’t know what may be lost. So, instead of deactivating all plugins at once, I take a more thoughtful approach to make the best use of my time.

Conflict Resolution Plan

The steps listed here will seem logical once you’ve gone through them. Indeed, they will probably even seem obvious once they’re pointed out.

  1. Do not disable any plugins or change the theme.
  2. Make a shortlist of any plugins that you think might be related to the conflict.
  3. Deactivate the first plugin on your shortlist and check to see if the conflict persists.

Does the conflict persist?

If so, reactivate that plugin and then repeat (step 3) with each plugin on your shortlist.

Is the conflict resolved?

If so, you now know which plugin is conflicting. There is usually no need to deactivate any remaining plugins.

If processing through your shortlist of suspected plugins does not reveal the conflict, start at the top of the main plugin list and repeat the process – deactivate, check for conflict, reactivate – until you find the conflicting plugin.

Wrapping Up

Deactivating all plugins in one quick action can be tempting when plugin conflicts arise, but, it’s often unnecessary. Without knowing exactly what every plugin does upon activation, it is very much a “shot in the dark” that mass-deactivation won’t actually create more work. Your gut instinct (which then becomes your shortlist) is often a very quick way to conflict resolution, and, if not, you have a more systematic approach to determine just where that conflict lies.

What do you think?

Are you in support of a thoughtful approach, or would you just deactivate them all and hope for the best? Have you ever had anything unexpected happen when you deactivated a plugin? I have my own opinion about what a plugin should do upon activation, but, what do you think? I’d love to hear your thoughts – let me know in the comments!

This tutorial has been provided by John Alarcon and was originally published on The original post can be found here.

How to read the wp-config file, and what can I do with it?

If you use an installer you might have never actually looked into the wp-config file. Many people will tell you that it is probably one of the more important files in your ClassicPress installation to understand. This is because there are so many things that it can do to cause problems if used incorrectly. That is why I want to take some time to decipher it piece by piece for people who might be intimidated by all the code. This explanation follows the base wp-config-sample.php of a clean install. Things might be added, out of order or missing in your production site. Just because there is something in your file that is not discussed here does not mean it is bad, but try to make note of these. When you are having problems you can then look if removing these unknown lines is the solution.

The database settings

The first and, arguably, most important part of the wp-config file are the database settings. It’s important that all six of these are filled in correctly or you might run into trouble with your database.

// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for ClassicPress */
define('DB_NAME', 'database_name_here');
/** MySQL database username */
define('DB_USER', 'username_here');
/** MySQL database password */
define('DB_PASSWORD', 'password_here');
/** MySQL hostname */
define('DB_HOST', 'localhost');
/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8');
/** The Database Collate type. Don't change this if in doubt. */
define('DB_COLLATE', '');

What do they mean?

define('DB_NAME', 'database_name_here');: This is the name of your database. This is often automatically generated by your hosting. This is basically just what your database is called.
define('DB_USER', 'username_here');: This is the username of your database. This is different from your database name, even though a lot of hostings use the same name for both. The username is a distinct login to gain access to your database.
define('DB_PASSWORD', 'password_here');: This is the password of the username from above. To login, ClassicPress needs the password belonging to the username you’ve chosen.
define('DB_HOST', 'localhost');: This is the location of your database. For a lot of people this will be Localhost. But in the rare cases that a database is in a seperate location from the ClassicPress installation, the correct ip-adress can be filled in here.
define('DB_CHARSET', 'utf8');: This is the set of characters that the database uses. The standard value is utf8 and is in almost all cases the correct one. Utf8 supports all languages, and as such is the most ideal value.
define('DB_COLLATE', '');: This is the specific subset of charset that your database should use. Do not change this unless you’re absolutely certain.

The security keys

Underneath the database settings, you have the security keys. These consist out of four secret keys and four salts. In very simplified terms, these keys make it harder to break your security barriers. The four salts further complicate your defenses. While the keys are nessecary, the salts are not, but it’s still recommended to use them!

define('AUTH_KEY',         'put your unique phrase here');
define('SECURE_AUTH_KEY',  'put your unique phrase here');
define('LOGGED_IN_KEY',    'put your unique phrase here');
define('NONCE_KEY',        'put your unique phrase here');
define('AUTH_SALT',        'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT',   'put your unique phrase here');
define('NONCE_SALT',       'put your unique phrase here');

Your keys are not something you have to remember so make them as long and complicated as possible. You can also use one of the many online key generators.

The table prefix

The next important line of code is the table prefix. What this does is tell ClassicPress what the prefix of your table is. That is not very surprising, but what is the prefix of a table?

$table_prefix  = 'cp_';

In your database there will be several characters in front of the table name, usually cp_ or wp_. But you can change this during installation. Do not change this value after installation or you will break your database!

The debug settings

Under the table prefix is the debug setting. This decides if errors are logged or not. Set this to false to hide errors

define('WP_DEBUG', false);

If you set this to true you can also add extra lines to decide how exactly the errors are logged.
define( 'WP_DEBUG_DISPLAY', true );: Insert this line to enable display errors in text on the browser. Or change true to false to hide these errors.
define( 'WP_DEBUG_LOG', true );: Insert this line to enable an error_log file that you can access through FTP or your file manager. Or change true to false to block this feature. You can also change true into a path to add these logs to a specific file. For example: define( 'WP_DEBUG_LOG', '/error/cperrors.log' );

The directory settings

The final two settings can usually just be left alone. They are there to help ClassicPress find its settings.

/** Absolute path to the ClassicPress directory. */
if ( !defined('ABSPATH') )
	define('ABSPATH', dirname(__FILE__) . '/');
/** Sets up ClassicPress vars and included files. */
require_once(ABSPATH . 'wp-settings.php');

The first part will define the ABSPATH. But what is the ABSPATH? Simply said it is a map for ClassicPress to find its own main folder. An absolute path to the main folder. The second setting will then use this ABSPATH to tell ClassicPress where it can find wp-settings.php.

Extra settings

Of course this is not everything that wp-config.php can do. There are many more settings for all kinds of objectives. If you want to use some of these, simply copy and paste them between WP-DEBUG and ABSPATH. Some of the more interesting of these are:


Using define( 'WP_SITEURL', '' ); you can change the location of your ClassicPress installation without changing your home url. Simply use your main URL and then / with the name of the folder that you placed ClassicPress in. This overrides the option from settings in your CMS.

define( 'WP_HOME', '' ); can be used in combination with the above to change the home URL to keep it at root level or to change the homepage to a / something. It can also be used to force https or a main url when your domain has aliases. This also overrides the option from settings in your CMS. This makes sure that it can’t accidentally be changed by another user.

Moving directories

You can move several directories into seperate folders. These are uploads, themes, plugins and/or the entire wp-content folder. You can use the following settings for this, simply changing the relative URL:
Wp-content: define( 'WP_CONTENT_DIR', dirname(__FILE__) . '/wp-content' );
Plugins: define( 'WP_PLUGIN_DIR', dirname(__FILE__) . '/wp-content/plugins' );
Uploads: define( 'UPLOADS', '/wp-content/uploads' );

But what about themes?

Themes are a little more complicated. The theme folder is hardcoded relative to the wp-content folder. But what you can do is register an extra themes folder using:
register_theme_directory( dirname( __FILE__ ) . '/themes' );


Using define( 'WP_CACHE', true ); you can turn ClassicPress’ advanced caching features on. You can also turn them off using define( 'WP_CACHE', false );.

Core updates

You can use the auto core update settings to decide how your ClassicPress installation should deal with updates. There are three settings:
define( 'WP_AUTO_UPDATE_CORE', false );: This turns off all automatic updates.
define( 'WP_AUTO_UPDATE_CORE', true );: This turns on all automatic updates.
define( 'WP_AUTO_UPDATE_CORE', 'minor' );: This turns on all minor automatic updates but will not do major updates automatically. This is the default.

PHP memory limit

There are a lot of errors that occur related to php memory limit. And while its better to change this in php.ini, not everyone has access to this. You can use wp-config to define a limit using: define( 'WP_MEMORY_LIMIT', '64M' ); This does not always work as some hosting providers block this.

Wrapping up

All in all, you can do a lot of stuff with this little file that most people ignore after installation. There is also a lot that I haven’t even mentioned yet! I hope that this article has given you a bit more insight if you were unfamiliar with using the config. Of course with this power comes a lot of responsibility and I advise against experimenting on a production site because you can also break a lot here. Please be careful and quoting the wp-config file: /* That's all, stop editing! Happy blogging. */. Well actually ‘start editing responsibly’. 😉

Create a Static Widget in the ClassicPress Dashboard

A static dashboard widget is a great way to share information, important links, or action items with your clients when you hand-off a site. Very little code – very high user impact!

When handing off a ClassicPress website to a client, do you provide them with information or links to get them off to a good start? A static widget in the dashboard – just like the one pictured below – is a great solution for this! Wouldn’t it be cool to add something like this to the client’s dashboard? Well, we’re going to build it shortly.

Depiction of a Static Text Widget

The image above depicts what we’ll be creating here today. However, before moving on, let’s make a few quick distinctions about widgets, shall we?

Static Widgets vs Dynamic Widgets

Whereas a dynamic widget shows content that changes over time, such as latest posts or recent comments, a static widget shows the same content always. In the image above, the widget is simply inviting the user (ie, your client) to contact their project manager.

Of course, this is just a simple example of how you might use a static widget. Indeed, you might want to include your business address, hours of operation, helpful links, payment info, or any of those other things that you might typically include in a hand-off document.

Dashboard Widgets vs Front-end Widgets

One last distinction to make before starting this project is the difference between dashboard widgets and front-end widgets. It’s simple, but, bears repeating.

Dashboard widgets will appear in the main dashboard view. The site admin can collapse and expand the widget, as well as move it to a new position, or even hide it altogether.

Front-end widgets are those that are displayed to visitors on your site. Visitors cannot usually expand or collapse front-end widgets (although there are exceptions,) but, they will not likely be able to move or hide the widget content.

Where to Place the Code?

If you’re coming from the WordPress space, you will be familiar with placing code into your theme’s functions.php file. This is the “old school, quick ‘n dirty” way, and is no longer recommended. The code in this tutorial should be placed into an utility plugin. If your site already has a utility plugin, great, you can just add the code below to that plugin. If you don’t yet have such a plugin, go build one. I’ll wait for you here.

The Process of Creating a Static Widget

To create a dashboard widget, three objectives must be achieved. The three objectives are to:

  1. create a function that prints the widget content, and
  2. create a function that registers the new widget in the system, and
  3. use an action hook to specify when the widget should be registered.

Let’s work through these objectives now. Move through the following steps, adding the code examples to your utility plugin. There’s no need to make customizations as you go – let’s just get it working first and fine-tune later.

1. Print the Widget Content

This simple function populates the widget with your content. As you can see, PHP tags are used in the function to allow for neater HTML markup. Add the code to your utility plugin.

function codepotent_display_static_dashboard_widget() {
    <h1>Hey, it worked!</h1>

2. Register the New Widget

This function registers the widget in the system by calling the wp_add_dashboard_widget function with several arguments. These arguments tell the system your preferred id and title for the widget, as well as the name of the function that will ultimately output the widget content (from step 1 above.) Add the code to your utility plugin.

function codepotent_register_static_dashboard_widget() {
        'my_static_dashboard_widget', // your own custom widget id
        'My Widget', // the widget box title
        'codepotent_display_static_dashboard_widget' // function that displays content

3. Hook the New Widget in at the Right Time

In case you didn’t notice, those functions created in Steps 1 & 2 aren’t actually called anywhere. Yet. If they aren’t called, they can’t run. That’s where an action hook comes into play. The action hook tells the system exactly when to run the function that registers your widget, which, in turn, tells the system which function to use to display the content. Now, that was a lot of words, but, it really just boils down to a single line of code that says “run this function during the wp_dashboard_setup action.” Add the line to your utility plugin.

add_action('wp_dashboard_setup', 'codepotent_register_static_dashboard_widget');

Verify your Work

With the above objectives out of the way, take a moment to verify your work. Head over to the dashboard and find that you now have a new widget showing in all its glory. Collapse it. Expand it. Move it around. Hide it. It should work just like every other widget in the dashboard.

Initial Static Text Widget

Add Meaningful Content

With the widget now displaying in the dashboard, you can revisit the display function (from Step 1) and flesh it out with whatever content you like. In the final example below, I’ve combined the code from above and added some additional markup to make the widget look like the original example image.

// Step 1
function codepotent_display_static_dashboard_widget() {
    <div style="display:grid;justify-content:space-between;grid-template-columns:repeat(auto-fit,minmax(48%,1fr));grid-template-rows:1fr;grid-gap:20px;">
            <img src="" style="border:1px solid #ccc;padding:2px;">
            <h2>Kelly Marks</h2>
            Your project manager, <strong>Kelly Marks</strong>, is committed to your success! If you need anything at all, drop Kelly a line!
                <li>(123) 456-7890 x 123</li>
                <li><a href="#">[email protected]</a></li>
// Step 2
function codepotent_register_static_dashboard_widget() {
        'my_static_dashboard_widget', // your own custom widget id
        'My Widget', // the widget box title
        'codepotent_display_static_dashboard_widget' // function that displays content
// Step 3
add_action('wp_dashboard_setup', 'codepotent_register_static_dashboard_widget');

Extra Credit

The example above will show the widget to anyone who has access to the main dashboard. Can you think of a way to show the widget to only admin users? Or, how about limiting it to just a single user? I think you can figure it out!

Wrapping Up

Adding a static widget to the ClassicPress dashboard is actually quite easy. There’s no need to add a whole plugin just to show some information in the dashboard. With very little work, you can create your own great-looking dashboard widgets and show your clients that their site is on your mind. Add text, links, images – or anything else that might be helpful to your clients!

What do you think?

Did you realize dashboard widgets were so easy to create? Have you been using a plugin and are going to switch to this method instead? What other things might you include in a dashboard widget? I’d love to hear your thoughts – let me know in the comments!

This tutorial has been provided by John Alarcon and was originally published on The original post can be found here.

Convert a Code Snip into a ClassicPress Utility Plugin

A beginner’s guide to converting procedural PHP into namespaced or object-oriented PHP – with a very understandable apples-to-apples comparison! This will be a primer for a more in-depth article on using namespacing in ClassicPress plugins.

The Tutorial

If you’re like most, you will have searched the web and found code-snips for your ClassicPress website. Let’s say you wanted to change the footer text in the dashboard. After a quick search, you find the following code-snip with instructions to place it into your theme’s functions.php file.

function custom_footer_text($text) {
    return 'The best debugging tool is a good night\'s sleep.';
add_filter('admin_footer_text', 'custom_footer_text');

First off, code-snips should go into a utility plugin, rather than your theme’s functions.php file. This is achieved by adding a short comment at the top. Additionally, the function name is prefixed to prevent code collisions. Here’s what that looks like.

* Plugin Name: My Utility
* Description: A safe place for code-snips.
* Note: save file to /wp-content/plugins/my-utility/my-utility.php 
function yourownprefix_custom_footer_text($text) {
    return 'The best debugging tool is a good night\'s sleep.';
add_filter('admin_footer_text', 'yourownprefix_custom_footer_text');

Great! The code-snip is now held safely in a utility plugin that can be activated and deactivated in your dashboard. The above example is written in basic, procedural PHP and, because the function name has a prefix, it is nicely isolated from clashing with other code in the system.

Prefixing your code in this way is usually enough to prevent collisions, so, if that’s all you’re after, you can stop here. However, also note that, as you find new code snips, you can add them to this same utility plugin; there’s no need to create another. Now, git ta steppin’, … the rest of us want to namespace this thing! So, let’s!

* Plugin Name: My Utility
* Description: A safe place for code-snips.
* Note: save file to /wp-content/plugins/my-utility/my-utility.php 
namespace YourOwnPrefix\Utility;
function custom_footer_text($text) {
    return 'The best debugging tool is a good night\'s sleep.';
add_filter('admin_footer_text', __NAMESPACE__.'\custom_footer_text');

As you can see, the big difference is that the prefix is used in the namespace instead of the function name, and the __NAMESPACE__ magic constant is used when hooking the function into ClassicPress. This is handy when your plugin grows to contain a lot of functions; you can change the namespace in one single place, instead of changing a bunch of prefixes. Namespacing is the actual built-in PHP method for isolating, or encapsulating, our code, but, more often, you’ll see code being encapsulated with object-oriented PHP. Here’s that same code-snip as an object-oriented plugin.

* Plugin Name: My Utility
* Description: A safe place for code-snips.
* Note: save file to /wp-content/plugins/my-utility/my-utility.php 
class Yourownprefix_Utility {
    // Add your actions and filters to this method.
    public function __construct() {
        add_filter('admin_footer_text', [$this, 'custom_footer_text']);
    public function custom_footer_text($text) {
        return 'The best debugging tool is a good night\'s sleep.';
new Yourownprefix_Utility;

In the case of object-oriented PHP, you can simply use the __construct() (or similar initialization) method to hold your action and filter hooks. I quite like this style of keeping all the actions and filters together and is the method I tend to use most. And, the $this variable is extremely handy when you want to pass data back and forth between the various methods (functions) inside the class.

Wrapping Up

As you can see, a code-snip can be added to your ClassicPress site without having to add it to your theme’s functions.php file. Placing your code-snips into a utility plugin is a better practice and gives you a quick means of activating and deactivating all of them quickly. And, of course, there are various ways to encapsulate our code and achieve the exact same result. There’s no requirement to use one method or another. You decide. As long as you have at least used unique prefixes, as shown in the first plugin example, you can be reasonably sure your code will be safe from collisions…and safe from theme changes, too!

What do you think?

Was it helpful to see a simple code-snip converted into a plugin? Did it answer any questions to see that plugin converted into other styles of code? Do you have a preference over which style to write your code? I’m curious to hear your thoughts – let me know in the comments!

Note: the header comment used in the examples here was very basic. There are more fields that can be used.

This tutorial has been provided by John Alarcon and was originally published on The original post can be found here.

Creating a Child Theme

When performing changes to your theme, like changing up the template; adding functionality; or adding CSS, it is often advised to use a child theme. But how do you make a child theme? What even is a child theme? Why do you need this? All questions that people new to this level of ClassicPress will come up against. This tutorial will do its best to answer these questions in the easiest way possible.

What is a child theme?

Simply said, a child theme is a theme that is dependent on another theme. The theme that the child theme is dependent on is called the parent theme. The child theme will pull its code from the parent theme to fill in any gaps. This will make it appear as if you’re using the parent theme.

So why use a child theme?

In the child theme you can overwrite templates, functions and CSS from the parent theme without actually changing the parent theme. This means that when you update the parent theme, these changes will remain in effect. So, you can safely make all the template, styling and functionality changes to a theme that you want, without having updates overwrite your efforts.

How do I make a child theme?

By now you should be convinced that if you are going to make changes to a theme, you should get a child theme. So let’s make one step by step.

What do I need?

  • Access to your ClassicPress files, either through FTP or a file manager.
  • A parent theme of your choosing. For this tutorial we will use Twenty Seventeen
  • A code/text editor.

The Tutorial

Step 1: Open your ClassicPress installation in FTP or a file manager and Navigate to wp-content > themes.

themes folder

Step 2: Create a new folder and access it. The name does not really matter, but for future reference, it is easiest to name this folder <themename>-child. So in this case it will be twentyseventeen-child.

child theme folder

Step 3: Create a file named style.css in the new folder and open it in an editor.


Step 4: Next we are going to create some theme details. Like below:

  • Theme Name => Your chosen theme name
  • Theme URL => Your URL
  • Description => A short description of the child theme
  • Author => Your name
  • Author URL => Your domain
  • Template => The folder name of your parent theme, in this case twentyseventeen, but this is different for each theme.
  • Text-domain => The folder name of your child theme, in this case twentyseventeen-child.

Note: Only Theme Name and Template are required, the rest is optional.

Now add these details to the style.css you created like below and save the file.

Theme Name: Twenty Seventeen Child
Theme URL:
Description: Example of a Child theme for Twenty Seventeen
Author: klein
Author URL:
Template: twentyseventeen
Text Domain: twentyseventeen-child
/* You can add custom CSS below */

style header

Step 5:
Create a file named functions.php in the child theme folder and open it in an editor.


Step 6: Add the following code to the functions.php file and save it.

//Enqueue parent theme css
add_action( ‘wp_enqueue_scripts’, ‘enqueue_parent_theme_css’ );
function enqueue_parent_theme_css() {
wp_enqueue_style( ‘parent-style’, get_template_directory_uri().’/style.css’ );
//Add custom functions below

enqueue parent style

Step 7:
Go to your ClassicPress admin area and go to themes. When here, ‘Activate‘ the child theme.

Step 8:
Your child theme is ready for use!

How do I start making changes?

Now that your child theme is ready for use, you obviously want to start making changes. As mentioned before, there are three main uses for your child theme: change styling, add functionality and edit templates. Doing these three things is easy!

Changing styles

To overwrite your theme’s CSS, simply go to the style.css file you made during the creation of this child theme. Add the CSS changes you want to this file below the details and save them!

Note: The child theme styles are rendered after the parent, so anything you add here will overwrite the specifications made in the parent’s style.css file.

Adding functionality

Often when you are trying to add functionality through snippets, you will be instructed to add them to your theme’s functions.php. It works the same way with a child theme. You can add these snippets or write your own in the functions.php file you made during the creation of this child theme. Just add them below the enqueue_parent_theme_css function.

Editing templates

To edit a template file you must first find the file in your parent theme. For example single.php, sidebar.php, footer.php, etc. When you have found the file you want to edit, make a copy and upload this copy to your child theme. Be careful to keep the URL structure intact! For example, if you found a file in the folder template-parts, make sure it’s also placed in a folder named template-parts in your child theme.

Some plugins also gives you the option to edit their templates in your child theme! An example of this is WooCommerce. To do this, you go to your plugin folder and look in the templates folder. Copy the file you want to edit. When in your child theme, make a folder with the same name as the plugin’s folder (This folder takes the place of templates in your URL structure) and add the copy of the file you wish to edit to this folder. Also make sure the URL structure stays intact from here, just like a theme file.

Note: Because the plugin folder in your child theme takes the place of templates, you do not need to add a templates folder in these plugin folders.

Resolving merge conflicts on the ClassicPress GitHub

There has been some interest / questions about resolving merge conflicts on GitHub. This happens when two pull requests (PR) change the same part of a file in different ways. We have an example of such a PR here, so I’ll walk through the steps I’m taking to resolve the conflict.

There are GUI tools that make this easier to understand, but basically: there are two different versions of this file, and this interface is asking me which one is correct.

In between the <<<<<<< and ======= markers, there is this line:

This corresponds to my PR: “This line was left in your PR”.

But, in between ======= and >>>>>>>, there is nothing: “This line was deleted in the `master` branch”.

This is because I deleted the line *below* that one in my PR, and in another PR the line that has the conflict was also deleted. So, in this case, the way to resolve the conflict is to delete that entire section

The next conflict is similar: I removed this whole section in this PR, but it was modified elsewhere. Since I still want to remove it, I’ll resolve the conflict by just removing that whole section.

Last one! In this case, this section was _modified_ in two different PRs, and I need to decide what the final version should be after all these changes.

After resolving all conflicts, you get a “Commit merge” button, which adds a new commit to the PR:

All done, now just waiting for the automated tests to make sure I didn’t break anything 😉