/* Transitions */
@view-transition {
navigation: auto;
}
/* Kadence css “fixings” */
body {
text-wrap: pretty;
}
/* header mobile */
.popup-drawer .drawer-content.content-align-center {
overflow-y: auto;
max-width: 90vh;
}
.mobile-navigation {
max-height: 100%;
}
.kt-btn-width-type-auto {
width: auto;
}
.kb-adv-form-message.kb-adv-form-warning {
padding: 0.1em 1em;
}
.new-row-diferent-height .kt-inner-column-height-full:not(.kt-row-layout-row) {
grid-auto-rows: unset;
}
@media (max-width: 1024px) {
#block-8 figure {
margin: 0 auto;
}
.kt-inner-column-height-full.kt-tab-layout-equal, .kt-inner-column-height-full:not(.kt-tab-layout-inherit):not(.kt-tab-layout-row) {
grid-auto-rows: unset;
}
}Script Genèric de Vinculació WPML
Script PHP per vincular traduccions de posts/CPT importats a WordPress amb WPML.
Què fa
Vincula automàticament posts o custom post types que han estat importats amb camps meta de traducció, connectant-los correctament a WPML perquè apareguin les banderes i el selector d’idiomes funcioni.
Requisits previs
IMPORTANT: Abans d’importar els posts, assegura’t d’incloure aquests dos custom fields:
wpmltranslationid– ID que agrupa les traduccions del mateix contingut- Exemple: Post CA id=100, Post ES id=200, Post EN id=300 → tots amb
wpmltranslationid = "1"
- Exemple: Post CA id=100, Post ES id=200, Post EN id=300 → tots amb
wpmllanguagecode– Codi d’idioma de cada post- Valors:
ca,es,en(o els idiomes que tinguis configurats)
- Valors:
Exemple d’importació CSV:
id,title,wpmltranslationid,wpmllanguagecode
100,"Títol en català",1,ca
200,"Título en español",1,es
300,"Title in english",1,en
Configuració
Edita les variables al principi del fitxer:
$CONFIG = [
'security_key' => 'mmkt2024', // Canvia-ho per seguretat
'post_type' => 'post', // 'post', 'page', 'product', etc.
'translation_id_meta' => 'wpmltranslationid',
'language_code_meta' => 'wpmllanguagecode',
'languages' => ['ca', 'es', 'en'], // Idiomes del teu site
'original_lang' => 'ca', // Idioma original/principal
'require_complete_groups' => true, // true = només vincular grups amb tots els idiomes
'allow_partial_groups' => false, // true = vincular també grups sense idioma original
];
Ús
- Puja el fitxer
wpml-link-generic.phpa l’arrel del WordPress - Accedeix via navegador:
https://elseuteu.com/wpml-link-generic.php?key=mmkt2024
- Segueix els passos:
- Verificació: Veure estadístiques i exemples
- Previsualització: Revisar què es vincularà
- Execució: Fer la vinculació
- Elimina el fitxer després d’usar-lo
Advertències
- ⚠️ Fes backup de la base de dades abans d’executar
- ⚠️ Revisa la previsualització abans d’executar
- ⚠️ Els grups sense l’idioma original (CA per defecte) no es processaran
- ⚠️ Si un grup ja està vinculat correctament, s’ignora
- ⚠️ Aquest script només funciona si els posts ja tenen els custom fields
wpmltranslationidiwpmllanguagecode
Casos d’ús
Importació estàndard (3 idiomes complets)
'require_complete_groups' => true // Només vincular CA+ES+EN
Importació parcial (acceptar grups incomplets)
'require_complete_groups' => false // Vincular fins i tot si falta algun idioma
'allow_partial_groups' => true // Vincular grups sense idioma original
Altres post types
'post_type' => 'product' // Per WooCommerce
'post_type' => 'page' // Per pàgines
Noms de camps personalitzats
'translation_id_meta' => 'custom_trans_id',
'language_code_meta' => 'custom_lang_code',
Troubleshooting
“No s’han trobat posts” → Comprova que els meta fields wpmltranslationid i wpmllanguagecode existeixen als posts
“Grups sense CA” → Assegura’t que cada grup té un post amb wpmllanguagecode = ca
“Ja vinculat” → Els posts ja estan correctament vinculats a WPML, no cal fer res
<?php
/**
* Script genèric de vinculació WPML
* Author: Milimetric Marketing
* Plugin URI: https://milimetricmkt.com
*
* CONFIGURACIÓ (canvia aquests valors segons la teva importació):
*/
// === CONFIGURACIÓ EDITABLE ===
$CONFIG = [
// Clau de seguretat (canvia-la!)
'security_key' => 'mmkt2024',
// Post type a vincular (post, page, product, etc.)
'post_type' => 'post',
// Meta keys dels camps importats
'translation_id_meta' => 'wpmltranslationid', // Camp que agrupa les traduccions
'language_code_meta' => 'wpmllanguagecode', // Camp amb l'idioma (ca, es, en...)
// Configuració d'idiomes
'languages' => ['ca', 'es', 'en'], // Idiomes disponibles
'original_lang' => 'ca', // Idioma original
// Opcions
'require_complete_groups' => true, // true = només vincular grups amb tots els idiomes
'allow_partial_groups' => false, // true = vincular també grups sense idioma original
];
// === FI CONFIGURACIÓ ===
// Seguretat
if (!isset($_GET['key']) || $_GET['key'] !== $CONFIG['security_key']) {
die('Accés denegat');
}
require_once('wp-load.php');
define('WP_USE_THEMES', false);
$mode = $_GET['mode'] ?? 'check'; // check | link | execute
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Vinculació WPML - <?php echo strtoupper($CONFIG['post_type']); ?></title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; padding: 20px; background: #f5f5f5; }
.container { background: white; padding: 30px; border-radius: 8px; max-width: 1400px; margin: 0 auto; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
h2, h3 { color: #2c3e50; border-bottom: 3px solid #3498db; padding-bottom: 10px; }
.nav { margin: 20px 0; padding: 15px; background: #ecf0f1; border-radius: 5px; }
.nav a { display: inline-block; padding: 10px 20px; margin: 0 5px; background: #3498db; color: white; text-decoration: none; border-radius: 5px; }
.nav a:hover { background: #2980b9; }
.nav a.active { background: #2c3e50; }
.box { padding: 20px; margin: 20px 0; border-radius: 5px; border-left: 5px solid; }
.success { background: #d4edda; border-color: #28a745; color: #155724; }
.warning { background: #fff3cd; border-color: #ffc107; color: #856404; }
.error { background: #f8d7da; border-color: #dc3545; color: #721c24; }
.info { background: #d1ecf1; border-color: #17a2b8; color: #0c5460; }
table { width: 100%; border-collapse: collapse; margin: 20px 0; font-size: 13px; }
th, td { padding: 12px 8px; text-align: left; border: 1px solid #ddd; }
th { background: #34495e; color: white; font-weight: 600; position: sticky; top: 0; }
tr:nth-child(even) { background: #f8f9fa; }
tr:hover { background: #e9ecef; }
.group { margin: 15px 0; padding: 15px; background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 5px; }
.badge { display: inline-block; padding: 4px 8px; border-radius: 3px; font-size: 11px; font-weight: bold; margin: 0 3px; }
.badge-success { background: #28a745; color: white; }
.badge-warning { background: #ffc107; color: #000; }
.badge-danger { background: #dc3545; color: white; }
.badge-info { background: #17a2b8; color: white; }
.btn { display: inline-block; padding: 12px 24px; margin: 10px 5px; border-radius: 5px; text-decoration: none; font-weight: 600; cursor: pointer; border: none; }
.btn-primary { background: #3498db; color: white; }
.btn-primary:hover { background: #2980b9; }
.btn-success { background: #28a745; color: white; }
.btn-success:hover { background: #218838; }
.btn-danger { background: #dc3545; color: white; }
.btn-danger:hover { background: #c82333; }
.config-box { background: #e8f4f8; padding: 15px; margin: 20px 0; border-radius: 5px; font-family: monospace; font-size: 12px; }
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin: 20px 0; }
.stat-card { background: white; padding: 20px; border-radius: 5px; border: 2px solid #e0e0e0; text-align: center; }
.stat-value { font-size: 32px; font-weight: bold; color: #2c3e50; }
.stat-label { color: #7f8c8d; margin-top: 5px; }
</style>
</head>
<body>
<div class="container">
<h2>🔗 Vinculació WPML - <?php echo strtoupper($CONFIG['post_type']); ?></h2>
<div class="nav">
<a href="?key=<?php echo $CONFIG['security_key']; ?>&mode=check" class="<?php echo $mode == 'check' ? 'active' : ''; ?>">📋 Verificació</a>
<a href="?key=<?php echo $CONFIG['security_key']; ?>&mode=link" class="<?php echo $mode == 'link' ? 'active' : ''; ?>">🔗 Previsualització</a>
</div>
<?php
global $wpdb;
// Mostrar configuració actual
echo '<div class="config-box">';
echo '<strong>⚙️ Configuració actual:</strong><br>';
echo "Post Type: <strong>{$CONFIG['post_type']}</strong><br>";
echo "Meta Translation ID: <strong>{$CONFIG['translation_id_meta']}</strong><br>";
echo "Meta Language Code: <strong>{$CONFIG['language_code_meta']}</strong><br>";
echo "Idiomes: <strong>" . implode(', ', $CONFIG['languages']) . "</strong><br>";
echo "Idioma original: <strong>{$CONFIG['original_lang']}</strong><br>";
echo "Només grups complets: <strong>" . ($CONFIG['require_complete_groups'] ? 'Sí' : 'No') . "</strong><br>";
echo '</div>';
// Obtenir posts
$posts_data = $wpdb->get_results($wpdb->prepare("
SELECT
p.ID,
p.post_title,
p.post_type,
pm.meta_value as translation_id,
pml.meta_value as language_code,
t.trid as current_trid,
t.language_code as wpml_lang,
t.source_language_code
FROM {$wpdb->posts} p
INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id AND pm.meta_key = %s
LEFT JOIN {$wpdb->postmeta} pml ON p.ID = pml.post_id AND pml.meta_key = %s
INNER JOIN {$wpdb->prefix}icl_translations t
ON p.ID = t.element_id
AND t.element_type = %s
WHERE p.post_status = 'publish'
AND p.post_type = %s
ORDER BY pm.meta_value, pml.meta_value
",
$CONFIG['translation_id_meta'],
$CONFIG['language_code_meta'],
'post_' . $CONFIG['post_type'],
$CONFIG['post_type']
));
if (empty($posts_data)) {
echo '<div class="box error"><strong>❌ No s\'han trobat posts amb els meta fields especificats.</strong><br>';
echo 'Comprova que els camps <code>' . $CONFIG['translation_id_meta'] . '</code> i <code>' . $CONFIG['language_code_meta'] . '</code> existeixen.</div>';
echo '</div></body></html>';
exit;
}
// Agrupar per translation_id
$groups = [];
foreach ($posts_data as $post) {
$groups[$post->translation_id][] = $post;
}
// Analitzar grups
$stats = [
'total_posts' => count($posts_data),
'total_groups' => count($groups),
'complete_groups' => 0,
'incomplete_groups' => 0,
'with_original' => 0,
'without_original' => 0,
'needs_linking' => 0,
'already_linked' => 0
];
$processable_groups = [];
$examples_complete = [];
$examples_incomplete = [];
foreach ($groups as $tid => $posts) {
$langs = array_map(fn($p) => strtolower($p->language_code ?? ''), $posts);
$has_original = in_array($CONFIG['original_lang'], $langs);
$is_complete = count($posts) == count($CONFIG['languages']) &&
count(array_intersect($langs, $CONFIG['languages'])) == count($CONFIG['languages']);
if ($has_original) $stats['with_original']++;
else $stats['without_original']++;
if ($is_complete) {
$stats['complete_groups']++;
if (count($examples_complete) < 3) {
$examples_complete[] = ['tid' => $tid, 'posts' => $posts];
}
} else {
$stats['incomplete_groups']++;
if (count($examples_incomplete) < 3) {
$examples_incomplete[] = ['tid' => $tid, 'posts' => $posts];
}
}
// Comprovar si necessita vinculació
$trids = array_unique(array_map(fn($p) => $p->current_trid, $posts));
$needs_linking = count($trids) > 1;
if ($needs_linking) {
$stats['needs_linking']++;
} else {
$stats['already_linked']++;
}
// Determinar si es pot processar
$can_process = false;
if ($CONFIG['require_complete_groups']) {
$can_process = $is_complete && $has_original && $needs_linking;
} else {
$can_process = ($has_original || $CONFIG['allow_partial_groups']) && count($posts) >= 2 && $needs_linking;
}
if ($can_process) {
$processable_groups[$tid] = $posts;
}
}
// === MODE VERIFICACIÓ ===
if ($mode == 'check') {
echo '<h3>📊 Estadístiques</h3>';
echo '<div class="stats-grid">';
echo '<div class="stat-card"><div class="stat-value">' . $stats['total_posts'] . '</div><div class="stat-label">Posts totals</div></div>';
echo '<div class="stat-card"><div class="stat-value">' . $stats['total_groups'] . '</div><div class="stat-label">Grups de traducció</div></div>';
echo '<div class="stat-card"><div class="stat-value" style="color:#28a745">' . $stats['complete_groups'] . '</div><div class="stat-label">Grups complets</div></div>';
echo '<div class="stat-card"><div class="stat-value" style="color:#ffc107">' . $stats['incomplete_groups'] . '</div><div class="stat-label">Grups incomplets</div></div>';
echo '<div class="stat-card"><div class="stat-value" style="color:#17a2b8">' . $stats['with_original'] . '</div><div class="stat-label">Amb ' . strtoupper($CONFIG['original_lang']) . '</div></div>';
echo '<div class="stat-card"><div class="stat-value" style="color:#dc3545">' . count($processable_groups) . '</div><div class="stat-label">Per vincular</div></div>';
echo '</div>';
// Exemples de grups complets
if (!empty($examples_complete)) {
echo '<h3>✅ Exemples de grups COMPLETS</h3>';
foreach ($examples_complete as $ex) {
$trids = array_unique(array_map(fn($p) => $p->current_trid, $ex['posts']));
$needs = count($trids) > 1;
echo '<div class="group">';
echo '<strong>Translation ID: ' . $ex['tid'] . '</strong> ';
echo $needs ? '<span class="badge badge-warning">Necessita vinculació</span>' : '<span class="badge badge-success">Ja vinculat</span>';
echo '<table><tr><th>ID</th><th>Idioma</th><th>TRID</th><th>Source</th><th>Títol</th></tr>';
usort($ex['posts'], function($a, $b) use ($CONFIG) {
$order = array_flip($CONFIG['languages']);
return ($order[strtolower($a->language_code)] ?? 99) - ($order[strtolower($b->language_code)] ?? 99);
});
foreach ($ex['posts'] as $p) {
echo '<tr>';
echo '<td>' . $p->ID . '</td>';
echo '<td><strong>' . strtoupper($p->language_code) . '</strong></td>';
echo '<td>' . $p->current_trid . '</td>';
echo '<td>' . ($p->source_language_code ?: 'NULL') . '</td>';
echo '<td>' . substr($p->post_title, 0, 50) . '</td>';
echo '</tr>';
}
echo '</table></div>';
}
}
// Exemples de grups incomplets
if (!empty($examples_incomplete)) {
echo '<h3>⚠️ Exemples de grups INCOMPLETS</h3>';
foreach ($examples_incomplete as $ex) {
$langs = array_map(fn($p) => strtolower($p->language_code), $ex['posts']);
$missing = array_diff($CONFIG['languages'], $langs);
echo '<div class="group">';
echo '<strong>Translation ID: ' . $ex['tid'] . '</strong> ';
echo '<span class="badge badge-warning">Falten: ' . implode(', ', $missing) . '</span>';
echo '<table><tr><th>ID</th><th>Idioma</th><th>TRID</th><th>Títol</th></tr>';
foreach ($ex['posts'] as $p) {
echo '<tr>';
echo '<td>' . $p->ID . '</td>';
echo '<td><strong>' . strtoupper($p->language_code) . '</strong></td>';
echo '<td>' . $p->current_trid . '</td>';
echo '<td>' . substr($p->post_title, 0, 50) . '</td>';
echo '</tr>';
}
echo '</table></div>';
}
}
// Conclusió
echo '<div class="box info">';
echo '<h3>📝 Resum</h3>';
if (count($processable_groups) > 0) {
echo "<p><strong style='color:#28a745'>✅ Hi ha " . count($processable_groups) . " grups preparats per vincular.</strong></p>";
echo '<a href="?key=' . $CONFIG['security_key'] . '&mode=link" class="btn btn-primary">➡️ Anar a previsualització</a>';
} else {
if ($stats['needs_linking'] == 0) {
echo '<p><strong style="color:#28a745">✅ Tots els grups ja estan correctament vinculats!</strong></p>';
} else {
echo '<p><strong style="color:#dc3545">⚠️ No hi ha grups que compleixin els requisits per vincular.</strong></p>';
if ($CONFIG['require_complete_groups']) {
echo '<p>Intenta desactivar <code>require_complete_groups</code> si vols vincular grups incomplets.</p>';
}
}
}
echo '</div>';
}
// === MODE PREVISUALITZACIÓ ===
elseif ($mode == 'link') {
if (empty($processable_groups)) {
echo '<div class="box error"><strong>❌ No hi ha grups per vincular.</strong></div>';
echo '<a href="?key=' . $CONFIG['security_key'] . '&mode=check" class="btn btn-primary">◀️ Tornar a verificació</a>';
echo '</div></body></html>';
exit;
}
echo '<div class="box warning">';
echo '<h3>⚠️ MODE PREVISUALITZACIÓ</h3>';
echo '<p>Es vincularan <strong>' . count($processable_groups) . ' grups</strong> amb un total de <strong>' . array_sum(array_map('count', $processable_groups)) . ' posts</strong>.</p>';
echo '</div>';
echo '<h3>Primers 10 grups que es vincularan:</h3>';
$count = 0;
foreach ($processable_groups as $tid => $posts) {
if ($count++ >= 10) break;
// Trobar post original
$original_post = null;
foreach ($posts as $p) {
if (strtolower($p->language_code) == $CONFIG['original_lang']) {
$original_post = $p;
break;
}
}
if (!$original_post && !$CONFIG['require_complete_groups']) {
$original_post = $posts[0];
}
$new_trid = min(array_map(fn($p) => $p->current_trid, $posts));
echo '<div class="group">';
echo "<strong>Translation ID: {$tid}</strong> → Nou TRID: <strong>{$new_trid}</strong><br>";
echo '<table><tr><th>ID</th><th>Idioma</th><th>TRID actual</th><th>Nou TRID</th><th>Source Lang</th><th>Acció</th></tr>';
usort($posts, function($a, $b) use ($CONFIG) {
$order = array_flip($CONFIG['languages']);
return ($order[strtolower($a->language_code)] ?? 99) - ($order[strtolower($b->language_code)] ?? 99);
});
foreach ($posts as $p) {
$is_original = ($original_post && $p->ID == $original_post->ID);
$new_source = $is_original ? 'NULL' : $CONFIG['original_lang'];
$action = $is_original ? '<span class="badge badge-success">ORIGINAL</span>' : '<span class="badge badge-info">Traducció</span>';
echo '<tr>';
echo '<td>' . $p->ID . '</td>';
echo '<td><strong>' . strtoupper($p->language_code) . '</strong></td>';
echo '<td>' . $p->current_trid . '</td>';
echo '<td><strong>' . $new_trid . '</strong></td>';
echo '<td>' . $new_source . '</td>';
echo '<td>' . $action . '</td>';
echo '</tr>';
}
echo '</table></div>';
}
if (count($processable_groups) > 10) {
echo '<p><em>... i ' . (count($processable_groups) - 10) . ' grups més</em></p>';
}
echo '<div class="box warning">';
echo '<h3>⚠️ IMPORTANT abans d\'executar:</h3>';
echo '<ol>';
echo '<li><strong>Fes un backup de la base de dades</strong></li>';
echo '<li>Revisa que els exemples són correctes</li>';
echo '<li>Assegura\'t que l\'idioma original és el correcte</li>';
echo '</ol>';
echo '<a href="?key=' . $CONFIG['security_key'] . '&mode=execute" class="btn btn-danger">▶️ EXECUTAR VINCULACIÓ</a> ';
echo '<a href="?key=' . $CONFIG['security_key'] . '&mode=check" class="btn btn-primary">◀️ Tornar</a>';
echo '</div>';
}
// === MODE EXECUCIÓ ===
elseif ($mode == 'execute') {
if (empty($processable_groups)) {
echo '<div class="box error"><strong>❌ No hi ha grups per vincular.</strong></div>';
echo '</div></body></html>';
exit;
}
echo '<div class="box info"><h3>🔄 Executant vinculació...</h3></div>';
$updated = 0;
$errors = 0;
$log = [];
foreach ($processable_groups as $tid => $posts) {
// Trobar post original
$original_post = null;
foreach ($posts as $p) {
if (strtolower($p->language_code) == $CONFIG['original_lang']) {
$original_post = $p;
break;
}
}
if (!$original_post && !$CONFIG['require_complete_groups']) {
$original_post = $posts[0];
}
if (!$original_post) {
$log[] = "⚠️ Grup {$tid}: No s'ha trobat post original, saltat";
continue;
}
$new_trid = min(array_map(fn($p) => $p->current_trid, $posts));
foreach ($posts as $p) {
$is_original = ($p->ID == $original_post->ID);
$result = $wpdb->update(
$wpdb->prefix . 'icl_translations',
[
'trid' => $new_trid,
'source_language_code' => $is_original ? null : $CONFIG['original_lang']
],
[
'element_id' => $p->ID,
'element_type' => 'post_' . $CONFIG['post_type']
]
);
if ($result !== false) {
$updated++;
$log[] = "✓ Post {$p->ID} [{$p->language_code}] → TRID {$new_trid}";
} else {
$errors++;
$log[] = "✗ ERROR: Post {$p->ID} [{$p->language_code}]";
}
}
}
echo '<div class="box success">';
echo '<h3>✅ Vinculació completada!</h3>';
echo "<p>Posts actualitzats: <strong>{$updated}</strong></p>";
echo "<p>Grups vinculats: <strong>" . count($processable_groups) . "</strong></p>";
if ($errors > 0) {
echo "<p style='color:#dc3545'>Errors: <strong>{$errors}</strong></p>";
}
echo '</div>';
if (!empty($log)) {
echo '<div class="box info">';
echo '<h3>📝 Log (primers 30):</h3>';
echo '<pre style="max-height:400px; overflow-y:auto; font-size:11px; background:#2c3e50; color:#ecf0f1; padding:15px; border-radius:5px;">';
foreach (array_slice($log, 0, 30) as $line) {
echo $line . "\n";
}
if (count($log) > 30) {
echo "... i " . (count($log) - 30) . " operacions més\n";
}
echo '</pre>';
echo '</div>';
}
echo '<div class="box info">';
echo '<h3>📋 Següents passos:</h3>';
echo '<ol>';
echo '<li>Comprova al backend que els posts estan vinculats</li>';
echo '<li>Prova el selector d\'idiomes al frontend</li>';
echo '<li>Si tot funciona, <strong>elimina aquest fitxer</strong></li>';
echo '</ol>';
echo '<a href="' . admin_url('edit.php?post_type=' . $CONFIG['post_type']) . '" class="btn btn-success" target="_blank">📝 Anar al backend</a> ';
echo '<a href="?key=' . $CONFIG['security_key'] . '&mode=check" class="btn btn-primary">◀️ Nova verificació</a>';
echo '</div>';
// Netejar cache
if (function_exists('icl_cache_clear')) {
icl_cache_clear();
}
}
?>
<hr>
<p style="text-align:center; color:#7f8c8d; font-size:12px;">
<em>Script genèric de vinculació WPML - Milimetric Marketing - https://milimetricmkt.com</em>
</p>
</div>
</body>
</html>CCS pel menu de WPMl a kadence (menu amb subrallat)
/* wpml */
.mobile-menu-container .wpml-ls-item a {
justify-content: center;
}
.primary-menu-container .wpml-ls-first-item {
position: relative;
padding-left: 12px;
margin-left: 12px;
}
.primary-menu-container .wpml-ls-first-item::before {
content: '';
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
width: 2px;
height: 20px;
background-color: var(--global-palette3);
}
.header-navigation[class*="header-navigation-style-underline"] .header-menu-container.primary-menu-container>ul>li.wpml-ls-current-language>a {
color: var(--global-palette2);
}
.header-navigation[class*="header-navigation-style-underline"] .header-menu-container.primary-menu-container>ul>li.wpml-ls-current-language>a:after {
transform: scale(1, 1) translate(50%, 0);
}Kadence, canviar el titols de archive i tax
El més importat és el tema de afegir prioritat al filtre, amb 100 es suficient, de moment.
/**
* Canviar títols d'arxiu a Kadence
* IMPORTANT: Prioritat alta (100) necessària perquè Kadence processa després
*/
function change_archive_titles( $title ) {
if ( is_post_type_archive( 'exposicio' ) ) {
return __( 'Les exposicions', 'kadence' );
}
if ( is_tax() && get_queried_object_id() == 4 ) {
$term_name = get_term( 4, 'estat' )->name;
return sprintf(__('Les exposicions %s','kadence'), $term_name);
}
return $title;
}
add_filter( 'get_the_archive_title', 'change_archive_titles', 100 );Traducció de les url del arxius dels CPT
Fem servir ACF per crear els CPT.
Es important no tocar aquest opció, encara que sigui la més evident (deixar la opció en blanc):

Sinó que hem de tocar-ho aquí:

Així després podem fer la traducció al WPML:

MAMP i bases de dades amb Laravel
Es important posar això al arxiu .env quan estem treballant en mac (no comprovat Windows):
DB_SOCKET=/Applications/MAMP/tmp/mysql/mysql.sockSinó dona error al fer migracions, etc… desde la terminal.
Traduïr titols de Archive a kadence
// WPML translate CPT 'immoble' archive title on es
function wpml_translate_cpt_archive_title($title)
{
if (apply_filters( 'wpml_current_language', null ) == 'es' && is_post_type_archive('immoble')) {
$title = __('Inmuebles', 'kadence-child');
}
return $title;
}
add_filter('get_the_archive_title', 'wpml_translate_cpt_archive_title', 100);CSS per al Switcher de WPML
Integració a la capçalera de kadence theme
/* wpml */
.header-html .wpml-ls-legacy-list-horizontal.wpml-ls-statics-footer {
margin-bottom: 0;
}
.wpml-ls-item {
position: relative;
}
.wpml-ls-item .wpml-ls-link {
padding-left: calc(2em / 2);
padding-right: calc(2em / 2);
padding-top: 0.6em;
padding-bottom: 0.6em;
}
.wpml-ls-item.wpml-ls-current-language:after {
content: '';
width: 100%;
position: absolute;
bottom: 0px;
height: 2px;
right: 50%;
background: var(--global-palette1);
-webkit-transform: scale(0, 0) translate(-50%, 0);
transform: scale(0, 0) translate(-50%, 0);
transition: color .0s ease-in-out, -webkit-transform .2s ease-in-out;
transition: transform .2s ease-in-out, color .0s ease-in-out;
transition: transform .2s ease-in-out, color .0s ease-in-out, -webkit-transform .2s ease-in-out;
width: calc(100% - 2em);
transform: scale(1, 1) translate(50%, 0);
}
.transparent-header .wpml-ls-item.wpml-ls-current-language:after {
background: var(--global-palette9);
}
.wpml-ls-item.wpml-ls-current-language .wpml-ls-link {
color: var(--global-palette1);
}
/* Si posem el shortcode dins del menú mobile, sinó esborrar o no actua */
#mobile-drawer .wpml-ls-item.wpml-ls-current-language:after,
#mobile-drawer .mobile-html .wpml-ls-item.wpml-ls-current-language .wpml-ls-link {
color: var(--global-palette9);
}Copy/Paste del “Block Content”, que ha desaperegut en Kadence🤷🏻♂️
De moment, pots fer servir el block Dynamic HTML block:

One page links per Kadence
function highlightAnchorLinks() {
// Get the menu elements
const primaryMenu = document.getElementById('primary-menu');
const mobileMenu = document.getElementById('mobile-menu');
// Get all anchor links within the primary menu
const primaryAnchorLinks = primaryMenu.querySelectorAll('li > a[href*="#"]');
// Get all anchor links within the mobile menu
const mobileAnchorLinks = mobileMenu.querySelectorAll('li > a[href*="#"]');
// Function to extract the target ID from the href attribute
const extractTargetId = (href) => {
const hashIndex = href.indexOf('#');
return hashIndex !== -1 ? href.substring(hashIndex + 1) : null;
};
// Create an intersection observer instance for the primary menu
const primaryObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
const targetId = entry.target.getAttribute('id');
const listItem = primaryMenu.querySelector(`li > a[href$="#${targetId}"]`).parentNode;
if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {
const activeListItem = primaryMenu.querySelector('.current-menu-item');
if (activeListItem) {
activeListItem.classList.remove('current-menu-item', 'current_page_item');
}
listItem.classList.add('current-menu-item', 'current_page_item');
} else {
listItem.classList.remove('current-menu-item', 'current_page_item');
}
});
}, { threshold: [0.5] });
// Create an intersection observer instance for the mobile menu
const mobileObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
const targetId = entry.target.getAttribute('id');
const listItem = mobileMenu.querySelector(`li > a[href$="#${targetId}"]`).parentNode;
if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {
const activeListItem = mobileMenu.querySelector('.current-menu-item');
if (activeListItem) {
activeListItem.classList.remove('current-menu-item', 'current_page_item');
}
listItem.classList.add('current-menu-item', 'current_page_item');
} else {
listItem.classList.remove('current-menu-item', 'current_page_item');
}
});
}, { threshold: [0.5] });
// Observe each section for the primary menu
primaryAnchorLinks.forEach(anchorLink => {
const targetId = extractTargetId(anchorLink.getAttribute('href'));
const section = document.getElementById(targetId);
if (section) {
primaryObserver.observe(section);
}
});
// Observe each section for the mobile menu
mobileAnchorLinks.forEach(anchorLink => {
const targetId = extractTargetId(anchorLink.getAttribute('href'));
const section = document.getElementById(targetId);
if (section) {
mobileObserver.observe(section);
}
});
}
// Call the function when the DOM is fully loaded
document.addEventListener('DOMContentLoaded', highlightAnchorLinks);
