Localizzazione del tema per gli "slug" (tipi di post personalizzati, tassonomie)
Nel mio tema voglio definire una serie di tipi di post personalizzati (custom post types) e tassonomie personalizzate, ognuno con il proprio slug personalizzato; la lingua base del mio tema è l'inglese, quindi gli slug saranno in lingua inglese
Per esempio, mentre definisco lo slug del custom post type "product" negli argomenti:
'rewrite' => array( 'slug' => 'product' ),
C'è un modo per tradurre lo "slug" attraverso i file po/mo? Posso scriverlo come:
'rewrite' => array( 'slug' => __('product', 'mytextdomain') )
oppure non funzionerà? Qual è la pratica corrente per localizzare gli slug?
Non consiglierei di localizzare i tuoi slug. Piuttosto, perché non dare agli utenti la possibilità di modificarli aggiungendo un altro campo alla pagina delle impostazioni dei permalink?
Agganciati a load-options-permalink.php
e configura alcune cose per catturare i dati $_POST
e salvare il tuo slug. Aggiungi anche un campo di impostazione alla pagina.
<?php
add_action( 'load-options-permalink.php', 'wpse30021_load_permalinks' );
function wpse30021_load_permalinks()
{
if( isset( $_POST['wpse30021_cpt_base'] ) )
{
update_option( 'wpse30021_cpt_base', sanitize_title_with_dashes( $_POST['wpse30021_cpt_base'] ) );
}
// Aggiungi un campo di impostazione alla pagina dei permalink
add_settings_field( 'wpse30021_cpt_base', __( 'Base CPT' ), 'wpse30021_field_callback', 'permalink', 'optional' );
}
Poi la funzione di callback per il campo di impostazione:
<?php
function wpse30021_field_callback()
{
$value = get_option( 'wpse30021_cpt_base' );
echo '<input type="text" value="' . esc_attr( $value ) . '" name="wpse30021_cpt_base" id="wpse30021_cpt_base" class="regular-text" />';
}
Quando registri il tuo post type, recupera lo slug con get_option
. Se non è presente, usa quello predefinito.
<?php
add_action( 'init', 'wpse30021_register_post_type' );
function wpse30021_register_post_type()
{
$slug = get_option( 'wpse30021_cpt_base' );
if( ! $slug ) $slug = 'slug-predefinito';
// registra il tuo post type, riferisci $slug per il rewrite
$args['rewrite'] = array( 'slug' => $slug );
// Ovviamente probabilmente ti serviranno più $args di uno...
register_post_type( 'wpse30021_pt', $args );
}
Ecco la parte del campo di impostazione come plugin https://gist.github.com/1275867
MODIFICA: Un'altra Opzione
Potresti anche cambiare lo slug in base a quanto definito nella costante WPLANG
.
Scrivi semplicemente una rapida funzione che contiene i dati...
<?php
function wpse30021_get_slug()
{
// restituisce uno slug predefinito
if( ! defined( 'WPLANG' ) || ! WPLANG || 'en_US' == WPLANG ) return 'press';
// array di dati slug
$slugs = array(
'fr_FR' => 'presse',
'es_ES' => 'prensa'
// ecc.
);
return $slugs[WPLANG];
}
Poi ottieni lo slug dove registri il tuo custom post type.
<?php
add_action( 'init', 'wpse30021_register_post_type' );
function wpse30021_register_post_type()
{
$slug = wpse30021_get_slug();
// registra il tuo post type, riferisci $slug per il rewrite
$args['rewrite'] = array( 'slug' => $slug );
// Ovviamente probabilmente ti serviranno più $args di uno...
register_post_type( 'wpse30021_pt', $args );
}
L'opzione migliore, secondo me, sarebbe sia dare all'utente la possibilità di scegliere sia fornire dei solidi valori predefiniti:
<?php
add_action( 'init', 'wpse30021_register_post_type' );
function wpse30021_register_post_type()
{
$slug = get_option( 'wpse30021_cpt_base' );
// Non hanno impostato un'opzione, ottieni il predefinito
if( ! $slug ) $slug = wpse30021_get_slug();
// registra il tuo post type, riferisci $slug per il rewrite
$args['rewrite'] = array( 'slug' => $slug );
// Ovviamente probabilmente ti serviranno più $args di uno...
register_post_type( 'wpse30021_pt', $args );
}

+1 per il plugin su gist e il codice ben documentato. Nel mio caso, però, va contro lo scopo, che è quello di non dare potere all'utente ma di creare URL localizzati (SEO friendly) per custom post types

Non sono sicuro di capire perché vorresti rimuovere un'opzione dal tuo utente. Inoltre, passare uno slug attraverso un filtro di traduzione dà loro la stessa opzione: cambiare lo slug. Solo senza un bel campo del modulo da compilare.

Sembra che questa opzione sia pensata per una localizzazione basata su WPLANG. Ma cosa succede se stai lavorando con un sito multilingua? (ad esempio, il plugin WPML). La domanda riguarda più la possibilità di visualizzare uno slug diverso a seconda della localizzazione del client, piuttosto che la possibilità di impostare uno slug per un custom post type dalle opzioni del server.

wpse = WordPress stack exchange. 30021 è il numero presente nell'URL. Buona fortuna con la tua ricerca; ho dato la mia risposta. La complessità aggiuntiva che stai introducendo e l'apparente cambiamento completo della domanda originale — inizialmente riguardante gli slug dei CPT — rafforza solo l'argomento a favore di permettere all'utente finale di scegliere il proprio slug.

La domanda chiede se la funzione __()
può essere utilizzata con gli slug e "qual è la pratica per localizzare gli slug". Questo potrebbe essere interpretato come avere uno slug tradotto come una stringa quando visualizzi un tema in una determinata lingua, indipendentemente dal suo utilizzo in un CPT. Ecco perché è stato messo il bounty in primo luogo.

Considerando che a partire da WordPress 4.7 gli utenti possono impostare una lingua preferita per il loro profilo, utilizzare un'opzione dal database è in realtà la soluzione preferita. Se un utente ha selezionato una lingua diversa da quella del sito e attiva un flush dei permalink, ad esempio visitando le impostazioni dei permalink, la traduzione dello slug del post cambierà in quella dell'utente, cosa che non si vuole che accada.

Sto facendo esattamente questo in un tema che stiamo sviluppando. È disponibile in 5 lingue diverse, e ogni lingua ha un insieme di categorie tradotte. La prima componente dell'URL nel tema viene analizzata per determinare quale lingua viene utilizzata, nel formato paese-lingua:
/uk-en
/fr-fr
/it-it
E poi le categorie tradotte vengono analizzate come ulteriori componenti dell'URL.
L'URL viene analizzato nella fase parse_request
:
function my_parse_request( $wp ) {
$path = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
$components = preg_split('|/|', $path, null, PREG_SPLIT_NO_EMPTY );
// Determina la lingua da $components[0]
$language = array_shift( $components );
...
// Carica il file di traduzione...
$mofile = get_stylesheet_directory()."/$language.mo";
load_textdomain( 'mydomain', $mofile );
...
// Determina la categoria da $components[0]
if( __( 'some-category', 'mydomain' ) == $components[0] )
$wp->query_vars['category'] = 'some-category';
...
}
add_action( 'parse_request', 'my_parse_request' );
Questo esempio è privo dei controlli necessari, ma serve solo come esempio.
Ci sono degli svantaggi in questo approccio, ovviamente, ma permette URL naturali in tutte le lingue. I principali svantaggi che vedo sono:
1) Non utilizza il meccanismo dei permalink. Probabilmente si potrebbe estendere in modo che vengano generate le regole corrette dei permalink per tutte le lingue e parse_request non sarebbe necessario, ma farlo per tutte le lingue comporterebbe il caricamento di un file MO dopo l'altro in un ciclo, e non so quanto questo sia ben supportato.
2) Se un traduttore cambia uno slug, allora i link diventano invalidi.

Hai aggiunto il dominio di testo corretto? <?php load_theme_textdomain(my_text_domain);?> ?

Attenzione a questo! Da WordPress 4.7, gli utenti possono impostare una lingua preferita per il loro profilo. Se un utente ha una lingua diversa da quella del sito e attiva un flush dei permalink, ad esempio visitando le impostazioni dei permalink, la traduzione dello slug del post cambierà in quella dell'utente! Ecco perché la risposta accettata, che utilizza un'opzione che viene caricata dal database, è in realtà una soluzione molto migliore e a prova di errore.

Ho effettivamente avuto questo problema, ecco la mia soluzione, che funziona quando conosci a priori le lingue del tuo sito web. Supponiamo che tu abbia un CPT chiamato "movie" e il tuo sito abbia 3 lingue. Devi riscrivere il permalink del tuo CPT per ogni lingua. Potresti farlo anche dinamicamente.
add_action("init", "rewrite_cpt", 10, 0);
function rewrite_cpt(){
add_rewrite_rule('^movie/([^/]*)/?', 'index.php?post_type=movie&name=$matches[1]', 'top'); // Inglese
add_rewrite_rule('^film/([^/]*)/?', 'index.php?post_type=movie&name=$matches[1]', 'top'); // Italiano
add_rewrite_rule('^фильм/([^/]*)/?', 'index.php?post_type=movie&name=$matches[1]', 'top'); // Russo
}
Ora devi solo ricostruire i tuoi permalink: vai su Impostazioni > Permalink e premi semplicemente "Salva"
La parte successiva è riscrivere gli URL per il tuo CPT, se hai un CPT tradotto devi ottenere la lingua del post, nel mio caso uso Polylang. È importante codificare i caratteri stranieri negli URL
add_filter("post_type_link", "x_tours_postlink", 10, 2);
function x_tours_postlink($post_link, $post){
$urls = array(
"en" => "movie",
"it" => "film",
"ru" => "фильм"
);
if(get_post_type($post) == "movie")
$post_link = str_replace("movie", urlencode($urls[pll_get_post_language($post->ID)]), $post_link);
return $post_link;
}

Potresti provare questo nel tuo functions.php
<?php
add_filter('rewrite_slugs', function($translated_slugs) {
// le possibili traduzioni per il tuo slug 'product'
$translated_slugs = array(
'product' => array(
'pt' => array(
'has_archive' => true,'rewrite' => array('slug' => 'produto'),
),
'es' => array(
'has_archive' => true,'rewrite' => array('slug' => 'producto'),
),
),
);
return $translated_slugs;
});
?>
come visto qui

Raccomanderei di non rendere traducibili gli slug.
La traduzione è destinata ai contenuti del sito rivolti agli utenti. Gli slug vengono utilizzati internamente e sono solo marginalmente "visibili pubblicamente" tramite i rewrite degli URL - e anche gli URL non dovrebbero essere traducibili.
Quindi: lascia gli slug così come li hai definiti. Rendi traducibili solo le stringhe destinate al pubblico.

gli slug tradotti, sia da una prospettiva SEO che di esperienza utente, hanno molto senso...

Non sono d'accordo sul fatto che gli slug abbiano un impatto sull'esperienza utente in alcun modo. Se uno slug viene utilizzato come parte di un link, il testo di ancoraggio del link sarà tradotto, quindi l'utente non noterà alcuna differenza. E quando le persone iniziano a parlare di "SEO", in genere penso "ciarlataneria". Non sono un esperto SEO, ma non credo nell'impatto SEO riguardo agli slug tradotti.

Dissento basandomi sull'esperienza. Abbiamo content manager stranieri interni che sono chiari sul fatto che gli URL slug dovrebbero essere localizzati. È una questione di creare un'esperienza completamente locale per l'utente straniero. Per alcuni paesi, come il Giappone, è letteralmente essenziale stabilire un'autentica fiducia e dimostrare di essere seri nel fare affari lì.

gli URL devono essere parlanti. Quindi, se lo slug è (come spesso accade) il nome dell'entità o della tassonomia, la riscrittura deve tenere conto sia dei plurali che delle traduzioni. Non è un'opzione, sia per la SEO che semplicemente per una buona pratica verso gli utenti finali.
