Easy Translation for WordPress, PHP, Bricks Builder, Native Post Type based translations

This is a prototype for now I am just exploring idea the most efficient and future proof way to create translation system for wordpress.

function snn_get_languages() {
    $languages = get_option( 'snn_languages', array() );
    return $languages;
}

function snn_debug_mode() {
    return get_option( 'snn_debug_mode', false );
}

function snn_register_language_post_types() {
    $languages = snn_get_languages();
    if ( empty( $languages ) ) {
        return;
    }
    foreach ( $languages as $lang ) {
        $lang = sanitize_key( $lang );
        if ( empty( $lang ) || post_type_exists( $lang ) ) {
            continue;
        }
        $labels = array(
            'name'               => sprintf( '%s', strtoupper( $lang ) ),
            'singular_name'      => sprintf( 'Translation (%s)', strtoupper( $lang ) ),
            'add_new'            => 'Add New',
            'add_new_item'       => sprintf( 'Add New Translation (%s)', strtoupper( $lang ) ),
            'edit_item'          => sprintf( 'Edit Translation (%s)', strtoupper( $lang ) ),
            'new_item'           => sprintf( 'New Translation (%s)', strtoupper( $lang ) ),
            'view_item'          => sprintf( 'View Translation (%s)', strtoupper( $lang ) ),
            'search_items'       => sprintf( 'Search Translations (%s)', strtoupper( $lang ) ),
            'not_found'          => 'No translations found',
            'not_found_in_trash' => 'No translations found in Trash',
        );
        $args = array(
            'labels'             => $labels,
            'public'             => true,
            'publicly_queryable' => true,
            'show_ui'            => true,
            'show_in_menu'       => true,
            'has_archive'        => false,
            'rewrite'            => array(
                'slug'       => $lang,
                'with_front' => false,
            ),
            'supports'           => array( 'title', 'editor', 'excerpt', 'thumbnail', 'revisions' ),
            'taxonomies'         => array( 'category', 'post_tag' ),
        );
        register_post_type( $lang, $args );
    }
}
add_action( 'init', 'snn_register_language_post_types', 15 );

function snn_hide_language_post_type_menu_items() {
    if ( snn_debug_mode() ) {
        return;
    }
    $languages = snn_get_languages();
    if ( empty( $languages ) ) {
        return;
    }
    echo '<style>';
    foreach ( $languages as $lang ) {
        $lang = sanitize_key( $lang );
        echo '#menu-posts-' . esc_attr( $lang ) . ' { display: none !important; }';
    }
    echo '</style>';
}
add_action( 'admin_head', 'snn_hide_language_post_type_menu_items' );

function snn_add_admin_menu() {
    add_menu_page(
        'SNN Translation',
        'SNN Translation',
        'manage_options',
        'snn-translation',
        'snn_translation_admin_page',
        'dashicons-translation',
        80
    );
}
add_action( 'admin_menu', 'snn_add_admin_menu' );

function snn_translation_admin_page() {
    if ( isset( $_POST['snn_save'] ) && check_admin_referer( 'snn_save_options', 'snn_nonce' ) ) {
        $langs = isset( $_POST['snn_languages'] ) ? sanitize_text_field( $_POST['snn_languages'] ) : '';
        $lang_array = array_filter( array_map( 'trim', explode( ',', $langs ) ) );
        update_option( 'snn_languages', $lang_array );
        $debug = isset( $_POST['snn_debug_mode'] ) ? true : false;
        update_option( 'snn_debug_mode', $debug );
        echo '<div class="updated"><p>Settings saved.</p></div>';
    }
    $languages     = snn_get_languages();
    $languages_str = implode( ', ', $languages );
    $debug         = snn_debug_mode();
    ?>
    <div class="wrap">
        <h1>SNN Translation Settings</h1>
        <form method="post">
            <?php wp_nonce_field( 'snn_save_options', 'snn_nonce' ); ?>
            <table class="form-table">
                <tr>
                    <th scope="row"><label for="snn_languages">Languages</label></th>
                    <td>
                        <input type="text" name="snn_languages" id="snn_languages" value="<?php echo esc_attr( $languages_str ); ?>" class="regular-text" />
                        <p class="description">Enter language codes separated by commas. E.g., en, fr, de</p>
                    </td>
                </tr>
                <tr>
                    <th scope="row">Debug Mode</th>
                    <td>
                        <label for="snn_debug_mode">
                            <input type="checkbox" name="snn_debug_mode" id="snn_debug_mode" <?php checked( $debug ); ?> />
                            Enable debug mode (translations remain visible in admin menus)
                        </label>
                    </td>
                </tr>
            </table>
            <?php submit_button( 'Save Settings', 'primary', 'snn_save' ); ?>
        </form>
    </div>
    <?php
}

function snn_add_translation_flags_column( $columns ) {
    $columns['snn_translation'] = 'Translations';
    return $columns;
}
add_filter( 'manage_posts_columns', 'snn_add_translation_flags_column' );
add_filter( 'manage_pages_columns', 'snn_add_translation_flags_column' );

function snn_render_translation_flags_column( $column, $post_id ) {
    if ( 'snn_translation' !== $column ) {
        return;
    }
    if ( get_post_meta( $post_id, '_snn_original_post', true ) ) {
        return;
    }
    $languages = snn_get_languages();
    if ( empty( $languages ) ) {
        return;
    }
    $output = '';
    foreach ( $languages as $lang ) {
        $translation = snn_get_translation_post( $post_id, $lang );
        if ( $translation ) {
            $edit_link = get_edit_post_link( $translation->ID );
            $output .= '<a style="margin-right:6px;" href="' . esc_url( $edit_link ) . '" title="Edit ' . esc_attr( $lang ) . ' translation">' . strtoupper( esc_html( $lang ) ) . '</a>';
        } else {
            $url = add_query_arg( array(
                'snn_translate' => 1,
                'lang'          => $lang,
                'post_id'       => $post_id,
            ), admin_url( 'admin-post.php' ) );
            $output .= '<a style="margin-right:6px;" href="' . esc_url( $url ) . '" title="Translate to ' . esc_attr( $lang ) . '">' . strtoupper( esc_html( $lang ) ) . '</a>';
        }
    }
    echo $output;
}
add_action( 'manage_posts_custom_column', 'snn_render_translation_flags_column', 10, 2 );
add_action( 'manage_pages_custom_column', 'snn_render_translation_flags_column', 10, 2 );

function snn_get_translation_post( $post_id, $lang ) {
    $args = array(
        'post_type'   => $lang,
        'meta_query'  => array(
            array(
                'key'     => '_snn_original_post',
                'value'   => $post_id,
                'compare' => '='
            ),
            array(
                'key'     => '_snn_translation_lang',
                'value'   => $lang,
                'compare' => '='
            )
        ),
        'post_status' => 'any',
        'numberposts' => 1,
    );
    $posts = get_posts( $args );
    return ! empty( $posts ) ? $posts[0] : null;
}

function snn_clone_post( $post_id, $lang ) {
    $original_post = get_post( $post_id );
    if ( ! $original_post ) {
        return new WP_Error( 'no_post', 'Original post not found.' );
    }
    $new_post = array(
        'post_title'     => $original_post->post_title,
        'post_content'   => $original_post->post_content,
        'post_excerpt'   => $original_post->post_excerpt,
        'post_status'    => 'draft',
        'post_type'      => $lang,
        'post_author'    => get_current_user_id(),
        'menu_order'     => $original_post->menu_order,
        'post_parent'    => $original_post->post_parent,
        'comment_status' => $original_post->comment_status,
        'ping_status'    => $original_post->ping_status,
    );
    $new_post_id = wp_insert_post( $new_post );
    if ( is_wp_error( $new_post_id ) ) {
        return $new_post_id;
    }
    update_post_meta( $new_post_id, '_snn_original_post', $post_id );
    update_post_meta( $new_post_id, '_snn_translation_lang', $lang );
    update_post_meta( $new_post_id, '_snn_original_post_type', $original_post->post_type );
    $meta = get_post_meta( $post_id );
    foreach ( $meta as $meta_key => $meta_values ) {
        if ( in_array( $meta_key, array( '_edit_lock', '_edit_last', '_snn_original_post', '_snn_translation_lang', '_snn_original_post_type' ), true ) ) {
            continue;
        }
        foreach ( $meta_values as $meta_value ) {
            add_post_meta( $new_post_id, $meta_key, maybe_unserialize( $meta_value ) );
        }
    }
    $taxonomies = get_object_taxonomies( $original_post->post_type );
    foreach ( $taxonomies as $taxonomy ) {
        $terms = wp_get_object_terms( $post_id, $taxonomy, array( 'fields' => 'slugs' ) );
        if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {
            wp_set_object_terms( $new_post_id, $terms, $taxonomy, false );
        }
    }
    $thumbnail_id = get_post_thumbnail_id( $post_id );
    if ( $thumbnail_id ) {
        set_post_thumbnail( $new_post_id, $thumbnail_id );
    }
    return $new_post_id;
}

function snn_handle_translation_action() {
    if ( isset( $_GET['snn_translate'] ) && $_GET['snn_translate'] == 1 && isset( $_GET['lang'] ) && isset( $_GET['post_id'] ) ) {
        $lang    = sanitize_text_field( $_GET['lang'] );
        $post_id = absint( $_GET['post_id'] );
        if ( ! current_user_can( 'edit_post', $post_id ) ) {
            wp_die( 'Permission denied.' );
        }
        $translation = snn_get_translation_post( $post_id, $lang );
        if ( ! $translation ) {
            $result = snn_clone_post( $post_id, $lang );
            if ( is_wp_error( $result ) ) {
                wp_die( 'Error cloning post: ' . $result->get_error_message() );
            }
            $translation = get_post( $result );
        }
        wp_redirect( get_edit_post_link( $translation->ID, '' ) );
        exit;
    }
}
add_action( 'admin_init', 'snn_handle_translation_action' );

function snn_disable_canonical_for_translations( $redirect_url, $requested_url ) {
    if ( is_singular() ) {
        $post = get_queried_object();
        $languages = array_map( 'sanitize_key', snn_get_languages() );
        if ( $post && in_array( $post->post_type, $languages, true ) ) {
            return false;
        }
    }
    return $redirect_url;
}
add_filter( 'redirect_canonical', 'snn_disable_canonical_for_translations', 10, 2 );