首页 / 跨境电商轻量软件 / 实操指南:实现多语言店铺切换的6个可靠方案

实操指南:实现多语言店铺切换的6个可靠方案

实操指南:实现多语言店铺切换的6个可靠方案

引言:为什么多语言店铺对跨境电商至关重要

在全球化的电商时代,语言壁垒是阻碍跨境交易的最大障碍之一。据统计,超过70%的消费者更倾向于使用母语浏览和购买商品,而超过50%的消费者表示,如果网站没有他们的母语版本,他们不会进行购买。对于基于WordPress的电商店铺来说,实现多语言功能不仅能提升用户体验,还能显著提高转化率和国际市场份额。

WordPress作为全球最流行的内容管理系统,拥有丰富的多语言解决方案生态系统。本文将深入探讨6种可靠的WordPress多语言店铺实现方案,从简单的插件应用到高级自定义开发,为行业新人和程序员提供全面的技术指导。

方案一:使用WPML插件实现完整多语言店铺

WPML插件概述与安装配置

WPML(WordPress Multilingual Plugin)是市场上最成熟、功能最全面的WordPress多语言插件之一。它专门为电商网站设计,与WooCommerce完美集成,支持超过40种语言。

安装与基础配置步骤:

  1. 从WordPress官方插件库或WPML官网下载插件
  2. 安装并激活WPML核心插件及以下组件:

    • WPML Multilingual CMS
    • WPML String Translation
    • WPML Media Translation
    • WooCommerce Multilingual(针对电商)
// 示例:检查WPML是否激活并获取当前语言
function check_wpml_status() {
    if (function_exists('icl_object_id')) {
        $current_lang = apply_filters('wpml_current_language', NULL);
        $default_lang = apply_filters('wpml_default_language', NULL);
        
        return array(
            'current' => $current_lang,
            'default' => $default_lang
        );
    }
    return false;
}

// 在主题中调用语言切换器
function display_wpml_language_switcher() {
    if (function_exists('icl_get_languages')) {
        $languages = icl_get_languages('skip_missing=0&orderby=code');
        if (!empty($languages)) {
            echo '<div class="language-switcher">';
            foreach ($languages as $language) {
                $class = $language['active'] ? 'active' : '';
                echo '<a class="' . $class . '" href="' . $language['url'] . '">';
                echo '<img src="' . $language['country_flag_url'] . '" alt="' . $language['language_code'] . '" />';
                echo $language['native_name'];
                echo '</a>';
            }
            echo '</div>';
        }
    }
}

WooCommerce与WPML的深度集成

WPML为WooCommerce提供了专门的模块,确保产品、分类、属性和购物车都能完美支持多语言。

关键配置要点:

  1. 产品同步设置:确保产品在不同语言间保持库存、价格和SKU同步
  2. 货币切换功能:结合WPML和货币插件实现语言与货币的关联切换
  3. 翻译管理:使用专业翻译服务或编辑器手动翻译产品内容
// 示例:获取多语言产品ID
function get_multilingual_product_id($product_id, $language_code = null) {
    if (function_exists('icl_object_id')) {
        $type = get_post_type($product_id);
        $multilingual_id = apply_filters(
            'wpml_object_id', 
            $product_id, 
            $type, 
            true, 
            $language_code
        );
        return $multilingual_id;
    }
    return $product_id;
}

// 在WooCommerce模板中使用
$current_language = apply_filters('wpml_current_language', NULL);
$product_id = get_the_ID();
$translated_product_id = get_multilingual_product_id($product_id, $current_language);

优势与局限性分析

优势:

  • 完整的电商多语言解决方案
  • 强大的翻译管理界面
  • 良好的SEO支持(hreflang标签自动生成)
  • 与主流主题和插件兼容性好

局限性:

  • 商业插件,需要付费授权
  • 对服务器资源要求较高
  • 学习曲线相对陡峭

方案二:Polylang插件 + WooCommerce多语言方案

Polylang免费方案实施

Polylang是另一款流行的WordPress多语言插件,提供免费版本和付费的Polylang Pro版本。与WPML不同,Polylang使用更直观的语言管理方式,将每种语言的内容作为独立文章/页面处理。

基础设置步骤:

  1. 安装Polylang插件
  2. 添加需要的语言
  3. 配置语言检测方式(URL前缀、子域名或域名)
  4. 安装Polylang for WooCommerce扩展
// 示例:创建自定义语言切换器
function custom_polylang_switcher() {
    if (function_exists('pll_the_languages')) {
        $languages = pll_the_languages(array('raw' => 1));
        
        if (!empty($languages)) {
            echo '<ul class="polylang-switcher">';
            foreach ($languages as $language) {
                $active_class = $language['current_lang'] ? 'active' : '';
                echo '<li class="' . $active_class . '">';
                echo '<a href="' . $language['url'] . '" hreflang="' . $language['slug'] . '">';
                echo '<span class="flag">' . $language['flag'] . '</span>';
                echo '<span class="name">' . $language['name'] . '</span>';
                echo '</a>';
                echo '</li>';
            }
            echo '</ul>';
        }
    }
}

// 在header.php中调用
add_action('wp_header', 'custom_polylang_switcher');

高级自定义功能开发

对于需要更多控制权的开发者,Polylang提供了丰富的API和钩子:

// 示例:根据语言加载不同的样式表
function load_language_specific_styles() {
    if (function_exists('pll_current_language')) {
        $current_lang = pll_current_language();
        
        switch ($current_lang) {
            case 'ar':
                wp_enqueue_style('rtl-style', get_template_directory_uri() . '/css/rtl.css');
                break;
            case 'ja':
                wp_enqueue_style('japanese-font', 'https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap');
                break;
        }
    }
}
add_action('wp_enqueue_scripts', 'load_language_specific_styles');

// 示例:语言特定的SEO标题
function language_specific_seo_title($title) {
    if (function_exists('pll_current_language') && is_product()) {
        $current_lang = pll_current_language();
        $product_id = get_the_ID();
        
        if ($current_lang !== pll_default_language()) {
            $title .= ' | ' . strtoupper($current_lang) . ' Version';
        }
    }
    return $title;
}
add_filter('wpseo_title', 'language_specific_seo_title');

与WooCommerce的集成技巧

Polylang for WooCommerce扩展提供了基础的产品多语言支持,但某些高级功能需要自定义开发:

// 示例:同步产品库存 across languages
function sync_product_stock_across_languages($product_id, $stock_quantity, $product) {
    if (!function_exists('pll_get_post_translations')) {
        return;
    }
    
    // 获取所有语言版本的产品ID
    $translations = pll_get_post_translations($product_id);
    
    foreach ($translations as $lang => $translated_id) {
        // 跳过当前产品
        if ($translated_id == $product_id) {
            continue;
        }
        
        // 更新其他语言版本的库存
        $translated_product = wc_get_product($translated_id);
        if ($translated_product) {
            $translated_product->set_stock_quantity($stock_quantity);
            $translated_product->save();
        }
    }
}
add_action('woocommerce_product_set_stock', 'sync_product_stock_across_languages', 10, 3);

方案三:Weglot翻译服务集成方案

Weglot云端翻译服务介绍

Weglot采用不同的多语言实现思路:它通过JavaScript和API在网站前端实时翻译内容,同时提供可视化编辑界面。这种方法特别适合非技术用户和需要快速上线的项目。

集成步骤:

  1. 注册Weglot账户并创建项目
  2. 安装Weglot WordPress插件
  3. 配置API密钥和语言设置
  4. 自定义翻译规则和排除元素
// 示例:手动集成Weglot(不通过插件)
function add_weglot_script_manually() {
    // 仅在前端显示
    if (is_admin()) {
        return;
    }
    
    $weglot_api_key = get_option('weglot_api_key');
    $original_language = get_option('weglot_original_language', 'en');
    $destination_languages = get_option('weglot_destination_languages', ['fr', 'es']);
    
    if (!empty($weglot_api_key) && !empty($destination_languages)) {
        ?>
        <script type="text/javascript" src="https://cdn.weglot.com/weglot.min.js"></script>
        <script>
            Weglot.initialize({
                api_key: '<?php echo esc_js($weglot_api_key); ?>',
                originalLanguage: '<?php echo esc_js($original_language); ?>',
                destinationLanguages: <?php echo json_encode($destination_languages); ?>,
                excludeBlocks: ['.do-not-translate', '.price', '.sku'],
                dynamic: [
                    {
                        url: '/shop/',
                        selector: '.product-description'
                    }
                ]
            });
        </script>
        <?php
    }
}
add_action('wp_footer', 'add_weglot_script_manually');

自定义翻译规则与排除项

对于电商网站,某些元素不应被翻译,如产品SKU、特定技术术语等:

// 示例:通过PHP动态排除翻译元素
function customize_weglot_exclusions() {
    if (function_exists('weglot_get_current_language') && weglot_get_current_language() !== weglot_get_original_language()) {
        // 添加特定CSS类到不应翻译的元素
        add_filter('body_class', function($classes) {
            $classes[] = 'weglot-translated';
            return $classes;
        });
        
        // 动态排除价格元素
        add_filter('woocommerce_get_price_html', function($price_html) {
            return '<span class="weglot-exclude">' . $price_html . '</span>';
        }, 10, 1);
    }
}
add_action('template_redirect', 'customize_weglot_exclusions');

性能优化与缓存策略

由于Weglot依赖JavaScript翻译,性能优化尤为重要:

// 示例:优化Weglot加载性能
function optimize_weglot_performance() {
    // 异步加载Weglot脚本
    add_filter('script_loader_tag', function($tag, $handle) {
        if (strpos($handle, 'weglot') !== false) {
            return str_replace(' src', ' async src', $tag);
        }
        return $tag;
    }, 10, 2);
    
    // 添加资源提示
    add_action('wp_head', function() {
        echo '<link rel="preconnect" href="https://cdn.weglot.com" crossorigin>';
        echo '<link rel="dns-prefetch" href="https://cdn.weglot.com">';
    });
    
    // 缓存翻译数据
    add_action('init', function() {
        if (isset($_GET['weglot-cache']) && current_user_can('manage_options')) {
            // 生成翻译缓存逻辑
            generate_weglot_translation_cache();
        }
    });
}

function generate_weglot_translation_cache() {
    // 实现缓存生成逻辑
    $languages = ['fr', 'es', 'de'];
    $urls = [
        home_url('/shop/'),
        home_url('/product-category/clothing/'),
        // 添加其他重要页面
    ];
    
    foreach ($languages as $language) {
        foreach ($urls as $url) {
            // 模拟访问页面以触发翻译缓存
            $translated_url = add_query_arg('wg_language', $language, $url);
            wp_remote_get($translated_url, array('timeout' => 5));
        }
    }
}

方案四:自定义多语言数据库架构

设计多语言数据库表结构

对于需要完全控制的大型电商项目,自定义数据库架构可能是最佳选择。这种方法虽然开发成本较高,但提供了最大的灵活性和性能优化空间。

基础表结构设计:

// 示例:创建多语言自定义表
function create_multilingual_tables() {
    global $wpdb;
    
    $charset_collate = $wpdb->get_charset_collate();
    
    // 语言表
    $language_table = $wpdb->prefix . 'custom_languages';
    $sql = "CREATE TABLE IF NOT EXISTS $language_table (
        id INT(11) NOT NULL AUTO_INCREMENT,
        code VARCHAR(10) NOT NULL,
        name VARCHAR(50) NOT NULL,
        native_name VARCHAR(50) NOT NULL,
        direction ENUM('ltr', 'rtl') DEFAULT 'ltr',
        flag_url VARCHAR(255),
        is_default TINYINT(1) DEFAULT 0,
        is_active TINYINT(1) DEFAULT 1,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        UNIQUE KEY code (code)
    ) $charset_collate;";
    
    // 翻译表
    $translation_table = $wpdb->prefix . 'custom_translations';
    $sql .= "CREATE TABLE IF NOT EXISTS $translation_table (
        id INT(11) NOT NULL AUTO_INCREMENT,
        original_id INT(11) NOT NULL,
        original_type VARCHAR(50) NOT NULL COMMENT 'post, term, string',
        language_code VARCHAR(10) NOT NULL,
        translated_title TEXT,
        translated_content LONGTEXT,
        translated_excerpt TEXT,
        meta_data LONGTEXT COMMENT 'Serialized array of meta fields',
        status ENUM('draft', 'published', 'needs_review') DEFAULT 'draft',
        translator_id INT(11),
        translated_at TIMESTAMP NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        KEY original_composite (original_id, original_type),
        KEY language_status (language_code, status),
        FOREIGN KEY (language_code) REFERENCES $language_table(code) ON DELETE CASCADE
    ) $charset_collate;";
    
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
}
register_activation_hook(__FILE__, 'create_multilingual_tables');

创建多语言内容管理类

实现一个自定义类来管理多语言内容:

class Custom_Multilingual_Manager {
    private $wpdb;
    private $current_language;
    private $default_language;
    
    public function __construct() {
        global $wpdb;
        $this->wpdb = $wpdb;
        $this->set_current_language();
        $this->default_language = $this->get_default_language();
        
        // 初始化钩子
        $this->init_hooks();
    }
    
    private function set_current_language() {
        // 从Cookie、URL参数或浏览器设置检测语言
        if (isset($_GET['lang']) && $this->is_valid_language($_GET['lang'])) {
            $this->current_language = sanitize_text_field($_GET['lang']);
            setcookie('site_language', $this->current_language, time() + 30 * DAY_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN);
        } elseif (isset($_COOKIE['site_language']) && $this->is_valid_language($_COOKIE['site_language'])) {
            $this->current_language = $_COOKIE['site_language'];
        } else {
            $browser_lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
            $this->current_language = $this->is_valid_language($browser_lang) ? $browser_lang : $this->get_default_language();
        }
    }
    
    public function get_translated_post($post_id, $post_type = 'post') {
        $table = $this->wpdb->prefix . 'custom_translations';
        
        // 如果是默认语言,返回原始内容
        if ($this->current_language === $this->default_language) {
            return get_post($post_id);
        }
        
        // 查询翻译内容
        $translation = $this->wpdb->get_row($this->wpdb->prepare(
            "SELECT * FROM $table 
            WHERE original_id = %d 
            AND original_type = %s 
            AND language_code = %s 
            AND status = 'published'",
            $post_id,
            $post_type,
            $this->current_language
        ));
        
        if ($translation) {
            // 创建虚拟文章对象
            $original_post = get_post($post_id);
            $translated_post = new stdClass();
            $translated_post->ID = $post_id;
            $translated_post->post_title = $translation->translated_title ?: $original_post->post_title;
            $translated_post->post_content = $translation->translated_content ?: $original_post->post_content;
            $translated_post->post_excerpt = $translation->translated_excerpt ?: $original_post->post_excerpt;
            $translated_post->post_type = $original_post->post_type;
            
            return $translated_post;
        }
        
        return get_post($post_id);
    }
    
    public function get_language_switcher() {
        $languages = $this->get_active_languages();

get_current_url();

    
    $switcher_html = '<div class="custom-language-switcher">';
    $switcher_html .= '<ul>';
    
    foreach ($languages as $language) {
        $is_current = ($language['code'] === $this->current_language);
        $class = $is_current ? 'current-language' : '';
        $url = $this->add_language_to_url($current_url, $language['code']);
        
        $switcher_html .= sprintf(
            '<li class="%s"><a href="%s" hreflang="%s">%s</a></li>',
            esc_attr($class),
            esc_url($url),
            esc_attr($language['code']),
            esc_html($language['name'])
        );
    }
    
    $switcher_html .= '</ul></div>';
    return $switcher_html;
}

private function init_hooks() {
    // 过滤文章内容
    add_filter('the_posts', [$this, 'translate_posts_query'], 10, 2);
    
    // 过滤菜单项
    add_filter('wp_nav_menu_objects', [$this, 'translate_menu_items'], 10, 2);
    
    // 添加hreflang标签
    add_action('wp_head', [$this, 'add_hreflang_tags']);
    
    // 重写规则
    add_action('init', [$this, 'add_rewrite_rules']);
    add_filter('query_vars', [$this, 'add_query_vars']);
}

public function add_rewrite_rules() {
    // 添加语言前缀到URL结构
    add_rewrite_rule(
        '^([a-z]{2})/(.*)?$',
        'index.php?lang=$matches[1]&pagename=$matches[2]',
        'top'
    );
}

}


### 实现URL重写与SEO优化

// 示例:多语言URL重写系统
class Multilingual_Rewrite_System {

public function __construct() {
    add_action('init', [$this, 'init_rewrites']);
    add_filter('post_link', [$this, 'translate_post_link'], 10, 2);
    add_filter('term_link', [$this, 'translate_term_link'], 10, 3);
    add_filter('page_link', [$this, 'translate_page_link'], 10, 2);
}

public function init_rewrites() {
    $languages = $this->get_active_language_codes();
    
    foreach ($languages as $lang) {
        if ($lang === $this->get_default_language()) {
            continue; // 默认语言不需要前缀
        }
        
        // 重写产品URL
        add_rewrite_rule(
            '^' . $lang . '/product/([^/]+)/?$',
            'index.php?lang=' . $lang . '&product=$matches[1]',
            'top'
        );
        
        // 重写产品分类URL
        add_rewrite_rule(
            '^' . $lang . '/product-category/([^/]+)/?$',
            'index.php?lang=' . $lang . '&product_cat=$matches[1]',
            'top'
        );
        
        // 重写页面URL
        add_rewrite_rule(
            '^' . $lang . '/([^/]+)/?$',
            'index.php?lang=' . $lang . '&pagename=$matches[1]',
            'top'
        );
    }
}

public function translate_post_link($permalink, $post) {
    $current_lang = $this->get_current_language();
    $default_lang = $this->get_default_language();
    
    if ($current_lang === $default_lang) {
        return $permalink;
    }
    
    // 获取翻译后的slug
    $translated_slug = $this->get_translated_slug($post->ID, 'post', $current_lang);
    
    if ($translated_slug) {
        $permalink = str_replace(
            $post->post_name,
            $translated_slug,
            $permalink
        );
    }
    
    // 添加语言前缀
    return $this->add_language_prefix($permalink, $current_lang);
}

private function add_language_prefix($url, $language_code) {
    $url_parts = parse_url($url);
    $path = $url_parts['path'] ?? '';
    
    // 检查是否已有语言前缀
    $pattern = '/^/([a-z]{2})//';
    if (preg_match($pattern, $path)) {
        $path = preg_replace($pattern, '/' . $language_code . '/', $path);
    } else {
        $path = '/' . $language_code . $path;
    }
    
    $url_parts['path'] = $path;
    return $this->build_url($url_parts);
}

public function add_hreflang_tags() {
    $languages = $this->get_active_languages();
    $current_url = $this->get_current_url();
    
    foreach ($languages as $language) {
        $url = $this->add_language_to_url($current_url, $language['code']);
        printf(
            '<link rel="alternate" hreflang="%s" href="%s" />' . "n",
            esc_attr($language['code']),
            esc_url($url)
        );
    }
    
    // 添加x-default
    $default_url = $this->add_language_to_url($current_url, $this->get_default_language());
    printf(
        '<link rel="alternate" hreflang="x-default" href="%s" />' . "n",
        esc_url($default_url)
    );
}

}


## 方案五:Headless WordPress + 多语言前端架构

### 构建多语言REST API扩展

对于现代Headless WordPress架构,可以通过扩展REST API来实现多语言支持:

// 示例:扩展WordPress REST API支持多语言
class Multilingual_REST_API {

public function __construct() {
    add_action('rest_api_init', [$this, 'register_routes']);
    add_filter('rest_prepare_post', [$this, 'add_translations_to_response'], 10, 3);
    add_filter('rest_prepare_product', [$this, 'add_translations_to_response'], 10, 3);
}

public function register_routes() {
    // 注册语言端点
    register_rest_route('multilingual/v1', '/languages', [
        'methods' => 'GET',
        'callback' => [$this, 'get_available_languages'],
        'permission_callback' => '__return_true'
    ]);
    
    // 注册翻译端点
    register_rest_route('multilingual/v1', '/translate', [
        'methods' => 'POST',
        'callback' => [$this, 'translate_content'],
        'permission_callback' => function() {
            return current_user_can('edit_posts');
        }
    ]);
    
    // 多语言产品搜索
    register_rest_route('multilingual/v1', '/products/search', [
        'methods' => 'GET',
        'callback' => [$this, 'search_products_multilingual'],
        'args' => [
            'query' => [
                'required' => true,
                'validate_callback' => function($param) {
                    return !empty($param);
                }
            ],
            'lang' => [
                'default' => 'en',
                'validate_callback' => function($param) {
                    return in_array($param, $this->get_available_language_codes());
                }
            ]
        ],
        'permission_callback' => '__return_true'
    ]);
}

public function add_translations_to_response($response, $post, $request) {
    $lang = $request->get_param('lang') ?: $this->detect_language_from_request($request);
    
    if ($lang !== $this->get_default_language()) {
        $translation = $this->get_post_translation($post->ID, $lang);
        
        if ($translation) {
            $response->data['title']['rendered'] = $translation['title'];
            $response->data['content']['rendered'] = $translation['content'];
            $response->data['excerpt']['rendered'] = $translation['excerpt'];
            
            // 添加翻译元数据
            $response->data['multilingual'] = [
                'original_id' => $post->ID,
                'language' => $lang,
                'translated_at' => $translation['translated_at']
            ];
        }
    }
    
    // 添加可用翻译链接
    $response->data['available_translations'] = $this->get_post_translation_links($post->ID);
    
    return $response;
}

public function search_products_multilingual($request) {
    $query = sanitize_text_field($request['query']);
    $lang = sanitize_text_field($request['lang']);
    
    // 根据语言搜索
    if ($lang === $this->get_default_language()) {
        $args = [
            'post_type' => 'product',
            's' => $query,
            'posts_per_page' => 10,
            'lang' => $lang
        ];
    } else {
        // 在翻译内容中搜索
        $args = [
            'post_type' => 'product',
            'meta_query' => [
                'relation' => 'OR',
                [
                    'key' => '_translation_title_' . $lang,
                    'value' => $query,
                    'compare' => 'LIKE'
                ],
                [
                    'key' => '_translation_content_' . $lang,
                    'value' => $query,
                    'compare' => 'LIKE'
                ]
            ],
            'posts_per_page' => 10
        ];
    }
    
    $products = get_posts($args);
    
    // 格式化响应
    $formatted_products = array_map(function($product) use ($lang) {
        $product_data = $this->get_product_data_for_language($product, $lang);
        return [
            'id' => $product->ID,
            'title' => $product_data['title'],
            'description' => wp_trim_words($product_data['description'], 30),
            'price' => get_post_meta($product->ID, '_price', true),
            'image' => get_the_post_thumbnail_url($product->ID, 'thumbnail'),
            'url' => $this->get_product_url_for_language($product->ID, $lang),
            'language' => $lang
        ];
    }, $products);
    
    return rest_ensure_response([
        'query' => $query,
        'language' => $lang,
        'results' => $formatted_products,
        'count' => count($formatted_products)
    ]);
}

}


### 前端多语言状态管理(React示例)

// 前端多语言上下文和状态管理
import React, { createContext, useContext, useReducer, useEffect } from 'react';
import axios from 'axios';

// 创建多语言上下文
const MultilingualContext = createContext();

// 初始状态
const initialState = {
currentLanguage: localStorage.getItem('preferredLanguage') || 'en',
availableLanguages: [],
translations: {},
isLoading: false,
error: null
};

// 动作类型
const actionTypes = {
SET_LANGUAGE: 'SET_LANGUAGE',
SET_TRANSLATIONS: 'SET_TRANSLATIONS',
SET_AVAILABLE_LANGUAGES: 'SET_AVAILABLE_LANGUAGES',
SET_LOADING: 'SET_LOADING',
SET_ERROR: 'SET_ERROR'
};

// reducer函数
function multilingualReducer(state, action) {
switch (action.type) {

case actionTypes.SET_LANGUAGE:
  localStorage.setItem('preferredLanguage', action.payload);
  return {
    ...state,
    currentLanguage: action.payload
  };
  
case actionTypes.SET_TRANSLATIONS:
  return {
    ...state,
    translations: {
      ...state.translations,
      [action.payload.language]: action.payload.translations
    }
  };
  
case actionTypes.SET_AVAILABLE_LANGUAGES:
  return {
    ...state,
    availableLanguages: action.payload
  };
  
case actionTypes.SET_LOADING:
  return {
    ...state,
    isLoading: action.payload
  };
  
case actionTypes.SET_ERROR:
  return {
    ...state,
    error: action.payload
  };
  
default:
  return state;

}
}

// 多语言提供者组件
export function MultilingualProvider({ children, apiEndpoint }) {
const [state, dispatch] = useReducer(multilingualReducer, initialState);

// 加载可用语言
useEffect(() => {

const fetchLanguages = async () => {
  try {
    dispatch({ type: actionTypes.SET_LOADING, payload: true });
    const response = await axios.get(`${apiEndpoint}/multilingual/v1/languages`);
    dispatch({ 
      type: actionTypes.SET_AVAILABLE_LANGUAGES, 
      payload: response.data 
    });
  } catch (error) {
    dispatch({ 
      type: actionTypes.SET_ERROR, 
      payload: error.message 
    });
  } finally {
    dispatch({ type: actionTypes.SET_LOADING, payload: false });
  }
};

fetchLanguages();

}, [apiEndpoint]);

// 切换语言
const switchLanguage = async (languageCode) => {

dispatch({ type: actionTypes.SET_LANGUAGE, payload: languageCode });

// 预加载翻译
if (!state.translations[languageCode]) {
  await loadTranslations(languageCode);
}

};

// 加载翻译
const loadTranslations = async (languageCode) => {

try {
  dispatch({ type: actionTypes.SET_LOADING, payload: true });
  const response = await axios.get(
    `${apiEndpoint}/multilingual/v1/translations/${languageCode}`
  );
  
  dispatch({
    type: actionTypes.SET_TRANSLATIONS,
    payload: {
      language: languageCode,
      translations: response.data
    }
  });
} catch (error) {
  dispatch({ 
    type: actionTypes.SET_ERROR, 
    payload: error.message 
  });
} finally {
  dispatch({ type: actionTypes.SET_LOADING, payload: false });
}

};

// 翻译函数
const t = (key, params = {}) => {

const translations = state.translations[state.currentLanguage] || {};
let text = translations[key] || key;

// 替换参数
Object.keys(params).forEach(param => {
  text = text.replace(`{{${param}}}`, params[param]);
});

return text;

};

const value = {

...state,
switchLanguage,
t,
loadTranslations

};

return (

<MultilingualContext.Provider value={value}>
  {children}
</MultilingualContext.Provider>

);
}

// 使用钩子
export function useMultilingual() {
const context = useContext(MultilingualContext);
if (!context) {

throw new Error('useMultilingual must be used within MultilingualProvider');

}
return context;
}

// 语言切换器组件
export function LanguageSwitcher() {
const { currentLanguage, availableLanguages, switchLanguage } = useMultilingual();

return (

<div className="language-switcher">
  {availableLanguages.map(language => (
    <button
      key={language.code}
      className={`language-button ${currentLanguage === language.code ? 'active' : ''}`}
      onClick={() => switchLanguage(language.code)}
      aria-label={`Switch to ${language.name}`}
    >
      <span className="language-flag">{language.flag}</span>
      <span className="language-name">{language.name}</span>
    </button>
  ))}
</div>

);
}


### 静态生成与ISR策略

// Next.js示例:多语言静态生成
export async function getStaticPaths() {
// 获取所有支持的语言
const languages = await fetchLanguages();

// 获取所有产品
const products = await fetchAllProducts();

// 为每种语言和每个产品生成路径
const paths = [];

languages.forEach(language => {

products.forEach(product => {
  paths.push({
    params: {
      lang: language.code,
      slug: product.slug
    }
  });
});

});

return {

paths,
fallback: 'blocking' // 增量静态再生

};
}

export async function getStaticProps({ params }) {
const { lang, slug } = params;

// 获取产品数据(根据语言)
const product = await fetchProductBySlug(slug, lang);

if (!product) {

return {
  notFound: true
};

}

// 获取相关翻译
const translations = await fetchProductTranslations(product.id);

// 获取语言信息
const languages = await fetchLanguages();

return {

props: {
  product,
  translations,
  currentLanguage: lang,
  languages
},
revalidate: 3600 // 每小时重新验证

};
}

// 产品页面组件
function ProductPage({ product, translations, currentLanguage, languages }) {
const { t } = useTranslation();

return (

<div>
  <Head>
    <title>{product.title} | {t('store_name')}</title>
    {/* 添加hreflang标签 */}
    {languages.map(lang => (
      <link
        key={lang.code}
        rel="alternate"
        hrefLang={lang.code}
        href={`https://example.com/${lang.code}/products/${product.slug}`}
      />
    ))}
  </Head>
  
  <LanguageSwitcher languages={languages} currentLanguage={currentLanguage} />
  
  <h1>{product.title}</h1>
  <div dangerouslySetInnerHTML={{ __html: product.description }} />
  
  <ProductPrice 
    price={product.price} 
    currency={getCurrencyForLanguage(currentLanguage)}
  />
  
  <AddToCartButton 
    productId={product.id}
    language={currentLanguage}
  />
</div>

);
}

本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/200.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

工作时间:周一至周五,9:00-17:30,节假日休息
返回顶部