Lang Forge integrates with Advanced Custom Fields (and Field Forge) to handle custom field translation.
Marking Fields as Translatable
In the ACF field settings, each field gets a “Translatable” toggle (enabled by default). Non-translatable fields (e.g., a “color” field or “layout” selector) will not be loaded from the translation.
php
acf_add_local_field_group([
'key' => 'group_hero',
'title' => 'Hero Section',
'fields' => [
[
'key' => 'field_hero_title',
'label' => 'Hero Title',
'name' => 'hero_title',
'type' => 'text',
'lf_translatable' => 1, // This field will be translated
],
[
'key' => 'field_hero_bg_color',
'label' => 'Background Color',
'name' => 'hero_bg_color',
'type' => 'color_picker',
'lf_translatable' => 0, // Same across all languages
],
],
'location' => [
[['param' => 'page_template', 'operator' => '==', 'value' => 'templates/home.php']],
],
]);Automatic Field Copying
When a translation is created, Lang Forge automatically copies all ACF fields from the source post:
- Text/Textarea/WYSIWYG fields: copied as-is
- Repeater fields: full row data copied with all sub-fields
- Flexible Content fields: all layouts and data copied intact
- Group fields: all sub-fields copied
- Image/File/Gallery fields: media references shared (same attachment IDs)
- Relationship/Post Object fields: original references kept
php
add_action('acf/save_post', function ($post_id) {
if (wp_is_post_revision($post_id)) return;
$translations = lf_get_post_translations($post_id);
$current_lang = lf_get_post_language($post_id);
foreach ($translations as $lang => $trans_id) {
if ($lang === $current_lang) continue;
LF_ACF_Integration::instance()->sync_media_fields($post_id, $trans_id);
}
}, 20);—