qtranslate / qtranslate-xt

qTranslate-XT (eXTended) - reviving qTranslate-X multilingual plugin for WordPress. A new community-driven plugin soon. Built-in modules for WooCommerce, ACF, slugs and others.
GNU General Public License v2.0
553 stars 104 forks source link

ACF Module: get raw value #1023

Open bichonnages opened 3 years ago

bichonnages commented 3 years ago

Hi,

Thanks for the great work. Quick question: is there any direct way to get the raw value ("[:fr]xxx[:en]xxx[:]") of a translatable field from ACF instead of the translation? The returned value seems to alway be translated before, through a filter. Use case: Generating a PDF from a CPT. The PDF must display both languages, whatever the current activated language of the website.

<?php $description = qtranxf_use('fr', get_field('description'), false, false); echo $description ?> does not work. It only outputs the current language translation of the field.

All the best!

herrvigg commented 3 years ago

The translation is done via acf/format_value filter: https://github.com/qtranslate/qtranslate-xt/blob/c157ee30a48727f48306097da13453bf05101a64/modules/acf/src/acf_5/acf.php#L22

We can't remove this without breaking everything in ACF. To test but you could try to disable it just before your call and enable it after but that would be a hack.

bichonnages commented 3 years ago

Well, here is workaround, probably useful for people who want to display multiple translations on the same page:

<?php

$postid = get_the_ID(); // current post id
$raw_field = $wpdb->get_var($wpdb->prepare("SELECT meta_value FROM `wp_postmeta` WHERE `post_id` = %s AND  `meta_key` = 'description'", $postid)); // get the raw field value directly from the database ('description' is the field name being queried, should be changed depending on your fields' names)
$raw_field = qtranxf_split($field); // qtranxf_split() makes an array for each translation available

foreach ($raw_field as $one_translation) {
    echo nl2br($one_translation); // nl2br() is optional (only to keep the automatic line breaks <br> from the textarea field)
    echo '<br>'; // prettier (optional)
}

?>

As you can seen it queries directly from the database.

MK-RD commented 3 years ago

Dependencies – It's getting ridiculous!

$value_loaded = get_field('post_subtitle', $post->ID);
$value_cached = wp_cache_get($post->ID, 'post_meta'); #! MIXED
$value_single = $value_cached['post_subtitle'][0];
bichonnages commented 3 years ago

Is it safer/better to use the wp_cache_get() function?

MK-RD commented 3 years ago

My statement concerns the general use!

Sorry if I confused you with my comment but after over 5 hours of code analysis this nasty form of implementation had to be clarified once.

Based on my example, a helper function could be implemented to serve all use cases, because I don't expect the hook chaos to be cleaned up.

How much time did you spend on your solution path?

herrvigg commented 3 years ago

Both solutions are workarounds / hacks that can work temporarily but not safe on the long run. We need to understand the use case better.

Use case: Generating a PDF from a CPT. The PDF must display both languages, whatever the current activated language of the website.

Can you show an example? What is the entry point to generate this PDF? It may be possible to disable some parts of the ACF handling if the context of the request is known.

herrvigg commented 3 years ago

An alternative solution would be to disable this QTX/ACF filter, but in fact we'd need to expose some functions to do so and get the instance of the QTX/ACF field, e.g. acf_qtranslate_acf_5_text.

bichonnages commented 3 years ago

How much time did you spend on your solution path?

Well, it took me a few hours in order to understand that I could not access the raw field value ( qtranxf_split() is somehow useless here since the field value is already translated through the filter, you just get the same translation twice within the array). I just thought it would be a common case to show both/all translations on the same page, whatever the reason.

Can you show an example? What is the entry point to generate this PDF? It may be possible to disable some parts of the ACF handling if the context of the request is known.

Woocommerce shop, single product pages in English and French with regular qtranslate-xt setup(no needs here for displaying both languages on the same page). Client wants his website to automatically generate a PDF on click (I am using html2pdf) for each product but the PDF must be same whatever the language activated by the visitor. In other words, the PDF must display French + English values from ACF fields.

To me, the MySQL does not seem so much like a hack. I am just bypassing qtranslate-xt/acf through a direct query to the database. It could help to have a function for this though. Language switching is obviously the perfect setting for consulting a website; although it seems pretty fair to think that certain parts of a website need to display multiple languages at once.

herrvigg commented 3 years ago

If the conversion to PDF is done from HTML "externally" there's nothing that can make the request discriminative so far. You could almost disable QT-XT for that kind of requests but I still don't understand the use case well. Why would you disable the translation for the ACF fields and not the rest of the page?

It is a hack for two reasons:

MK-RD commented 3 years ago

An alternative solution would be to disable this QTX/ACF filter, but in fact we'd need to expose some functions to do so and get the instance of the QTX/ACF field, e.g. acf_qtranslate_acf_5_text.

I would like to see an example of this?

bichonnages commented 3 years ago

If the conversion to PDF is done from HTML "externally" there's nothing that can make the request discriminative so far. You could almost disable QT-XT for that kind of requests but I still don't understand the use case well. Why would you disable the translation for the ACF fields and not the rest of the page?

I am fine with disabling QT-XT for the entire page, that's no problem. What function should I use in that case?

Edit: At first, I thought that <?php $description = qtranxf_use('fr', get_field('field_name')); echo $description ?> should have worked. qtranxf_use() makes sense to me in that case.

MK-RD commented 3 years ago

@bichonnages NO PLUGIN = NO API = NO FUN

MK-RD commented 3 years ago

Maybe we should just live with it :-)

herrvigg commented 3 years ago

Edit: At first, I thought that <?php $description = qtranxf_use('fr', get_field('field_name')); echo $description ?> should have worked. qtranxf_use() makes sense to me in that case.

That doesn't work because get_field returns translated content due to the QT-XT filter so it's too late.

In fact, there should be a much simpler solution. Try this:

function format_html_all_languages( $value )
{
  if (! is_string($value)) { 
    return $value;
  }
  $result = '';
  $raw_field = qtranxf_split($value);
  foreach ($raw_field as $one_translation) {
     $result .= nl2br($one_translation);
     $result .= '<br>';
  }
  return  $result;
}

add_filter( 'acf/format_value', 'format_html_all_languages', 4 );

By putting a priority at 4, your filter will run before QT-XT and translate it by removing the tags so the next filter in QT-XT ACF won't have any effect.

bichonnages commented 3 years ago

Thanks for the reply. Unfortunately this filter output the activated language translation multiple times and not both languages.

MK-RD commented 3 years ago

Thanks for the reply. Unfortunately this filter output the activated language translation multiple times and not both languages.

I thought your original solution worked for you?

Regardless, if the filter (herrvigg) is useful for you, you can get the missing translations by additionally deactivating the following filter.

remove_filter('get_post_metadata', 'qtranxf_filter_postmeta', 5 , 4);
herrvigg commented 3 years ago

Thanks for the reply. Unfortunately this filter output the activated language translation multiple times and not both languages.

Also I don't see why this would not work, I took the base code you provided. How could this output the same language multiple times? This makes no sense.

Try to debug it for example like this:

function format_html_all_languages( $value )
{
  if (! is_string($value)) { 
    return $value;
  }
  $result = '';
  $raw_field = qtranxf_split($value);
  foreach ($raw_field as $one_translation) {
     $result .= nl2br($one_translation);
     $result .= '<br>';
  }
  // return  $result;
  echo 'DEBUG: ' . $result;
  exit(1);
}
MK-RD commented 3 years ago

Thanks for the reply. Unfortunately this filter output the activated language translation multiple times and not both languages.

Also I don't see why this would not work, I took the base code you provided. How could this output the same language multiple times? This makes no sense.

Try to debug it for example like this:

function format_html_all_languages( $value )
{
  if (! is_string($value)) { 
    return $value;
  }
  $result = '';
  $raw_field = qtranxf_split($value);
  foreach ($raw_field as $one_translation) {
     $result .= nl2br($one_translation);
     $result .= '<br>';
  }
  // return  $result;
  echo 'DEBUG: ' . $result;
  exit(1);
}

@herrvigg Have you (really) tried it yourself?