In my efforts to get my WordPress theme on the official theme directory, I had to update the .pot file. I started out with a manual process, and eventually settled on a completely automated process (as any good developer should).

My WordPress theme, Cover, is based on the starter theme Underscores. It’s not a framework, but rather a starting point for building a new theme. Included in its download is the .pot file, which is used to provide localization for static text strings within the theme.

In my theme’s submission, I had neglected to modify cover.pot to accurately reflect the changes in the php files. It was no surprise that my submission was rejected.

I started out fixing cover.pot manually; going line by line through each php file referenced. It then occurred to me that there might exist a utility to assist me with the process. So after a little searching, I found Easy Po, an application capable of scanning all the php files in my theme for localization function calls. I ended up with a generated cover.pot that was more accurate than if I’d coded it by hand.

Easy Po automatically detects all the relevant php files in the directory you specify.

As happy as I was that I didn’t have to code the file by hand, it was still a manually initiated process. It would be nice if I could incorporate the .pot file generation into my Grunt workflow.


I already have a pretty decent set of automated commands defined in Cover’s GruntFile.js. A quick search revealed an existing Grunt plugin, grunt-pot. It didn’t take much to incorporate it into the init:

  // other stuff
  pot: {
    options: {
      text_domain: 'cover',
      dest: 'languages/',
      keywords: [ '__', '_e', 'esc_html__', 'esc_html_e', 'esc_attr__', 'esc_attr_e', 'esc_attr_x', 'esc_html_x', 'ngettext', '_n', '_ex', '_nx' ]
    build: {
      src: [
      expand: true
  // more stuff

A note here: I had to exclude the folder node_modules so the plugin wouldn’t parse other resources I didn’t plan on bundling with my theme.

Don’t forget to load the task, too.


Feeling confident, I ran the command to start the process.

$ grunt pot

I was met with this error, followed by sadness.

Running "pot:build" (pot) task
Destination: languages/cover.pot
Warning: Command failed: 'xgettext' is not recognized as an internal or external command, operable program or batch file.
Use --force to continue.

Aborted due to warnings.

The plugin page for grunt-pot listed no dependencies, but that wasn’t strictly true. It still needed the xgettext command to be available. Fortunately, I had already installed it — it just couldn’t be run from the command line yet.

Inside the application folder for Easy Po, there was a gettext folder, inside which was an application: xgettext.exe. I needed to make this application available from the command line, which meant adding it to the system path.

I opened the Environment Variables dialog from inside the Windows System Properties. I edited the Path user variable, adding this directory. (Your path may differ, depending on where you put the application folder.)

C:\Easy Po\gettext

I clicked OK to close all the open dialog windows, and ran the Grunt command again.

$ grunt pot

This time, it ran successfully:

Running "pot:build" (pot) task
Destination: languages/cover.pot

Done, without errors.


I’ve also added the pot task to the main build process in GruntFile.js so that every time I do a build — which compiles the Sass into a stylesheet and minifies all the JavaScript — it also rescans the php files for any changes and outputs an updated cover.pot file.

Husband. Daddy. Programmer. Artist. I'm not an expert, I just play one in real life.