如何为WordPress菜单设置添加自定义语言下拉字段
解决方案
核心问题修正
你之前使用的wp_nav_menu是前端渲染菜单的钩子,无法在后台菜单设置区域输出内容。正确的钩子是wp_nav_menu_options,它专门用于在菜单设置区域(“自动添加页面”“显示位置”下方)插入自定义字段。
同时,将菜单语言值存储为菜单的Post元数据而非独立Option,更符合WordPress数据结构规范,也便于管理。
完整修正代码
// 在菜单设置区域添加语言下拉框 add_action('wp_nav_menu_options', 'add_language_field_to_menu_settings'); function add_language_field_to_menu_settings() { // 获取当前选中的菜单ID $menu_id = isset($_GET['menu']) ? intval($_GET['menu']) : 0; if (!$menu_id) return; // 获取已保存的语言值 $selected_language = get_post_meta($menu_id, '_menu_language', true); $available_languages = get_theme_available_languages(); // 输出Nonce字段用于安全验证 wp_nonce_field('save_menu_language_nonce', 'menu_language_nonce'); // 输出字段(匹配WordPress默认表单样式) echo '<p class="form-field">'; echo '<label for="menu_language">' . __('Menu Language', 'text-domain') . '</label>'; echo '<select name="menu_language" id="menu_language" class="widefat">'; echo '<option value="" ' . selected($selected_language, '', false) . '>' . __('No Language Selected', 'text-domain') . '</option>'; foreach ($available_languages as $lang_code => $lang_name) { echo '<option value="' . esc_attr($lang_code) . '" ' . selected($selected_language, $lang_code, false) . '>' . esc_html($lang_name) . '</option>'; } echo '</select>'; echo '<span class="description">' . __('Select the language associated with this menu.', 'text-domain') . '</span>'; echo '</p>'; } // 保存菜单语言设置 add_action('wp_update_nav_menu', 'save_menu_language_settings'); function save_menu_language_settings($menu_id) { // 验证Nonce和权限 if (!isset($_POST['menu_language_nonce']) || !wp_verify_nonce($_POST['menu_language_nonce'], 'save_menu_language_nonce')) { return; } if (!current_user_can('edit_nav_menu', $menu_id)) { return; } // 处理并保存语言值 $menu_language = isset($_POST['menu_language']) ? sanitize_text_field($_POST['menu_language']) : ''; update_post_meta($menu_id, '_menu_language', $menu_language); } // 获取菜单关联的语言值 function get_menu_language($menu_id) { return get_post_meta($menu_id, '_menu_language', true); } // 获取主题可用语言(优化版) function get_theme_available_languages() { $languages = array(); $language_dir = get_template_directory() . '/languages'; if (is_dir($language_dir)) { $files = glob($language_dir . '/*.po'); foreach ($files as $file) { $lang_code = basename($file, '.po'); // 尝试从PO文件中获取语言名称(更可靠的方式) $lang_name = $lang_code; $handle = fopen($file, 'r'); if ($handle) { while (($line = fgets($handle)) !== false) { if (strpos($line, '"Language:') !== false) { preg_match('/"Language: ([^\\\]+)\\\/', $line, $matches); if (!empty($matches[1])) { $lang_name = trim($matches[1]); break; } } } fclose($handle); } $languages[$lang_code] = $lang_name; } } // 确保英文选项存在 if (!isset($languages['en-US'])) { $languages['en-US'] = 'English (United States)'; } return $languages; }
关键修改说明
- 钩子替换:用
wp_nav_menu_options替代wp_nav_menu,确保字段显示在后台菜单设置区域的正确位置。 - 数据存储优化:使用
get_post_meta/update_post_meta将语言值存储为菜单的Post元数据,而非独立Option,符合WordPress数据规范。 - 样式匹配:用
p.form-field包裹字段,和WordPress默认菜单设置字段的样式保持一致。 - 安全增强:添加
current_user_can权限验证,确保只有有权限的用户才能修改设置。 - 语言名称提取优化:从PO文件的
Language:行提取语言名称,比读取第一行更可靠。
使用方法
- 将上述代码添加到主题的
functions.php文件中,或自定义插件中。 - 进入后台外观 > 菜单,选择目标菜单,即可在“菜单设置”区域看到语言下拉框。
- 在主题中调用
get_menu_language($menu_id)获取菜单关联的语言值,例如:// 获取当前菜单ID(示例:主菜单) $main_menu_id = get_nav_menu_locations()['primary']; $menu_language = get_menu_language($main_menu_id); // 根据语言值执行逻辑,比如加载对应语言的样式或内容
内容的提问来源于stack exchange,提问作者Dejan Dozet
相关产品推荐
相关产品推荐

