: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
'encode_url' => $encode_url,
function update_main_table( $id, $code, $default_locale, $encode_url, $tag ) {
$wpdb->prefix . 'icl_languages', [
'default_locale' => $default_locale,
'encode_url' => $encode_url,
function insert_translation( $name, $language_code, $display_language_code ) {
$insert_sql = "INSERT INTO {$wpdb->prefix}icl_languages_translations (name, language_code, display_language_code) VALUES(%s, %s, %s)";
$insert_prepared = $wpdb->prepare( $insert_sql, [ $name, $language_code, $display_language_code ] );
return $wpdb->query( $insert_prepared );
function update_translation( $name, $language_code, $display_language_code ) {
$update_sql = "UPDATE {$wpdb->prefix}icl_languages_translations SET name=%s WHERE language_code = %s AND display_language_code = %s";
$update_prepared = $wpdb->prepare( $update_sql, [ $name, $language_code, $display_language_code ] );
$wpdb->query( $update_prepared );
function insert_flag( $lang_code, $flag, $from_template ) {
$insert_sql = "INSERT INTO {$wpdb->prefix}icl_flags (lang_code, flag, from_template) VALUES(%s, %s, %s)";
$insert_prepared = $wpdb->prepare( $insert_sql, [ $lang_code, $flag, $from_template ] );
return $wpdb->query( $insert_prepared );
function update_flag( $lang_code, $flag, $from_template ) {
$update_sql = "UPDATE {$wpdb->prefix}icl_flags SET flag= %s,from_template=%s WHERE lang_code = %s";
$update_prepared = $wpdb->prepare( $update_sql, [ $flag, $from_template, $lang_code ] );
$wpdb->query( $update_prepared );
if ( ! isset( $_POST['icl_edit_languages'] ) || ! is_array( $_POST['icl_edit_languages'] ) ) {
$this->set_errors( __( 'Please, enter valid data.', 'sitepress' ) );
global $sitepress, $wpdb;
// First check if add and validate it.
if ( isset( $_POST['icl_edit_languages']['add'] ) && $_POST['icl_edit_languages_ignore_add'] == 'false' ) {
if ( $this->validate_one( 'add', $_POST['icl_edit_languages']['add'] ) ) {
$this->insert_one( $this->sanitize( $_POST['icl_edit_languages']['add'] ) );
// Reset flag upload field.
$_POST['icl_edit_languages']['add']['flag_upload'] = 'false';
foreach ( $_POST['icl_edit_languages'] as $id => $data ) {
// Validate and sanitize data.
if ( ! $this->validate_one( $id, $data ) ) {
$data = stripslashes_deep( $data );
$this->update_main_table( $id, $data['code'], $data['default_locale'], $data['encode_url'], $data['tag'] );
$wpdb->prepare( "SELECT code FROM {$wpdb->prefix}icl_locale_map WHERE code = %s", $data['code'] )
$wpdb->update( $wpdb->prefix . 'icl_locale_map', [ 'locale' => $data['default_locale'] ], [ 'code' => $data['code'] ] );
$wpdb->prefix . 'icl_locale_map', [
'locale' => $data['default_locale'],
// Update translations table.
foreach ( $data['translations'] as $translation_code => $translation_value ) {
// If new (add language) translations are submitted.
if ( $translation_code == 'add' ) {
if ( ( $this->is_new_data_and_invalid() ) || $_POST['icl_edit_languages_ignore_add'] == 'true' ) {
if ( empty( $translation_value ) ) {
$translation_value = $data['english_name'];
$translation_code = $_POST['icl_edit_languages']['add']['code'];
"SELECT id FROM {$wpdb->prefix}icl_languages_translations WHERE language_code = %s AND display_language_code=%s",
$this->update_translation( $translation_value, $data['code'], $translation_code );
if ( ! $this->insert_translation( $translation_value, $data['code'], $translation_code ) ) {
$this->set_errors( sprintf( __( 'Error adding translation %1$s for %2$s.', 'sitepress' ), $data['code'], $translation_code ) );
$from_template = $this->handle_flag_post_data( $data, $id );
$this->update_flag( $data['code'], $data['flag'], $from_template );
// Reset flag upload field.
$_POST['icl_edit_languages'][ $id ]['flag_upload'] = 'false';
$sitepress->get_language_name_cache()->clear();
$sitepress->clear_flags_cache();
delete_option( '_icl_cache' );
if ( $this->is_new_data_and_valid() ) {
unset( $_POST['icl_edit_languages']['add'] );
// Reset active languages.
$this->get_active_languages();
$this->update_language_packs( $sitepress );
private function handle_flag_post_data( array &$data, $id ) {
if ( $this->is_flag_uploading_process( $data, $id ) ) {
if ( $filename = $this->upload_flag( $id ) ) {
$data['flag'] = $filename;
$data['flag'] = $data['code'] . '.png';
$this->set_errors( __( 'Error uploading flag file.', 'sitepress' ) );
$this->wpml_flags->clear();
} elseif ( empty( $data['flag'] ) || 'false' === $data['flag_upload'] ) {
$data['flag'] = $data['code'] . '.png';
private function is_flag_uploading_process( array &$data, $id ) {
return array_key_exists( 'flag_upload', $data ) && 'true' == $data['flag_upload'] && ! empty( $_FILES['icl_edit_languages']['name'][ $id ]['flag_file'] );
function insert_one( $data ) {
global $sitepress, $wpdb;
$data = stripslashes_deep( stripslashes_deep( $data ) );
if ( ! $this->insert_main_table( $data['code'], $data['english_name'], $data['default_locale'], 0, 1, $data['encode_url'], $data['tag'] ) ) {
$this->set_errors( __( 'Adding language failed.', 'sitepress' ) );
$locale_exists = $wpdb->get_var(
FROM {$wpdb->prefix}icl_locale_map
WHERE code=%s", $data['code']
$wpdb->update( $wpdb->prefix . 'icl_locale_map', [ 'locale' => $data['default_locale'] ], [ 'code' => $data['code'] ] );
$wpdb->prefix . 'icl_locale_map', [
'locale' => $data['default_locale'],
$all_languages = $sitepress->get_languages();
foreach ( $all_languages as $key => $lang ) {
if ( array_key_exists( $lang['code'], $data['translations'] ) ) {
if ( empty( $data['translations'][ $lang['code'] ] ) ) {
$data['translations'][ $lang['code'] ] = $data['english_name'];
if ( ! $this->insert_translation(
$data['translations'][ $lang['code'] ],
__( 'Error adding translation %1$s for %2$s.', 'sitepress' ),
if ( ! $this->insert_translation( $data['english_name'], $data['code'], $lang['code'] ) ) {
__( 'Error adding translation %1$s for %2$s.', 'sitepress' ),
if ( ! isset( $data['translations']['add'] ) || empty( $data['translations']['add'] ) ) {
$data['translations']['add'] = $data['english_name'];
if ( ! $this->insert_translation( $data['translations']['add'], $data['code'], $data['code'] ) ) {
$this->set_errors( __( 'Error adding native name.', 'sitepress' ) );
$from_template = $this->handle_flag_post_data( $data, 'add' );
if ( ! $this->insert_flag( $data['code'], $data['flag'], $from_template ) ) {
$this->set_errors( __( 'Error adding flag.', 'sitepress' ) );
SitePress_Setup::insert_default_category( $data['code'] );
function validate_one( $id, $data ) {
$new_record = 'add' === $id;
'code' => esc_html__( 'The Language code already exists.', 'sitepress' ),
'english_name' => esc_html__( 'The Language name already exists.', 'sitepress' ),
'default_locale' => esc_html__( 'The default locale already exists.', 'sitepress' ),
'tag' => esc_html__( 'The hreflang already exists.', 'sitepress' ),
foreach ( $unique_columns as $column => $message ) {
$exists_args = [ $data[ $column ] ];
$exists_query = 'SELECT ' . esc_sql( $column ) . ' FROM ' . $wpdb->prefix . 'icl_languages WHERE ' . esc_sql( $column ) . '=%s ';
$exists_query .= 'AND id!=%d ';
$exists_query .= 'LIMIT 1';
$exists = $wpdb->get_var( $wpdb->prepare( $exists_query, $exists_args ) );
$this->set_validation_failed( $id );
foreach ( $this->required_fields as $name => $type ) {
if ( 'flag' === $name ) {
if ( isset( $data['flag_upload'] ) && 'true' === $data['flag_upload'] ) {
$check = $_FILES['icl_edit_languages']['name'][ $id ]['flag_file'];
if ( ! $this->check_extension( $check ) ) {
$this->set_validation_failed( $id );
if ( 'code' === $name ) {
if ( ! $this->is_language_code_valid( $data[ $name ] ) ) {
$this->set_errors( __( 'Invalid character in language code.', 'sitepress' ) );
$this->set_validation_failed( $id );
if ( ! isset( $_POST['icl_edit_languages'][ $id ][ $name ] ) || empty( $_POST['icl_edit_languages'][ $id ][ $name ] ) ) {
if ( 'true' === $_POST['icl_edit_languages_ignore_add'] ) {
$this->set_errors( __( 'Please, enter required data.', 'sitepress' ) );
$this->set_validation_failed( $id );
if ( 'array' === $type && ! is_array( $_POST['icl_edit_languages'][ $id ][ $name ] ) ) {
$this->set_validation_failed( $id );
$this->set_errors( __( 'Please, enter valid data.', 'sitepress' ) );
* Checks that language code is valid.
* @param string $language_code Unvalidated language code from input.
private function is_language_code_valid( $language_code ) {
$pattern = '/^[a-zA-Z0-9\-\_]+$/';
return (bool) preg_match( $pattern, $language_code );
private function is_delete_language_action() {
return isset( $_GET['action'] ) && 'delete-language' === $_GET['action'] && wp_create_nonce( 'delete-language' . (int) $_GET['id'] ) == $_GET['icl_nonce'];
private function must_display_new_language_translation_column() {
return $this->is_edit_mode() || $this->is_new_data_and_valid();
private function is_new_data_and_invalid() {
return $this->validation_action && $this->validation_failed && 'add' === $this->validation_action;
private function is_new_data_and_valid() {
return $this->validation_action && ! $this->validation_failed && 'add' === $this->validation_action;
private function is_edit_mode() {
return 'edit' === $this->mode;
private function set_validation_failed( $id ) {
$this->validation_action = ( 'add' === $id ) ? 'add' : 'update';
$this->validation_failed = true;
function delete_language( $lang_id ) {
global $wpdb, $sitepress;
$lang = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}icl_languages WHERE id=%d", $lang_id ) );
if ( in_array( $lang->code, $this->built_in_languages, true ) ) {
$error = __( "Error: This is a built in language. You can't delete it.", 'sitepress' );
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}icl_languages WHERE id=%d", $lang_id ) );
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}icl_languages_translations WHERE language_code=%s", $lang->code ) );
$translation_ids = $wpdb->get_col( $wpdb->prepare( "SELECT translation_id FROM {$wpdb->prefix}icl_translations WHERE language_code=%s", $lang->code ) );
if ( $translation_ids ) {
$rids = $wpdb->get_col( "SELECT rid FROM {$wpdb->prefix}icl_translation_status WHERE translation_id IN (" . wpml_prepare_in( $translation_ids, '%d' ) . ')' );
$job_ids = $wpdb->get_col( "SELECT job_id FROM {$wpdb->prefix}icl_translate_job WHERE rid IN (" . wpml_prepare_in( $rids, '%d' ) . ')' );
$wpdb->query( "DELETE FROM {$wpdb->prefix}icl_translate WHERE job_id IN (" . wpml_prepare_in( $job_ids, '%d' ) . ')' );
$post_ids = $wpdb->get_col(
"SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE element_type LIKE %s AND language_code=%s",
[ wpml_like_escape( 'post_' ) . '%', $lang->code ]
remove_action( 'delete_post', [ $sitepress, 'delete_post_actions' ] );
foreach ( $post_ids as $post_id ) {
wp_delete_post( $post_id, true );
add_action( 'delete_post', [ $sitepress, 'delete_post_actions' ] );
remove_action( 'delete_term', [ $sitepress, 'delete_term' ], 1, 3 );
$tax_ids = $wpdb->get_col(
"SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE element_type LIKE %s AND language_code=%s",
[ wpml_like_escape( 'tax_' ) . '%', $lang->code ]
foreach ( $tax_ids as $tax_id ) {
$row = $wpdb->get_row( $wpdb->prepare( "SELECT term_id, taxonomy FROM {$wpdb->term_taxonomy} WHERE term_taxonomy_id=%d", $tax_id ) );
wp_delete_term( $row->term_id, $row->taxonomy );
add_action( 'delete_term', [ $sitepress, 'delete_term' ], 1, 3 );
global $IclCommentsTranslation;
remove_action( 'delete_comment', [ $IclCommentsTranslation, 'delete_comment_actions' ] );
foreach ( $post_ids as $post_id ) {
wp_delete_post( $post_id, true );
add_action( 'delete_comment', [ $IclCommentsTranslation, 'delete_comment_actions' ] );
'wpml_translation_update',
'type' => 'before_language_delete',
'language' => $lang->code,
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}icl_translations WHERE language_code=%s", $lang->code ) );
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}icl_strings WHERE language=%s", $lang->code ) );
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}icl_string_translations WHERE language=%s", $lang->code ) );
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}icl_locale_map WHERE code=%s", $lang->code ) );
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}icl_flags WHERE lang_code=%s", $lang->code ) );
icl_cache_clear( false );
$sitepress->get_translations_cache()->clear();
$sitepress->clear_flags_cache();
$sitepress->get_language_name_cache()->clear();
$this->set_messages( sprintf( esc_html__( 'The language %s was deleted.', 'sitepress' ), '<strong>' . $lang->code . '</strong>' ) );
$this->update_language_packs( $sitepress );
$error = __( 'Error: Language not found.', 'sitepress' );