Comments (17)
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 TranslationComponent
s. 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.
Trans
component from react-i18next might be somewhat an inspiration: https://react.i18next.com/latest/trans-component
from i18next-vue.
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.
Hehe, I'll see if I can get a new version ready later today :)
from i18next-vue.
@kkuegler, thank you for letting me know. I'll come back with feedback after trying on the component :)
from i18next-vue.
@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.
- 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 viaTranslationComponent
, the outer brackets are rendered as text.
Is it possible to use the prefixes and suffixes from thei18next
setup inTranslationComponent
without changing the setup to single brackets in our code in order to keep the localization terms with double brackets?
- 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.
from i18next-vue.
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.
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.
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.
@kkuegler, any updates on this? I would appreciate any response on the possibility of implementing that.
from i18next-vue.
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 theTranslationComponent
inside a "normal" tag if desired.
What do you think?
from i18next-vue.
@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.
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.
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)
- Update GitHub workflows to match the new organization HOT 5
- support esm export
- importing i18next-vue breaks type checking a basic nuxt app HOT 4
- Please update for i18next > v22.5.0 HOT 2
- Changes for `i18next-vue` v3 HOT 1
- test HOT 1
- [Typescript Error] useTranslation - Type instantiation is excessively deep and possibly infinite HOT 2
- Vue 2 compatible TranslationComponent not working as expected HOT 2
- Unable to install via npm? HOT 2
- dont work lazy loading file HOT 2
- how to access this.$i18next in composition api setup HOT 2
- Support TypeScript HOT 7
- The `i18next` object returned from the `useTranslation()` is not reactive. HOT 3
- Limit the scope of a SFC component to some namespace and key prefix. HOT 7
- support v-t directive HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from i18next-vue.