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

i18n component interpolation with variables in loop not working properly #676

Closed
picssel opened this issue Aug 2, 2019 · 4 comments

Comments

@picssel
Copy link

commented Aug 2, 2019

vue & vue-i18n version

"vue": "^2.5.22",
"vue-i18n": "8.12.0"
"@kazupon/vue-i18n-loader": "0.4.1",

Reproduction Link

Working sample at
See components -> HelloWorld.vue for code
codesandbox

Steps to reproduce

Having this locale JSON object:

{
  "companyName": "picssel",
  "section1": {
    "s1p1": "This is p1, and company name is '@:(companyName)', and var1 is {var1}",
    "s1p2": "This is p2, and again company name is '@:(companyName)', and var2 is {var2}",
    "s1p3": "This is p3, and last company name is '@:(companyName)', and var3 is {var3}"
  },
  "section2": {
    "s2p1": "This is p1, and company name is '@:(companyName)', and the common variable value is {commonvar}",
    "s2p2": "This is p2, and company name is '@:(companyName)', and the common variable value is {commonvar}",
    "s2p3": "This is p3, and company name is '@:(companyName)', and the common variable value is {commonvar}"
  }
}

Please note we are using two type of vars:

  • @:(companyName) to refer another string in the locale
  • {var1} to refer an external (reactive) variable

If we consume the properties inside the object individually, everything works fine; e.g.

  <i18n path="section1.s1p1" tag="p">
	<span place="var1">"value p1"</span>
  </i18n>
  <i18n path="section1.s1p2" tag="p">
	<span place="var2">"value for p2"</span>
  </i18n>

it renders (as expected)

This is p1, and company name is 'picssel', and var1 is "value p1"
This is p2, and again company name is 'picssel', and var2 is "value for p2"

What is actually happening?

However, if we iterate over the properties of the object section2 for example (where they share the same variables), the text is rendered but not the variables; e.g.

  <div v-for="(p, index) in $t('section2')" v-bind:key="index">
	<i18n :path="p" tag="p">
	  <span place="commonvar">{{commonvar}}</span>
	</i18n>
  </div>

it renders

This is p1, and company name is '@:(companyName)', and the common variable value is {commonvar}
This is p2, and company name is '@:(companyName)', and the common variable value is {commonvar}
This is p3, and company name is '@:(companyName)', and the common variable value is {commonvar}
BTW, I noticed I have to use ':path' for the attribute because 'path' alone only renders 'p'.
See demo link for further reference

What is expected?

The variables should be properly rendered, either consuming the strings individually or in a loop

We have tried several combinations, including using v-html with the same results so

Questions

  • Are we missing something in our approach?
  • Is this a bug?
  • The results in the "loop" are expected since this feature is not yet implemented?

We want to loop over the strings because we want to optimize our HTML templates (think we may have several paragraphs on each section, therefore hard-coding a HTML tag for each of them individually is a "no-go")

Thanks

@exoego

This comment has been minimized.

Copy link
Collaborator

commented Aug 2, 2019

I am afraid that such usage is not supported right now.
Because $t('section2') returns its content (object) and therefore it is used in v-for, but vue-i18n does not interporate its content.
IIUC, i18n interporates messge string only if there is a string value corresponding to the given message key, or key missing.

I think the issue #460 is about same usecase of your situation.

@exoego

This comment has been minimized.

Copy link
Collaborator

commented Aug 2, 2019

I am not sure what use case looping language object is useful.
Could you give more detail for us to understand why it is better than plain simple large string, like

"section2": {
    "s2p1": 
      "This is p1, and company name is '@:(companyName)', ...\
        This is p2, and company name is '@:(companyName)', ...\
        This is p3, and company name is '@:(companyName)', ..."
  }
@picssel

This comment has been minimized.

Copy link
Author

commented Aug 3, 2019

@exoego Thanks for your comments.

Managing a simple large string like s2p1 in your example above, may not be optimal from the translator and translations tools point of view.

Looping over a language object is useful to reduce to a minimum your HTML code, where you can abstract the section object regardless how many nested paragraphs it may contain

Unless you have a case test example where such scenario can be implemented with simple large strings?

@picssel

This comment has been minimized.

Copy link
Author

commented Aug 3, 2019

Well, I found a work around (hack) to get the result I wanted.

Within the loop, I am using a custom method that returns the locale string with the variables properly rendered.

This custom method receives 2 parameters:

  • the name of the parent object (as string), which I am iterating over
  • the index (key) of the child property

So my HTML template that iterates over the properties of the object section2 for example, now it looks like:

  <div v-for="(paragraph, index) in $t('section2')" v-bind:key="index">
    <p>{{ i18nStringBuilder("section2", index) }}</p>
  </div>

And the i18nStringBuilder method

  i18nStringBuilder: function(section, index) {
    // pass any variable the string(s) may require
    let args = { 
      commonvar: this.commonvar, 
      var1: "custom value" 
    };
    return this.$t(`${section}.${index}`, args);
  }

Notice that we can pass any variable regardless whether they exist or not in the string we are iterating over (useful when we have different variables)

New codesandbox

Note
I will close this issue for now, that may be reopened if a better approach comes out or this use case is natively supported by the plugin

@picssel picssel closed this Aug 3, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.