[root]\n" ); exit( 1 ); } $domain = $argv[1]; $root = $argv[2] ?? '.'; $functions = array( '__', '_e', '_x', '_ex', '_n', '_nx', '_n_noop', '_nx_noop', 'esc_html__', 'esc_html_e', 'esc_html_x', 'esc_attr__', 'esc_attr_e', 'esc_attr_x', ); $problems = 0; $iterator = new RecursiveIteratorIterator( new RecursiveCallbackFilterIterator( new RecursiveDirectoryIterator( $root, FilesystemIterator::SKIP_DOTS ), static function ( $file ) { $name = $file->getFilename(); return ! in_array( $name, array( '.git', 'node_modules', 'vendor', 'build' ), true ); } ) ); foreach ( $iterator as $file ) { if ( 'php' !== strtolower( $file->getExtension() ) ) { continue; } $path = $file->getPathname(); $tokens = token_get_all( file_get_contents( $path ) ); $count = count( $tokens ); for ( $i = 0; $i < $count; $i++ ) { $token = $tokens[ $i ]; if ( ! is_array( $token ) || T_STRING !== $token[0] || ! in_array( $token[1], $functions, true ) ) { continue; } // Skip method calls and definitions: ->__(), function __(). $prev = $i - 1; while ( $prev >= 0 && is_array( $tokens[ $prev ] ) && T_WHITESPACE === $tokens[ $prev ][0] ) { --$prev; } if ( $prev >= 0 && is_array( $tokens[ $prev ] ) && in_array( $tokens[ $prev ][0], array( T_OBJECT_OPERATOR, T_DOUBLE_COLON, T_FUNCTION ), true ) ) { continue; } // Find the opening parenthesis. $j = $i + 1; while ( $j < $count && is_array( $tokens[ $j ] ) && T_WHITESPACE === $tokens[ $j ][0] ) { ++$j; } if ( $j >= $count || '(' !== $tokens[ $j ] ) { continue; } // Collect every literal string passed at the top level of this call. $depth = 0; $strings = array(); for ( $k = $j; $k < $count; $k++ ) { $t = $tokens[ $k ]; if ( '(' === $t ) { ++$depth; continue; } if ( ')' === $t ) { --$depth; if ( 0 === $depth ) { break; } continue; } if ( is_array( $t ) && T_CONSTANT_ENCAPSED_STRING === $t[0] ) { $strings[] = trim( $t[1], "'\"" ); } } if ( ! in_array( $domain, $strings, true ) ) { printf( "::error file=%s,line=%d::The %s() call is missing the text domain '%s'.\n", ltrim( str_replace( $root, '', $path ), '/' ), $token[2], $token[1], $domain ); ++$problems; } } } if ( $problems > 0 ) { printf( "\n%d translation calls are missing the text domain.\n", $problems ); exit( 1 ); } echo "Every translation call carries the text domain '{$domain}'.\n"; exit( 0 );