首页 > 解决方案 > 用 Svelte 制作的语言切换器不起作用

问题描述

我目前正在学习 svelte 3,我想做一个将在 github 上以英语发布的项目,但我有朋友不会说英语,所以我尝试制作一个语言切换器。

这是我的尝试:

<script lang="typescript">
  var selectedLang = "en_us";
  const _lang_filename = "./lang/%.json".replace("%", selectedLang);
  import lang from _lang_filename;
</script>

<div id="_app_">
  <h1>{lang.welcome}</h1>

  <button
    on:click={() => {
      selectedLang = "pt_br";
    }}>Português (Brasil)</button
  >
  <button
    on:click={() => {
      selectedLang = "en_us";
    }}>English (United States)</button
  >
</div>

关于 lang 文件的导入,当我放置一个变量时它给出了一个错误:Unexpected Token,我试图将 string.replace() 放在导入本身上,但它也不起作用。

标签: javascripttypescriptsvelte-3

解决方案


您遇到的第一个问题是对 Svelte 工作原理的误解。

与其他框架不同, and 之间的部分<script></script>执行一次。这意味着无论您多久按下该按钮,lang_filename不会改变。为了告诉编译器一个变量依赖于另一个变量,您必须使用$:.

let selectedLang = "en_us";
$: _lang_filename = "./lang/%.json".replace("%", selectedLang);

now_lang_filename将在更改时更新selectedLang

(注意:我会在这里使用模板文字)

$: _lang_filename = `./lang/${selectedLang}.json`

现在您有了正确的文件名,我们必须加载实际文件。为此,您可以执行 dynamic import,但 html 规范拒绝以这种方式导入文件以外的任何内容javascript

但是,您可以通过使用fetch来解决此问题 获取文件。所以现在你必须声明一个变量lang来保存你的语言对象,以及一个加载函数来加载它。

let lang = {}
function load(filename) {
  lang = await fetch(filename).then(res => res.json())
}

剩下的就是告诉 Svelteload在文件名更改时重新运行,这再次可以通过使用反应性来实现:

$: load(filename)

我们当然可以在这里传入selectedLang并在 load 函数中构造路径。

为了完整起见,这里将是整个脚本:

<script>
    let selectedLang = "en_us";
    let lang = {}

    $: loadLanguage(selectedLang)

    async function loadLanguage() {
        lang = await fetch(`./lang/${selectedLang}.json`).then(res => res.json())
    }
</script>

需要注意的是,起初lang将是一个完全空的对象,这将给人一种undefined无处不在的闪光。


推荐阅读