Refactoring : sécurité (XSS), découpage en modules inc/* et js/admin/*, IDs résolus par slug, perf (caches, cron Gravatar, assets auto-hébergés), tests
This commit is contained in:
120
inc/i18n.php
Normal file
120
inc/i18n.php
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
/**
|
||||
* Multilingue maison (remplace Polylang).
|
||||
*
|
||||
* Détection de langue par préfixe /en/, champs bilingues "FR // EN",
|
||||
* préfixage des URLs internes, traduction des noms de catégories,
|
||||
* filtres Twig (|bilingual, |en_url, |cat_name) et sélecteur de langue.
|
||||
*/
|
||||
|
||||
// ── Language detection (replaces Polylang) ───────────────────────
|
||||
define( 'THALIM_ORIGINAL_URI', $_SERVER['REQUEST_URI'] ?? '/' );
|
||||
|
||||
function thalim_current_language(): string {
|
||||
if ( isset( $GLOBALS['thalim_lang_override'] ) ) return $GLOBALS['thalim_lang_override'];
|
||||
$uri = THALIM_ORIGINAL_URI;
|
||||
return ( strpos( $uri, '/en/' ) === 0 || rtrim( $uri, '/' ) === '/en' ) ? 'en' : 'fr';
|
||||
}
|
||||
|
||||
// Strip /en/ prefix before WordPress resolves the URL
|
||||
add_filter( 'do_parse_request', function ( $do_parse ) {
|
||||
$uri = THALIM_ORIGINAL_URI;
|
||||
if ( strpos( $uri, '/en/' ) === 0 ) {
|
||||
$_SERVER['REQUEST_URI'] = substr( $uri, 3 );
|
||||
} elseif ( rtrim( $uri, '/' ) === '/en' ) {
|
||||
$_SERVER['REQUEST_URI'] = '/';
|
||||
}
|
||||
return $do_parse;
|
||||
}, 1 );
|
||||
|
||||
// Prevent WP canonical redirect from overriding /en/ URLs
|
||||
add_filter( 'redirect_canonical', function ( $redirect ) {
|
||||
if ( strpos( THALIM_ORIGINAL_URI, '/en/' ) === 0 ) return false;
|
||||
return $redirect;
|
||||
}, 10, 2 );
|
||||
|
||||
// Split "FR // EN" bilingual fields — returns the right part for the given lang
|
||||
function thalim_bilingual( string $value, string $lang = null ): string {
|
||||
if ( $lang === null ) $lang = thalim_current_language();
|
||||
if ( strpos( $value, ' // ' ) === false ) return $value;
|
||||
$parts = explode( ' // ', $value, 2 );
|
||||
return ( $lang === 'en' && trim( $parts[1] ?? '' ) !== '' ) ? trim( $parts[1] ) : trim( $parts[0] );
|
||||
}
|
||||
|
||||
// Prepend /en to any internal URL when current language is EN.
|
||||
// Idempotent: safe to call multiple times on the same URL.
|
||||
function thalim_en_url( string $url ): string {
|
||||
if ( thalim_current_language() !== 'en' ) return $url;
|
||||
$home = rtrim( home_url(), '/' );
|
||||
$path = substr( $url, strlen( $home ) );
|
||||
if ( str_starts_with( $path, '/en/' ) || $path === '/en' ) return $url;
|
||||
return $home . '/en' . $path;
|
||||
}
|
||||
|
||||
// Auto-prefix all WP-generated internal URLs in EN mode.
|
||||
// Safe on admin: THALIM_ORIGINAL_URI starts with /wp-admin/ there,
|
||||
// so thalim_current_language() returns 'fr' and thalim_en_url() is a no-op.
|
||||
add_filter( 'term_link', 'thalim_en_url' ); // get_term_link(), get_category_link(), get_tag_link()
|
||||
add_filter( 'post_link', 'thalim_en_url' ); // get_permalink() on regular posts
|
||||
add_filter( 'page_link', 'thalim_en_url' ); // get_permalink() on pages
|
||||
add_filter( 'post_type_link', 'thalim_en_url' ); // get_permalink() on CPTs
|
||||
add_filter( 'author_link', 'thalim_en_url' ); // get_author_posts_url()
|
||||
|
||||
// Return the translated category name if viewing in EN and titre_anglais is set.
|
||||
// Accepts a WP_Term, Timber\Term, term_id (int), or a name string + term_id.
|
||||
function thalim_cat_name( $cat, string $lang = null ): string {
|
||||
if ( $lang === null ) $lang = thalim_current_language();
|
||||
if ( is_object( $cat ) ) {
|
||||
$term_id = $cat->term_id ?? ( $cat->id ?? 0 );
|
||||
$fallback = $cat->name;
|
||||
} elseif ( is_numeric( $cat ) ) {
|
||||
$term_id = (int) $cat;
|
||||
$term = get_term( $term_id, 'category' );
|
||||
$fallback = $term && ! is_wp_error( $term ) ? $term->name : (string) $cat;
|
||||
} else {
|
||||
return (string) $cat;
|
||||
}
|
||||
if ( $lang !== 'en' ) return $fallback;
|
||||
$en = get_term_meta( $term_id, 'titre_anglais', true );
|
||||
return ( $en !== '' && $en !== false ) ? $en : $fallback;
|
||||
}
|
||||
|
||||
// Register bilingual and en_url as Twig filters
|
||||
add_filter( 'timber/twig', function ( $twig ) {
|
||||
$twig->addFilter( new \Twig\TwigFilter( 'bilingual', 'thalim_bilingual' ) );
|
||||
$twig->addFilter( new \Twig\TwigFilter( 'en_url', 'thalim_en_url' ) );
|
||||
$twig->addFilter( new \Twig\TwigFilter( 'cat_name', 'thalim_cat_name' ) );
|
||||
return $twig;
|
||||
} );
|
||||
|
||||
// Language switcher data (replaces pll_the_languages)
|
||||
// Output matches the structure header.twig expects: slug, url, current_lang
|
||||
function thalim_language_switcher(): array {
|
||||
$uri = THALIM_ORIGINAL_URI;
|
||||
$path = parse_url( $uri, PHP_URL_PATH ) ?? '/';
|
||||
$query = ( $q = parse_url( $uri, PHP_URL_QUERY ) ) ? '?' . $q : '';
|
||||
$is_en = thalim_current_language() === 'en';
|
||||
|
||||
$fr_path = $is_en ? ( substr( $path, 3 ) ?: '/' ) : $path;
|
||||
$en_path = $is_en ? $path : '/en' . $path;
|
||||
|
||||
return [
|
||||
'fr' => [ 'slug' => 'fr', 'url' => home_url( $fr_path ) . $query, 'current_lang' => ! $is_en ],
|
||||
'en' => [ 'slug' => 'en', 'url' => home_url( $en_path ) . $query, 'current_lang' => $is_en ],
|
||||
];
|
||||
}
|
||||
|
||||
// Apply bilingual split to the browser tab title + translate category names
|
||||
add_filter('document_title_parts', function ($title_parts) {
|
||||
if (!empty($title_parts['title'])) {
|
||||
$title_parts['title'] = thalim_bilingual($title_parts['title']);
|
||||
// On category archives, replace the title with the translated category name
|
||||
if ( is_category() ) {
|
||||
$cat = get_queried_object();
|
||||
if ( $cat ) {
|
||||
$title_parts['title'] = thalim_cat_name( $cat );
|
||||
}
|
||||
}
|
||||
}
|
||||
return $title_parts;
|
||||
});
|
||||
Reference in New Issue
Block a user