wp-cli / language-command

Installs, activates, and manages language packs.
MIT License
13 stars 22 forks source link

Incorrect language installation status when plugin's slug is different from its text domain #136

Open mrcasual opened 10 months ago

mrcasual commented 10 months ago

Bug Report

Describe the current, buggy behavior

When listing available languages for a plugin using the wp language plugin list <plugin> command, the status is always uninstalled if the plugin's slug ≠ plugin's text domain.

This is due to the wp_get_installed_translations() method used in https://github.com/wp-cli/language-command/blob/24f76e35f477887d09f1fd40a60d9011a6da18bf/src/WP_CLI/CommandWithTranslation.php#L251-L257

wp_get_installed_translations() returns an array keyed by the text domain. As a result, the subsequent check for available languages ($available = ! empty( $available[ $slug ] ) ? array_keys( $available[ $slug ] ) : array();) results in an empty array if the plugin's slug is different from its text domain.

get_installed_languages() is used by the list command: https://github.com/wp-cli/language-command/blob/24f76e35f477887d09f1fd40a60d9011a6da18bf/src/Plugin_Language_Command.php#L92-L153

That's where the following check (against an empty $installed_translations array returned by get_installed_languages()) results in the uninstalled value: https://github.com/wp-cli/language-command/blob/24f76e35f477887d09f1fd40a60d9011a6da18bf/src/Plugin_Language_Command.php#L125

A solution is to account for the discrepancy between plugin slugs and text domains in the get_installed_languages() method.

swissspidy commented 10 months ago

Can you give an example of a plugin where this is happening?

How would WP-CLI know what the correct text domain would be for the plugin?

WordPress plugins are really meant to have matching slugs and text domains. If they don't match, this kind of situation is to be expected. I assume WordPress itself also doesn't recognize the translations as being installed in that case.

mrcasual commented 10 months ago

I assume WordPress itself also doesn't recognize the translations as being installed in that case.

It does because it relies on the text domain, not the plugin slug.

Can you give an example of a plugin where this is happening?

It can happen with any plugin if it's placed in a folder that doesn't match its text domain. For example, install Gravity Forms, rename the gravityforms folder to gfforms, and you will see an issue.

How would WP-CLI know what the correct text domain would be for the plugin?

Something like this:

$slug_to_text_domain_map = [];

foreach ( get_plugins() as $plugin_file => $plugin_data ) {
    $slug_to_text_domain_map[ dirname( $plugin_file ) ] = $plugin_data['TextDomain'];
}
swissspidy commented 10 months ago

It does because it relies on the text domain, not the plugin slug.

For loading, yes, but for updates I don't think WP has any such logic. At least I can't find it.

Looking at the Text Domain header sounds like an interesting hardening step, but also a bit unusual because of that.

mrcasual commented 10 months ago

By the way, updating translations via WP CLI doesn't work since get_translations_update() also uses the get_installed_languages() method. Similarly, the update status is always none. Installation works just fine though except the status that always shows uninstalled (i.e., the issue at hand).

Anyway, this is an easy fix. Thanks for looking into this!