Contents

Multilingual (WPML / Polylang) — Plugixa FAQ

Plugixa FAQ integrates with WPML and Polylang out of the box. If either is active, the plugin automatically detects it and makes your FAQs, categories, and custom fields translatable. No separate setup or switch is required.

Multilingual FAQs filtered by language

How it works (in 30 seconds)

Plugixa FAQ uses the Translation Group pattern. Every FAQ, category, and custom field has two extra columns:

  • language_codeen, fr, de, etc.
  • translation_group — a UUID shared by all translations of the same item.

Items with the same translation_group UUID are translations of each other, regardless of language. This is the same model WPML uses internally, so it plays nicely with both WPML and Polylang.

┌─────────────────────────────────────────────┐
│ wp_plugixa_faqs                             │
├──┬──────────────────┬──────────┬────────────┤
│id│ question         │ lang     │ group      │
├──┼──────────────────┼──────────┼────────────┤
│ 1│ How do I reset…  │ en       │ abc-123…   │  ← English
│ 2│ Comment réiniti… │ fr       │ abc-123…   │  ← French (same group)
│ 3│ Wie setze ich…   │ de       │ abc-123…   │  ← German  (same group)
│ 4│ Shipping info    │ en       │ def-456…   │  ← different item
└──┴──────────────────┴──────────┴────────────┘

Enable / disable

Multilingual is on by default when WPML or Polylang is detected. Turn it off globally from Plugixa FAQ → Settings → Multilingual:

Setting Values Default Effect
multilingual_enabled auto, off auto auto = enable when WPML/Polylang is present. off = ignore language, show everything.
multilingual_fallback default_language, hide default_language What to show for items that don’t have a translation in the current language.

Fallback behavior

When a visitor requests a language and the FAQ has no translation:

  • default_language (default) — show the default-language version so the FAQ always appears. Best for SEO.
  • hide — omit the FAQ entirely. Best when strict per-language content is a requirement.

Which fields are translatable

Entity Translatable Shared across languages
FAQs question, answer, slug category_id, parent_id, image_id, status, visibility, feedback_enabled, menu_order, author_alias, source
Categories name, slug, description icon, color, menu_order, feedback_enabled
Custom Fields PRO field_label, placeholder field_key, field_type, field_options, is_required, show_in_frontend, menu_order

“Shared” fields are copied automatically when you create a translation, so you don’t have to set the category or icon again in every language.

Creating translations

Admin UI

From the FAQ or category list:

  1. Switch to the language you want to translate into (using WPML or Polylang’s language switcher).
  2. Click the Add translation button next to the item.
  3. Fill in the translatable fields. Shared fields are pre-populated from the source.
  4. Save.

Creating a French FAQ translation

Filtering by language

The admin list respects the current language:

  • Single language — shows FAQs in that language only.
  • All languages — shows every FAQ grouped by translation.

FAQs filtered to show all languages

Categories with the multilingual “All” filter active

REST API

# Get translations for an FAQ
GET /wp-json/plugixa-faq/v1/multilingual/faqs/{id}/translations

# Link two existing FAQs as translations
POST /wp-json/plugixa-faq/v1/multilingual/faqs/link-translations
{
  "source_id": 5,
  "target_id": 12
}

# Get a specific translation
GET /wp-json/plugixa-faq/v1/multilingual/faqs/{id}/translations/{lang}

See Hooks for filtering these responses in custom code.

Frontend behavior

Automatic language detection

On the frontend, the shortcode detects the current language from:

  1. WPML — the ICL_LANGUAGE_CODE constant.
  2. Polylangpll_current_language(), with ?lang= query parameter as an override (useful when a shortcode appears on an untranslated page).
  3. Fallback — the site’s default language.

Only FAQs matching the current language are rendered. Fallback behavior follows the setting above.

Forcing a language in a shortcode

You can force a language regardless of WPML/Polylang state:

[plugixa_faq language="fr"]

This is useful for:

  • Building a language-specific landing page without setting up full page translation.
  • Embedding FAQs in a single language from a language picker component.

Where language is stored

Database columns

Every multilingual-aware table has these columns:

language_code      VARCHAR(10)    -- e.g., 'en', 'fr'
translation_group  VARCHAR(36)    -- UUID v4

UNIQUE KEY lang_group (translation_group, language_code)

The unique key guarantees that a single translation group can have at most one translation per language — no duplicates.

Migration for existing installs

When you upgrade to a multilingual-aware version:

  1. The activator adds language_code and translation_group columns if missing.
  2. A one-time migration backfills every existing FAQ/category with:
    • language_code = site default language
    • translation_group = a new UUID (unique per item)
  3. The plugixa_faq_multilingual_migrated option is set so this only runs once.

If the migration fails, the plugixa_faq_upgrade_attempts counter prevents retry storms (max 3 attempts). See Troubleshooting.

Usage in custom code

Check if multilingual is active

if ( \PlugixaFaq\Multilingual::instance()->is_multilingual_active() ) {
    // WPML or Polylang is installed AND the feature isn't disabled
}

Get the current language

$lang = \PlugixaFaq\Multilingual::instance()->get_current_language();
// → 'en', 'fr', etc.

Build a language-aware WHERE clause

$ml      = \PlugixaFaq\Multilingual::instance();
$current = $ml->get_current_language();
$default = $ml->get_default_language();

[ $where_sql, $where_values ] = $ml->build_language_where(
    'f',                // table alias
    'plugixa_faqs',     // logical table
    $current,
    $default
);

$sql = "SELECT * FROM {$wpdb->prefix}plugixa_faqs f WHERE 1=1 $where_sql";
$faqs = $wpdb->get_results( $wpdb->prepare( $sql, ...$where_values ) );
\PlugixaFaq\Multilingual::instance()->link_translations(
    'plugixa_faqs',
    $source_faq_id,
    $target_faq_id
);

Troubleshooting

I see the same FAQ in every language

  • Check that the FAQ has a non-empty language_code. Empty = “belongs to every language” (legacy behavior).
  • In Settings → Multilingual, set multilingual_fallback to hide to filter strictly.

Translation not showing up on the frontend

  1. Confirm the FAQ has status = published in every language (each translation has its own status).
  2. Confirm the language_code matches the URL language (e.g., fr not fr_FR).
  3. Try ?plugixa_faq_debug=1 on the page and check the JS console for the detected language.

My existing FAQs have no language

Run the migration manually from Settings → Advanced → Re-run multilingual migration. This sets every NULL-language item to the site default language.

Quick Links