Support Log in

45. Cross-Plugin Integration: Form Forge

Developer Guide
Prefer video? Watch the Lang Forge tutorials 9 short guides covering every feature Watch

Lang Forge ships a built-in listener that picks up Form Forge’s translation hooks and exposes form labels / placeholders / options / submit text / success messages in the standard String Translation admin page. The integration class is LF_FormForge_Integration (includes/class-formforge-integration.php), loaded on plugins_loaded after the regular LF_String_Translation boot.

Hook contract

Form Forge emits three hooks; Lang Forge listens on all three.

HookDirectionUsed for
do_action('formforge/strings_registered', $form_id, $strings)FF → LFIdempotent batch register on save
do_action('formforge/strings_unregistered', $form_id)FF → LFDomain cleanup on delete
apply_filters('formforge_translate_string', $string, $key, $field_id, $form_id)FF → LFPer-string lookup at render time
apply_filters('formforge_current_language', $default, $form_id)LF → FFRender-time language hint for AJAX submit roundtrip
apply_filters('formforge_translate_lang_override', $lang, $form_id)LF → FF (via own hook)AJAX-context override for success_message

Per-form domain

Lang Forge uses formforge: as the string_domain in wp_lf_strings so:

  • Each form’s strings are grouped together on the String Translation admin page
  • A form delete is a single DELETE WHERE string_domain = ? cleanup
  • Two forms can share the same source string with different translations (e.g. “Submit” can be translated differently per form)

Stable string names

The integration uses these names so renaming a label’s text without changing its field['id'] does not invalidate existing translations:

  • Field-level: field__field_email_label, field_category_option_label:business
  • Form-level: submit_text, success_message, schedule_message

Example: writing your own listener (replacing or extending the built-in)

php
// Replace the bundled listener with a custom one.
remove_filter('formforge_translate_string', [LF_FormForge_Integration::instance(), 'translate'], 10);

add_filter('formforge_translate_string', function ($string, $key, $field_id, $form_id) {
    // Custom resolution: route through your own translation memory, glossary, etc.
    $current_lang = LF_Core::instance()->get_current_language();
    $default_lang = LF_Core::instance()->get_default_language();
    if ($current_lang === $default_lang) return $string;

    $name = $field_id !== '' ? "field_{$field_id}_{$key}" : $key;
    $domain = "formforge:{$form_id}";

    return my_custom_lookup($string, $name, $domain, $current_lang) ?: $string;
}, 10, 4);

General extensibility — registering form-style strings from other plugins

The same domain convention works for any plugin that wants to register and translate per-instance strings. Pick a unique domain prefix (mailpoet:42, learndash:97, etc.) and re-use the LF_String_Translation API directly:

php
// Register a string at instance creation time
LF_String_Translation::instance()->register_string(
    'Welcome message text',                // value
    'instance_42_welcome',                  // name (stable)
    'mycart:42',                            // domain (per-instance)
    LF_Core::instance()->get_default_language()
);

// Translate at render time
$translated = LF_String_Translation::instance()->translate(
    $original_string,
    'instance_42_welcome',
    'mycart:42'
);

This pattern (the one Form Forge uses) keeps strings discoverable in the admin, scoped per instance, and cleanly removable on delete. It is the recommended way for any third-party plugin to integrate with Lang Forge for per-instance string translation.

Forge AI Assistant Online

Hi! I'm the Lang Forge AI assistant. Ask me anything about the plugin — setup, features, troubleshooting, or development.

Just now
Powered by Forge AI · Browse docs