Internationalization (i18n) enables ShahiAssist to be translated into multiple languages, making it accessible to a global audience. This guide covers complete i18n implementation, translation management, and localization best practices.
Text Domain Setup
Plugin Text Domain
`php
// Main plugin file
class ShahiAssist_Plugin {
public function __construct() {
// Load plugin textdomain
addaction(‘init’, [$this, ‘loadtextdomain’]);
// Load textdomain for admin
addaction(‘admininit’, [$this, ‘loadadmintextdomain’]);
}
public function load_textdomain() {
loadplugintextdomain(
‘shahi-assist’,
false,
dirname(plugin_basename(FILE)) . ‘/languages/’
);
}
public function loadadmintextdomain() {
loadplugintextdomain(
‘shahi-assist-admin’,
false,
dirname(plugin_basename(FILE)) . ‘/languages/admin/’
);
}
}
// Instantiate the plugin
new ShahiAssist_Plugin();
`
Text Domain Constants
`php
// Define text domain constants
define(‘SHAHIASSISTTEXT_DOMAIN’, ‘shahi-assist’);
define(‘SHAHIASSISTADMINTEXTDOMAIN’, ‘shahi-assist-admin’);
// Helper functions for consistent text domain usage
function _shahiassist($text) {
return _($text, SHAHIASSISTTEXTDOMAIN);
}
function eshahi_assist($text) {
e($text, SHAHIASSISTTEXTDOMAIN);
}
function nshahi_assist($single, $plural, $number) {
return n($single, $plural, $number, SHAHIASSISTTEXTDOMAIN);
}
`
String Translation
Basic Translation Functions
`php
// Basic translations
echo __(‘Hello World’, ‘shahi-assist’);
echo __(‘Welcome to ShahiAssist’, ‘shahi-assist’);
// With context for disambiguation
echo _x(‘Post’, ‘noun’, ‘shahi-assist’);
echo _x(‘Post’, ‘verb’, ‘shahi-assist’);
// Plural forms
printf(
_n(‘%s ticket’, ‘%s tickets’, $count, ‘shahi-assist’),
numberformati18n($count)
);
// Echo directly
_e(‘Settings saved successfully’, ‘shahi-assist’);
`
Dynamic String Translation
`php
// Translate dynamic content
function getstatuslabel($status) {
$labels = [
‘open’ => __(‘Open’, ‘shahi-assist’),
‘closed’ => __(‘Closed’, ‘shahi-assist’),
‘pending’ => __(‘Pending’, ‘shahi-assist’),
‘resolved’ => __(‘Resolved’, ‘shahi-assist’),
];
return $labels[$status] ?? __(‘Unknown’, ‘shahi-assist’);
}
// Translate with variables
function getwelcomemessage($user_name) {
return sprintf(
__(‘Welcome back, %s!’, ‘shahi-assist’),
eschtml($username)
);
}
`
JavaScript Translation
`php
// Enqueue script with translations
function enqueuefrontendscripts() {
wpenqueuescript(‘shahi-assist-frontend’, plugindirurl(FILE) . ‘js/frontend.js’, [‘jquery’], ‘1.0.0’, true);
// Localize script with translations
wplocalizescript(‘shahi-assist-frontend’, ‘shahiAssistL10n’, [
‘ajaxUrl’ => admin_url(‘admin-ajax.php’),
‘nonce’ => wpcreatenonce(‘shahiassistnonce’),
‘messages’ => [
‘confirmDelete’ => __(‘Are you sure you want to delete this ticket?’, ‘shahi-assist’),
‘saving’ => __(‘Saving…’, ‘shahi-assist’),
‘saved’ => __(‘Changes saved successfully’, ‘shahi-assist’),
‘error’ => __(‘An error occurred’, ‘shahi-assist’),
],
‘labels’ => [
‘priority’ => __(‘Priority’, ‘shahi-assist’),
‘status’ => __(‘Status’, ‘shahi-assist’),
‘category’ => __(‘Category’, ‘shahi-assist’),
]
]);
}
addaction(‘wpenqueuescripts’, ‘enqueuefrontend_scripts’);
// In JavaScript file
jQuery(document).ready(function($) {
$(‘.delete-ticket’).on(‘click’, function() {
if (confirm(shahiAssistL10n.messages.confirmDelete)) {
// Delete ticket
}
});
});
`
POT File Generation
WP-CLI POT Generation
`bash
Generate POT file using WP-CLI
wp i18n make-pot . languages/shahi-assist.pot –domain=shahi-assist
Generate POT for admin strings
wp i18n make-pot . languages/admin/shahi-assist-admin.pot –domain=shahi-assist-admin –include=”admin/”
`
Grunt/Gulp Task for POT Generation
`javascript
// gulpfile.js
const gulp = require(‘gulp’);
const wpPot = require(‘gulp-wp-pot’);
gulp.task(‘pot’, function() {
return gulp.src(‘*/.php’)
.pipe(wpPot({
domain: ‘shahi-assist’,
package: ‘ShahiAssist’,
bugReport: ‘https://example.com’,
lastTranslator: ‘Your Name
team: ‘Your Team
}))
.pipe(gulp.dest(‘languages/shahi-assist.pot’));
});
gulp.task(‘pot-admin’, function() {
return gulp.src(‘admin/*/.php’)
.pipe(wpPot({
domain: ‘shahi-assist-admin’,
package: ‘ShahiAssist Admin’,
bugReport: ‘https://example.com’,
lastTranslator: ‘Your Name
team: ‘Your Team
}))
.pipe(gulp.dest(‘languages/admin/shahi-assist-admin.pot’));
});
`
Custom POT Generation Script
`php
// tools/make-pot.php
require_once ‘vendor/autoload.php’;
use Gettext\Translations;
use Gettext\Generator\PoGenerator;
function generatepotfile($sourcedirs, $outputfile, $domain) {
$translations = new Translations();
$translations->setDomain($domain);
$translations->setHeader(‘Language’, ‘en’);
$translations->setHeader(‘Content-Type’, ‘text/plain; charset=UTF-8’);
foreach ($source_dirs as $dir) {
$files = glob($dir . ‘*/.php’);
foreach ($files as $file) {
$content = filegetcontents($file);
// Extract __() calls
pregmatchall(‘/_\(([“\’])(.?)\1\s,\s[“\’]’ . pregquote($domain) . ‘[“\’]\s\)/s’, $content, $matches);
foreach ($matches[2] as $string) {
$translation = $translations->find(null, $string);
if (!$translation) {
$translation = $translations->insert(null, $string);
}
$translation->addReference($file, 0);
}
// Extract _e() calls
pregmatchall(‘/e\(([“\’])(.?)\1\s,\s[“\’]’ . pregquote($domain) . ‘[“\’]\s\)/s’, $content, $matches);
foreach ($matches[2] as $string) {
$translation = $translations->find(null, $string);
if (!$translation) {
$translation = $translations->insert(null, $string);
}
$translation->addReference($file, 0);
}
// Extract _n() calls
pregmatchall(‘/n\(([“\’])(.?)\1\s,\s([“\’])(.?)\3\s,\s[^,]+\s,\s[“\’]’ . pregquote($domain) . ‘[“\’]\s*\)/s’, $content, $matches);
for ($i = 0; $i < count($matches[2]); $i++) {
$translation = $translations->find(null, $matches[2][$i]);
if (!$translation) {
$translation = $translations->insert(null, $matches[2][$i]);
$translation->setPlural($matches[4][$i]);
}
$translation->addReference($file, 0);
}
}
}
$generator = new PoGenerator();
$generator->generateFile($translations, $output_file);
}
// Generate main POT file
generatepotfile(
[‘includes/’, ‘public/’, ‘admin/’],
‘languages/shahi-assist.pot’,
‘shahi-assist’
);
// Generate admin POT file
generatepotfile(
[‘admin/’],
‘languages/admin/shahi-assist-admin.pot’,
‘shahi-assist-admin’
);
echo “POT files generated successfully!\n”;
`
Translation File Management
Loading Translation Files
`php
// Load translations for current locale
function loadshahiassist_translations() {
$locale = get_locale();
// Load main translations
$mofile = plugindir_path(FILE) . ‘languages/shahi-assist-‘ . $locale . ‘.mo’;
if (fileexists($mofile)) {
loadtextdomain(‘shahi-assist’, $mofile);
}
// Load admin translations
$adminmofile = plugindirpath(FILE) . ‘languages/admin/shahi-assist-admin-‘ . $locale . ‘.mo’;
if (fileexists($adminmo_file)) {
loadtextdomain(‘shahi-assist-admin’, $adminmo_file);
}
}
addaction(‘init’, ‘loadshahiassisttranslations’);
`
Translation Update Checker
`php
class ShahiAssistTranslationUpdater {
private $api_url = ‘https://api.github.com/repos/your-org/shahi-assist-translations/contents/’;
public function checkforupdates() {
$locale = get_locale();
$remotetranslations = $this->getremote_translations($locale);
$localtranslations = $this->getlocal_translations($locale);
$updates_available = [];
foreach ($remotetranslations as $file => $remotedata) {
$localfile = plugindir_path(FILE) . ‘languages/’ . $file;
if (!fileexists($localfile) ||
filemtime($localfile) < strtotime($remotedata[‘last_modified’])) {
$updates_available[] = $file;
}
}
if (!empty($updates_available)) {
updateoption(‘shahiassisttranslationupdates’, $updates_available);
$this->notifyadminofupdates($updatesavailable);
}
}
private function getremotetranslations($locale) {
$response = wpremoteget($this->api_url . $locale);
if (iswperror($response)) {
return [];
}
$files = jsondecode(wpremoteretrievebody($response), true);
$translations = [];
foreach ($files as $file) {
if (pathinfo($file[‘name’], PATHINFO_EXTENSION) === ‘po’) {
$translations[$file[‘name’]] = [
‘url’ => $file[‘download_url’],
‘lastmodified’ => $file[‘lastmodified’]
];
}
}
return $translations;
}
private function getlocaltranslations($locale) {
$pattern = plugindirpath(FILE) . ‘languages/*-‘ . $locale . ‘.po’;
return glob($pattern);
}
private function notifyadminof_updates($files) {
$adminemail = getoption(‘admin_email’);
$subject = __(‘ShahiAssist Translation Updates Available’, ‘shahi-assist’);
$message = sprintf(
__(‘New translations are available for ShahiAssist: %s’, ‘shahi-assist’),
implode(‘, ‘, $files)
);
wpmail($adminemail, $subject, $message);
}
}
`
Date, Time, and Number Formatting
Localized Date/Time Formatting
`php
// Localized date formatting
function formatticketdate($timestamp) {
$dateformat = getoption(‘date_format’);
$timeformat = getoption(‘time_format’);
return sprintf(
__(‘Created on %s at %s’, ‘shahi-assist’),
datei18n($dateformat, $timestamp),
datei18n($timeformat, $timestamp)
);
}
// Relative time
function getrelativetime($timestamp) {
$timediff = humantimediff($timestamp, currenttime(‘timestamp’));
if ($timestamp > current_time(‘timestamp’)) {
return sprintf(_(‘in %s’, ‘shahi-assist’), $timediff);
} else {
return sprintf(_(‘%s ago’, ‘shahi-assist’), $timediff);
}
}
`
Number Formatting
`php
// Localized number formatting
function formatticketcount($count) {
return sprintf(
_n(‘%s ticket’, ‘%s tickets’, $count, ‘shahi-assist’),
numberformati18n($count)
);
}
// Currency formatting
function format_currency($amount, $currency = ‘USD’) {
$formatted = numberformati18n($amount, 2);
// Add currency symbol based on locale
$locale = get_locale();
switch ($locale) {
case ‘en_US’:
return ‘$’ . $formatted;
case ‘en_GB’:
return ‘£’ . $formatted;
case ‘de_DE’:
return $formatted . ‘ €’;
default:
return $formatted . ‘ ‘ . $currency;
}
}
`
RTL Language Support
RTL Stylesheet
`php
// Enqueue RTL stylesheet
function enqueuertlstyles() {
if (is_rtl()) {
wpenqueuestyle(
‘shahi-assist-rtl’,
plugindirurl(FILE) . ‘css/rtl.css’,
[‘shahi-assist-main’],
‘1.0.0’
);
}
}
addaction(‘wpenqueuescripts’, ‘enqueuertl_styles’);
addaction(‘adminenqueuescripts’, ‘enqueuertl_styles’);
`
RTL CSS Rules
`css
/ css/rtl.css /
body.rtl .ticket-list {
direction: rtl;
}
.rtl .ticket-meta {
text-align: right;
}
.rtl .ticket-actions {
float: left; / In RTL, left becomes right /
}
.rtl .priority-high::before {
content: “\f344”; / Dashicon pointing left in RTL /
margin-left: 5px;
margin-right: 0;
}
`
RTL JavaScript Adjustments
`javascript
// Adjust layout for RTL
jQuery(document).ready(function($) {
if ($(‘body’).hasClass(‘rtl’)) {
// Adjust positioning for RTL
$(‘.ticket-sidebar’).css(‘float’, ‘left’);
$(‘.ticket-content’).css(‘margin-left’, ‘300px’);
$(‘.ticket-content’).css(‘margin-right’, ‘0’);
}
});
`
Translation Contribution
Translation Interface
`php
// Add translation interface to admin
addaction(‘adminmenu’, function() {
addsubmenupage(
‘shahi-assist-settings’,
__(‘Translations’, ‘shahi-assist’),
__(‘Translations’, ‘shahi-assist’),
‘manage_options’,
‘shahi-assist-translations’,
‘shahiassisttranslations_page’
);
});
function shahiassisttranslations_page() {
$locale = get_locale();
$translations = gettranslationsforcurrentlocale(‘shahi-assist’);
?>
‘ . $locale . ‘‘
); ?>
count’] / $translations[‘totalcount’]) * 100)
); ?>
`
Export Translation Template
`php
// Generate translation template for contributors
function exporttranslationtemplate() {
if (!currentusercan(‘manage_options’)) {
return;
}
$locale = sanitizetextfield($_GET[‘locale’] ?? ‘en’);
$potfile = plugindir_path(FILE) . ‘languages/shahi-assist.pot’;
if (!fileexists($potfile)) {
wpdie(_(‘POT file not found’, ‘shahi-assist’));
}
header(‘Content-Type: application/octet-stream’);
header(‘Content-Disposition: attachment; filename=”shahi-assist-‘ . $locale . ‘.po”‘);
header(‘Content-Length: ‘ . filesize($pot_file));
readfile($pot_file);
exit;
}
addaction(‘adminpostexporttranslationtemplate’, ‘exporttranslation_template’);
`
Testing Internationalization
i18n Testing Functions
`php
// Test translation loading
function test_translations() {
$test_strings = [
__(‘Hello World’, ‘shahi-assist’),
__(‘Settings’, ‘shahi-assist’),
_n(‘%s ticket’, ‘%s tickets’, 1, ‘shahi-assist’),
_n(‘%s ticket’, ‘%s tickets’, 5, ‘shahi-assist’),
];
$results = [];
foreach ($test_strings as $string) {
$results[] = [
‘original’ => $string,
‘translated’ => $string !== __(‘Hello World’, ‘shahi-assist’), // Check if different from English
];
}
return $results;
}
// RTL testing
function isrtllanguage() {
$rtl_languages = [‘ar’, ‘he’, ‘fa’, ‘ur’, ‘yi’];
$locale = get_locale();
$language_code = substr($locale, 0, 2);
return inarray($languagecode, $rtl_languages);
}
`
Locale Switching for Testing
`php
// Switch locale for testing
function switchlocalefor_testing($locale) {
global $wp_locale;
switchtolocale($locale);
// Reload text domains
unload_textdomain(‘shahi-assist’);
loadplugintextdomain(‘shahi-assist’, false, dirname(plugin_basename(FILE)) . ‘/languages/’);
// Force reload of admin text domain
unload_textdomain(‘shahi-assist-admin’);
loadplugintextdomain(‘shahi-assist-admin’, false, dirname(plugin_basename(FILE)) . ‘/languages/admin/’);
}
// Test different locales
addaction(‘admininit’, function() {
if (isset($GET[‘testlocale’])) {
$locale = sanitizetextfield($GET[‘testlocale’]);
switchlocalefor_testing($locale);
// Redirect back to remove query param
wpredirect(removequeryarg(‘testlocale’));
exit;
}
});
`
Resources
Share this article
Still need help?
Our support team is ready to assist you with personalized guidance for your workspace.