# Test Internationalization Functions
Share on Social Plugin uses WordPress Internationalization (i18n) functions extensively and we need an easy method to test the string translations. In this blog, we explain the unit tests of i18n functions.
Setup Language Files for Tests
In WordPress Localization, we installed GetText software required for WordPress i18n and l10n, and also generated language files for the plugin.
To test plugin internationalization, we require separate set of language files. Procedure to generate test language files is described here.
Language files for tests are placed in tests/phpunit/langs
directory.
Create a new directory with next command.
$ cd share-on-social/tests/phpunit
$ mkdir langs
Next, copy the POT file generated by localization, to the test langs directory.
$ cd share-on-social
$ cp langs/share-on-social.pot tests/phpunit/langs
Next, generate PO file for the default language. The default language of Share on Social Plugin is en_US.
$ cd tests/phpunit/langs
$ msginit -i share-on-social.pot -o sos-domain-en_US.po -l en_US
The PO for en_US is shown in the next listing. For default language, both msgid (orginal string) and msgstr (translated string) will have same string.
share-on-social/tests/phpunit/langs/sos-domain-en_US.po
# Copyright (C) 2014 Share on Social
# This file is distributed under the same license as the Share on Social package.
msgid ""
msgstr ""
"Project-Id-Version: Share on Social 1.0.0n"
"Report-Msgid-Bugs-To: http://wordpress.org/support/plugin/share-on-socialn"
"POT-Creation-Date: 2014-11-14 13:45:33+00:00n"
"MIME-Version: 1.0n"
"Content-Type: text/plain; charset=UTF-8n"
"Content-Transfer-Encoding: 8bitn"
"PO-Revision-Date: 2014-11-14 19:16+0530n"
"Last-Translator: m <m@m>n"
"Language-Team: Englishn"
"Language: en_USn"
"Plural-Forms: nplurals=2; plural=(n != 1);n"
#: admin/class-activator.php:109
msgid "Content is Locked"
msgstr "Content is Locked"
#: admin/class-activator.php:110
msgid "Share to unlock the content"
msgstr "Share to unlock the content"
....
Copy the default PO file to Esperanto France language file.
$ cd tests/phpunit/langs
$ cp sos-domain-en_US.po sos-domain-eo_FR.po
Next, edit the sos-domain-eo_FR.po
and prefix each and every
msgstr string with Espéranto-France. The default and modified
msgstr looks as follows.
# ORIGINAL
msgstr "Content is Locked"
# MODIFIED
msgstr "Espéranto-France Content is Locked"
Also, modify the header and change Language-Team to Esperanto and
Language to es_FR. The modified sos-domain-eo_FR.po
file is shown
in the next listing.
share-on-social/tests/phpunit/langs/sos-domain-eo_FR.po
# Copyright (C) 2014 Share on Social
# This file is distributed under the same license as the Share on Social package.
msgid ""
msgstr ""
"Project-Id-Version: Share on Social 1.0.0n"
"Report-Msgid-Bugs-To: http://wordpress.org/support/plugin/share-on-socialn"
"POT-Creation-Date: 2014-11-14 13:45:33+00:00n"
"MIME-Version: 1.0n"
"Content-Type: text/plain; charset=UTF-8n"
"Content-Transfer-Encoding: 8bitn"
"PO-Revision-Date: 2014-11-14 19:17+0530n"
"Last-Translator: m <m@m>n"
"Language-Team: Esperanton"
"Language: eo_FRn"
"Plural-Forms: nplurals=2; plural=(n != 1);n"
#: admin/class-activator.php:109
msgid "Content is Locked"
msgstr "Espéranto-France Content is Locked"
#: admin/class-activator.php:110
msgid "Share to unlock the content"
msgstr "Espéranto-France Share to unlock the content"
....
Finally, generate MO file for Esperanto from PO using GetText’s msgfmt
command.
$ cd tests/phpunit/langs
$ msgfmt -o sos-domain-eo_FR.mo sos-domain-eo_FR.po
With that, language files for i18n unit tests are ready, and we can go ahead with the translation tests.
Test Internationalization Functions
In translation tests, we use Util::change_locale()
method to change
the locale and load the language files from tests/phpunit/langs
directory.
share-on-social/tests/phpunit/util/class-util.php
static function change_locale ( $lang ) {
global $locale;
$locale = $lang;
load_plugin_textdomain( 'sos-domain', FALSE,
'share-on-social/tests/phpunit/langs' );
}
Text domain is unloaded in teardown() method which reverts the test case back to the default language.
share-on-social/tests/phpunit/tests/test-help.php
class Test_Help extends WP_UnitTestCase {
public function setup () {
parent::setup();
require_once 'admin/class-help.php';
$this->sos_help = new Sos_Help();
}
public function teardown () {
parent::teardown();
unload_textdomain( 'sos-domain' );
}
Let’s go through a method which uses internationalization function to
understand how translations are tested. In Sos Locker admin screen, we
display context help to create a new locker and these help text tabs are
generated in Sos_Help
class. Sos_Help::locker_id_tab()
returns help
text tab for locker id, and as we use i18n function __()
for the help
text, they get translated based on locale.
share-on-social/admin/class-help.php
function locker_id_tab () {
$label = __( 'Locker ID', 'sos-domain' );
$help1 = __( 'Enter a uniquie ID for the locker. ', 'sos-domain' );
$help1 .= __( 'Both name and number are allowed as the id. ',
'sos-domain' );
$help2 = __(
'Use some descriptive name as locker id which is easy to remember',
'sos-domain' );
$html = <<<EOD
<h3>$label</h3>
<p>$help1</p>
<p>$help2</p>
EOD;
return $this->get_tab( 'locker_id_tab', $label, $html );
}
The method is tested in test case Test_Help
, where the method
Test_Help::test_locker_id_tab()
test the locker id help text for
default language en_US.
share-on-social/tests/phpunit/tests/test-help.php
public function test_locker_id_tab () {
$tab = $this->sos_help->locker_id_tab();
$this->assertCount( 3, $tab );
$this->assertSame( 'locker_id_tab', $tab[ 'id' ] );
$this->assertSame( 'Locker ID', $tab[ 'title' ] );
$expected = $this->expected_locker_id_tab();
$this->assertSame( Util::trim_whitespaces( $expected ),
Util::trim_whitespaces( $tab[ 'content' ] ) );
}
It fetch the help tab array from method under test
Sos_Help::locker_id_tab()
. As the text domain is not loaded, the
$tab[’title’] returns default string ‘Locker ID’.
To test the help text, it calls a private method
Test_Help::expected_locker_id_tab()
which returns the expected help
text for the tab. For default language, the $lang_str parameter is
null, so the expected text will not have any prefix.
share-on-social/tests/phpunit/tests/test-help.php
private function expected_locker_id_tab ( $lang_str = '' ) {
$lang_str == '' ? $lang_str : $lang_str .= ' ';
$html = <<<EOD
<h3>{$lang_str}Locker ID</h3>
<p>{$lang_str}Enter a uniquie ID for the locker. {$lang_str}Both name and number are allowed as the id. </p>
<p>{$lang_str}Use some descriptive name as locker id which is easy to remember</p>
EOD;
return $html;
}
Actual translation is tested in next test,
Test_Help::test_locker_id_tab_translate()
.
share-on-social/tests/phpunit/tests/test-help.php
public function test_locker_id_tab_translate () {
Util::change_locale( 'eo_FR' );
$tab = $this->sos_help->locker_id_tab();
$this->assertCount( 3, $tab );
$this->assertSame( 'locker_id_tab', $tab[ 'id' ] );
$this->assertSame( 'Espéranto-France Locker ID', $tab[ 'title' ] );
$expected = $this->expected_locker_id_tab( 'Espéranto-France' );
$this->assertSame( Util::trim_whitespaces( $expected ),
Util::trim_whitespaces( $tab[ 'content' ] ) );
}
In this test, we first change the locale to Esperanto France by calling
utility method Util::change_locale( 'eo_FR' )
. Earlier, while
preparing the eo_FR language file, we prefixed all msgstr items
with Espéranto-France. Now, i18n functions kicks in and returns the
translated strings. For example, for string ‘Locker ID’, it returns
‘Espéranto-France Locker ID’.
As done before, we fetch the help tab array from method under test
Sos_Help::locker_id_tab()
. But this time, as text domain is set to
Esperanto by Util::change_locale(), the $tab[’title’] is loaded with
the string from eo_FR file, and it is ‘Espéranto-France Locker ID’
instead of default ‘Locker ID’.
Since eo_FR is loaded, tabs’ help text is also now prefixed with Espéranto-France. So, while calling the private method Test_Help::expected_locker_id_tab(), we pass string Espéranto-France as parameter so that expected text is also prefixed with string Espéranto-France. If everything is in order - translation files in proper directory, loading of text domain and proper use of i18n function - then test passes through.
In the next blog, we show how to test WordPress Ajax calls.