svelte-time icon indicating copy to clipboard operation
svelte-time copied to clipboard

How do I load multiple locales and update the <Time> using $locale?

Open elron opened this issue 11 months ago • 1 comments

Hey

In my i18n supported website I have a store called $locale and it changes the value from "en" (English) to "he" (Hebrew) and more.

I want that whenever a $locale change is made, all <Time> instances would be updated.

How do I achieve that?

Thanks

elron avatar Jul 15 '23 06:07 elron

For now I found a custom solution, thanks for making this library!

I installed pnpm i dayjs -D and added two files: LocaleTime.svelte

<script lang="ts">
  import { locale } from '$lib/i18n/i18n';
  import Time from './Time.svelte';

  import 'dayjs/locale/he';

  export let timestamp: any;
  export let relative: boolean = true;
</script>

{#key $locale}
  <Time {...$$props} {timestamp} {relative} locale={$locale} />
{/key}

and Time.svelte (based on your code):

<script>
  /**
   * Thanks:
   * https://github.com/metonym/svelte-time 
  */
  import dayjs from 'dayjs';
  import { onMount } from 'svelte';
  import relativeTime from 'dayjs/plugin/relativeTime.js';

  dayjs.extend(relativeTime);

  export let locale;
  dayjs.locale(locale);

  /**
   * Original timestamp
   * @type {import("dayjs").ConfigType}
   */
  export let timestamp = new Date().toISOString();

  /**
   * Timestamp format for display.
   * It's also used as a title in the `relative` mode
   * @type {import("dayjs").OptionType}
   * @example "YYYY-MM-DD"
   */
  export let format = 'MMM DD, YYYY';

  /**
   * Set to `true` to display the relative time from the provided `timestamp`.
   * The value is displayed in a human-readable, relative format (e.g., "4 days ago", "Last week")
   * @type {boolean}
   */
  export let relative = false;

  /**
   * Set to `true` to update the relative time at 60 second interval.
   * Pass in a number (ms) to specify the interval length
   * @type {boolean | number}
   */
  export let live = false;

  /**
   * Formatted timestamp.
   * Result of invoking `dayjs().format()`
   * @type {string}
   */
  export let formatted = '';

  /** @type {undefined | NodeJS.Timer} */
  let interval = undefined;

  const DEFAULT_INTERVAL = 60 * 1_000;

  onMount(() => {
    if (relative && live !== false) {
      interval = setInterval(() => {
        formatted = dayjs(timestamp).from();
      }, Math.abs(typeof live === 'number' ? live : DEFAULT_INTERVAL));
    }

    return () => {
      if (typeof interval === 'number') {
        clearInterval(interval);
      }
    };
  });

  $: formatted = relative ? dayjs(timestamp).from() : dayjs(timestamp).format(format);
  $: title = relative ? dayjs(timestamp).format(format) : undefined;
</script>

<time {...$$restProps} {title} datetime={timestamp}>
  {formatted}
</time>

elron avatar Jul 15 '23 19:07 elron