Polyconseil / vue-gettext

Translate your Vue.js applications with gettext.
MIT License
278 stars 55 forks source link

Slot-based interpolation #93

Open mitar opened 5 years ago

mitar commented 5 years ago

Currently, if one wants to translate a paragraph of text, which includes also <router-link> links, the suggested approach is to use v-translate directive. The problem with this approach is with how to interpolate <router-link> so that clicking on a link does not reload the app. Namely, <router-link> does not just render <a href> but it also intercepts a click and just modifies the history instead. Otherwise clicking on the link would reload the whole app.

I think that this package should make <directive> work with slots which would then be rendered inside placeholders. So something like:

<translate>
  Click <router-link translate-name="login" :to="{name: 'login'}" v-translate>to login</router-link> or <router-link translate-name="signup" :to="{name: 'signup'}" v-translate>to sign-up</router-link>. Or <a translate-name="escape" v-translate href="https://www.google.com">escape</a>.
</translate>

That should generate four translation strings:

So any child of <translate> should have translate-name attribute which is then mapped to a placeholder in its string. Then text around those children is translated and changed according to translation. And children are left as-is, with all Vue rendering, event handling, and everything else.

Oh, and probably the string inside the component should be trimmed of any whitespace at the start and end.

So I can see how this would work through Vue, but I do not know how such strings could be automatically correctly extracted.

vperron commented 5 years ago

I see how we could proceed to a (quite massive) addition to vue-gettext to support your idea, however as you said, easygettext is not yet smart enough (and nothing else is, either !) to be able to extract such a string in the way you're expecting it. It may theoretically be programmed, but I don't think it's a good idea because that would require a vue-router specific heuristic and that will most probably never be accepted in a generic token-extracting package :)

Your use case seems complicated. You're in a SPA, you hava a paragraph of text that you want to translate, which is full of not simple <a> but <router-link> and upon clicks, you trigger changes in your DOM without a full reload.

I'm not sure which idea is the best to get around this, but yours (or introducing generic templated slots inside a paragraph of text) will in any case require some huge work.

mitar commented 5 years ago

It may theoretically be programmed, but I don't think it's a good idea because that would require a vue-router specific heuristic and that will most probably never be accepted in a generic token-extracting package

I do no think it is too hard, BTW. It would be mostly converting any string of form:

<translate>XXX<... translate-name="NNN" ...>...</...>YYY</translate>

to:

XXX%{NNN}YYY

So I think this can be done through regex expressions. Anything inside <translate></translate> you simply remove any HTML tags. The only exception is that if a HTML tag has translate-name attribute, you convert that to a placeholder.

You do not know necessary have to hard-code too specific things about Vue, and especially this is unrelated to vue-router.

vperron commented 5 years ago

Indeed :) Do you think you could try this in a pull request in both easygettext & vue-gettext ? Not sure we'll succeed in the first pass but it's definitely worth a try to demonstrate the solution and get there sooner.

mitar commented 5 years ago

I think this is slightly over my head, but I opened: https://github.com/Polyconseil/easygettext/issues/58

vperron commented 5 years ago

Aha :) Yep, so we'll keep that in mind and think about it when we next proceed to major changes. But it won't be immediate, we don't have much time to spend on this package's improvement usually, unless merging other community-issued pull requests :)

Someday !