solid-primitives icon indicating copy to clipboard operation
solid-primitives copied to clipboard

Add Rich Text Support to SolidJS i18n

Open 0-don opened this issue 1 year ago • 10 comments

Describe The Problem To Be Solved

Currently, we can't add links or styled text inside i18n translations in SolidJS. We need a simple way to add components like <A> or tags within our translated text, similar to how next-intl does it.

Suggest A Solution

Add a simple t.rich() method that allows mapping custom tags to Solid components:

Example usage:

{
  "message": "Please refer to <guidelines>{name}</guidelines>"
}

const t = useTranslations();

t.rich('message', {
  guidelines: (text) => <A href="/guidelines">{text}</A>
  name: "the guidelines"
})

Key features:

  • Support basic tag mapping
  • Work with existing SolidJS components
  • Keep the same simple API as regular translations

This would give us an easy way to add links and formatting to our translations while keeping the code clean and maintainable.

0-don avatar Oct 31 '24 21:10 0-don

I like the simple concept Maybe not that rich here is a method on whatever t is If this could be done as a separate helper I wouldn't really mind Don't see a way to make this type-safe though At least not without codegen So the "maintainable" part is up for debate

thetarnav avatar Oct 31 '24 21:10 thetarnav

Thanks for the feedback @thetarnav

You're right about the implementation concerns. I think we could start simple with just basic runtime validation of the tags and mapping object. No need to overcomplicate things with type safety or codegen at this stage.

The separate helper approach you suggested makes sense too. The main goal is just to enable basic rich text support in translations.

0-don avatar Oct 31 '24 21:10 0-don

I like the idea of a resolveTags helper. Not being type safe may be a drawback, but not one that should concern us. We should use a callback function that emits a warning in DEV and strips the tags in prod.

atk avatar Nov 01 '24 08:11 atk

This is a must need. Not the best/easiest way to implement it, but some feature is better than no feature

joaofranciscoguarda avatar Nov 06 '24 04:11 joaofranciscoguarda

I found a good example which next-intl uses internally https://github.com/formatjs/formatjs/blob/main/packages/icu-messageformat-parser/parser.ts#L346

0-don avatar Nov 06 '24 17:11 0-don

I would love this!

masylum avatar Apr 07 '25 20:04 masylum

A workaround would be returning JSX instead of strings and pass in a component like this:

{
  message: (Guidelines: ParentComponent, name: string) => <>Please refer to <Guidelines>{params.name}</Guidelines></>
}

t(
  "message",
  (props) => <A href="/guidelines">{props.children}</A>,
  "the guidelines"
)

niko-gardenanet avatar Jun 26 '25 07:06 niko-gardenanet

Dynamic components are not yet supported like this IIRC. You would need to use Dynamic, but otherwise, it illustrates well what is meant.

atk avatar Jun 26 '25 09:06 atk

I'm using the above solution right now and it works without issues as far as i can tell

niko-gardenanet avatar Jun 26 '25 09:06 niko-gardenanet

Ah, then that's already fixed, it seems.

atk avatar Jun 26 '25 13:06 atk