maximeschoeni / sublanguage

Multilanguage plugin for wordpress
42 stars 13 forks source link

Extend 'Hide this menu item in this language' to work with pages and posts #49

Closed jamielaw-jellyfish closed 4 years ago

jamielaw-jellyfish commented 4 years ago

Hi, Maxime. First of all, what a wonderful plugin you've built. It's the most elegant and least bloated solution to a multi-language WordPress site I've come across.

I can see it's possible to hide menu items based on language, but is it possible to hide pages and posts as well?

For my use case, I have a custom post type of 'Product' and I want to disable some products in particular languages so that they don't show up in queries, and that trying to visit them in those locales gives a 404. Another use case could be to have a cookie policy page that is only available to users on the English or French version of the site, but not on the US or Canadian version.

maximeschoeni commented 4 years ago

Hello, thank you for feed-back. No you can't do this directly via the user interface. You need to hook before or after a wp query to filter out pages or posts you want to hide. You can use the global $sublanguage to test parameters against language ($sublanguage->get_language() to get current language)

jamielaw-jellyfish commented 4 years ago

Thank you for your quick response. I suspected this was the case. My plan, therefore, is as follows:

I began experimenting with this, but broke the site in the process. If I succeed, I'll post a follow-up.

maximeschoeni commented 4 years ago

Hooking directly into the sql query can be tricky. I suggest rather to hook into the request filter to just add a few query vars (see doc):

add_filter('request', function($query_vars) {
    global $sublanguage;
    $query_vars['meta_key'] = $sublanguage->get_prefix() . 'hide'; // -> _xx_hide
    $query_vars['meta_value'] = '1';
    $query_vars['meta_compare'] = '!=';
    return $query_vars;
});

This way you will filter out posts that have a meta_key _xx_hide equal to 1 (where xx is the current language slug, hide the custom field meta key and 1 the meta value ).

jamielaw-jellyfish commented 4 years ago

With a little tweaking, it worked like a charm. Thank you so much for your guidance. For future readers, here's what I did:

I was using Advanced Custom Fields, but I image this technique will work if you're using the native custom fields in WordPress.

Like I said above, I added a translatable custom field with the label, "Hide this post in this language", and the name sublanguage_hide. In hindsight, maybe using the sublanguage namespace was a bad idea, in case it ever gets implemented in the plugin directly, but at least it's clear what it does.

I set the field to be translatable. This required that I check the field on at least on post so that it would show up in the Sublanguage options. I could later uncheck it for all the languages I didn't want it hidden for.

I modified the function a little, and ended up with the following:

add_filter('request', function ($query_vars) {
  global $sublanguage;
  $prefix = $sublanguage->is_main() ? '' : $sublanguage->get_prefix();

  if (isset($sublanguage) && isset($query_vars['post_type'])) {
    $query_vars['meta_query'] = [
      'relation' => 'OR',
      [
        'key' => $prefix . 'sublanguage_hide',
        'value' => '1', // https://core.trac.wordpress.org/ticket/23268
        'compare' => 'NOT EXISTS',
      ],
      [
        'key' => $prefix . 'sublanguage_hide',
        'value' => '1',
        'compare' => '!=',
      ]
    ];
  }
  return $query_vars;
});

Simply checking that the _xx_sublanguage_hide meta_key was not equal to 1 also happened to filter out posts where the key was unset, so I added another query to account for that.

And the only other thing was that I was getting a PHP error in the admin panel that $sublanguage was null, so I wrapped the bulk of the function in an isset so that that wouldn't be an issue.

But the core of what you suggested worked perfectly. I really appreciate that you took the time to point me in the right direction.

maximeschoeni commented 4 years ago

well done! And thanks for sharing your solution.