• Hi!

    When translating custom fields NOT added via ACF, the default field in the translation interface is an input of type text.

    In many scenarios, this is not suitable, because metadata can be anything from a one-liner to a block of text, or a data structure, like a JSON string.

    There is no hook to alter this behavior (the field is hard-coded in falang/admin/views/edit_post_page.php).
    A way for developers working with field meta not part of ACF would be to emulate get_field_objects – which is a lot of work, error-prone, limited in scope, and too opinionated.

    A low-hanging fruit (but far from ideal) solution to make sure all text-based meta can actually be edited would be to use a textarea for all the custom meta, in falang/admin/views/edit_post_page.php:

    
    <input type="text" name="<?php echo $key; ?>" id="<?php echo $key; ?>" value="<?php echo isset($previous_value[0])?esc_attr($previous_value[0]):''; ?>" class="falang">
    

    to be replaced with:

    
    <textarea name="<?php echo $key; ?>" id="<?php echo $key; ?>" class="falang"><?php echo isset($previous_value[0])?esc_attr($previous_value[0]):''; ?></textarea>
    

    A better solution (a bit more work-intensive, but with the bulk of the responsibility offloaded to the developer integrating the falang plugin) would be to expose a filter for each translatable field for developers to override the translation interface of the field.
    Indeed, some meta fields may be stored one way, but displayed and edited in another, for example stored as JSON but edited with a custom interface.
    Another use case would be that some values are to be selected from a pre-determined set, and not free text, where free text could introduce bugs. This is specially important given that a translation interface is not aimed at developers, but at users.
    One current example of this limitation is the featured image, which many users struggle with (unless they’ve been trained) because they must input an attachment ID.

    For now, I can add a JS snippet to alter the input I need and transform them to textarea, or edit falang/admin/views/edit_post_page.php and lose the changes at each plugin update, which is not ideal.
    Having the possibility to override the interface would be the best solution, limiting the amount of maintenance for falang itself while opening the potential for a whole array of possible improvements.

Viewing 11 replies - 1 through 11 (of 11 total)
  • Thread Starter Alexandre Froger

    (@frogerme)

    Here is actually the full solution, not that much work-intensive, all considering:

    Replace this block:

    
    <!-- Manage MetaKeys -->
    	        <?php foreach ($falang_translated_metakeys as $key) { ?>
                <!-- ACF FIELDS are displayed with specific edit post page -->
                <?php $is_acf_field = false; ?>
                <?php if(isset($acf_fields)) {$is_acf_field = isset($acf_fields[$key]) ? true:false;}?>
                <?php if ($is_acf_field){continue;} ?>
    
    		        <?php $search_metakey = Falang_Core::get_prefix($falang_target_language_locale).$key?>
    		        <?php $previous_value = isset($falang_post->metakey[$search_metakey])?$falang_post->metakey[$search_metakey]:''; ?>
                    <div class="row">
                        <h2><?php echo $key ?></h2>
                        <div class="col-source">
                            <div id="original_value_<?php echo $key;?>" name="original_value_<?php echo $key;?>" style="display: inline-block">
    			                <?php echo $original_post->{$key}; ?>
                            </div>
                        </div><!-- col-source -->
                        <div class="col-action">
                            <button class="button-secondary button-copy" onclick="copyToTranslation('<?php echo $key;?>','copy');return false;" title="<?php  echo __( 'Copy', 'falang' ) ?>"><i class="far fa-copy"></i></button>
                            <!-- add yandex/azure button -->
                            <?php if ($falang_model->get_option('enable_service') == '1') { ?>
                                <?php if ($falang_model->get_option('service_name') == 'yandex') { ?>
                                    <button class="button-secondary button-copy" onclick="copyToTranslation('<?php echo $key;?>','translate');return false;" title="<?php  echo __( 'Translate with Yandex', 'falang' ) ?>"><i class="fab fa-yandex-international"></i></button>
                                <?php } ?>
                                <?php if ($falang_model->get_option('service_name') == 'azure') { ?>
                                    <button class="button-secondary button-copy" onclick="copyToTranslation('<?php echo $key;?>','translate');return false;" title="<?php  echo __( 'Translate with Azure', 'falang' ) ?>"><i class="fab fa-windows"></i></button>
                                <?php } ?>
                                <?php if ($falang_model->get_option('service_name') == 'lingvanex') { ?>
                                    <button class="button-secondary button-copy" onclick="copyToTranslation('<?php echo $key;?>','translate');return false;" title="<?php  echo __( 'Translate with Lingvanex', 'falang' ) ?>"><i class="fas fa-globe"></i></button>
                                <?php } ?>
                            <?php } ?>
                        </div><!-- col-action -->
                        <div class="col-target">
                            <input type="text" name="<?php echo $key; ?>" id="<?php echo $key; ?>" value="<?php echo isset($previous_value[0])?esc_attr($previous_value[0]):''; ?>" class="falang">
                        </div><!-- col-target -->
                    </div><!-- row -->
    	        <?php }//foreach metakeay ?>
    
              <!-- Manage ACF  -->
    
    

    With this block:

    <!-- Manage MetaKeys -->
    	        <?php foreach ($falang_translated_metakeys as $key) { ?>
                <!-- ACF FIELDS are displayed with specific edit post page -->
                <?php $is_acf_field = false; ?>
                <?php if(isset($acf_fields)) {$is_acf_field = isset($acf_fields[$key]) ? true:false;}?>
                <?php if ($is_acf_field){continue;} ?>
    
    		        <?php $search_metakey = Falang_Core::get_prefix($falang_target_language_locale).$key?>
    		        <?php $previous_value = isset($falang_post->metakey[$search_metakey])?$falang_post->metakey[$search_metakey]:''; ?>
                    <?php do_action( 'falang_translation_meta_field_' . $key, $key, $original_post, $falang_post, $falang_model, $previous_value ); ?>;
                    <?php if ( did_action( 'falang_translation_meta_field_' . $key ) ) { continue; } ?>;
                    <div class="row">
                        <h2><?php echo $key ?></h2>
                        <div class="col-source">
                            <div id="original_value_<?php echo $key;?>" name="original_value_<?php echo $key;?>" style="display: inline-block">
    			                <?php echo $original_post->{$key}; ?>
                            </div>
                        </div><!-- col-source -->
                        <div class="col-action">
                            <button class="button-secondary button-copy" onclick="copyToTranslation('<?php echo $key;?>','copy');return false;" title="<?php  echo __( 'Copy', 'falang' ) ?>"><i class="far fa-copy"></i></button>
                            <!-- add yandex/azure button -->
                            <?php if ($falang_model->get_option('enable_service') == '1') { ?>
                                <?php if ($falang_model->get_option('service_name') == 'yandex') { ?>
                                    <button class="button-secondary button-copy" onclick="copyToTranslation('<?php echo $key;?>','translate');return false;" title="<?php  echo __( 'Translate with Yandex', 'falang' ) ?>"><i class="fab fa-yandex-international"></i></button>
                                <?php } ?>
                                <?php if ($falang_model->get_option('service_name') == 'azure') { ?>
                                    <button class="button-secondary button-copy" onclick="copyToTranslation('<?php echo $key;?>','translate');return false;" title="<?php  echo __( 'Translate with Azure', 'falang' ) ?>"><i class="fab fa-windows"></i></button>
                                <?php } ?>
                                <?php if ($falang_model->get_option('service_name') == 'lingvanex') { ?>
                                    <button class="button-secondary button-copy" onclick="copyToTranslation('<?php echo $key;?>','translate');return false;" title="<?php  echo __( 'Translate with Lingvanex', 'falang' ) ?>"><i class="fas fa-globe"></i></button>
                                <?php } ?>
                            <?php } ?>
                        </div><!-- col-action -->
                        <div class="col-target">
                            <textarea name="<?php echo $key; ?>" id="<?php echo $key; ?>" class="falang"><?php echo isset($previous_value[0])?esc_attr($previous_value[0]):''; ?></textarea>
                        </div><!-- col-target -->
                    </div><!-- row -->
    	        <?php }//foreach metakeay ?>
    
              <!-- Manage ACF  -->

    See the input changed into a textarea, and the follwing 2 added lines:

    
    <?php do_action( 'falang_translation_meta_field_' . $key, $key, $original_post, $falang_post, $falang_model, $previous_value ); ?>;
                    <?php if ( did_action( 'falang_translation_meta_field_' . $key ) ) { continue; } ?>;
    
    Plugin Author sbouey

    (@sbouey)

    Hi,

    i look your solution and to put this in the next release.
    the next release is for next week.

    Stéphane

    Thread Starter Alexandre Froger

    (@frogerme)

    Thanks!
    After consideration, I realised did_action won’t do the job.
    I’ll update with a proper solution shortly.

    Thread Starter Alexandre Froger

    (@frogerme)

    This should actually do the trick:

    
    <?php if ( has_action( 'falang_translation_meta_field_' . $key ) ) {
        do_action( 'falang_translation_meta_field_' . $key, $key, $original_post, $falang_post, $falang_model, $previous_value );
        continue;
    } ?>;
    
    • We check if hooks are registered for the specified $key
    • If it is the case, we execute them
    • We skip the rest of the output for the field with that key, as it’s handled by the registered hooks
    Plugin Author sbouey

    (@sbouey)

    thank you for your suggestion,

    1) i have changed for the next release the input to

                            <textarea name="<?php echo $key; ?>" id="<?php echo $key; ?>" class="falang"><?php echo isset($previous_value[0])?esc_textarea($previous_value[0]):''; ?></textarea>
    

    i have changed esc_attr to esc_textarea

    2) but i you don’t manage the translation for this field in FAlang where do you manage it ?
    why you just set in falang > settings > Translate option > post not to translate this meta

    Thread Starter Alexandre Froger

    (@frogerme)

    Regarding 2 (a bit of a rant – TL;DR at the bottom):

    Some metadata of custom post types are sometimes simply extra content shown in the frontend, and this can come in any shape or form, since metaboxes are entirely customisable. It can be a color picker, or a multiple fields widget, or any combination, really.

    In my own case, I have to maintain a custom metabox in a WooCommerce product ; this metabox contains a list of text fields of variable length with buttons to add or remove fields, and upon saving the product, the content of the fields is collected and saved as a JSON string in the metadata of the product. The content is then parsed and displayed in the frontend, which is why they need translation.

    So far, what I was forced to do was to edit the translation myself, and edit the JSON string in the input field from the translation interface. But if I can override the UI with a hook, I can simply replicate the same UI as in the metabox of the main post in the translation page, which then allow users to get a similar experience all around, without them needing to learn how to edit JSON.

    I am aware this is a particular case that I describe ; however, the translation of media (indicating the ID in a text field instead of using a media library selector) for example suffers from the same issue as it’s not exactly user-friendly, and falls more into the “power user” territory ; I can already imagine how many other plugins adding extra fields would be in that case too.

    It would be unfair to require Falang to cover all cases, but adding the possibility for developers to satisfy their users by handling the UI themselves will increase the user experience all around.

    Having an action hook here (and actions and filter hooks elsewhere in the plugin, really) would also enable you to create companion plugins more easily (potentially premium ones) down the line, so I can see a lot of benefits for everyone here ;).

    TL;DR: some metadata saved in the database in an non-UI-friendly way with specific UI in the main post page may need to be exposed to the frontend, therefore need to be translated with a consistent UI/UX, plus actions and filter hooks are WordPress best practice and a huge benefit for all.

    Plugin Author sbouey

    (@sbouey)

    Hi,

    I’m ok to put this in the next release Alexandre but do you have a way to test your code

    
    <?php if ( has_action( 'falang_translation_meta_field_' . $key ) ) {
        do_action( 'falang_translation_meta_field_' . $key, $key, $original_post, $falang_post, $falang_model, $previous_value );
        continue;
    } ?>;
    

    I want to release the next version thuesday

    Stéphane

    Thread Starter Alexandre Froger

    (@frogerme)

    Hello Stéphane!

    Thanks for following up, really appreciated!

    To test, I quickly added the following code to a custom plugin’s main file:

    
    add_action( 'falang_translation_meta_field__thumbnail_id', function( $key, $original_post, $falang_post, $falang_model, $previous_value  ) {
    	?>
    	<div class="row">
    		<h2>Custom Row Title</h2>
    		<div class="col-source">
    			<div>
    				<code>Some custom markup for the original !!!</code>
    			</div>
    		</div><!-- col-source -->
    		<div class="col-action">
    			<button class="button-secondary button-copy" title="Custom handling of copy"><i class="far fa-copy"></i></button>
    		</div><!-- col-action -->
    		<div class="col-target">
    			<code>Some custom markup for the translation !!!</code>
    		</div><!-- col-target -->
    	</div>
    	<?php
    }, 10, 5 );
    

    It effectively overrides the translation interface for the featured image (not functional, it’s only a dummy example of markup – it is up to the developer to provide input with proper id, name, and other attributes for the form to be submitted correctly to save the translation), while the other fields remain untouched.

    You can see the intended result here: https://pasteboard.co/zlB5FQZwk3T5.png

    Plugin Author sbouey

    (@sbouey)

    Hi,

    i have tested your code and it’s work perfectly,
    i have put it in the next release 1.3.29

    Thanks a lot

    Stéphane

    Thread Starter Alexandre Froger

    (@frogerme)

    Got the latest version, thx for credits in the comments ??

    Plugin Author sbouey

    (@sbouey)

    Hi,

    It’s normal to put credits, I chose to put only your nickname, if you prefer your name i can replace it

    your suggestion is good and after that i can make improvment to have a way for woocommerce thumbnail , actualy i can set directly the id but i can change this and make an image selector

    Stéphane

Viewing 11 replies - 1 through 11 (of 11 total)
  • The topic ‘Metadata translation fields’ is closed to new replies.