select 值绑定和 svelte-i18n 集成问题

select value binding and svelte-i18n integration problem

我正在处理的事情似乎有点超出我的知识范围...

它是关于 select 值绑定的。在下面,这是一段简单的和平代码,可以在经典的 svelte SPA 中完美运行。

<script>
  let countrySelected = {
    code: 'BE',
    name: 'Belgium',
  };

  const countries = [
    {
      code: 'FR',
      name: 'France',
    },
    {
      code: 'BE',
      name: 'Belgium',
    },
    {
      code: 'GA',
      name: 'Gabon',
    },
  ];
</script>

<select bind:value={countrySelected}>
  {#each countries as country}
    <option value={country} selected={country.code === countrySelected.code}>
      {country.name}
    </option>
  {/each}
</select>

但无论出于何种原因,当它在使用 svelte-i18n npm 包的 sveltekit 应用程序中工作时,它不再起作用。

/src/routes/__layout.svelte

<script>
  import { setupI18n, isLocaleLoaded } from '$lib/services/i18n.js';

  $: if (!$isLocaleLoaded) {
    setupI18n({ withLocale: 'fr-FR' });
  }
</script>

{#if !$isLocaleLoaded}
  Please wait...
{:else}
  <main>
    <slot />
  </main>
{/if}

/src/lib/services/i18n.js

/src/lib/services/i18n.js的代码来自:

https://phrase.com/blog/posts/how-to-localize-a-svelte-app-with-svelte-i18n/ & https://lokalise.com/blog/svelte-i18n/

import { derived } from 'svelte/store';
import { dictionary, locale, _, date, time, number } from 'svelte-i18n';

const MESSAGE_FILE_URL_TEMPLATE = 'http://localhost:3000/lang/{locale}.json';

let cachedLocale;

async function setupI18n({ withLocale: _locale } = { withLocale: 'en-GB' }) {
  const messsagesFileUrl = MESSAGE_FILE_URL_TEMPLATE.replace(
    '{locale}',
    _locale
  );

  const res = await fetch(messsagesFileUrl);
  const messages = await res.json();
  dictionary.set({ [_locale]: messages });
  cachedLocale = _locale;
  locale.set(_locale);
}


// Before any locale is set, svelte-i18n will give locale an object type.
// Once it is correctly set, the libray will set locale
// to the code of the active locale, e.g. "en", a string type.
// We check for this in our devired store, and make sure that isLocaleLoaded‘s value
// is true only after i18n initialization is successful.
const isLocaleLoaded = derived(locale, $locale => typeof $locale === 'string');


export { _, locale, setupI18n, isLocaleLoaded, date, time, number };

问题:

index.svelte 文件中的 <select> 元素应显示“比利时”,因为:

countrySelected = { code: 'BE', name: 'Belgium', }

问题在于,在 __layout.svelte 中,svelte-i18n 会在项目 selected 之后进行某种刷新,因此看起来什么都没有 selected。 这可能是因为我在我的项目中集成 svelte-i18n 的方式,因为我只理解粗略的笔触,但再一次......细节决定成败 :D

非常感谢您的帮助。你可以克隆这个 repos,它会更容易理解:

git clone https://github.com/BigBoulard/sveltekit-sveltei18n
npm i
npm run dev

对于您的示例,如果您在浏览器中检查 select 元素,则 selected 属性未设置在任何 option.

Svelte 有一种非常简单易用的方法来设置初始 selected 值。

在将值绑定到 select 元素时,它会自动处理 option 元素上的必需属性。 您示例中的问题是,countrySelected 看起来与 countries 数组中的 object/dictionary 相同,但实际上是一个新对象,因此 Svelte 不能 select 它。

这个例子应该有效:

<script>
  const countries = [
    {
      code: 'FR',
      name: 'France',
    },
    {
      code: 'BE',
      name: 'Belgium',
    },
    {
      code: 'GA',
      name: 'Gabon',
    },
  ];

  let countrySelected = countries.find(x => x.code === 'BE');
</script>

<select bind:value={countrySelected}>
  {#each countries as country}
    <option value={country}>
      {country.name}
    </option>
  {/each}
</select>