Make WordPress Core

Opened 3 years ago

Last modified 4 months ago

#52696 new enhancement

__() avoiding default language fallback

Reported by: drzraf's profile drzraf Owned by:
Milestone: Future Release Priority: normal
Severity: minor Version:
Component: I18N Keywords: good-first-bug has-patch needs-refresh
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 (10)

#1 @swissspidy
15 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
4 months ago

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

#3 @samuelsilvapt
4 months ago

Hi! I'm exploring an approach like:

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

#4 @ckanitz
4 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
4 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.


4 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.


4 months ago

@swissspidy commented on PR #4581:


4 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
4 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
4 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.

Note: See TracTickets for help on using tickets.