本周,我也面临着类似的困境,最终制定了一个解决方案,我认为这可能会对您有所帮助。
我个人不喜欢为此目的使用分类法。我认为唯一的pro是它已经内置了,也许它提供了一个很好的开箱即用的permalink结构,但它感觉像是对分类法最初用途的破坏。
我的方法是相当自给自足的,并使用Posteta存储翻译。要过滤有翻译的帖子,你所要做的就是检查_translate_content_{$lang}
后元(例如。_translate_content_fr_FR
). 我还没有对前端部分进行编码,但根据您在主题中想要做什么,这应该会有很大的不同。
代码已被注释,但如果有任何不清楚的地方,请告诉我。
注意:我只对页面执行此操作,但向其中添加帖子也应该很容易。另外,请记住,我还没有用修订版来测试这一点,我没有使用修订版。
# Create a list of available languages for translation;
# Note: the keys are WordPress locale codes, so we can easily integrate it
function my_available_languages() {
return array(
\'en_US\' => array(
\'value\' => \'en_US\',
\'label\' => \'English (U.S.)\',
),
\'fr_FR\' => array(
\'value\' => \'fr_FR\',
\'label\' => \'Français\',
),
\'de_DE\' => array(
\'value\' => \'de_DE\',
\'label\' => \'Deutsch\',
),
\'es_ES\' => array(
\'value\' => \'es_ES\',
\'label\' => \'Español\',
),
);
}
# Allow translations
add_action(\'current_screen\', \'enable_translation\');
function enable_translation($screen) {
# Only process translations for existing posts
if(in_array($screen->post_type, array(\'page\')) && $screen->base == \'post\' && $screen->action != \'add\') {
if(isset($_GET[\'translate\']) && array_key_exists($_GET[\'translate\'], my_available_languages())) {
# Load translated fields instead of the original post content
add_filter(\'title_edit_pre\', create_function(\'\', \'return get_translate_field("title", "\' . $_GET[\'translate\'] . \'");\'));
add_filter(\'content_edit_pre\', create_function(\'\', \'return get_translate_field("content", "\' . $_GET[\'translate\'] . \'");\'));
add_filter(\'excerpt_edit_pre\', create_function(\'\', \'return get_translate_field("excerpt", "\' . $_GET[\'translate\'] . \'");\'));
# Add hidden field so that \'translate\' param persists
add_action(\'submitpage_box\', \'doing_translate_hidden_field\');
# Remove unnecessary metaboxes, which are not pertinent for translation
add_action(\'add_meta_boxes\', \'redo_metaboxes_on_translate\', 99, 2);
# Reduce the layout columns options
add_filter(\'screen_layout_columns\', \'screen_layout_columns_translate_page\');
function screen_layout_columns_translate_page($columns) {
$columns[\'page\'] = 1;
return $columns;
}
# Set one column default layout on dashboard
add_filter(\'get_user_option_screen_layout_page\', create_function(\'\', \'return 1;\'));
# Notify user that he is viewing a translated version
add_action(\'admin_notices\', \'doing_translation_notification\');
}
}
}
add_action(\'add_meta_boxes\', \'add_translation_metabox\', 98, 2);
function add_translation_metabox($post_type, $post) {
# Optional: add this box conditionally
$types = array(\'page\');
if(in_array($post_type, $types)) {
foreach($types as $type) {
add_meta_box(\'translate_mgmt\', __(\'Translations\', \'text_domain\'), \'output_translate_mgmt_metabox\', $type, \'side\', \'low\');
}
}
}
# Output a list of links of available languages for translation
function output_translate_mgmt_metabox() {
global $post;
$default = \'en_US\';
# get_edit_post_link will return a filtered admin_url link, so we must attempt to remove the translate param, in case it\'s already added
$link = remove_query_arg(\'translate\', get_edit_post_link($post->ID));
echo(\'<ul>\');
foreach(my_available_languages() as $code => $lang) {
$href = $code != $default ? add_query_arg(array(\'translate\' => $code), $link) : $link;
echo(\'<li><a href="\' . $href . \'">\' . $lang[\'label\'] . \'</a></li>\');
}
echo(\'</ul>\');
}
function redo_metaboxes_on_translate($post_type, $post) {
# Add alternative save metabox
add_meta_box(\'translate_save\', __(\'Save\', \'text_domain\'), \'output_translate_save_metabox\', \'page\', \'normal\', \'low\');
# Remove unnecessary metaboxes
remove_meta_box(\'slugdiv\', \'page\', \'normal\');
remove_meta_box(\'authordiv\', \'page\', \'normal\');
remove_meta_box(\'postcustom\', \'page\', \'normal\');
remove_meta_box(\'commentsdiv\', \'page\', \'normal\');
remove_meta_box(\'commentstatusdiv\', \'page\', \'normal\');
remove_meta_box(\'submitdiv\', \'page\', \'side\');
remove_meta_box(\'pageparentdiv\', \'page\', \'side\');
remove_meta_box(\'revisionsdiv\', \'page\', \'side\');
remove_meta_box(\'trackbacksdiv\', \'page\', \'side\');
remove_meta_box(\'postimagediv\', \'page\', \'side\');
}
# Output a simpler, \'just save\' button, so translators are not confronted with too many options that affect main post
function output_translate_save_metabox() { ?>
<input type="submit" class="ui_button big save" value="<?php _e(\'Save\', \'text_domain\'); ?>" />
<?php
}
# Add a notice to the user (like the update WordPress nag) so that it\'s clear that he is currently viewing a translated version
function doing_translation_notification() {
global $post;
$langs = my_available_languages();
echo "<div class=\'update-nag\'>" . sprintf(__(\'You are currently translating the page "%s" into %s.\', \'text_domain\'), get_the_title($post->ID), $langs[$_REQUEST[\'translate\']][\'label\']) . "</div>";
}
# Add hidden input which will add \'translate\' to the $_POST object, thus allowing it to persist after redirection
# Note: I use jQuery to remove the slug below the title, but it\'s optional, I guess
function doing_translate_hidden_field() { ?>
<input type="hidden" name="translate" value="<?php echo($_REQUEST[\'translate\']); ?>" />
<script type="text/javascript">
jQuery(function($){
$(\'#edit-slug-box\').remove();
});
</script>
<?php
}
# Return translated content
function get_translate_field($field, $lang) {
global $post;
return get_post_meta($post->ID, \'_translate_\' . $field . \'_\' . $lang, true);
}
add_action(\'admin_init\', \'add_translation_content_filters\');
function add_translation_content_filters() {
$fields = array(\'title\', \'content\', \'excerpt\'); // As named in filters, not on their form inputs / db
foreach($fields as $field) {
add_action($field . \'_save_pre\', create_function(\'$cont\', \'return update_translation_on_save($cont, "\' . $field . \'");\'), 1, 1);
}
}
# If doing translation, update pertinent post meta instead of post row on database
function update_translation_on_save($content, $field) {
$db_fields = array(
\'title\' => \'post_title\',
\'content\' => \'post_content\',
\'excerpt\' => \'post_excerpt\',
);
global $post;
if(is_object($post) && isset($_REQUEST[\'translate\'])) {
update_post_meta($post->ID, \'_translate_\' . $field . \'_\' . $_REQUEST[\'translate\'], $content);
$content = $post->{$db_fields[$field]};
}
return $content;
}
# Function to add \'translate\' param to a given URL (to be used with filters)
function add_translate_param($link) {
# Optional: don\'t add \'translate\' on pages which are not for content management
if(strpos($link, \'post.php\') === false && strpos($link, \'edit.php\') === false) {
return $link;
}
return add_query_arg(array(\'translate\' => isset($_REQUEST[\'translate\']) ? $_REQUEST[\'translate\'] : \'\'), $link);
}
if(isset($_REQUEST[\'translate\'])) {
# Make \'translate\' URL parameter persistent
add_filter(\'admin_url\', \'add_translate_param\');
add_filter(\'wp_redirect\', \'add_translate_param\');
# Add \'doing_translate\' body class
add_filter(\'admin_body_class\', create_function(\'$c\', \'$c .= " doing_translate"; return $c;\'), 99);
}