Make WordPress Core

Opened 3 years ago

Last modified 5 weeks ago

#52696 new enhancement

Add a way to determine whether a translation exists

Reported by: drzraf's profile drzraf Owned by:
Milestone: Future Release Priority: normal
Severity: minor Version:
Component: I18N Keywords: good-first-bug needs-patch
Focuses: Cc:

Description

Currently __() wraps pomo/translations.php::translate_entry()̀ in such a way:

<?php
                function translate( $singular, $context = null ) {
                        $entry      = new Translation_Entry(
                                array(
                                        'singular' => $singular,
                                        'context'  => $context,
                                )
                        );
                        $translated = $this->translate_entry( $entry );
                        return ( $translated && ! empty( $translated->translations ) ) ? $translated->translations[0] : $singular;
                }

If no translation exist, the original is returned which is the more frequently desirable behavior.

But in some cases, the user may want to know whether the string obtained from __() is actually the translation or the original.

Use-case: I'm inserting programmatically taxonomy terms translated using a 3rd-party service. I'm iterating over [__("t1"), __("t2"), ...] and I would like to only insert those actually translated, ignoring the others.

Currently, I've no way to discriminate between the original and the translation (which may or may not be identical btw).

I'd like a function providing me this ability like. One such example
__i18n_exists($term, $context = null);

Change History (13)

#1 @swissspidy
22 months ago

  • Milestone changed from Awaiting Review to Future Release

This would make it consistent with the @wordpress/i18n JS package which has a hasTranslation function for this purpose as well.

#2 @swissspidy
11 months ago

  • Keywords needs-patch good-first-bug added
  • Version 5.6.2 deleted

#3 @samuelsilvapt
10 months ago

Hi! I'm exploring an approach like:

is_translated( $string, $domain );
is_translated_n( $string, $domain );

#4 @ckanitz
10 months ago

Hi!

I've startet working on this on the WCEU contributor day. My first approach of the requested feature looks like this:

<?php
function __i18n_exists( $text, $domain = 'default' ) {
        $translations = get_translations_for_domain( $domain );
        $translation  = $translations->translate( $text );

        if ( empty( $translations->entries ) ) {
                return null;
        }

        return $translation;
}

If I test it against de_DE translations "Post" translates to "Beitrag" but en_EN will just return null.

Let me know if that's the kind of behaviour you're looking for.

#5 @samuelsilvapt
10 months ago

@ckanitz I'm here too! What's your name? I'll try to find you :D

About your approach, I think we should return always a bool, not a string.
So, what do you think about this:

<?php
return empty( $translations->entries );

This ticket was mentioned in PR #4581 on WordPress/wordpress-develop by ckanitz.


10 months ago
#6

  • Keywords has-patch added; needs-patch removed

Worked together with @samuelsilvapt (wp.org profile: https://profiles.wordpress.org/samuelsilvapt/) on this.

We updated the __ and translate() function within /wp-includes/i18n.php as well as Translations::translate() function to support a new optional parameter $return_singular.

The new parameter defaults to true but if set to false, instead of the inputed $text as a fallback if no translation exists for that string null will returned instead.

We also introduced a new function has_translation( $text, $domain ) for explicit checks (like hasTranslation is already part of the @wordpress/i18n package).

Trac ticket: https://core.trac.wordpress.org/ticket/52696

This ticket was mentioned in Slack in #core by samuelsilvapt. View the logs.


10 months ago

@swissspidy commented on PR #4581:


10 months ago
#8

Great progress so far 👍

I would just recommend that instead of adding a new parameter to the translate() method, there should be a new has_translation() method. Also no need for changes to the __() function.

Something like this:

function has_translation( $text, $domain = 'default' ) {
        $translations = get_translations_for_domain( $domain );
        return $translations->has_translation( $text );
}

That makes everything much easier to understand and more maintainable.

#9 @ckanitz
10 months ago

Thanks for the feedback! I got the idea of your recommendation and agree, that has_translation() should be part of the Translate() (and NOOP_Translate()) class in translations.php and a wrapper in l10n.php.

But that's just for the helper functions, which is nice to have, but wouldn't be quiet "elegant" if you'd have to loop over a bunch of strings instead of just calling the known translation functions with an extra parameter tweaking the returned value.

We've started with an own function but since it was just a copy of __ we dropped it and thought about a more DRY approach with a new optional nonbreaking parameter.

If it's a real "no-go" to update the existing functions I'd propose for a new function after all but could need some help to find a better name instead of __i18n_exists.

#10 @swissspidy
10 months ago

  • Keywords needs-refresh added

Repurposing __() in such a way is a non-goal, so I would really just add a separate translation_exists() or has_translation function and a separate method on the translations class as described in my previous comment.

#11 @swissspidy
7 weeks ago

  • Keywords needs-patch added; has-patch needs-refresh removed

#12 @swissspidy
7 weeks ago

  • Summary changed from __() avoiding default language fallback to Add a way to determine whether a translation exists

This ticket was mentioned in Slack in #core by hellofromtonya. View the logs.


5 weeks ago

Note: See TracTickets for help on using tickets.