首页 > 解决方案 > 从浏览器获取语言不适用于 SSR

问题描述

我有一个多语言网站 ['de', 'fr', 'it', 'en']

当前行为:

当我在没有前一个会话的情况下进入example.com时,我被重定向到example.com/de(数组中的第一个值)

想要的行为:

我想被重定向到我拥有的浏览器语言(如果会话中没有)

我扩展了服务LanguageService以覆盖initialize()函数,如下所示:

initialize(): void {
    let value;
    this.getActive()
        .subscribe((val) => (value = val))
        .unsubscribe();
    if (value) {
        // don't initialize, if there is already a value (i.e. retrieved from route or transferred from SSR)
        return;
    }


    const languages = this.getLanguages();
    const sessionLanguage = this.sessionStorageCustom && this.sessionStorageCustom.getItem('language');

    if (sessionLanguage && languages?.includes(sessionLanguage)) {
        this.setActive(sessionLanguage);
    } else {
        const browserLanguage = this.getBrowserLanguage();
        if (browserLanguage && languages?.includes(browserLanguage)) {
            this.setActive(browserLanguage);
        }
    }
}

帮手:

private getLanguages(): string[] | null {
    let languages = this.siteContextParamsService.getParamValues('language');

    // Removing English from options
    languages = languages.filter((l) => !(l.toLowerCase() === 'en'));

    if (languages) return languages;
    return null;
}

private getBrowserLanguage(): string | null {
    let language = this.winRef.nativeWindow?.navigator.language;
    if (language) {
        language = language.slice(0, 2);
        return language;
    }
    return null;
}

构造函数:

private sessionStorageCustom: Storage | undefined;

constructor(
    protected store: Store<StateWithSiteContext>,
    protected winRef: WindowRef,
    protected config: SiteContextConfig,
    protected siteContextParamsService: SiteContextParamsService
) {
    super(store, winRef, config);

    // cannot use default variable because it's private
    this.sessionStorageCustom = winRef.sessionStorage;
}

在 CSR 上,一切都按预期工作,但在 SSR 中,我总是使用默认语言。

(因为在服务器端没有浏览器的语言。我假设。)

如何强制此代码在客户端执行?或者我该怎么做才能做到这一点?

标签: spartacus-storefront

解决方案


默认情况siteContext下,如果在运行浏览器语言逻辑之前存在,Spartacus 将始终默认为 SSR 传输状态。

我可以看到您可以尝试的两种解决方案:

  1. 您可以移除 SSR 传输状态。这样,斯巴达克斯每次都会在浏览器中运行您的逻辑。你可以这样做:
      state: {
        ssrTransfer: {
          keys: { [SITE_CONTEXT_FEATURE]: false },
        },
      },

此解决方案并不理想,因为 SSR 页面将包含默认的回退语言,该语言可能不是用户正在使用的语言,因此页面可能会闪烁。

  1. 您可以在LanguageService仅在服务器中运行的自定义逻辑中添加自定义逻辑,并使用Accept-Language标头设置语言。此标头由浏览器设置,让服务器知道用户想要什么语言。你可以阅读这篇文章,它提供了一个很好的例子来说明如何在 Angular 中使用这种机制。该示例不在 Spartacus 中,但可以使用相同的逻辑。

最后一个想法,SpartacussiteContext持久化将在 4.0 中更新以使用全局状态持久化机制。


推荐阅读