Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature idea: Trans component #4

Open
adrai opened this issue Apr 9, 2022 · 5 comments
Open

feature idea: Trans component #4

adrai opened this issue Apr 9, 2022 · 5 comments

Comments

@adrai
Copy link

adrai commented Apr 9, 2022

It would be awesome to have also something like a Trans component, like in react-i18next.

That would help to interpolate components/html elements...

<Trans i18nKey="test.key">
    Hi from <a href="https://www.i18next.com" target="_blank" rel="noopener">i18next</a> 👋
</Trans>
@ralyodio
Copy link

why would you want this? just curious.

@adrai
Copy link
Author

adrai commented Apr 28, 2022

why would you want this? just curious.

How would you interpolate a text like the one in my example?

i.e. english like this:

<div>
  Hi from <a href="https://www.i18next.com" target="_blank" rel="noopener">i18next</a> 👋
</div>

i.e. german like this:

<div>
  Ein freundliches 👋 "Hallo" von <a href="https://www.i18next.com" target="_blank" rel="noopener">i18next</a>
</div>

i.e. italian like this:

<div>
  <a href="https://www.i18next.com" target="_blank" rel="noopener">i18next</a> ti saluta 👋
</div>

@CanRau
Copy link

CanRau commented Oct 26, 2022

Yes please I'm in the need for the same thing in Svelte trying to add links to translations 🙏

@coeursoft
Copy link

I concur. Running into this issue with HTML and a on:click in the middle of the string. Not sure how to address this right now

@coeursoft
Copy link

coeursoft commented Jun 6, 2024

I've come up with a quick solution to be improved

Translation component: (loc is the translation store)

<script lang="ts">
import { derived, readable } from 'svelte/store';
import { loc } from './store';
import { isString } from 'lodash-es';
import type { ComponentType, ComponentProps } from 'svelte';

export let key: string;

export let parts: Array<[ComponentType, ComponentProps, string]> = [];


const content = key
  ? derived(loc, (loc) => {
    const result = loc.t(key);
    const final = result && result !== key ? result : null;
    if (!final) {
      console.warn('No translation found for ' + key + ' - ');
    }
    return final ?? '';
  })
  : readable('');

const contentParts = derived(content, content => {
  if (!isString(content)) {
    return [];
  }
  if (!content?.trim()) {
    return [];
  }

  const regex = /(?<=@@\d+)|(?=@@\d+)/;
  const split = content.split(regex);
  const prefix = '@@';
  const replaced = split.map(part => {
    if (part.startsWith(prefix)) {
      const index = Number(part.replace(prefix, ''));
      if (isNaN(index)) {
        return part;
      }
      return parts[index];
    }
    return part;
  });
  
  return replaced.length > 0 ? replaced : [ content ];
});


</script>


{#if $contentParts.length}
  {#each $contentParts as part}
    {#if isString(part)}
      {part}
    {:else}
      <svelte:component this={part[0]} { ...part[1] }>{part[2]}</svelte:component>
    {/if}
  {/each}
{:else}
  <slot />
{/if}

Translation file

{
  "home.contact": "Contact us on @@0 or @@1.",
}

Then in one template

      <I18n key="home.contact"
            html={true}
            parts={[
              [ Link, { href: discordUrl, target: '_blank' }, 'Discord' ],
              [ Link, { href: facebookUrl, target: '_blank' }, 'Discord' ],
            ]}
      >
        Contact us on [[<Link href={discordUrl} target="_blank">Discord</Link>]] or [[<Link href={facebookUrl} target="_blank">Facebook</Link>]].
      </I18n>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants