Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save senlin/4fd15ba7a19533ceb9fe to your computer and use it in GitHub Desktop.
Save senlin/4fd15ba7a19533ceb9fe to your computer and use it in GitHub Desktop.
How to get language independent ACF theme options on a WPML site
<?php
/**
* To get this to work, you need to tinker with the acf/settings/ filter and reset the default language
* so that the get_field() function returns the correct results even when not on the default language.
*
* You can add the filter before you call the get_field() function and then call it again with the current
* language to reset it again, so it will affect other pages.
*
* answer courtesy of James of ACF Support
*/
// add this
add_filter( 'acf/settings/current_language', function() {
global $sitepress;
return $sitepress->get_default_language();
});
// this is already in your code
$my_field = get_field( 'my_field', 'option' );
// reset to original language
add_filter( 'acf/settings/current_language', function() {
return ICL_LANGUAGE_CODE;
});
@elliotcondon
Copy link

Hi guys,

This could be even simpler.

The code within ACF whice appends the lang code looks like:

// append language code
    if( $post_id == 'options' ) {

        $dl = acf_get_setting('default_language');
        $cl = acf_get_setting('current_language');

        if( $cl && $cl !== $dl ) {

            $post_id .= '_' . $cl;

        }

    }

If there is no $cl, this is never appended.
So, simply use this code to prevent the options page lang change

add_filter( 'acf/settings/current_language', function() {
     return false;
});

@johnolek
Copy link

We could make it even a tiny bit simpler by using a built-in WordPress function:

add_filter( 'acf/settings/current_language',  '__return_false' );

@johnolek
Copy link

Here's the implementation I ended up going with. I have a class that I'm using to contain a lot of custom functionality for this site, so these are defined within that class (not shown).

/**
     * This is the string for the ACF current langauge filter
     *
     * @see http://www.advancedcustomfields.com/resources/acfsettings/
     */
    const LANGUAGE_SETTING_ACF_FILTER = 'acf/settings/current_language';

    /**
     * Use this to stop ACF from trying to look for a language-specific version of fields.
     *
     * @see http://www.advancedcustomfields.com/resources/acfsettings/
     */
    public static function disableAcfLanguageAppending()
    {
        add_filter(self::LANGUAGE_SETTING_ACF_FILTER, '__return_false');
    }

    /**
     * Use this to re-enable language-specific retrieval of ACF fields.
     *
     * @see http://www.advancedcustomfields.com/resources/acfsettings/
     * @see self::disableAcfLanguageAppending
     */
    public static function reEnableAcfLanguageAppending()
    {
        remove_filter(self::LANGUAGE_SETTING_ACF_FILTER, '__return_false');
    }

This allows me to easily turn this functionality on and off where needed.

Thanks again for the help, guys!

@senlin
Copy link
Author

senlin commented Apr 8, 2016

Bizarre that I never received any notification from Github, that people are commenting on this Gist.

Sorry guys, just seeing this now. Thanks for all the input! Very useful alternatives!

@Klayemore
Copy link

Klayemore commented Jul 20, 2016

I like where this is headed, as it means the options page within the WP admin remains the same, even when switching languages in the top toolbar. I'm hoping to extend this slightly, so that some fields always remain the same, whereas others can be modified for each language. For example:

  • A theme colour selector should remain the same across all languages.
  • Custom footer text should be changed dependant on language.

Any ideas on how I can accomplish this? By the sound of joleksow's last post, he may be doing this already, however I don't fully understand how to use it.

Cheers!

@nocean
Copy link

nocean commented Dec 6, 2016

Awesome. This worked beautifully (for a slightly clunky solution to begin with). I modified @johnolek's solution above for a class-less version (let it never be said I have any class).

// Use this to stop ACF from trying to look for a language-specific version of fields.
add_filter('acf/settings/current_language', '__return_false');

// Insert your regular ACF code between the add_filter and remove_filter lines.
$my_field =  get_field( 'my_field', 'option' );

// Use this to re-enable language-specific retrieval of ACF fields.
remove_filter('acf/settings/current_language', '__return_false');

PS: Hey Piet (@senlin). Small world! :)

@elliottmangham
Copy link

elliottmangham commented Aug 31, 2018

Just to jump in and thank you guys for the progressive solution here! I ultimately went with @nocean's solution as it worked for me.

In the admin area, you can still change languages when viewing the Options page. Is there a way to prevent this so admins can only see one set of fields? OR, perhaps default to the 'All Languages' set instead? Thinking of the best way to avoid confusion for (already confused) clients.

screen shot 2018-08-31 at 10 07 09

Thanks

@IlanVivanco
Copy link

This was extremely helpful! thanks!

@peterblickenstorfer
Copy link

peterblickenstorfer commented May 13, 2019

Hi and thanks for the code-snippets.

Because there is no way to handle this smart in the WP-Backend (see the comment of @elliottmangham) I use the "language=all"-soloution with a force-redirect in the backend by admin_init-action.

Template-Code:

// Use this to force ACF to look for the "all" version of the fields.
	add_filter('acf/settings/current_language', function() { return 'all' ; } );

// Insert your regular ACF code between the add_filter and remove_filter lines.
	echo get_field('my_language_independet_option_field', 'option');

// Use this to re-enable language-specific retrieval of ACF fields.
	remove_filter('acf/settings/current_language', function() { return ICL_LANGUAGE_CODE ; } );

Backend- / Admin-Code (functions.php):

function force_redirect_to_the__all__version_of_global_options() {
	// correct page
		global $pagenow ;
		if($pagenow === "admin.php" && isset($_GET['page']) && $_GET['page'] === "global-options") { // global-options is the menu_slug you defined in acf_add_options_page
			// lang not 'all'?
				if(ICL_LANGUAGE_CODE !== 'all') {
					// manipulate query (set lang to "all")
						$query = $_GET;
						$query['lang'] = 'all';
						$query_result = http_build_query($query);
					// redirect and die
						wp_redirect(get_admin_url() . 'admin.php?' . $query_result);
						die();
				}
		}
}
add_action( 'admin_init', 'force_redirect_to_the__all__version_of_global_options');

@teej043
Copy link

teej043 commented Aug 28, 2019

Nice gist, in particular the solution by @peterblickenstorfer (Backend/Admin Code) works for me. I just needed to group the really global option fields to a separate field group and option page.

It does makes a lot of sense to use the "All Languages" instead of setting the default language custom fields.

Update:
I have posted too soon without checking if things are working properly. There is just something wrong when I used add_filter('acf/settings/current_language', function() { return 'all' ; } );. It might be my WPML setup?

So I have reverted back to using the "default language" field as a global field, and used the Backend/Admin Code by @peterblickenstorfer

@graham73may
Copy link

graham73may commented Jun 26, 2024

I see ACFML 2.0 has been released which has had some pretty major improvements.

I can set my field to "Copy" mode, this has the nice bonus that on the translated Options page, it shows the field as locked with this tootlip:
image

However if I use my normal code:

$twitter_handle = get_field( 'twitter_handle', 'option' );

It is still looking for a French value, which obviously won't exist.

I've implemented @nocean's solution, but to be honest I was expecting this ACFML upgrade to understand the field is set to "Copy" mode, and to get the value from the default language.

Am I doing something wrong? Is this snippet still required?

I'm currently using this as a helper function in my theme.

/**
 * Get an option value from the default language.
 * Useful if a field is set to "Copy" mode in ACFML.
 *
 * @param string $field_name ACF field name (field slug).
 *
 * @return false|mixed
 */
function get_global_field( $field_name ) {
	// Use this to stop ACF from trying to look for a language-specific version of fields.
	add_filter( 'acf/settings/current_language', '__return_false' );

	// Insert your regular ACF code between the add_filter and remove_filter lines.
	$my_field = get_field( $field_name, 'option' );

	// Use this to re-enable language-specific retrieval of ACF fields.
	remove_filter( 'acf/settings/current_language', '__return_false' );

	return $my_field;
}

EDIT: Ok this does work, but you have to save the options page in every language.

Found this thread:
https://wpml.org/forums/topic/wpml-acf-pro-options-page-default-language-values/#post-11901025

I'm not sure how I feel about this solution. If the default language's options change, you (or your client) then need to remember to go into each language's options page and hit save (even though the page only contains locked fields!).

The snippet above doesn't require that extra save process.

@senlin
Copy link
Author

senlin commented Jun 26, 2024

@graham73may the original snippet is from 2016... prolly not necessary anymore

@graham73may
Copy link

graham73may commented Jun 26, 2024

@senlin yep, a bit surprised at the current state on this one too.

Options as of today with ACFML 2.1.3 seem to be:

A. Having to hit save on the translated options pages (I think each time the default language changes). I'm not sure I can trust end users to do / to remember to do this.
B. Or use the snippet mentioned above.


Update: Checked with WPML, and the behaviour of "Copy" is working as intended. They confirmed if the default language is updated, you then need to go into each translation and hit update (This feels super clunky!).

Thread for reference:
https://wpml.org/forums/topic/acf-wpml-acfwpml-fields-on-options-pages-set-to/

I've suggested that maybe the UI could be made a bit clearer as it currently shows the default languages value in the backend, greyed out and disabled before you've hit save.

I've also asked to submit a feature request for a setting so fields pull directly from the default language.

Probably won't go anywhere but hey-ho!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment