You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ember.js切换语言环境时如何重新渲染页面链接?

解决Ember多语言URL前缀与页面链接自动更新的问题

我之前也遇到过类似的场景,用ember-i18n做多语言同时要满足SEO的URL前缀需求,切换语言时页面链接不更新确实很头疼。下面给你一套可行的解决方案,分两种思路来处理:

思路1:用路由结构原生支持语言前缀(推荐)

最符合Ember路由机制的方式是把语言作为顶级路由参数,这样href-to会自动感知当前语言并生成正确的链接,不需要额外修改辅助函数。

1. 调整路由配置

把所有业务路由嵌套在语言路由下:

// app/router.js
import EmberRouter from '@ember/routing/router';
import config from 'your-app/config/environment';

export default class Router extends EmberRouter {
  location = config.locationType;
  rootURL = config.rootURL;
}

Router.map(function() {
  // 语言前缀路由,:lang 作为参数
  this.route('localized', { path: '/:lang' }, function() {
    // 这里放你所有的业务路由
    this.route('posts', function() {
      this.route('show', { path: ':post_id' });
    });
    this.route('about');
  });
});

2. 初始化语言与路由跳转

在应用路由的钩子中从URL获取语言参数,设置i18n的locale:

// app/routes/localized.js
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';

export default class LocalizedRoute extends Route {
  @service i18n;

  beforeModel(transition) {
    // 从路由参数获取语言,默认用'en'
    const lang = transition.params.localized.lang || 'en';
    this.i18n.set('locale', lang);
  }
}

3. 语言切换逻辑

切换语言时,用transitionTo跳转到当前路由的对应语言版本,全程无页面刷新:

// app/controllers/application.js
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';

export default class ApplicationController extends Controller {
  @service i18n;
  @service router;

  actions = {
    switchLanguage(newLang) {
      // 获取当前路由的名称和参数
      const currentRoute = this.router.currentRouteName.replace('localized.', '');
      const currentParams = this.router.currentRoute.params;
      
      // 更新locale并跳转到对应语言的当前路由
      this.i18n.set('locale', newLang);
      this.router.transitionTo(`localized.${currentRoute}`, newLang, currentParams.post_id);
    }
  };
}

这种方式下,{{href-to 'posts'}}会自动生成/en/posts或/zh/posts这样的链接,语言切换后所有链接会自动更新,完全符合你的需求。

思路2:重写href-to辅助函数(适合不想改路由结构的场景)

如果不想调整现有路由结构,可以重写href-to,让它自动在生成的链接前加上当前语言前缀。

1. 重写href-to辅助函数

// app/helpers/href-to.js
import HrefToHelper from 'ember-href-to/helpers/href-to';
import { inject as service } from '@ember/service';

export default class LocalizedHrefToHelper extends HrefToHelper {
  @service i18n;

  compute(params, hash) {
    // 调用原生href-to生成原始路径
    const originalPath = super.compute(params, hash);
    const currentLang = this.i18n.locale;
    
    // 移除旧的语言前缀(防止重复添加)
    const langRegex = /^\/[a-z]{2}(-[a-z]{2})?\//; // 支持en、en-US这类格式
    const pathWithoutLang = originalPath.replace(langRegex, '/');
    
    // 拼接新的语言前缀
    if (originalPath === '/') {
      return `/${currentLang}/`;
    }
    return `/${currentLang}${pathWithoutLang}`;
  }
}

2. 语言切换时触发链接更新

切换语言后,需要让所有使用href-to的组件重新渲染。可以通过在i18n的locale变化时,发送一个全局事件,让相关组件重新计算:

// app/services/i18n.js(如果没有就新建)
import I18n from 'ember-i18n/services/i18n';
import { inject as service } from '@ember/service';

export default class I18nService extends I18n {
  @service eventBus; // 需要自己实现一个简单的事件总线服务

  set locale(newLocale) {
    super.locale = newLocale;
    // 发送locale变化事件
    this.eventBus.trigger('localeChanged');
  }
}

然后在使用href-to的组件中监听这个事件,触发重新渲染:

// 比如在application组件中
import Component from '@ember/component';
import { inject as service } from '@ember/service';
import { scheduleOnce } from '@ember/runloop';

export default class ApplicationComponent extends Component {
  @service eventBus;

  init() {
    super.init(...arguments);
    this.eventBus.on('localeChanged', this, this.rerender);
  }

  willDestroy() {
    super.willDestroy(...arguments);
    this.eventBus.off('localeChanged', this, this.rerender);
  }
}

这种方式不需要修改路由,但需要额外处理组件的重新渲染,相对来说不如第一种思路优雅。

关键注意事项

  • 所有页面链接必须使用{{href-to}}辅助函数,不能写静态的<a href="/posts">,否则无法自动更新。
  • 配合FastBoot做服务端渲染,进一步提升SEO效果,确保搜索引擎能正确抓取不同语言版本的页面。
  • 语言切换时绝对不要直接修改window.location.pathname,会触发全页面刷新,破坏Ember的客户端路由优势。

内容的提问来源于stack exchange,提问作者G-we

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:17:29