Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/s3th-hub/ai-multilingual-translator/archive/refs/heads/main.zipAutomatic AI-powered multilingual translation for WordPress using the OpenAI API.
✨ Features
| Feature | Details |
|---|---|
| AI Translation | OpenAI GPT-4o-mini (or GPT-4o) translates Title, Content, Excerpt, Slug |
| Language Switcher | Shortcode [ai_language_switcher] — dropdown, flags, or buttons style |
| URL Routing | /sw/page, /fr/page, /es/page via WP rewrite rules |
| Non-destructive | Original content is never overwritten |
| DB-backed | All translations in wp_ai_translations with upsert safety |
| Auto-translate | Optional: translate on publish/update via background scheduling |
| Kiswahili first | sw included and enabled by default |
| Extensible | Add custom language codes in Settings |
🗂 Plugin Folder Structure
ai-multilingual-translator/
├── ai-multilingual-translator.php ← Main plugin file
├── composer.json
├── phpunit.xml
├── docker-compose.yml
├── .github/
│ └── workflows/
│ └── ci.yml
├── admin/
│ ├── css/admin.css
│ └── js/admin.js
├── bin/
│ └── install-wp-tests.sh
├── frontend/
│ ├── css/frontend.css
│ └── js/frontend.js
├── includes/
│ ├── class-plugin.php
│ ├── class-installer.php
│ ├── class-languages.php
│ ├── class-translationengine.php
│ ├── class-router.php
│ ├── class-ajax.php
│ ├── class-languageswitcher.php
│ └── admin/
│ └── class-settings.php
├── languages/
├── templates/
│ ├── admin-settings.php
│ ├── admin-status.php
│ ├── post-meta-box.php
│ └── language-switcher.php
└── tests/
├── bootstrap.php
└── test-plugin.php
🚀 Installation
Option A — Manual upload
# 1. Clone or download the repo
git clone https://github.com/your-org/ai-multilingual-translator.git
cp -r ai-multilingual-translator /path/to/wp-content/plugins/
# 2. Activate
wp plugin activate ai-multilingual-translator
Option B — Docker local dev (recommended)
# Start the stack (WordPress on :8080, phpMyAdmin on :8081)
docker compose up -d
# Wait ~20s for MySQL to initialise, then install WP:
docker compose exec wordpress wp core install \
--url="http://localhost:8080" \
--title="Dev Site" \
--admin_user=admin \
--admin_password=admin \
--admin_email=dev@example.com \
--allow-root
# Activate plugin
docker compose exec wordpress wp plugin activate ai-multilingual-translator --allow-root
After activation
- Go to AI Translator → Settings in wp-admin.
- Paste your OpenAI API key.
- Choose your base language (default: English).
- Tick the languages you want.
- Save Settings.
- Go to Settings → Permalinks → click Save Changes (activates URL routing).
⚙️ Configuration
Settings page options
| Option | Description |
|---|---|
| OpenAI API Key | Get from platform.openai.com/api-keys |
| Model | gpt-4o-mini (cheap, fast) or gpt-4o (best quality) |
| Base Language | Language your content is written in |
| Translate Into | Multi-select checkboxes — includes all 14 built-in languages + custom |
| Auto-translate on Publish | Background-translate when a post is published/updated |
| Generate on Missing | Auto-generate when a visitor hits an untranslated URL |
Adding custom languages
In Settings → Custom Languages, add a language code (e.g. yo) and name (Yoruba). OpenAI supports 90+ languages.
🔗 URL Structure
After enabling languages and flushing permalinks:
example.com/ ← English (base)
example.com/sw/page/ ← Kiswahili
example.com/fr/page/ ← French
example.com/es/page/ ← Spanish
example.com/ar/page/ ← Arabic (RTL auto-handled)
🌐 Language Switcher
Shortcode
[ai_language_switcher]
[ai_language_switcher style="flags"]
[ai_language_switcher style="buttons" show_flags="true" show_names="true"]
Styles: dropdown (default) · flags · buttons
Widget
Go to Appearance → Widgets and add the AI Language Switcher widget to any sidebar.
Gutenberg Block
The switcher is registered as a server-side block: search for AI Language Switcher in the block inserter.
🛠 Developer Hooks
// Add custom post types to auto-translate.
add_filter( 'aimt_translatable_post_types', function( $types ) {
$types[] = 'product'; // WooCommerce
return $types;
} );
// Hook after a translation is saved.
add_action( 'aimt_translation_saved', function( int $post_id, string $lang, string $field ) {
// e.g. bust a cache
}, 10, 3 );
🧪 Running Tests
# 1. Install PHP deps
composer install
# 2. Install WP test suite (once)
bash bin/install-wp-tests.sh wordpress_test root root 127.0.0.1 latest
# 3. Run PHPUnit
WP_TESTS_DIR=/tmp/wordpress-tests-lib vendor/bin/phpunit
One-liner test command:
composer install && bash bin/install-wp-tests.sh wordpress_test root root 127.0.0.1 latest && WP_TESTS_DIR=/tmp/wordpress-tests-lib vendor/bin/phpunit
🔒 Security Notes
- All user inputs sanitized with
sanitize_text_field,sanitize_key,absint,wp_kses_post. - All AJAX handlers verify nonces via
check_ajax_referer(). - All admin actions check
current_user_can()before executing. - API key stored in
wp_options(same as Stripe, Mailchimp plugins). - No raw SQL — all queries use
$wpdb->prepare(). - Original post content is never modified.
🗄 Database Table
CREATE TABLE wp_ai_translations (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
post_id BIGINT UNSIGNED NOT NULL,
lang_code VARCHAR(10) NOT NULL,
field VARCHAR(50) NOT NULL,
translated LONGTEXT NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY post_lang_field (post_id, lang_code, field)
);
Fields stored per row: post_title, post_content, post_excerpt, post_name (slug).
🧩 Elementor & Gutenberg Compatibility
The plugin swaps content through WordPress filters (the_title, the_content, the_excerpt). This means it works with:
- ✅ Gutenberg / Block Editor
- ✅ Classic Editor
- ✅ Elementor (reads post content via WP filters)
- ✅ Beaver Builder
- ✅ WooCommerce product pages
For page builders that store content in post meta (not post_content), additional filters may be needed per builder.
📜 License
GPL-2.0-or-later — see LICENSE.