我想创建一个astro组件,考虑到localstorage中的一个变量来获取每个组件的文本,但Astro显示为null。
let locale = "en"; //default
const userLanguage = localStorage.getItem("language");
if (userLanguage ) {
locale = userLanguage;
} let menu;
import(`../locale/${locale}/menu.json`).then((lang) =\> {
menu = lang.default;
});
我需要找到一种方法来拥有基于语言的json或标记文件,并加载每个用户的语言。我正在考虑使用svelte/react,但我将不得不创建很多调用,或者可能有其他方法来实现它?
1条答案
按热度按时间41zrol4v1#
为什么会这样
正如我所理解的,您希望创建
*.astro
组件并在其中使用localStorage
API。但是,浏览器相关的API(如document
和window
)在服务器上无法访问,即在Astro和MDN中,您可以看到localStorage
是window
对象一部分。window
接口的**localStorage
**只读属性允许访问Document
的原点的Storage
对象;所存储的数据在浏览器会话之间被保存。记住,正确使用
localStorage
将是window.localStorage
,这将导致以下Astro错误:未定义
document
(或window
)从Astro docs中,你可以看到这实际上意味着什么:
Astro组件在服务器上运行,所以你不能在frontmatter中访问这些特定于浏览器的对象。
可能的解决方案
因此,潜在的解决方案将是使用带有生命周期钩子的框架组件(例如React的
useEffect
,Vue的onMounted
等)或Astro文档中提到的<script>
:如果代码在Astro组件中,则将其移动到frontmatter外部的
<script>
标记中。这告诉Astro在客户端上运行此代码,其中document
和window
可用。如果代码在框架组件中,请尝试在使用生命周期方法呈现后访问这些对象。。通过使用
client:
指令(如client:load
)来运行这些生命周期方法,告诉框架组件对客户端进行水合。怎么解决
然而,根据我的经验,我会通过加载所有翻译,即每种语言,将
json
翻译的异步加载从客户端移动到服务器。假设您有以下用于翻译的文件夹结构:
然后我们可以使用glob import一次导入所有内容:
然后,您只需将这个translations对象(该对象的键表示文件路径,值表示
json
字符串)传递给您的Framework组件。你可以在这里了解更多关于glob import的信息。框架组件本身应该使用生命周期方法来访问
localStorage
,以读取用户区域设置,并有条件地从输入 prop 中获取正确的翻译。下面是Vue示例:因此,最终的Astro文件看起来像这样:
我希望它能有所帮助,但请记住,我是用JavaScript(而不是TypeScript)编写的,这可能会导致
null
/undefined
值出现一些问题。另外,我没有测试这段代码,所以它可能无法开箱即用:)