robisim74 / qwik-speak

Translate your Qwik apps into any language
https://robisim74.gitbook.io/qwik-speak/
MIT License
133 stars 15 forks source link

Issue with runtime translation in some scenarios #101

Closed gnemanja closed 11 months ago

gnemanja commented 11 months ago

inlineTranslate doesn't always translate the key during runtime. I will try to explain the scenario.

I have a form with an input field inside, as well as the option of displaying and translating error once I validate the data on submit:

<form>
<input name="aaa" />
<span> {translate(formErrorKey)} </span>

<button type="submit" />

Now let's say that I've registered runtime assets like this: useSpeak({runtimeAssets: ["FORM"]})

Okey, let's add the file: .../FORM.json

{
  "key-1": "111",
}

The {translate(formErrorKey)} function will return just the key as a string.

Now let's hard code this key as if I also want it to be translated the first time code is executed on the client side:

<form>
<input name="aaa" />
<span> {translate(formErrorKey)} </span>

{translate("FORM.key-1")}

<button type="submit" />

When server side rendered, obviously {translate("FORM.key-1")} will result in FORM.key-1. Then, after any logic is triggered (when I click on the form for example), {translate("FORM.key-1")} will properly be translated in runtime to "111". But after I submit the form, the {translate(formErrorKey)} will result in "FORM.key-1".

I don't have access rights to branch out and fix this so I will just add a clue to where the issue is: In getValue(key, data, ...) function, when the translation is invoked after validating the form, key is proper, but data isn't. data object is empty and only has "default" attribute inside which looks like this:

data: {
  default: {
    FORM: {
      key-1: "111"
    }
  }
}

Thank You in advance

robisim74 commented 11 months ago

Hi,

When server side rendered, obviously {translate("FORM.key-1")} will result in FORM.key-1

No, it should also be translated during SSR, so it means that the component does not have the translation file available.

Where did you put useSpeak? Did you put it in the parent component of where it is used?

See https://github.com/robisim74/qwik-speak/blob/main/docs/lazy-loading.md

gnemanja commented 11 months ago

If I don't register FORM as an asset, just as a runtimeAsset, it shouldn't translate it during SSR, right?

I added {translate("FORM.key-1")} just to speed up the process of finding the source of the issue. Runtime translate obviously works in this scenario, so the whole thing is properly registered with useSpeak

robisim74 commented 11 months ago

Server side, both assets and runtimeAssetsare available, so it should be translated.

Client side, only runtimeAssets are available, because assets are inlined in chunks during compilation.

gnemanja commented 11 months ago

Hmm okey.

Than to answer your question, yes, useSpeak is registered in the layout (layout.tsx) while I am using the translation function in the component (index.tsx). I can console log and see how the data object looks for FORM.key-1 during the SSR?

Also, if possible, the code would be much cleaner if it is possible to use useSpeak inside the component where I need these translations :)

Also, for bigger projects, having a global place for translations might not be the best practice. Maybe adding an option to have translation files inside src next to components/routes, might be a good idea.

But all these ideas aren't crucial now :D I really need this to work so I can launch the website :D

robisim74 commented 11 months ago

the code would be much cleaner if it is possible to use useSpeak inside the component where I need these translations

I know, I get it, but Qwik works like this: components are rendered asynchronously in isolation: and doing reactive translations would unnecessarily destroy performance, the main reason why Qwik is used.

About your actual problem, please provide a reproduction, or at least the complete logic of your component.

gnemanja commented 11 months ago

Okey, thanks for explaining.

The issue has nothing to do with what I wrote before.

When the asset is named with words separated by "-" it doesn't always work.

So: useSpeak('terms-and-privacy.test') won't work. useSpeak('termsAndPrivacy.test') works.

robisim74 commented 11 months ago

Uhm... the problem is not in the name of the assets by itself, ma in the key names.

With dynamic import the keys must be valid variable names: https://github.com/robisim74/qwik-speak/blob/main/docs/translation-functions.md#bundling-files

In fact, import.meta.glob of Vite transforms files into javascript objects, as you can see by inspecting /server/assets after a build.