spartacus-storefront - 从浏览器获取语言不适用于 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 中,我总是使用默认语言。
(因为在服务器端没有浏览器的语言。我假设。)
如何强制此代码在客户端执行?或者我该怎么做才能做到这一点?
解决方案
默认情况siteContext
下,如果在运行浏览器语言逻辑之前存在,Spartacus 将始终默认为 SSR 传输状态。
我可以看到您可以尝试的两种解决方案:
- 您可以移除 SSR 传输状态。这样,斯巴达克斯每次都会在浏览器中运行您的逻辑。你可以这样做:
state: {
ssrTransfer: {
keys: { [SITE_CONTEXT_FEATURE]: false },
},
},
此解决方案并不理想,因为 SSR 页面将包含默认的回退语言,该语言可能不是用户正在使用的语言,因此页面可能会闪烁。
- 您可以在
LanguageService
仅在服务器中运行的自定义逻辑中添加自定义逻辑,并使用Accept-Language
标头设置语言。此标头由浏览器设置,让服务器知道用户想要什么语言。你可以阅读这篇文章,它提供了一个很好的例子来说明如何在 Angular 中使用这种机制。该示例不在 Spartacus 中,但可以使用相同的逻辑。
最后一个想法,SpartacussiteContext
持久化将在 4.0 中更新以使用全局状态持久化机制。
推荐阅读
- python - 是否可以使用不确定的迭代器进行列表理解?
- visual-studio - 我在哪里将文件放在 nuget 包中以便恢复它们?
- android - Androidx BottomNavigationView 不会相应地播放过渡动画
- java - 如果一个数字在列表中出现多次,如何生成错误
- docker - traefik - 同一主机的多个端口绑定 V2
- python - 如何将多个 NumPy 数组从函数返回到单独的 Dataframe 列中
- angular - 当setValue存储在单选按钮中时如何防止循环?
- swift - Swift 4 到 Swift 5 Xcode 错误
- laravel - 使用模型加入时 Laravel 加入错误
- reactjs - 当我更改我的 Redux 状态时,文本没有更新