Git Product home page Git Product logo

Comments (17)

YehorPytomets avatar YehorPytomets commented on July 28, 2024 3

Hello @kkuegler, thank you for your response :)

Now I see why the single curly braces are preferred. Btw, we have already accustomed to using single curly braces syntax for terms intended for TranslationComponents. It just required changing the terms in several places.

The fix for the Vue 3 compat build worked for us too, thanks for that.

So, it seems this issue is no longer a problem and I consider this solved for us.
Thank you a lot for your support and quick feedback on the emergent issues. It significantly simplified the migration of our apps to the Vue 3 ecosystem 🙂

from i18next-vue.

jamuhl avatar jamuhl commented on July 28, 2024 1

Trans component from react-i18next might be somewhat an inspiration: https://react.i18next.com/latest/trans-component

from i18next-vue.

YehorPytomets avatar YehorPytomets commented on July 28, 2024 1

Hello, @kkuegler, thank you for explaining that. Yes, that was exactly what I was asking for. Since everything is now clear to me, I will look forward to trying this component in our code :)

from i18next-vue.

kkuegler avatar kkuegler commented on July 28, 2024 1

Hehe, I'll see if I can get a new version ready later today :)

from i18next-vue.

YehorPytomets avatar YehorPytomets commented on July 28, 2024 1

@kkuegler, thank you for letting me know. I'll come back with feedback after trying on the component :)

from i18next-vue.

YehorPytomets avatar YehorPytomets commented on July 28, 2024 1

@kkuegler, I've tried the TranslationComponent in our components. Thank you for your help. It worked for all our cases.

But, there were some obstacles, that I would like to mention.

  1. We are using double curly braces as interpolation prefixes {{ and suffixes }} in all our localization terms, as mentioned in i18next docs. Without explicitly changing the prefixes and suffixes to single brackets ({, }) in particular terms that are displayed via TranslationComponent, the outer brackets are rendered as text.
    Is it possible to use the prefixes and suffixes from the i18next setup in TranslationComponent without changing the setup to single brackets in our code in order to keep the localization terms with double brackets?

Screenshot 2022-08-29 at 18 17 22

  1. As we are using migration build to migrate our apps from Vue 2 to Vue 3 with the Vue CLI setup, I found out that the TranslationComponent doesn't work in Vue 2 compat mode. It took some time for me to just disable the compat mode by removing the lines from the Vue CLI setup and see that everything works 🙂. Mainly this is because I thought that the component would work in the compat mode, but I think it would be good to mention that in docs for others to know.

Screenshot 2022-08-31 at 10 55 32

from i18next-vue.

kkuegler avatar kkuegler commented on July 28, 2024 1

Hey @YehorPytomets, thanks for your comments :)

Single/double braces

To me the first problem sounds like a misunderstanding. I chose the single-curly {termsOfUseLink} syntax for slots explicitly to work nicely with the default double curly braces interpolation for 'normal' values {{ someValue }}.

I'll try to explain this with an example:

<i18next :translation="$t('license.goToTermsOfUse', { interpolateMe: 42 })">
    <template #termsOfUseLink>
    ...
    </template>
</i18next>

with the translation looking like this:

license: {
    goToTermsOfUse: "Read our {termsOfUseLink}. Traditional interpolation: {{interpolateMe}}",
}

By using single braces to refer to the slot {termsOfUseLink} the $t function will just treat this as normal text and not do any interpolation with it. That's what we want, because there is no interpolation value for the key termsOfUseLink.

The normal interpolations with double braces still happens as usual (i.e. for {{interpolateMe}} in the example). The :translation passed to TranslationComponent will be Read our {termsOfUseLink}. Traditional interpolation: 42.

Then TranslationComponent takes this string and replaces all single curly brace references with the corresponding slots.

So there is a mix of double braces for traditional value interpolation and single braces for slot/template interpolation. If I'm not mistaken, you only need to remove the extra braces for the slots and everything works as expected.

Does this make sense?

This all still needs proper documentation. When we come around to document this, this is probably a gotcha that we should explicitly point out.

Compatibility mode

I could reproduce the problem with the Vue 3 compat build. Apparently it tries to handle TranslationComponent as an async Vue 2 component instead of a "normal" Vue 3 one. As a workaround, disabling the compat feature flag COMPONENT_ASYNC should already help, but disabling compatibility mode altogether also works.

Following https://v3-migration.vuejs.org/migration-build.html#compat-configuration this would look like this:

configureCompat({
    COMPONENT_ASYNC: false,
})

With the next release, I'll switch the TranslationComponent implementation from a (stateless) functional component to a traditional stateful component. This way it works without any workarounds in compat mode, too. As https://v3-migration.vuejs.org/breaking-changes/functional-components.html says, this should not have any significant performance penalties.

from i18next-vue.

kkuegler avatar kkuegler commented on July 28, 2024 1

Using the double curly brace syntax also for slots could technically work, as the t() function just returns {{termsOfUseLink}} if there is no such interpolation value passed to the translation function.

There is however an optional configuration option (missingInterpolationHandler, see https://www.i18next.com/overview/configuration-options#missing-keys) that would get called in these cases. As this option might help with finding broken translation messages, I don't want to rely on it being a no-op.

Having a separate syntax (single curly braces) does not interfere with this, that's why I prefer it.

from i18next-vue.

kkuegler avatar kkuegler commented on July 28, 2024 1

Thanks @YehorPytomets for your kind feedback!
I'm happy this feature works for you now and we could work out some of the hurdles along the way 😃

from i18next-vue.

YehorPytomets avatar YehorPytomets commented on July 28, 2024

@kkuegler, any updates on this? I would appreciate any response on the possibility of implementing that.

from i18next-vue.

kkuegler avatar kkuegler commented on July 28, 2024

I looked into this and like the Vue slot approach taken here https://vue-i18n.intlify.dev/guide/advanced/component.html#slots-syntax-usage quite a bit. It's quite similar to the @panter/vue-i18next one, but feels even more "Vue-y".

This is less flexible than https://react.i18next.com/latest/trans-component, but to me seems to be easier to use (and implement).

<!--
Proposed i18next-vue syntax
  -->
<template>
<!-- ...some other template code... -->
<p class="value"><!-- the wrapper tag just uses normal template syntax -->
    <TranslationComponent :translation="$t('license.goToTermsOfUse')"> <!-- translation in the parent -->
        <template #termsOfUseLink> <!-- will be referenced via {termsOfUseLink} in the localized message -->
            <router-link :to="{ name: 'LICENSE' }"
                         class="link">
                {{ $t("license.termsOfUse") }}
            </router-link>
        </template>
    </TranslationComponent>
</p>
</template>

with the translations looking like this:

        en: {
            translation: {
                license: {
                    goToTermsOfUse: "Read our {termsOfUseLink}",
                    termsOfUse: 'Terms of Use'
                }
            }
       }

Some additional considerations:

  • I named it TranslationComponent for now. i18next as a component name seems somewhat ambiguous, especially when importing it explicitly inside a Vue component.
  • The translation itself happens in the parent component (using $t()).
    • Are there any downsides to this?
    • Especially when one wants to pass options (e.g. values for interpolation), this seems easier to me than having to pass all the options to TranslationComponent which then would actually translate a given key.
  • There is no tag attribute, but one can just wrap the TranslationComponent inside a "normal" tag if desired.

What do you think?

from i18next-vue.

YehorPytomets avatar YehorPytomets commented on July 28, 2024

@kkuegler, thank you for your response!

I've looked through your proposal and our code that employs the <i18next> component and it seems that your approach covers all our cases as it allows passing template code (HTML and components) as interpolation values.

The slots approach feels familiar when using it for interpolation points.

No problem with the absence of the tag attribute. The proposed way seems concise and easier to use than the tag attribute for me.

I have doubts about passing the $t('license.goToTermsOfUse')" to the :translation property. It seems that the call to the function will produce the output without interpolated value => Read our {{termsOfUseLink}}.
Or this is intentional for implementation purposes?
If not, passing options separately seems not bad as well as the :translation="$t('license.goToTermsOfUse')" way:

<TranslationComponent key="license.goToTermsOfUse" :options="optionsObject">

Can the t() function be used as well as $t() here?

Would be grateful to hear back from you on that.

from i18next-vue.

kkuegler avatar kkuegler commented on July 28, 2024

Hey @YehorPytomets, thanks for the feedback :)

As you said, the $t('license.goToTermsOfUse') would just produce the un-interpolated string 'Read our {termsOfUseLink}' (with single curly braces) and pass that to the TranslationComponent. The "magic" then happens inside the render logic of TranslationComponent. That outputs the text parts of the translation as well as the slot contents in the correct places.

The i18next translation always needs to happen as a separate step before the interpolation using slots, even if we did the translation within the TranslationComponent. Is that what your concern about :translation was about?

Locally, I have a working implementation using :translation. I just want to make sure this also makes sense from a user perspective :)

When the translation happens outside of TranslationComponent (i.e. with :translation), you can use any kind of translation function. If we do the translation inside (with key/:options), one would need to pass the t function as a prop as well, because otherwise only $t is available inside.

from i18next-vue.

kkuegler avatar kkuegler commented on July 28, 2024

It's out now. As you can see in the release notes I changed the default component name (back) to <i18next>, but also made the component available as a named export if you like another name better.

from i18next-vue.

Related Issues (16)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.