Here’s how localization (aka Internationalization or i18n ) of a WordPress plugin with Vue front-end can be done. Language resources need to be used both in plugin WordPress backend and Vue based front end. Plugin should be translatable with WordPress standard tools. and translations (.po, .mo files) should be served by WordPress.
Before you start
You should have gettext installed in your system. Y
Defining translatable resources
We can not use strings for showing information to end user in multi-language plugin. We will use gettext functions instead. These functions provide a mechanism for automatic generation of central language resources (.po files) and means to present translated strings from that resource. Here is an example how function __() is used for this purpose in WordPress plugin backend code :
<?php echo '<strong>' . __('Mango Form Processor works only when Contact Form 7 is installed and activated.') . '</strong>';
All the language resources that are used in Vue component need to be defined in plugin php code and should be passed to Javascript front end with the help of WordPress function wp_localize_script. Goal here is to generate localized resources that can be accessed in Javascript as global variable. For more details, see here.
The function is called in callback for the action admin_enqueue_scripts
<?php function loadAdminJs() { add_action('admin_enqueue_scripts', 'initAdminPage'); } function initAdminPage() { registerVueScripts(); //encqueues JS Vue frontend scripts wp_localize_script( 'mangofp_vuejs', 'MANGOFP_RESOURCES', //name of the global variable that is geenrated for Javascript [ 'adminUrl' => get_rest_url( null, '/mangofp', 'rest'), //uri for backend api that Vue frontend will use 'strings' => MangoFp\Localization::getStrings() //actual language resources that will be used in Vue ] ); }
registerVueScripts enqueues all our plugin Javascript resouces to the front end. For details, look here. Data passed to Javascripts with wp_language_script does not have to be only l18n resources. We are also passing url to our plugin API that Javascript front end will use. Actual localization resources are fetched with MangoFp\Localization::getStrings() and are defined like this:
<?php class Localization { static public function getStrings() { $MANGOFP = 'mangofp'; //domain for the plugin language resources return [ 'Send' => esc_html__('Send', $MANGOFP), 'State' => esc_html__('State', $MANGOFP), 'All' => esc_html__('All', $MANGOFP), 'Confirm' => esc_html__('Confirm', $MANGOFP), 'Confirm and send' => esc_html__('Confirm and send', $MANGOFP) //... ]; } }
esc_html__ here is a gettext function that “guards” our plugin’s front end from invalid UTF8 characters and unwanted HTML code.
Generate POT file
There are several ways for generating pot-files. Our solution is based on Grunt. If you don’t have already (but for Vue front end you probably have) NPM installed, then do it. In your plugin directory add package.json file
{ "name": "Your plugin name", "version": "0.0.1", "description": "Your plugin description", "scripts": { "gettext": "grunt gettext" }, "dependencies": {}, "devDependencies": { "grunt": "^0.4.5", "grunt-pot": "^0.2.1" } }
If you already have package.json file, just add devDependencies to it. Now execute on command line in your plugin directory:
npm install
in your plugin directory create Gruntfile.js
module.exports = function(grunt) { grunt.initConfig({ pot: { options: { text_domain: 'mangofp', //Your text domain. Produces mangofp.pot dest: 'languages/', //directory to place the pot file keywords: ['gettext', '__', 'esc_html__', 'esc_html_e'], //gettext functions to look for language resources }, files: { src: ['**/*.php'], //Parse all php files expand: true, } }, }); grunt.loadNpmTasks('grunt-pot'); grunt.registerTask('gettext', [ 'pot', ]); };
Now you are ready to create the pot file. You can do it from command line like this:
npm run gettext
Localize language resources
For the actual translation we are using WordPress plugin Loco Translate. We recommend using local WordPress installation for plugin development and then it is also convenient to install Loco Translate there, too. Now you can translate the resources from primary language to some additional language in your local development environment.
Make sure that you transfer generated po files to your versioning system and/or staging environments.
Use translations in Vue components
Now localized language resources are accessible in end-user browser.
Language resources could be referenced from this global object, but from Vue component its more convenient through a Vue plugin.
Here is the source code of this plugin. Function $locStr accesses a string. If the string is not found, it returns the text in the original language (key for the language resouce)
/*globals MANGOFP_RESOURCES:false */ const locStr = { install(Vue) { Vue.prototype.$locStr = function(key) { if ( !MANGOFP_RESOURCES || !MANGOFP_RESOURCES.strings || !MANGOFP_RESOURCES.strings[key] ) { return key; } return MANGOFP_RESOURCES.strings[key]; }; }, }; export default locStr;
Plugin is stored in plugins/locStr.js and the plugin needs to be used by your Vue object. This is usually done in main.js through use of command: Vue.use(locStr).
Here is an example of the complete main.js file that uses locStr ja vuetify plugins:
import Vue from 'vue'; import App from './App.vue'; import store from './store'; import vuetify from './plugins/vuetify'; import locStr from './plugins/locStr'; Vue.config.productionTip = false; Vue.use(locStr); //add this to your main.js file new Vue({ store, vuetify, render: h => h(App), }).$mount('#app');
Language string in Vue code templates can now be used like this:
<v-sheet v-if="selectedItem"> {{ $locStr('Change') }} <v-select :items="labels" v-model="selectedLabel" :label="$locStr('Label')" > </v-select> ... </v-sheet>
And in Javascript objects like this:
<script> export default { data() { return { expanded: [], headers: [ { text: this.$locStr('Date'), value: 'dateTime' }, { text: this.$locStr('Status'), value: 'changeSubType' }, { text: this.$locStr('To'), value: 'contentTo' }, ], }; }, ... } </script>
Happy localizing!