Make WordPress Core

Opened 16 months ago

Last modified 16 months ago

#58616 new defect (bug)

Replace apostrophe with hyphen for slugs

Reported by: anrghg's profile anrghg Owned by:
Milestone: Awaiting Review Priority: normal
Severity: major Version:
Component: Formatting Keywords:
Focuses: Cc:

Description

I wonder if anybody ever complained about WordPress deleting apostrophes when generating slugs, unlike news outlets replacing them with hyphens for readability.

Title-derived slugs are designed for human readability, but WordPress defeats the point by removing all apostrophes. In the resulting mess, genitives appear like plurals, it’s becomes its, and in other locales even more confusing or ridiculous constructs build up like when “l’a” (has it) becomes “la” (the, in French).

Letter apostrophe and ʻokina need to become underscores along the same lines.

A solution is to add the following near the start of sanitize_title_with_dashes() in wp-includes/formatting.php:

<?php
/**
 * Converts punctuation apostrophe to hyphen-minus.
 */
$p_s_title = str_replace(
        array(
                '’',  // Punctuation apostrophe.
                '\'', // ASCII apostrophe.
        ),
        '-',
        $p_s_title
);

/**
 * Converts letter apostrophe and ʻokina to underscore.
 */
$p_s_title = str_replace(
        array(
                'ʼ',  // Letter apostrophe.
                'ʻ',  // ʻokina.
        ),
        '_',
        $p_s_title
);

A current workaround consists in adding this code in a child theme’s functions.php:

<?php
/**
 * Filters a sanitized title string respecting apostrophes.
 *
 * @courtesy WordPress
 * @see sanitize_title()
 * @link https://developer.wordpress.org/reference/functions/sanitize_title/
 *
 * @param string $p_s_title     Sanitized title.
 * @param string $p_s_raw_title The title prior to sanitization.
 * @param string $p_s_context   The context for which the title is being sanitized.
 */
add_filter(
        'sanitize_title',
        function( $p_s_title, $p_s_raw_title, $p_s_context = 'save' ) {
                if ( '' === $p_s_raw_title || false === $p_s_raw_title ) {
                        $p_s_raw_title = $p_s_title; // Already $fallback_title.
                }
                $p_s_title = $p_s_raw_title;

                /**
                 * Converts punctuation apostrophe to hyphen-minus.
                 */
                $p_s_title = str_replace(
                        array(
                                '’',  // Punctuation apostrophe.
                                '\'', // ASCII apostrophe.
                        ),
                        '-',
                        $p_s_title
                );

                /**
                 * Converts letter apostrophe and ʻokina to underscore.
                 */
                $p_s_title = str_replace(
                        array(
                                'ʼ',  // Letter apostrophe.
                                'ʻ',  // ʻokina.
                        ),
                        '_',
                        $p_s_title
                );

                if ( 'save' === $p_s_context || 'display' === $p_s_context ) {
                        $p_s_title = remove_accents( $p_s_title, $p_s_locale = 'fr_FR' );
                        $p_s_title = sanitize_title_with_dashes( $p_s_title, '', $p_s_context );
                }

                return $p_s_title;
        },
        PHP_INT_MAX,
        3
);

Change History (2)

#1 @anrghg
16 months ago

  • Summary changed from Replace apostrophe with hyphen for page slugs to Replace apostrophe with hyphen for slugs

#2 @anrghg
16 months ago

Forgot to change the variable names to WordPress’:

<?php
/**
 * Converts punctuation apostrophe to hyphen-minus.
 */
$title = str_replace(
        array(
                '’',  // Punctuation apostrophe.
                '\'', // ASCII apostrophe.
        ),
        '-',
        $title
);

/**
 * Converts letter apostrophe and ʻokina to underscore.
 */
$title = str_replace(
        array(
                'ʼ',  // Letter apostrophe.
                'ʻ',  // ʻokina.
        ),
        '_',
        $title
);
Note: See TracTickets for help on using tickets.