# Dashboard Widget: Posts Missing WPML Translations

> Adds a dashboard widget that lists your 20 most recent posts and pages in the default language with the languages they still need translating into.

- Type: PHP
- Runs: Admin only
- Category: [Multilingual](https://wpide.com/library/category/multilingual/)
- Tags: wpml, dashboard, translations
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/wpml-missing-translations-widget/

## Code

```php
add_action( 'wp_dashboard_setup', function () {
    if ( ! defined( 'ICL_SITEPRESS_VERSION' ) || ! current_user_can( 'edit_others_posts' ) ) {
        return;
    }

    wp_add_dashboard_widget( 'wpide_wpml_missing', __( 'Missing translations' ), function () {
        $rows = get_transient( 'wpide_wpml_missing' );

        if ( false === $rows ) {
            $rows      = array();
            $languages = array_keys( (array) apply_filters( 'wpml_active_languages', null, array( 'skip_missing' => 0 ) ) );
            $default   = apply_filters( 'wpml_default_language', null );

            do_action( 'wpml_switch_language', $default );
            $ids = get_posts( array(
                'post_type'        => array( 'post', 'page' ),
                'numberposts'      => 20,
                'fields'           => 'ids',
                'no_found_rows'    => true,
                'suppress_filters' => false,
            ) );
            do_action( 'wpml_switch_language', null );

            foreach ( $ids as $id ) {
                $type    = apply_filters( 'wpml_element_type', get_post_type( $id ) );
                $trid    = apply_filters( 'wpml_element_trid', null, $id, $type );
                $have    = $trid ? array_keys( (array) apply_filters( 'wpml_get_element_translations', null, $trid, $type ) ) : array();
                $missing = array_diff( $languages, $have );
                if ( $missing ) {
                    $rows[] = array( 'id' => $id, 'missing' => array_values( $missing ) );
                }
            }
            set_transient( 'wpide_wpml_missing', $rows, HOUR_IN_SECONDS );
        }

        if ( ! $rows ) {
            echo '<p>' . esc_html__( 'Everything recent is translated.' ) . '</p>';
            return;
        }

        echo '<ul>';
        foreach ( $rows as $row ) {
            printf(
                '<li><a href="%1$s">%2$s</a> <span style="color:#646970">%3$s</span></li>',
                esc_url( (string) get_edit_post_link( $row['id'] ) ),
                esc_html( get_the_title( $row['id'] ) ),
                esc_html( strtoupper( implode( ', ', $row['missing'] ) ) )
            );
        }
        echo '</ul>';
    } );
} );

add_action( 'save_post', function () {
    delete_transient( 'wpide_wpml_missing' );
} );
```

## Notes

Cached for an hour and refreshed whenever a post is saved. Only editors and administrators see it.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Dashboard Widget: Posts Missing WPML Translations" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
