• How I’m testing the internationalization and localization of my WordPress plugins

    How I’m testing the internationalization and localization of my WordPress plugins

    A few months ago, having resolved to internationalize, localize and test my WordPress plugins, I started busily beavering away at a solution that will enable me to automatically deliver UK English versions of my plugins.

    Now that Global WordPress Translation Day #3 is fast approaching it seems timely to write up an outline of my approach. The solution involves a number of fairly well defined processes, and a lot of repetition.


    WordPress.org provides a tool that enables translators, known as polyglots, to provide translations of text written in US English into the translator’s own locale. A tool called makepot discovers the strings to be translated directly from the source code. There is a defined set of functions which makepot looks for. It extracts the strings to be translated from the parameters passed to these functions. It also extracts any notes for the translators. The polyglots perform their translations on GlotPress. Once the strings have been translated and approved, the target language files are automatically delivered. If the translatable strings are changed, in a new version of a plugin, then the polyglots have to revisit their translations.

    /* translators: examine the tone */
    $translated = _x( 'Check color', 'examine', 'my-text-domain' );

    My WordPress plugins were written in UK English; code, comments and translatable text. A long time ago, to reduce development effort, I encapsulated calls to the WordPress translation functions within functions provided by my own plugins.

    p( "This box intentionally left blank." );

    I then used a modified version of makepot ( called makeoik ) to detect the strings being passed to higher level functions. The English version of the file was then available for translation.

    This solution worked fine for my self hosted plugins. But it was no good for plugins hosted on wordpress.org since makepot detected hardly any of my translatable strings.


    I had two options.

    1. Try to convince the rest of the WordPress community that makepot can be extended to detect translatable strings being passed to just about any function/method and that this could lead to easier to read and more efficient code.
    2. Fall in line and change my code.

    Thinking it would be easier, I chose the second option.

    I developed a conversion strategy involving:

    • A new shared library delivering static methods that don’t perform any translation.
    • Support for translatable strings in shared libraries.
    • Backward compatibility for existing unchanged plugins.
    • PHP Unit testing of the original code before any conversion.
    • Pragmatic fixing of any problems discovered.
    • Automatic build time localization.
    • PHP Unit testing of the converted code for UK English.
    • PHP Unit testing of the converted code for the bbboing language.

    Class BW_, delivered by shared library file libs/class-BW-.php, provides the new static methods that don’t perform translation. So any strings that need translating must be passed through the standard WordPress functions. ie. Any calls that previously performed translation implicitly, need to be converted to calls performing translation explicitly.

    BW_::p( __( "This box intentionally left blank", "oik" ) );

    For source code in shared libraries I use a text domain of null. My newly invented Just Translate It logic, working in cahoots with makepot, ensures that it’ll find a translation from the text domain of the plugin that delivered the shared library file at run time.

    Automatic build time localization

    I developed a routine to automatically produce the UK English version direct from the US English version, applying the known spelling variants, and a couple of special overrides which take context into account.

    Since my source code was written in UK English I included logic to detect strings which needed to be converted to the US English spelling.

    99.999% of the time, testing the output generated for UK English will not identify problems where translation has not been performed. So I modified the code from my bbboing plugin to generate the strings for the bb_BB locale.

    The new logic, which no longer uses [api shuffle()], since that produces random results, ensures that most strings will be different. e.g. “This box intentionally left blank” becomes “Tihs bOx itnneitnolaly lfet balnk”.

    PHP Unit Testing

    I’ve extended my PHPUnit testing in situ logic to include helper functions in class BW_UnitTestCase. This reduces the effort to create a test case.

    The process for each internationalisable testable function is something like this.

    • Develop pre-conversion tests for en_GB.
    • If necessary, allow the original code to use deprecated logic.
    • Convert the code.
    • Automatically generate language files.
    • Retest for en_GB.
    • Allow for very few translation differences.
    • Do not allow deprecated logic.
    • Copy / cobble the en_GB test for bb_BB.
    • Retest.
    • Visually check for bb_BB language where applicable.
    • Commit changes.

    The process for writing each test is iterative, involving helper functions that manipulate the output in order to generate the expected output, which is saved to tests/data/locale/test_name.html. On subsequent iterations the calls to some of the helper functions are removed.

    For example. For this simple function

    function oik_callback() {
    BW_::p( __( "This box intentionally left blank", "oik" ) );

    the first iteration of the test for the bb_BB locale is as follows.

    function test_oik_callback_bb_BB() {
      $this->switch_to_locale( 'bb_BB' );
      $html = bw_ret( oik_callback() );
      $html_array = $this->tag_break( $html );
      $this->generate_expected_file( $html_array );
      $this->assertArrayEqualsFile( $html_array );
      $this->switch_to_locale( 'en_GB' );

    This produces the following test output.

    oik-wp running WordPress 4.8.1
    Using wordpress-develop-tests plugin
    PHPUnit 6.2.0 by Sebastian Bergmann and contributors.
    Runtime: PHP 7.0.7
    Configuration: C:\apache\htdocs\wordpress\wp-content\plugins\oik\phpunit.xml.dist
    ............................................................... 63 / 112 ( 56%)
    Tihs bOx itnneitnolaly lfet balnk
    There was 1 failure:
    1) Tests_oik_admin::test_oik_callback_bb_BB
    Failed asserting that file "tests/data/bb_BB/test_oik_callback_bb_BB.html" exists.

    To finalise the test, having previously verified that all the expected translations have been performed, I

    • Edit the missing file tests/data/bb_BB/test_oik_callback_bb_BB.html.
    • Paste in the echo’ed output and Save.
    • Remove the call to $this->generate_expected_file.
    • Rerun phpunit.

    Note: Subsequent changes to the source code involving changes to the translatable strings will require related updates to the expected output files, both UK English and bb_BB.

    Current status ( Sep 2017)

    The internationalization work is approximately 50% complete.

    • oik v3.2 is still under development.
    • In the most recent development version on wordpress.org makepot found 123 strings.
    • 100% of these have been translated to UK English.
    • Locally I have 660 strings translated to UK English and bb_BB.
    • That’s over 5 times the number on wordpress.org
    • oik now contains 157 tests, 1195 assertions.
    • oik-libs now contains 64 tests, 577 assertions.

    I’m not quite sure what I’ll get up to on the 30th of September. It depends on how I progress over the next couple of days.


    Topic GitHub reference
    WordPress plugin internationalization
    Global WordPress Translation Day #3
    WordPress Internationalization codex
    100% translatable and localizable on WordPress.org bobbingwide/oik#9
    Using null text domain for Just Translate It bobbingwide/oik-libs#7
    PHP Unit tests for shared libraries bobbingwide/oik-libs#6
    Internationalization for the oik suite of plugins bobbingwide/oik-i18n
    Help functions in BW_UnitTestCase bobbingwide/oik-batch#24
    In situ PHPUnit testing How to run PHPUnit tests for WordPress plugins in situ
    GlotPress GlotPress/GlotPress-WP
    Semi-automatic status reporting bobbingwide/greprecated
    bbboing plugin bobbingwide/bbboing


    Last updated:

    November 7, 2017

Today’s word is this:







Tide times from tidetimes.org.uk

Tide Times & Heights for Langstone Harbour on
14th April 2024
03:54 High Tide ( 4.45m )
09:07 Low Tide ( 1.41m )
16:32 High Tide ( 4.33m )
21:33 Low Tide ( 1.73m )

Tide times from tidetimes.org.uk

Tide Times & Heights for Northney on
14th April 2024
04:13 High Tide ( 4.3m )
09:12 Low Tide ( 0.9m )
16:49 High Tide ( 4.13m )
21:36 Low Tide ( 1.31m )