Polylang pro slugs sync acf
Skill Lonsdale201/wp-agent-skills/polylang/polylang-pro-slugs-sync-acf
A community-maintained collection of agent skills for WordPress plugin and theme development.
npx -y skills add Lonsdale201/wp-agent-skills --skill polylang-pro-slugs-sync-acfAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 21 stars21 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Work with Polylang Pro 3.8.5 features that affect plugin/theme compatibility: translated slugs, shared slugs, duplicate/sync post workflows, ACF Pro integration, translated ACF labels, ACF field translation strategies, import/export/machine-translation hooks, and sync metadata filters. Use when code touches rewrite slugs, custom permalink structures, duplicated translations, synchronized custom fields, ACF fields containing post/term/media IDs, ACF field groups, or hooks such as pll_translated_slugs, pll_sync_post_fields, pll_copy_post_metas, pll_translate_post_meta, pll_post_synchronized, pll_created_sync_post, or pll_enable_acf_labels_translation.
SKILL.md
9.5 KB, as published. Nobody here has run it
Polylang Pro Slugs, Sync, and ACF
Use this skill when compatibility depends on Pro-only behavior rather than the core Polylang API.
Polylang Pro 3.8.5 adds major behavior in three areas:
- translated and shared slugs;
- duplicate/sync workflows;
- ACF Pro integration.
Guard Pro-only code:
if ( ! defined( 'POLYLANG_PRO' ) ) {
return;
}
Translated rewrite slugs
Polylang Pro translates rewrite slugs through strings translation. The model scans registered post types, archives, taxonomies, post formats, and miscellaneous bases such as author, search, attachment, page, and the front base.
It stores the computed map in the transient pll_translated_slugs and refreshes rewrite rules after string translations are saved.
Add your plugin's custom slug source with:
add_filter(
'pll_translated_slugs',
static function ( array $slugs, PLL_Language $language, PLL_MO $mo ): array {
$source = 'courses';
$slugs['myplugin_courses']['slug'] = $source;
$translated = $mo->translate( $source );
$slugs['myplugin_courses']['translations'][ $language->slug ] = $translated ?: $source;
return $slugs;
},
10,
3
);
Rules:
- Register CPTs and taxonomies before
wp_loaded; Pro initializes translated slugs onwp_loadedpriority 1. - Flush rewrite rules when your base slug changes, not on every request.
- Do not read
get_option( 'rewrite_rules' )and mutate rules manually. Hook Polylang's slug filters and let the model rebuild. - Expect object caches: Pro deletes the transient option row explicitly when an external object cache is active.
Shared slugs
Polylang Pro can allow translated posts or terms to share the same slug in different languages. It filters slug uniqueness and query resolution by language.
Compatibility rule: never assume post_name or term slug is globally unique.
Bad:
$post = get_page_by_path( $slug, \OBJECT, 'page' );
Safer:
$post_id = pll_get_post( $source_post_id, $target_lang );
If you must query by slug, include language in the query:
$query = new WP_Query( array(
'name' => sanitize_title( $slug ),
'post_type' => 'book',
'lang' => $target_lang,
) );
Pro's shared post slug class adds joins and where clauses for name and pagename queries. Custom SQL must do the same through Polylang's model or avoid slug lookup entirely.
Duplicate and sync workflows
Polylang Pro's sync model can copy or synchronize posts. It sets language early, saves translation groups, copies taxonomies and metas through Polylang sync services, and fires hooks:
pll_created_sync_postpll_save_postpll_post_synchronizedpll_sync_post_fieldspll_copy_taxonomiespll_copy_post_metaspll_translate_post_meta
Use hooks instead of re-copying all data after the fact.
Example: exclude volatile meta from sync:
add_filter(
'pll_copy_post_metas',
static function ( array $keys, bool $sync, int $from, int $to, string $lang ): array {
if ( 'book' !== get_post_type( $from ) ) {
return $keys;
}
return array_diff( $keys, array( '_myplugin_render_cache', '_myplugin_last_webhook_id' ) );
},
10,
5
);
Example: translate stored IDs while copying:
add_filter(
'pll_translate_post_meta',
static function ( $value, string $key, string $lang, int $from, int $to ) {
if ( '_myplugin_related_book' !== $key || ! is_numeric( $value ) ) {
return $value;
}
$translated = pll_get_post( (int) $value, $lang );
return $translated ?: $value;
},
10,
5
);
Do not call private Pro internals unless no public/hook-based integration exists. If you must interact with PLL()->sync_post_model, wrap it in defined( 'POLYLANG_PRO' ), isset(), and method checks because it is not a public stable API.
ACF Pro integration
Polylang Pro's ACF integration requires ACF 6.0+. It is bootstrapped under WP_Syntex\Polylang_Pro\Integrations\ACF.
Important 3.7+ model:
- ACF field groups are not translated anymore.
- Field groups can be displayed by language using a custom ACF location rule.
- ACF labels are translated through strings translation.
- ACF custom field values are handled by Pro's strategy system, not by raw
post_metasync.
Polylang Pro adds a field setting named translations with these choices:
| Choice | Meaning |
|---|---|
ignore | Do not copy/sync/translate this field. |
copy_once | Copy when creating a translation, then allow divergence. |
translate | Translate value through import/export/machine translation flows. |
translate_once | Translate when creating/importing, then allow divergence. |
sync | Keep synchronized across translations. |
Text-like fields get translate and translate_once; other fields typically get copy/sync choices.
ACF relationship IDs
ACF fields often store post IDs, term IDs, media IDs, or nested arrays containing them. Pro's Dispatcher registers collectors and translators:
pll_collect_post_idspll_collect_term_idspll_translate_blocks_with_contextpll_filter_translated_postacf/fields/relationship/queryacf/fields/post_object/query
If your custom ACF field type stores IDs in a custom shape, integrate with these collectors so Pro can export/import and sync them.
Pattern for a custom stored post ID:
add_filter( 'pll_translate_post_meta', static function ( $value, $key, $lang ) {
if ( '_myplugin_acf_extra_post' !== $key || ! is_numeric( $value ) ) {
return $value;
}
return pll_get_post( (int) $value, $lang ) ?: $value;
}, 10, 3 );
For fields owned by ACF itself, do not duplicate ACF's own meta keys manually. Pro removes ACF metas from generic Polylang sync so its ACF strategy layer can handle them.
ACF labels
ACF field-group, field, custom post type, and taxonomy labels can be translated. The feature can be disabled:
add_filter( 'pll_enable_acf_labels_translation', '__return_false' );
Use this only when another system fully owns ACF label translation. Otherwise leave it enabled and keep labels as stable source strings.
You can extend the field label keys that Polylang translates:
add_filter( 'pll_acf_field_labels_to_translate', static function ( array $labels ): array {
$labels['my_custom_field_type'][] = 'button_label';
return $labels;
} );
Common mistakes
- Assuming ACF field groups are translated posts in Pro 3.7+. They are not.
- Copying raw ACF meta after Pro has already applied ACF strategies.
- Looking up translated content by slug without a language filter when shared slugs are enabled.
- Returning translated rewrite slugs after
wp_loadedand wondering why rewrite rules do not change. - Flushing rewrite rules on every request after changing translatable slugs.
- Synchronizing cache/transient/meta fields that should be language-specific.
Cross-references
- Use
polylang-object-translationsfor post/term language assignment and translation groups. - Use
polylang-rest-headlessfor Pro REST duplication and untranslated-post endpoints. - Use
polylang-wc-compatibilitybefore applying generic Pro sync rules to products or orders.
Verification
Local source checked against:
- Translated slug model:
wp-content/plugins/polylang-pro/src/modules/translate-slugs/translate-slugs-model.php - Shared slug query filters:
src/modules/share-slug/share-post-slug.php - Pro sync model and hooks:
src/modules/sync-post/sync-post-model.php - ACF integration README, field settings, dispatcher, and label filters:
src/integrations/ACF/*
References
- Official documentation: https://polylang.pro/doc/developpers-how-to/
- Official documentation: https://polylang.pro/doc/strings-translation/
- Verified source paths:
wp-content/plugins/polylang-pro/src/pro.phpwp-content/plugins/polylang-pro/src/modules/translate-slugs/translate-slugs-model.phpwp-content/plugins/polylang-pro/src/modules/share-slug/share-post-slug.phpwp-content/plugins/polylang-pro/src/modules/share-slug/share-term-slug.phpwp-content/plugins/polylang-pro/src/modules/sync-post/sync-post-model.phpwp-content/plugins/polylang-pro/src/modules/sync-post/sync-post.phpwp-content/plugins/polylang-pro/src/integrations/ACF/README.mdwp-content/plugins/polylang-pro/src/integrations/ACF/Main.phpwp-content/plugins/polylang-pro/src/integrations/ACF/Field_Settings.phpwp-content/plugins/polylang-pro/src/integrations/ACF/Dispatcher.phpwp-content/plugins/polylang-pro/src/integrations/ACF/Labels/Field_Groups.php